コード例 #1
0
ファイル: test_signals.py プロジェクト: uktrade/data-hub-api
def test_investment_project_syncs_when_adviser_changes(opensearch_with_signals,
                                                       field):
    """
    Tests that when an adviser is updated, investment projects related to that adviser are
    resynced.
    """
    adviser = AdviserFactory()
    project = InvestmentProjectFactory(**{field: adviser})

    adviser.dit_team = TeamFactory()
    adviser.save()

    opensearch_with_signals.indices.refresh()

    result = search_investment_project_by_id(project.pk)

    assert result.hits.total.value == 1
    assert result.hits[0][field]['dit_team']['id'] == str(adviser.dit_team.id)
    assert result.hits[0][field]['dit_team']['name'] == adviser.dit_team.name
コード例 #2
0
def test_investment_project_syncs_when_team_member_adviser_changes(es_with_signals, team_member):
    """
    Tests that when an adviser that is a team member of an investment project is updated,
    the related investment project is resynced.
    """
    adviser = team_member.adviser

    adviser.dit_team = TeamFactory()
    adviser.save()

    es_with_signals.indices.refresh()

    result = get_search_by_entity_query(
        InvestmentProject,
        term='',
        filter_data={'id': team_member.investment_project.pk},
    ).execute()

    assert result.hits.total == 1
    assert result.hits[0]['team_members'][0]['dit_team']['id'] == str(adviser.dit_team.id)
    assert result.hits[0]['team_members'][0]['dit_team']['name'] == adviser.dit_team.name
コード例 #3
0
    def test_can_update_subscription(self):
        """Test that notification subscription can be updated."""
        project = InvestmentProjectFactory()
        user = create_test_user(dit_team=TeamFactory())

        notification_choice = InvestmentNotificationSubscription.EstimatedLandDateNotification
        InvestmentNotificationSubscriptionFactory(
            investment_project=project,
            adviser=user,
            estimated_land_date=[
                notification_choice.ESTIMATED_LAND_DATE_30,
                notification_choice.ESTIMATED_LAND_DATE_60,
            ],
        )

        api_client = self.create_api_client(user=user)

        url = reverse(
            'api-v3:investment:notification:notification-subscription',
            kwargs={
                'project_pk': project.pk,
            },
        )
        notification_choice = InvestmentNotificationSubscription.EstimatedLandDateNotification
        response = api_client.post(
            url,
            data={
                'estimated_land_date': [
                    str(notification_choice.ESTIMATED_LAND_DATE_30),
                ],
            })
        assert response.status_code == status.HTTP_200_OK

        subscription = InvestmentNotificationSubscription.objects.get(
            investment_project_id=project.pk,
            adviser_id=user.pk,
        )
        assert subscription.estimated_land_date == [
            notification_choice.ESTIMATED_LAND_DATE_30,
        ]
コード例 #4
0
ファイル: test_signals.py プロジェクト: uktrade/data-hub-api
def test_investment_project_syncs_when_team_member_adviser_changes(
    opensearch_with_signals,
    team_member,
):
    """
    Tests that when an adviser that is a team member of an investment project is updated,
    the related investment project is resynced.
    """
    adviser = team_member.adviser

    adviser.dit_team = TeamFactory()
    adviser.save()

    opensearch_with_signals.indices.refresh()

    result = search_investment_project_by_id(team_member.investment_project.pk)

    assert result.hits.total.value == 1
    assert result.hits[0]['team_members'][0]['dit_team']['id'] == str(
        adviser.dit_team.id)
    assert result.hits[0]['team_members'][0]['dit_team'][
        'name'] == adviser.dit_team.name
コード例 #5
0
def test_investment_project_syncs_when_adviser_changes(es_with_signals, field):
    """
    Tests that when an adviser is updated, investment projects related to that adviser are
    resynced.
    """
    adviser = AdviserFactory()
    project = InvestmentProjectFactory(**{field: adviser})

    adviser.dit_team = TeamFactory()
    adviser.save()

    es_with_signals.indices.refresh()

    result = get_search_by_entity_query(
        InvestmentProject,
        term='',
        filter_data={'id': project.pk},
    ).execute()

    assert result.hits.total == 1
    assert result.hits[0][field]['dit_team']['id'] == str(adviser.dit_team.id)
    assert result.hits[0][field]['dit_team']['name'] == adviser.dit_team.name
