From 347952f5db0496c05e901d23b81310992539dc03 Mon Sep 17 00:00:00 2001
From: Valentin Deniaud <vdeniaud@entrouvert.com>
Date: Thu, 10 Oct 2019 11:26:29 +0200
Subject: [PATCH] csv_import: display all row errors (#36832)

---
 src/authentic2/csv_import.py |  1 +
 tests/test_user_manager.py   | 64 ++++++++++++++++++++++--------------
 2 files changed, 40 insertions(+), 25 deletions(-)

diff --git a/src/authentic2/csv_import.py b/src/authentic2/csv_import.py
index 563b312f..6c519576 100644
--- a/src/authentic2/csv_import.py
+++ b/src/authentic2/csv_import.py
@@ -293,6 +293,7 @@ class UserCsvImporter(object):
                         try:
                             if not self.do_import_row(row, unique_map):
                                 self.rows_with_errors += 1
+                                self.row.is_valid = False
                         except CancelImport:
                             self.rows_with_errors += 1
                         if row.errors:
diff --git a/tests/test_user_manager.py b/tests/test_user_manager.py
index 7a6a880e..283addd4 100644
--- a/tests/test_user_manager.py
+++ b/tests/test_user_manager.py
@@ -352,6 +352,32 @@ def test_su_superuser_dialog(app, app_factory, superuser, simple_user):
     new_app.get(su_url).maybe_follow()
     assert new_app.session['_auth_user_id'] == str(simple_user.pk)
 
+
+def import_csv(csv_content, app):
+    response = app.get('/manage/users/')
+    response = response.click('Import users')
+    index = [i for i in response.forms if 'import_file' in response.forms[i].fields][0]
+    response.forms[index].set(
+        'import_file',
+        Upload('users.csv', csv_content.encode('utf-8'), 'application/octet-stream'))
+    response.forms[index].set('encoding', 'utf-8')
+    response.forms[index].set('ou', str(get_default_ou().pk))
+    response = response.forms[index].submit().follow()
+    response = response.forms['action-form'].submit(name='execute').follow()
+
+    start = time.time()
+    response = response.click('Users Import')
+    while 'Running' in response.text:
+        response = response.click('Users Import')
+        assert time.time() - start < 2
+        time.sleep(.1)
+
+    # report
+    urls = re.findall('<a href="(/manage/users/import/[^/]+/[^/]+/)">', response.content)
+    response = app.get(urls[0])
+    return response
+
+
 @skipif_sqlite
 def test_user_import_attributes(transactional_db, app, admin, media):
     Attribute.objects.create(name='more', kind='string', label='Signe particulier')
@@ -365,35 +391,12 @@ def test_user_import_attributes(transactional_db, app, admin, media):
     user_count = User.objects.count()
     login(app, admin, '/manage/users/')
 
-    def import_csv(csv_content):
-        response = app.get('/manage/users/')
-        response = response.click('Import users')
-        index = [i for i in response.forms if 'import_file' in response.forms[i].fields][0]
-        response.forms[index].set(
-            'import_file',
-            Upload('users.csv', csv_content.encode('utf-8'), 'application/octet-stream'))
-        response.forms[index].set('encoding', 'utf-8')
-        response.forms[index].set('ou', str(get_default_ou().pk))
-        response = response.forms[index].submit().follow()
-        response = response.forms['action-form'].submit(name='execute').follow()
-
-        start = time.time()
-        response = response.click('Users Import')
-        while 'Running' in response.text:
-            response = response.click('Users Import')
-            assert time.time() - start < 2
-            time.sleep(.1)
-
-        # report
-        urls = re.findall('<a href="(/manage/users/import/[^/]+/[^/]+/)">', response.content)
-        response = app.get(urls[0])
-        return response
 
     csv_lines = [
         u"email key verified,first_name,last_name,more,title,bike,saintsday,birthdate,zip,phone",
         u"elliot@universalpictures.com,Elliott,Thomas,petit,Mr,True,2019-7-20,1972-05-26,75014,1234",
         u"et@universalpictures.com,ET,the Extra-Terrestrial,long,??,False,1/2/3/4,0002-2-22,42,home"]
-    response = import_csv('\n'.join(csv_lines))
+    response = import_csv('\n'.join(csv_lines), app)
     urls = re.findall('<a href="(/manage/users/import/[^/]+/[^/]+/)">', response.content)
     response = app.get(urls[0])
     assert 'Select a valid choice. ?? is not one of the available choices.' in response.content
@@ -414,7 +417,7 @@ def test_user_import_attributes(transactional_db, app, admin, media):
 
     csv_lines[2] = \
         u"et@universalpictures.com,ET,the Extra-Terrestrial,,,,,,42000,+888 5678"
-    response = import_csv('\n'.join(csv_lines))
+    response = import_csv('\n'.join(csv_lines), app)
     assert '0 rows have errors' in response.content
 
     assert User.objects.count() == user_count + 2
@@ -426,3 +429,14 @@ def test_user_import_attributes(transactional_db, app, admin, media):
     assert 'birthdate' not in et.attributes.values
     assert et.attributes.values['zip'].content == '42000'
     assert et.attributes.values['phone'].content == '+8885678'
+
+
+@skipif_sqlite
+def test_user_import_row_error_display(transactional_db, app, admin, media):
+    User.objects.create(first_name='Elliott', last_name='1', ou=get_default_ou())
+    User.objects.create(first_name='Elliott', last_name='2', ou=get_default_ou())
+    content = '''first_name key,last_name update
+Elliott,3'''
+    login(app, admin, '/manage/users/')
+    response = import_csv(content, app)
+    assert 'row-invalid' in response.content
-- 
2.20.1

