Beispiel #1
0
    def test_save_returns_unmatched_rows(self, num_unmatched, num_multiple_matches):
        """Test that save() returns an UnmatchedRowCollector with the expected rows."""
        num_matching = 2

        matched_rows = make_matched_rows(num_matching)
        unmatched_rows = make_unmatched_rows(num_unmatched)
        multiple_matches_rows = make_multiple_matches_rows(num_multiple_matches)
        user = AdviserFactory(first_name='Admin', last_name='User')

        file = make_csv_file_from_dicts(
            *matched_rows,
            *unmatched_rows,
            *multiple_matches_rows,
        )
        file_contents = file.getvalue()

        form = InteractionCSVForm(
            files={
                'csv_file': SimpleUploadedFile(file.name, file_contents),
            },
        )

        assert form.is_valid()
        _, unmatched_row_collector = form.save(user)

        assert unmatched_row_collector.rows == [
            *unmatched_rows,
            *multiple_matches_rows,
        ]
Beispiel #2
0
    def test_save_returns_correct_counts(self, num_unmatched, num_multiple_matches):
        """Test that save() returns the expected counts for each matching status."""
        num_matching = 1

        matched_rows = make_matched_rows(num_matching)
        unmatched_rows = make_unmatched_rows(num_unmatched)
        multiple_matches_rows = make_multiple_matches_rows(num_multiple_matches)
        user = AdviserFactory(first_name='Admin', last_name='User')

        file = make_csv_file_from_dicts(
            *matched_rows,
            *unmatched_rows,
            *multiple_matches_rows,
        )
        file_contents = file.getvalue()

        form = InteractionCSVForm(
            files={
                'csv_file': SimpleUploadedFile(file.name, file_contents),
            },
        )

        assert form.is_valid()
        matching_counts, _ = form.save(user)

        assert matching_counts == {
            ContactMatchingStatus.matched: num_matching,
            ContactMatchingStatus.unmatched: num_unmatched,
            ContactMatchingStatus.multiple_matches: num_multiple_matches,
        }
    def test_save_creates_interactions(self, num_unmatched,
                                       num_multiple_matches):
        """Test that save() creates interactions."""
        num_matching = 3

        matched_rows = make_matched_rows(num_matching)
        unmatched_rows = make_unmatched_rows(num_unmatched)
        multiple_matches_rows = make_multiple_matches_rows(
            num_multiple_matches)
        user = AdviserFactory(first_name='Admin', last_name='User')

        file = make_csv_file_from_dicts(
            *matched_rows,
            *unmatched_rows,
            *multiple_matches_rows,
        )
        file_contents = file.getvalue()

        form = InteractionCSVForm(files={
            'csv_file':
            SimpleUploadedFile(file.name, file_contents),
        }, )

        assert form.is_valid()
        form.save(user)

        created_interactions = list(Interaction.objects.all())
        assert len(created_interactions) == num_matching

        expected_contact_emails = {
            row['contact_email']
            for row in matched_rows
        }
        actual_contact_emails = {
            interaction.contacts.first().email
            for interaction in created_interactions
        }
        # Make sure the test was correctly set up with unique contact emails
        assert len(actual_contact_emails) == num_matching
        # Check that the interactions created are the ones we expect
        # Note: the full saving logic for a row is tested in the InteractionCSVRowForm tests
        assert expected_contact_emails == actual_contact_emails

        expected_source = {
            'file': {
                'name': file.name,
                'size': len(file_contents),
                'sha256': hashlib.sha256(file_contents).hexdigest(),
            },
        }
        # `source` has been set (list used rather than a generator for useful failure messages)
        assert all([
            interaction.source == expected_source
            for interaction in created_interactions
        ])