コード例 #6
0
    def test_view_returns_200(self):
        """
        Tests view returns 200
        """
        permission = Permission.objects.get(codename='view_permissionmodel')
        permission_group = GroupFactory()
        permission_group.permissions.add(permission)
        team = TeamFactory()
        team.role.groups.add(permission_group)
        user = create_test_user(dit_team=team)
        token = self.get_token(user=user)

        request = factory.get(
            '/',
            data={},
            content_type='application/json',
            Authorization=f'Bearer {token}',
        )
        my_view = PermissionModelViewset.as_view(actions={'get': 'list'}, )
        response = my_view(request)

        assert response.status_code == status.HTTP_200_OK
コード例 #7
0
    def test_restricted_user_cannot_add_non_associated_investment_project_interaction(self):
        """
        Test that a restricted user cannot add an interaction for a non-associated investment
        project.
        """
        project_creator = AdviserFactory()
        project = InvestmentProjectFactory(created_by=project_creator)
        requester = create_test_user(
            permission_codenames=[InteractionPermission.add_associated_investmentproject],
            dit_team=TeamFactory(),  # different dit team from the project creator
        )
        url = reverse('api-v3:interaction:collection')
        api_client = self.create_api_client(user=requester)
        response = api_client.post(
            url,
            data={
                'kind': Interaction.KINDS.interaction,
                'company': CompanyFactory().pk,
                'contacts': [ContactFactory().pk],
                'communication_channel': random_obj_for_model(CommunicationChannel).pk,
                'subject': 'whatever',
                'date': date.today().isoformat(),
                'dit_adviser': requester.pk,
                'notes': 'hello',
                'investment_project': project.pk,
                'service': Service.trade_enquiry.value.id,
                'dit_team': Team.healthcare_uk.value.id,
                'was_policy_feedback_provided': False,
            },
        )

        assert response.status_code == status.HTTP_400_BAD_REQUEST
        assert response.json() == {
            'investment_project': [
                "You don't have permission to add an interaction for this "
                'investment project.',
            ],
        }
コード例 #8
0
    def test_basic_search_no_permissions(self, es_with_collector):
        """Tests model permissions enforcement in basic search for a user with no permissions."""
        user = create_test_user(permission_codenames=[], dit_team=TeamFactory())
        api_client = self.create_api_client(user=user)

        SimpleModel.objects.create(name='test')

        es_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:basic')
        response = api_client.get(
            url,
            data={
                'term': '',
                'entity': 'simplemodel',
            },
        )

        assert response.status_code == status.HTTP_200_OK
        response_data = response.json()
        assert response_data['count'] == 0

        assert len(response_data['aggregations']) == 0
コード例 #9
0
    def test_search_event_lead_team(self, es_with_collector):
        """Tests lead_team filter."""
        url = reverse('api-v3:search:event')

        team = TeamFactory()
        EventFactory.create_batch(5)
        EventFactory.create_batch(5, lead_team_id=team.id)
        es_with_collector.flush_and_refresh()

        response = self.api_client.post(
            url,
            data={
                'lead_team': team.id,
            },
        )

        assert response.status_code == status.HTTP_200_OK
        assert response.data['count'] == 5
        assert len(response.data['results']) == 5

        team_ids = [result['lead_team']['id'] for result in response.data['results']]

        assert all(team_id == str(team.id) for team_id in team_ids)
コード例 #10
0
    def test_permissions(self, es_with_collector, permission,
                         permission_entity, entity):
        """
        Tests model permissions enforcement in basic search.

        TODO: we should test permissions relevant to a specific search app in the tests for that
            search app, and remove this test.
        """
        user = create_test_user(permission_codenames=[permission],
                                dit_team=TeamFactory())
        api_client = self.create_api_client(user=user)

        InvestmentProjectFactory(created_by=user)
        CompanyFactory()
        ContactFactory()
        EventFactory()
        CompanyInteractionFactory()
        OrderFactory()

        es_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:basic')
        response = api_client.get(
            url,
            data={
                'term': '',
                'entity': entity,
            },
        )

        assert response.status_code == status.HTTP_200_OK
        response_data = response.json()
        assert (response_data['count'] == 0) == (permission_entity != entity)

        assert len(response_data['aggregations']) == 1
        assert response_data['aggregations'][0]['entity'] == permission_entity
