def test_invalid_row(self): result: csv_utils.CsvStatus = csv_utils.validate_csv( self.fields, self.csv_dir + '/invalid_row.csv') self.assertEqual(result.valid, False) self.assertNotEqual(result.error_message, None) self.assertEqual(result.data, None) result = csv_utils.validate_csv(self.fields, self.csv_dir + '/invalid_row2.csv') self.assertEqual(result.valid, False) self.assertNotEqual(result.error_message, None) self.assertEqual(result.data, None)
def test_primary_key(self): result: csv_utils.CsvStatus = csv_utils.validate_csv( ['user_id', 'name'], self.csv_dir + '/invalid_duplicate_pk.csv', primary_key_field='user_id') self.assertEqual(result.valid, False) self.assertNotEqual(result.error_message, '') self.assertNotEqual(result.error_message, None) self.assertNotEqual(result.data, None) self.assertEqual(len(result.data), 1) self.assertEqual(result.data[0]['user_id'], 'fred') self.assertEqual(result.data[0]['name'], 'The Fred') result: csv_utils.CsvStatus = csv_utils.validate_csv( self.fields, self.csv_dir + '/valid_users.csv', primary_key_field='user_id') self.assertEqual(result.valid, True) self.assertNotEqual(result.data, None)
def test_header_validation(self): # Pass when all fields are also in the csv header # Pass when there are spaces after the ',' delimiter result: csv_utils.CsvStatus = csv_utils.validate_csv( self.fields, self.csv_dir + '/valid.csv') self.assertEqual(result.valid, True, "Could not find all the fields in csv header") # Fail when field not found in csv header result = csv_utils.validate_csv(self.fields, self.csv_dir + '/invalid_header.csv') self.assertEqual(result.valid, False) self.assertEqual(result.data, None) self.assertNotEqual(result.error_message, None) # Pass when there are extra fields in the csv header result = csv_utils.validate_csv( self.fields, self.csv_dir + '/valid_header_extra.csv') self.assertEqual(result.valid, True)
def test_unicode(self): result: csv_utils.CsvStatus = csv_utils.validate_csv( fields=self.fields, file_path=self.csv_dir + '/valid_unicode.csv' ) # If the server does not crash, we assume success self.assertEqual(result.valid, True) self.assertNotEqual(result.data, None) self.assertEqual(result.error_message, None)
def test_corrupt(self): # csv_utils prints when handling corrupt file logging.disable(logging.CRITICAL) result: csv_utils.CsvStatus = csv_utils.validate_csv( fields=self.fields, file_path=self.csv_dir + '/invalid_corrupt.csv' ) self.assertEqual(result.valid, False) self.assertEqual(result.data, None) self.assertNotEqual(result.error_message, None) logging.disable(logging.NOTSET)
def test_styles(self): result: csv_utils.CsvStatus = csv_utils.validate_csv( self.fields, self.csv_dir + '/valid_style.csv') self.assertEqual(result.valid, True) user2: Dict[str, str] = dict() user2['title'] = 'Mr' user2['initials'] = 'J' user2['name'] = 'John Fred James' user2['surname'] = 'Doe' user2['email'] = '*****@*****.**' user2['cell'] = '838374742' user2['user_id'] = 'johny' self.assertDictEqual(result.data[0], user2)
def test_user_validation(self): result: csv_utils.CsvStatus = csv_utils.validate_csv( self.fields, self.csv_dir + '/valid_users.csv') self.assertEqual(result.valid, True) self.assertNotEqual(result.data, None) self.assertEqual(len(result.data), 3) user1: Dict[str, str] = dict() user1['title'] = 'Mrs' user1['initials'] = 'T' user1['name'] = 'Tina' user1['surname'] = 'Smith' user1['email'] = '*****@*****.**' user1['cell'] = '323424' user1['user_id'] = 'u478955545' user2: Dict[str, str] = dict() user2['title'] = 'Mr' user2['initials'] = 'J' user2['name'] = 'John' user2['surname'] = 'Doe' user2['email'] = '*****@*****.**' user2['cell'] = '838374742' user2['user_id'] = 'johny' user3: Dict[str, str] = dict() user3['title'] = 'Mr' user3['initials'] = 'F' user3['name'] = 'Fred' user3['surname'] = 'Smith' user3['email'] = '*****@*****.**' user3['cell'] = '333343' user3['user_id'] = 'TheFred' # Pass when users are returned in order according to the structure # List[Dict[str, str]] self.assertDictEqual(result.data[0], user2) self.assertDictEqual(result.data[1], user3) self.assertDictEqual(result.data[2], user1)
def test_no_users(self): result: csv_utils.CsvStatus = csv_utils.validate_csv( self.fields, self.csv_dir + '/no_users.csv') self.assertEqual(result.valid, False) self.assertNotEqual(result.error_message, None) self.assertEqual(result.data, None)
def confirm_csv(request) -> HttpResponse: """Add the users in the given CSV file Note: Expects files to be in ./media/documents Context Args: request_id (str): The path of the CSV file on the server confirm (int): 0: Cancel operation 1: Add users Context Returns: message (str): Message indicating success or failure error_code (int): 0 - No error 1 - Some error """ # TODO(egeldenhuys): Get fields from User Model fields: list = [ 'title', 'initials', 'name', 'surname', 'cell', 'email', 'user_id' ] base_dir: str = 'media/documents' context_data: Dict[str, Any] = init_context_data() if request.method == 'POST': if 'request_id' in request.POST and 'confirm' in request.POST: request_id: str = str(request.POST['request_id']) confirm: int = int(request.POST['confirm']) file_path = os.path.join(base_dir, request_id) if confirm == 1: status: CsvStatus = csv_utils.validate_csv(fields, file_path) if status.valid: if not users_exist(status.data): for user in status.data: if not create_user(user): context_data['error_code'] = 1 context_data[ 'message'] = 'Error creating the user with user_id %s' % user[ 'user_id'] break # Success context_data['error_code'] = 0 context_data[ 'message'] = 'All users were succesfully created' else: context_data['error_code'] = 1 context_data[ 'message'] = 'A user in the csv already exists in the database. \ Please retry for more information.' else: context_data['error_code'] = 1 context_data[ 'message'] = 'Yer a wizard! The csv file on the server has been corrupted.' else: context_data['error_code'] = 0 context_data['message'] = 'Operation has been cancelled' if os.path.isfile(file_path): os.remove(file_path) else: context_data['error_code'] = 1 context_data['message'] = 'Invalid or no parameters sent' return render(request, 'peer_review/userAdmin.html', context_data)
def submit_csv(request) -> HttpResponse: """Validate the CSV and return the status and data in the context Note: Saves the file to ./media/documents The file is only deleted here when not valid. confirm_csv() is responsible for deleting valid files. Files that are not confirmed or cancelled the file is not deleted. Context Args: doc_file (FILE): The CSV file that was uploaded Context Returns: message (str): A message indicating the error, if not valid possible_users (List[Dict[str, str]]): A list of users to be added, or already existing, if valid request_id (str): The name of the uploaded file, if valid error_code (int): 0: No error 1: CSV error 2: User(s) already exists 3: CSV upload error `error_code` will always be returned. """ # TODO(egeldenhuys): Get fields from User Model fields: list = [ 'title', 'initials', 'name', 'surname', 'cell', 'email', 'user_id' ] context_data: Dict[str, Any] = init_context_data() context_data['error_code'] = 3 if request.method == 'POST' and \ DocumentForm(request.POST, request.FILES).is_valid(): csv_file = Document(doc_file=request.FILES['doc_file']) csv_file.save() # [1:] Strip the leading / file_path: str = csv_file.doc_file.url[1:] result: CsvStatus = csv_utils.validate_csv(fields, file_path=file_path, primary_key_field='user_id') if result.valid: existing_users: List[Dict[str, str]] = list() for user in result.data: if user_exists(user['user_id']): existing_users.append(user) if existing_users: context_data[ 'message'] = 'The following user_id(s) already exist' context_data['possible_users'] = existing_users context_data['error_code'] = 2 else: context_data[ 'message'] = 'The CSV file is valid. The following users will be added:' context_data['possible_users'] = result.data context_data['error_code'] = 0 context_data['request_id'] = path_leaf(csv_file.doc_file.url) else: if result.data: context_data['possible_users'] = result.data context_data['message'] = result.error_message context_data['error_code'] = 1 if context_data['error_code'] != 0 and context_data['error_code'] != 3: if os.path.isfile(file_path): os.remove(file_path) else: context_data['message'] = 'Error uploading document. Please try again' context_data['error_code'] = 1 return render(request, 'peer_review/userAdmin.html', context_data)