Beispiel #4
0
    def test_to_csv(self):
        """Test CSV file generation."""
        collector = UnmatchedRowCollector()
        input_rows = make_unmatched_rows(2)

        for input_row in input_rows:
            collector.append_row(InteractionCSVForm(data=input_row))

        csv_contents = collector.to_raw_csv()
        with io.BytesIO(csv_contents) as stream:
            reader = csv.reader(io.TextIOWrapper(stream, encoding='utf-8-sig'))
            csv_rows = list(reader)

        assert csv_rows == [
            [
                'theme',
                'kind',
                'date',
                'adviser_1',
                'contact_email',
                'service',
                'communication_channel',
            ],
            [
                input_rows[0]['theme'],
                input_rows[0]['kind'],
                input_rows[0]['date'],
                input_rows[0]['adviser_1'],
                input_rows[0]['contact_email'],
                input_rows[0]['service'],
                input_rows[0]['communication_channel'],
            ],
            [
                input_rows[1]['theme'],
                input_rows[1]['kind'],
                input_rows[1]['date'],
                input_rows[1]['adviser_1'],
                input_rows[1]['contact_email'],
                input_rows[1]['service'],
                input_rows[1]['communication_channel'],
            ],
        ]

        # Check that the file re-validates (so it can be re-uploaded)
        form = InteractionCSVForm(
            files={
                'csv_file': SimpleUploadedFile('test.csv', csv_contents),
            },
        )
        assert form.is_valid()
        assert form.are_all_rows_valid()
    def test_get_matching_summary(
        self,
        num_matching,
        num_unmatched,
        num_multiple_matches,
        max_returned_rows,
    ):
        """Test get_matching_summary() with various inputs."""
        input_matched_rows = make_matched_rows(num_matching)
        unmatched_rows = make_unmatched_rows(num_unmatched)
        multiple_matches_rows = make_multiple_matches_rows(
            num_multiple_matches)

        file = make_csv_file_from_dicts(
            *input_matched_rows,
            *unmatched_rows,
            *multiple_matches_rows,
        )

        form = InteractionCSVForm(files={
            'csv_file':
            SimpleUploadedFile(file.name, file.getvalue()),
        }, )

        assert form.is_valid()

        matching_counts, returned_matched_rows = form.get_matching_summary(
            max_returned_rows)

        assert matching_counts == {
            ContactMatchingStatus.matched: num_matching,
            ContactMatchingStatus.unmatched: num_unmatched,
            ContactMatchingStatus.multiple_matches: num_multiple_matches,
        }

        expected_num_returned_rows = min(num_matching, max_returned_rows)
        assert len(returned_matched_rows) == expected_num_returned_rows

        # Check the the rows returned are the ones we expect
        expected_contact_emails = [
            row['contact_email']
            for row in input_matched_rows[:expected_num_returned_rows]
        ]
        actual_contact_emails = [
            row['contacts'][0].email for row in returned_matched_rows
        ]
        assert expected_contact_emails == actual_contact_emails
Beispiel #6
0
def _create_file_in_cache(token, num_matching, num_unmatched, num_multiple_matches):
    matched_rows = make_matched_rows(num_matching)
    unmatched_rows = make_unmatched_rows(num_unmatched)
    multiple_matches_rows = make_multiple_matches_rows(num_multiple_matches)

    file = make_csv_file_from_dicts(
        *matched_rows,
        *unmatched_rows,
        *multiple_matches_rows,
        filename='cache-test.csv',
    )
    with file:
        compressed_contents = gzip.compress(file.read())
    contents_key = _cache_key_for_token(token, CacheKeyType.file_contents)
    name_key = _cache_key_for_token(token, CacheKeyType.file_name)

    cache.set(contents_key, compressed_contents)
    cache.set(name_key, file.name)

    return matched_rows
Beispiel #7
0
    def test_get_row_errors_with_duplicate_rows(self):
        """Test that duplicate rows are tracked and errors returned when encountered."""
        matched_rows = make_matched_rows(5)

        file = make_csv_file_from_dicts(
            # Duplicate the first row
            matched_rows[0],
            *matched_rows,
            *make_unmatched_rows(5),
            *make_multiple_matches_rows(5),
        )

        form = InteractionCSVForm(
            files={
                'csv_file': SimpleUploadedFile(file.name, file.getvalue()),
            },
        )

        assert form.is_valid()

        row_errors = list(form.get_row_error_iterator())
        assert row_errors == [
            CSVRowError(1, NON_FIELD_ERRORS, '', DUPLICATE_OF_ANOTHER_ROW_MESSAGE),
        ]