コード例 #11
0
    def test_who_am_i_authenticated(self):
        """Who am I."""
        permission_names = [
            'view_lorem',
            'view_ipsum',
            'add_cats',
        ]
        content_type = ContentType.objects.first()

        permissions = PermissionFactory.create_batch(
            len(permission_names),
            codename=factory.Iterator(permission_names),
            content_type=content_type,
        )

        group = GroupFactory()
        group.permissions.add(permissions[0])
        role = TeamRoleFactory(name='Test Role')

        team = TeamFactory(name='Test Team', role=role)
        team.role.groups.add(group)

        user_test = create_test_user(dit_team=team)
        user_test.user_permissions.set(permissions[1:])
        api_client = self.create_api_client(user=user_test)

        url = reverse('who_am_i')
        response = api_client.get(url)

        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        if 'permissions' in response_data:
            response_data['permissions'].sort()

        expected_permissions = [
            f'{content_type.app_label}.add_cats',
            f'{content_type.app_label}.view_ipsum',
            f'{content_type.app_label}.view_lorem',
        ]

        assert response_data == {
            'id': str(user_test.id),
            'name': user_test.name,
            'last_login': None,
            'first_name': user_test.first_name,
            'last_name': user_test.last_name,
            'email': user_test.email,
            'contact_email': user_test.contact_email,
            'telephone_number': user_test.telephone_number,
            'dit_team': {
                'id': str(team.id),
                'name': 'Test Team',
                'role': {
                    'id': str(role.id),
                    'name': 'Test Role',
                },
                'uk_region': {
                    'id': str(team.uk_region_id),
                    'name': 'East Midlands',
                },
                'country': {
                    'id': str(team.country_id),
                    'name': 'France',
                },
                'disabled_on': None,
            },
            'permissions': expected_permissions,
        }
コード例 #12
0
class TestInteractionCSVRowForm:
    """Tests for InteractionCSVRowForm."""
    @pytest.mark.parametrize(
        'data,errors',
        (
            # kind blank
            (
                {
                    'kind': ''
                },
                {
                    'kind': ['This field is required.']
                },
            ),
            # kind invalid
            (
                {
                    'kind': 'invalid'
                },
                {
                    'kind': [
                        'Select a valid choice. invalid is not one of the available choices.'
                    ]
                },
            ),
            # date blank
            (
                {
                    'date': ''
                },
                {
                    'date': ['This field is required.']
                },
            ),
            # invalid date
            (
                {
                    'date': '08/31/2020'
                },
                {
                    'date': ['Enter a valid date.']
                },
            ),
            # invalid contact_email
            (
                {
                    'contact_email': 'invalid'
                },
                {
                    'contact_email': ['Enter a valid email address.']
                },
            ),
            # blank adviser_1
            (
                {
                    'adviser_1': ''
                },
                {
                    'adviser_1': ['This field is required.']
                },
            ),
            # adviser_1 doesn't exist
            (
                {
                    'adviser_1': 'Non-existent adviser'
                },
                {
                    'adviser_1': [ADVISER_NOT_FOUND_MESSAGE]
                },
            ),
            # multiple matching values for adviser_1
            (
                {
                    'adviser_1':
                    lambda: AdviserFactory.create_batch(
                        2,
                        first_name='Pluto',
                        last_name='Doris',
                    )[0].name,
                },
                {
                    'adviser_1': [MULTIPLE_ADVISERS_FOUND_MESSAGE]
                },
            ),
            # adviser_1 and team_1 mismatch
            (
                {
                    'adviser_1':
                    lambda: AdviserFactory(
                        first_name='Pluto',
                        last_name='Doris',
                        dit_team__name='Team Advantage',
                    ).name,
                    'team_1':
                    lambda: TeamFactory(name='Team Disadvantage', ).name,
                },
                {
                    'adviser_1': [ADVISER_WITH_TEAM_NOT_FOUND_MESSAGE]
                },
            ),
            # adviser_2 doesn't exist
            (
                {
                    'adviser_2': 'Non-existent adviser'
                },
                {
                    'adviser_2': [ADVISER_NOT_FOUND_MESSAGE]
                },
            ),
            # multiple matching values for adviser_2
            (
                {
                    'adviser_2':
                    lambda: AdviserFactory.create_batch(
                        2,
                        first_name='Pluto',
                        last_name='Doris',
                    )[0].name,
                },
                {
                    'adviser_2': [MULTIPLE_ADVISERS_FOUND_MESSAGE]
                },
            ),
            # adviser_2 and team_2 mismatch
            (
                {
                    'adviser_2':
                    lambda: AdviserFactory(
                        first_name='Pluto',
                        last_name='Doris',
                        dit_team__name='Team Advantage',
                    ).name,
                    'team_2':
                    lambda: TeamFactory(name='Team Disadvantage', ).name,
                },
                {
                    'adviser_2': [ADVISER_WITH_TEAM_NOT_FOUND_MESSAGE]
                },
            ),
            # service doesn't exist
            (
                {
                    'service': 'Non-existent service'
                },
                {
                    'service': [
                        'Select a valid choice. That choice is not one of the available choices.',
                    ],
                },
            ),
            # service is disabled
            (
                {
                    'service': lambda: _random_service(disabled=True).name,
                },
                {
                    'service': [OBJECT_DISABLED_MESSAGE],
                },
            ),
            # Multiple matching services
            (
                {
                    'service':
                    lambda: ServiceFactory.create_batch(2, name='Duplicate')[0]
                    .name,
                },
                {
                    'service': ['There is more than one matching service.'],
                },
            ),
            # communication_channel doesn't exist
            (
                {
                    'communication_channel':
                    'Non-existent communication channel'
                },
                {
                    'communication_channel': [
                        'Select a valid choice. That choice is not one of the available choices.',
                    ],
                },
            ),
            # Multiple matching communication channels
            (
                {
                    'communication_channel':
                    lambda: CommunicationChannelFactory.create_batch(
                        2,
                        name='Duplicate',
                    )[0].name,
                },
                {
                    'communication_channel': [
                        'There is more than one matching communication channel.',
                    ],
                },
            ),
            # communication_channel is disabled
            (
                {
                    'communication_channel':
                    lambda: _random_communication_channel(disabled=True, ).
                    name,
                },
                {
                    'communication_channel': [OBJECT_DISABLED_MESSAGE],
                },
            ),
            # event_id invalid
            (
                {
                    'event_id': 'non_existent_event_id'
                },
                {
                    'event_id': [
                        "'non_existent_event_id' is not a valid UUID.",
                    ],
                },
            ),
            # event_id is for a disabled event
            (
                {
                    'event_id': lambda: str(DisabledEventFactory().pk),
                },
                {
                    'event_id': [OBJECT_DISABLED_MESSAGE],
                },
            ),
            # event_id non-existent
            (
                {
                    'event_id': '00000000-0000-0000-0000-000000000000'
                },
                {
                    'event_id': [
                        'Select a valid choice. That choice is not one of the available '
                        'choices.',
                    ],
                },
            ),
            # cannot specify event_id for an interaction
            (
                {
                    'kind': Interaction.KINDS.interaction,
                    'event_id': lambda: str(EventFactory().pk),
                },
                {
                    'event_id': [INTERACTION_CANNOT_HAVE_AN_EVENT_MESSAGE],
                },
            ),
        ),
    )
    def test_validation_errors(self, data, errors):
        """Test validation for various fields."""
        adviser = AdviserFactory(first_name='Neptune', last_name='Doris')
        service = _random_service()

        resolved_data = {
            'kind': 'interaction',
            'date': '01/01/2018',
            'adviser_1': adviser.name,
            'contact_email': '*****@*****.**',
            'service': service.name,
            **_resolve_data(data),
        }

        form = InteractionCSVRowForm(data=resolved_data)
        assert form.errors == errors

    @pytest.mark.parametrize(
        'field,input_value,expected_value',
        (
            # UK date format without leading zeroes
            (
                'date',
                '1/2/2013',
                date(2013, 2, 1),
            ),
            # UK date format with leading zeroes
            (
                'date',
                '03/04/2015',
                date(2015, 4, 3),
            ),
            # ISO date format
            (
                'date',
                '2016-05-04',
                date(2016, 5, 4),
            ),
            # Subject
            (
                'subject',
                'A subject',
                'A subject',
            ),
            # Notes (trailing blank lines are stripped)
            (
                'notes',
                'Notes with\nmultiple lines\n',
                'Notes with\nmultiple lines',
            ),
        ),
    )
    def test_simple_value_cleaning(self, field, input_value, expected_value):
        """Test the conversion and cleaning of various non-relationship fields."""
        adviser = AdviserFactory(first_name='Neptune', last_name='Doris')
        service = _random_service()

        resolved_data = {
            'kind': 'interaction',
            'date': '01/01/2018',
            'adviser_1': adviser.name,
            'contact_email': '*****@*****.**',
            'service': service.name,
            field: input_value,
        }

        form = InteractionCSVRowForm(data=resolved_data)
        assert not form.errors
        assert form.cleaned_data[field] == expected_value

    @pytest.mark.parametrize(
        'kind',
        (Interaction.KINDS.interaction, Interaction.KINDS.service_delivery),
    )
    @pytest.mark.parametrize(
        'field,object_creator,input_transformer',
        (
            # adviser_1 look-up (same case)
            (
                'adviser_1',
                lambda: AdviserFactory(
                    first_name='Pluto',
                    last_name='Doris',
                ),
                lambda obj: obj.name,
            ),
            # adviser_1 look-up (case-insensitive)
            (
                'adviser_1',
                lambda: AdviserFactory(
                    first_name='Pluto',
                    last_name='Doris',
                ),
                lambda obj: obj.name.upper(),
            ),
            # adviser_2 look-up (same case)
            (
                'adviser_1',
                lambda: AdviserFactory(
                    first_name='Pluto',
                    last_name='Doris',
                ),
                lambda obj: obj.name,
            ),
            # adviser_2 look-up (case-insensitive)
            (
                'adviser_1',
                lambda: AdviserFactory(
                    first_name='Pluto',
                    last_name='Doris',
                ),
                lambda obj: obj.name.upper(),
            ),
            # service look-up (same case)
            (
                'service',
                lambda: ServiceFactory(name='UNIQUE EXPORT DEAL'),
                lambda obj: obj.name,
            ),
            # service look-up (case-insensitive)
            (
                'service',
                lambda: ServiceFactory(name='UNIQUE EXPORT DEAL'),
                lambda obj: obj.name.lower(),
            ),
        ),
    )
    def test_common_relation_fields(self, kind, field, object_creator,
                                    input_transformer):
        """
        Test the looking up of values for relationship fields common to interactions and
        service deliveries.
        """
        adviser = AdviserFactory(first_name='Neptune', last_name='Doris')
        service = _random_service()
        obj = object_creator()

        resolved_data = {
            'kind': kind,
            'date': '01/01/2018',
            'adviser_1': adviser.name,
            'contact_email': '*****@*****.**',
            'service': service.name,
            field: input_transformer(obj),
        }

        form = InteractionCSVRowForm(data=resolved_data)
        assert not form.errors
        assert form.cleaned_data[field] == obj

    @pytest.mark.parametrize(
        'field,object_creator,input_transformer',
        (
            # communication channel look-up (same case)
            (
                'communication_channel',
                lambda: _random_communication_channel(),
                lambda obj: obj.name,
            ),
            # communication channel look-up (case-insensitive)
            (
                'communication_channel',
                lambda: _random_communication_channel(),
                lambda obj: obj.name.upper(),
            ),
        ),
    )
    def test_interaction_relation_fields(self, field, object_creator,
                                         input_transformer):
        """Test the looking up of values for relationship fields specific to interactions."""
        adviser = AdviserFactory(first_name='Neptune', last_name='Doris')
        service = _random_service()
        obj = object_creator()

        resolved_data = {
            'kind': 'interaction',
            'date': '01/01/2018',
            'adviser_1': adviser.name,
            'contact_email': '*****@*****.**',
            'service': service.name,
            field: input_transformer(obj),
        }

        form = InteractionCSVRowForm(data=resolved_data)
        assert not form.errors
        assert form.cleaned_data[field] == obj

    @pytest.mark.parametrize(
        'field,object_creator,input_transformer,expected_value_transformer',
        (
            # communication channel should be ignored
            (
                'communication_channel',
                lambda: _random_communication_channel(),
                lambda obj: obj.name,
                lambda obj: None,
            ),
            # event look-up
            (
                'event_id',
                lambda: EventFactory(),
                lambda obj: str(obj.pk),
                lambda obj: obj,
            ),
        ),
    )
    def test_service_delivery_relation_fields(
        self,
        field,
        object_creator,
        input_transformer,
        expected_value_transformer,
    ):
        """Test the looking up of values for relationship fields specific to service deliveries."""
        adviser = AdviserFactory(first_name='Neptune', last_name='Doris')
        service = _random_service()
        obj = object_creator()

        resolved_data = {
            'kind': 'service_delivery',
            'date': '01/01/2018',
            'adviser_1': adviser.name,
            'contact_email': '*****@*****.**',
            'service': service.name,
            field: input_transformer(obj),
        }

        form = InteractionCSVRowForm(data=resolved_data)
        assert not form.errors
        assert form.cleaned_data[field] == expected_value_transformer(obj)

    @pytest.mark.parametrize(
        'kind',
        (Interaction.KINDS.interaction, Interaction.KINDS.service_delivery),
    )
    def test_subject_falls_back_to_service(self, kind):
        """Test that if subject is not specified, the name of the service is used instead."""
        adviser = AdviserFactory(first_name='Neptune', last_name='Doris')
        service = _random_service()

        data = {
            'kind': kind,
            'date': '01/01/2018',
            'adviser_1': adviser.name,
            'contact_email': '*****@*****.**',
            'service': service.name,
        }

        form = InteractionCSVRowForm(data=data)
        assert not form.errors
        assert form.cleaned_data['subject'] == service.name