def test_csv_is_for_latest_live_dos_framework(self, latest_dos_framework,
                                                  s3):
        self.user_role = "admin-ccs-category"

        self.data_api_client.find_frameworks.return_value = {
            "frameworks": [
                FrameworkStub(framework_live_at="2016-03-03 12:00:00",
                              slug="digital-outcomes-and-specialists",
                              status="expired").response(),
                FrameworkStub(framework_live_at="2018-10-01 10:58:09.43134",
                              slug="digital-outcomes-and-specialists-3",
                              status="live").response(),
                FrameworkStub(framework_live_at="2019-12-18 15:13:24.53636",
                              slug=latest_dos_framework,
                              status="live").response(),
                FrameworkStub(framework_live_at="2020-12-18 15:13:24.53636",
                              slug="g-cloud-12",
                              status="live").response(),
            ]
        }

        response = self.client.get(self.url)

        assert s3.S3().get_signed_url.call_args == mock.call(
            f"{latest_dos_framework}/reports/opportunity-data.csv")
        assert latest_dos_framework in response.location
    def test_lots_kwarg_changes_lots_and_framework_agreement_details(self):
        lots = [
            LotStub(slug='cloud-hosting', name='Cloud hosting').response(),
            LotStub(slug='cloud-support', name='Cloud support').response(),
        ]

        expected = FrameworkStub().response()
        expected["lots"] = lots
        expected["frameworkAgreementDetails"]["lotOrder"] = [
            "cloud-hosting", "cloud-support"
        ]
        expected["frameworkAgreementDetails"]["lotDescriptions"] = {
            "cloud-hosting": "Lot 1: Cloud hosting",
            "cloud-support": "Lot 2: Cloud support",
        }

        response = FrameworkStub(lots=lots).response()

        assert response["lots"] == lots
        assert response["frameworkAgreementDetails"]["lotOrder"] == [
            "cloud-hosting", "cloud-support"
        ]
        assert response["frameworkAgreementDetails"]["lotDescriptions"] == {
            "cloud-hosting": "Lot 1: Cloud hosting",
            "cloud-support": "Lot 2: Cloud support",
        }

        assert response == expected
示例#3
0
    def test_only_known_application_editing_decorated_views_are_protected(
        self, current_user_mock, require_login_mock, services_data_api_client, frameworks_data_api_client,
    ):
        decorated_views = {
            'main.edit_service_submission',
            'main.remove_subsection',
            'main.delete_draft_service',
            'main.start_new_draft_service',
            'main.previous_services',
            'main.complete_draft_service',
            'main.copy_draft_service',
            'main.copy_previous_service',
            'main.copy_all_previous_services',
            'main.framework_supplier_declaration_submit',
            'main.framework_start_supplier_declaration',
            'main.reuse_framework_supplier_declaration',
            'main.reuse_framework_supplier_declaration_post',
            'main.framework_supplier_declaration_edit',
        }

        services_data_api_client.get_framework.return_value = FrameworkStub(status='pending').single_result_response()
        frameworks_data_api_client.get_framework.return_value = FrameworkStub(status='pending').single_result_response()
        current_user_mock.supplier_id = 123
        require_login_mock.return_value = False

        from app.main.helpers.frameworks import EnsureApplicationCompanyDetailsHaveBeenConfirmed as \
            company_details_decorator_class

        for view_name, view_callable in self.app.view_functions.items():
            if inspect.isfunction(view_callable):
                with mock.patch.object(
                    company_details_decorator_class, 'validator', mock.MagicMock()
                ) as validator_mock:
                    # Always validate true to bypass EnsureApplicationCompanyDetailsHaveBeenConfirmed decorator
                    validator_mock.return_value = True

                    with self.app.test_request_context('/suppliers'):
                        if view_name in decorated_views:
                            response = view_callable(framework_slug='Sausage-Cloud 6')

                            assert response[1] == 404
                            assert "Applications closed - Digital Marketplace" in response[0]

                        else:
                            # If it's not decorated, we don't care if the call is succesful or errors, as long it
                            # doesn't use our decorator. This call will ALWAYS error if the decorator is used.
                            try:
                                response = view_callable()

                            except Exception as e:
                                if type(e) == HTTPException:
                                    assert e.value.code != 500 and e.value.description != (
                                        "There was a problem accessing this page of your application. Please try "
                                        "again later."
                                    )
示例#4
0
    def test_returns_correct_status_for_framework_status_and_project_combinations(
            self, project_locked_at, fwork_status, following_fwork_status,
            status):

        temp_message_status = get_saved_search_banner_message_status(
            {'lockedAt': project_locked_at},
            FrameworkStub(slug='B-Cloud-1', status=fwork_status).response(),
            FrameworkStub(slug='B-Cloud-2',
                          status=following_fwork_status).response(),
        )

        assert temp_message_status == status
def get_frameworks_list_fixture_data():
    g_cloud_8_variation = {
        "1": {
            "countersignedAt": "2016-10-05T11:00:00.000000Z",
            "countersignerName": "Dan Saxby",
            "countersignerRole": "Category Director",
            "createdAt": "2016-08-19T15:31:00.000000Z"
        }
    }

    frameworks = [
        FrameworkStub(id=4,
                      slug='g-cloud-7',
                      status='live',
                      lots=as_a_service_lots()).single_result_response(),
        FrameworkStub(id=1,
                      slug='g-cloud-6',
                      status='expired',
                      lots=as_a_service_lots()).single_result_response(),
        FrameworkStub(
            id=6,
            slug='g-cloud-8',
            status='live',
            lots=as_a_service_lots(),
            framework_agreement_version='v1.0',
            framework_variations=g_cloud_8_variation).single_result_response(),
        FrameworkStub(id=3,
                      slug='g-cloud-5',
                      status='expired',
                      lots=as_a_service_lots()).single_result_response(),
        FrameworkStub(id=2,
                      slug='g-cloud-4',
                      status='expired',
                      lots=as_a_service_lots()).single_result_response(),
        FrameworkStub(id=7,
                      slug='digital-outcomes-and-specialists-2',
                      status='live',
                      lots=dos_lots(),
                      framework_agreement_version='v1.0',
                      has_further_competition=True).single_result_response(),
        FrameworkStub(id=12,
                      slug='digital-outcomes-and-specialists-4',
                      status='live',
                      lots=dos_lots(),
                      has_further_competition=True).single_result_response(),
        FrameworkStub(id=5,
                      slug='digital-outcomes-and-specialists',
                      status='live',
                      lots=dos_lots(),
                      framework_agreement_version='v1.0',
                      has_further_competition=True).single_result_response(),
        FrameworkStub(id=8, slug='g-cloud-9', status='live',
                      lots=cloud_lots()).single_result_response(),
    ]

    return {
        'frameworks': [framework['frameworks'] for framework in frameworks]
    }
    def test_csv_handles_tricky_characters(self, data_api_client):
        data_api_client.find_brief_responses.return_value = self.tricky_character_responses
        data_api_client.get_framework.return_value = FrameworkStub(
            framework_slug='digital-outcomes-and-specialists-4',
            status='live',
            lots=[
                LotStub(slug='digital-specialists',
                        allows_brief=True).response(),
            ]).single_result_response()
        data_api_client.get_brief.return_value = self.brief

        self.login_as_buyer()
        res = self.client.get(self.url)
        page = res.get_data(as_text=True)
        lines = page.splitlines()

        assert len(lines) == 3
        assert lines[0] == (
            '''"Supplier","Date the specialist can start work","Day rate","Nice1","Nice2","Nice3","Email address"'''
        )
        # The values with internal commas are surrounded by quotes, and all other characters appear as in the data
        assert lines[1] == '"Kev\'s \'Pies",""A week Friday&rdquot;","€3.50","False","True","True",' \
                           '"te,[email protected]"'
        assert lines[2] == '"K,ev’s ""Bu,tties","❝Next — Tuesday❞","¥1.49,","True","False","False",' \
                           '"*****@*****.**"'
示例#7
0
    def test_returns_404_and_logs_if_framework_status_not_open(
            self, current_user_mock, status):
        # 'coming' and 'expired' frameworks are caught by `get_framework_or_404`
        self.data_api_client_mock.get_framework.return_value = FrameworkStub(
            status=status).single_result_response()
        current_user_mock.supplier_id = 123

        @return_404_if_applications_closed(lambda: self.data_api_client_mock)
        def view_function(framework_slug):
            pass

        with mock.patch(
                'app.main.helpers.frameworks.current_app') as current_app_mock:
            with self.app.test_request_context('/suppliers'):
                response = view_function(framework_slug='g-cloud-9')

        assert current_app_mock.logger.info.call_args_list == [
            mock.call(
                'Supplier {supplier_id} requested "{method} {path}" after {framework_slug} applications closed.',
                extra={
                    'supplier_id': 123,
                    'method': 'GET',
                    'path': '/suppliers',
                    'framework_slug': 'g-cloud-9'
                })
        ]
        assert response[1] == 404
示例#8
0
    def test_award_brief_details_post_valid_form_calls_api_and_redirects(self):
        self.data_api_client.update_brief_award_details.return_value = FrameworkStub(
            slug='digital-outcomes-and-specialists-4',
            status='awarded',
            lots=[
                LotStub(slug='digital-outcomes', allows_brief=True).response()
            ]
        ).single_result_response()
        self.login_as_buyer()
        res = self.client.post(
            self.url.format(brief_id=1234, brief_response_id=5678),
            data={
                "awardedContractStartDate-day": "31",
                "awardedContractStartDate-month": "12",
                "awardedContractStartDate-year": "2020",
                "awardedContractValue": "88.84"
            }
        )

        assert self.data_api_client.update_brief_award_details.call_args == mock.call(
            '1234', '5678',
            {'awardedContractStartDate': "2020-12-31", "awardedContractValue": "88.84"},
            updated_by="*****@*****.**"
        )
        assert res.status_code == 302
        assert res.location == "http://localhost{}".format(self.briefs_dashboard_url)

        expected_message = "You’ve updated ‘I need a thing to do a thing’"
        expected_category = "success"
        self.assert_flashes(expected_message, expected_category)
        self.assert_flashes_with_dm_alert(expected_message, expected_category)
示例#9
0
    def setup_method(self, method):
        super(TestAwardBriefDetails, self).setup_method(method)

        self.data_api_client_patch = mock.patch('app.main.views.outcome.data_api_client', autospec=True)
        self.data_api_client = self.data_api_client_patch.start()

        self.data_api_client.get_framework.return_value = FrameworkStub(
            slug='digital-outcomes-and-specialists-4',
            status='live',
            lots=[
                LotStub(slug='digital-outcomes', allows_brief=True).response(),
            ]
        ).single_result_response()

        self.data_api_client.get_brief.return_value = BriefStub(
            framework_slug='digital-outcomes-and-specialists-4', lot_slug="digital-outcomes", status='closed'
        ).single_result_response()
        self.data_api_client.get_brief_response.return_value = {
            "briefResponses": {
                "id": 5678,
                "briefId": 1234,
                "status": "pending-awarded",
                "supplierName": "BananaCorp",
                "awardDetails": {"pending": True}
            }
        }
    def brief(self, request):
        """A live brief on a live or expired framework"""

        framework_status = request.param

        self.data_api_client.get_framework.return_value = FrameworkStub(
            slug="digital-outcomes-and-specialists-4",
            status=framework_status,
            lots=[
                LotStub(slug="digital-specialists",
                        allows_brief=True).response()
            ],
        ).single_result_response()

        brief_json = BriefStub(
            framework_slug="digital-outcomes-and-specialists-4",
            status="live",
        ).single_result_response()

        brief_json["briefs"]["publishedAt"] = "2016-04-02T20:10:00.00000Z"
        brief_json["briefs"]["specialistRole"] = "communicationsManager"
        brief_json["briefs"]["clarificationQuestionsAreClosed"] = True

        self.data_api_client.get_brief.return_value = brief_json

        return brief_json["briefs"]
    def test_show_clarification_questions_page_for_live_brief_with_no_questions(
            self, framework_status):
        with self.app.app_context():

            self.data_api_client.get_framework.return_value = FrameworkStub(
                slug='digital-outcomes-and-specialists-4',
                status=framework_status,
                lots=[
                    LotStub(slug='digital-specialists',
                            allows_brief=True).response(),
                ]).single_result_response()
            brief_json = BriefStub(
                framework_slug="digital-outcomes-and-specialists-4",
                status="live",
            ).single_result_response()
            brief_json['briefs']['publishedAt'] = "2016-04-02T20:10:00.00000Z"
            brief_json['briefs']["clarificationQuestionsAreClosed"] = False
            self.data_api_client.get_brief.return_value = brief_json

            res = self.client.get(
                "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234/supplier-questions"  # noqa
            )

            assert res.status_code == 200
            page_html = res.get_data(as_text=True)
            assert "Supplier questions" in page_html
            assert "No questions or answers have been published" in page_html
            assert "Answer a supplier question" in page_html
    def test_404_if_brief_does_not_belong_to_user(self):
        self.data_api_client.get_framework.return_value = FrameworkStub(
            slug='digital-outcomes-and-specialists-4',
            status='live',
            lots=[
                LotStub(slug='digital-specialists',
                        allows_brief=True).response(),
            ]).single_result_response()
        brief_json = BriefStub(
            framework_slug="digital-outcomes-and-specialists-4",
            user_id=234,
        ).single_result_response()
        brief_json['briefs']["clarificationQuestionsAreClosed"] = False
        self.data_api_client.get_brief.return_value = brief_json

        res = self.client.post(
            "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements"
            "/digital-specialists/1234/supplier-questions/answer-question",
            data={
                "question": "Why?",
                "answer": "Because",
            })

        assert res.status_code == 404
        assert not self.data_api_client.add_brief_clarification_question.called
    def test_add_brief_clarification_question_for_live_and_expired_framework(
            self):
        framework_statuses = ['live', 'expired']
        for framework_status in framework_statuses:
            self.data_api_client.get_framework.return_value = FrameworkStub(
                slug="digital-outcomes-and-specialists-4",
                status=framework_status,
                lots=[
                    LotStub(slug="digital-specialists",
                            allows_brief=True).response(),
                ]).single_result_response()
            brief_json = BriefStub(
                framework_slug="digital-outcomes-and-specialists-4",
                status="live",
            ).single_result_response()
            brief_json['briefs']["clarificationQuestionsAreClosed"] = False
            self.data_api_client.get_brief.return_value = brief_json

            res = self.client.post(
                "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements"
                "/digital-specialists/1234/supplier-questions/answer-question",
                data={
                    "question": "Why?",
                    "answer": "Because",
                })

            assert res.status_code == 302
            self.data_api_client.add_brief_clarification_question.assert_called_with(
                "1234", "Why?", "Because", "*****@*****.**")

            # test that the redirect ends up on the right page
            assert res.headers['Location'].endswith(
                '/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234/supplier-questions'  # noqa
            ) is True
    def test_clarification_questions_page_returns_404_if_brief_not_correct(
            self):
        self.data_api_client.get_framework.return_value = FrameworkStub(
            slug='digital-outcomes-and-specialists-4',
            status='live',
            lots=[
                LotStub(slug='digital-specialists',
                        allows_brief=True).response(),  # 'Incorrect' lot slug
            ]).single_result_response()
        brief_json = BriefStub(
            framework_slug="digital-outcomes-and-specialists-4",
            status="live",
            clarification_questions=[{
                "question":
                "Why is my question a question?",
                "answer":
                "Because",
                "publishedAt":
                "2016-01-01T00:00:00.000000Z"
            }]).single_result_response()
        brief_json['briefs']['lotSlug'] = "wrong lot slug"
        self.data_api_client.get_brief.return_value = brief_json

        res = self.client.get(
            "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234/supplier-questions"  # noqa
        )

        assert res.status_code == 404
示例#15
0
    def test_returns_framework(self):
        data_api_client_mock = mock.Mock()
        data_api_client_mock.get_framework.return_value = FrameworkStub(
        ).single_result_response()

        assert get_framework_or_500(data_api_client_mock,
                                    'g-cloud-10')['slug'] == 'g-cloud-10'
    def test_download_brief_responses_for_brief_without_nice_to_haves(
            self, data_api_client):
        data_api_client.get_framework.return_value = FrameworkStub(
            framework_slug='digital-outcomes-and-specialists-4',
            status='live',
            lots=[
                LotStub(slug='digital-specialists',
                        allows_brief=True).response(),
            ]).single_result_response()

        for response in self.brief_responses['briefResponses']:
            del response["niceToHaveRequirements"]
        data_api_client.find_brief_responses.return_value = self.brief_responses

        data_api_client.get_brief.return_value = self.brief

        self.login_as_buyer()

        del self.brief['briefs']['niceToHaveRequirements']
        res = self.client.get(self.url)
        assert res.status_code, 200

        self.brief['briefs']['niceToHaveRequirements'] = []
        res = self.client.get(self.url)
        assert res.status_code, 200
示例#17
0
    def test_renders_error_page_correctly_if_following_framework_content_set(
        self, content_loader_mock, content_set, status
    ):
        self.data_api_client_mock.get_framework.return_value = FrameworkStub(status=status).single_result_response()
        if content_set:
            content_loader_mock.get_metadata.return_value = {
                'name': 'Next Framework 2', 'slug': 'n-f-2', 'coming': '2042'
            }
        else:
            content_loader_mock.get_metadata.side_effect = ContentNotFoundError()

        @return_404_if_applications_closed(lambda: self.data_api_client_mock)
        def view_function(framework_slug):
            pass

        with mock.patch('app.main.helpers.frameworks.current_user'):
            with mock.patch('app.main.helpers.frameworks.current_app'):
                with self.app.test_request_context('/suppliers'):
                    response = view_function(framework_slug='g-cloud-9')

        document = html.fromstring(response[0])
        assert response[1] == 404
        assert document.xpath('//title/text()')[0].strip() == "Applications closed - Digital Marketplace"
        assert document.xpath('//h1/text()')[0] == "You can no longer apply to G-Cloud 10"
        assert "The deadline for applying was 12am GMT, Monday 3 January 2000." in \
            document.xpath('//div[@class="dmspeak"]/p/text()')[0]

        if content_set:
            assert "Next Framework 2 is expected to open in 2042." in \
                document.xpath('//div[@class="dmspeak"]/p/text()')[1]
        else:
            assert "is expected to open in" not in response[0]
    def test_404_if_framework_is_not_live_or_expired(self):
        for framework_status in ['coming', 'open', 'pending', 'standstill']:
            self.data_api_client.find_brief_responses.return_value = {
                'briefResponses': self.responses
            }
            self.data_api_client.get_framework.return_value = FrameworkStub(
                framework_slug='digital-outcomes-and-specialists-4',
                status=framework_status,
                lots=[
                    LotStub(slug='digital-specialists',
                            allows_brief=True).response(),
                ]).single_result_response()
            self.data_api_client.get_brief.return_value = {
                'briefs': self.brief
            }

            with mock.patch.object(download_responses, 'data_api_client',
                                   self.data_api_client):
                self.login_as_buyer()
                res = self.client.get(
                    "/buyers/frameworks/digital-outcomes-and-specialists-4"
                    "/requirements/digital-specialists/1234/responses/download"
                )

            assert res.status_code == 404
    def test_csv_includes_all_eligible_responses_and_no_ineligible_responses(
            self, data_api_client, brief_status):
        self.brief['status'] = brief_status
        if brief_status == 'awarded':
            self.brief['awardedBriefResponseId'] = 999
        for framework_status in ['live', 'expired']:
            data_api_client.find_brief_responses.return_value = self.brief_responses
            data_api_client.get_framework.return_value = FrameworkStub(
                framework_slug='digital-outcomes-and-specialists',
                status=framework_status,
                lots=[
                    LotStub(slug='digital-specialists',
                            allows_brief=True).response(),
                ]).single_result_response()
            data_api_client.get_brief.return_value = self.brief

            self.login_as_buyer()
            res = self.client.get(self.url)
            page = res.get_data(as_text=True)
            lines = page.splitlines()
            # There are only the two eligible responses included
            assert len(lines) == 3
            assert lines[0] == (
                '''"Supplier","Date the specialist can start work","Day rate","Nice1","Nice2","Nice3","Email address"'''
            )
            # The response with two nice-to-haves is sorted to above the one with only one
            assert lines[
                1] == '''"Kev's Pies","A week Friday","£3.50","False","True","True","*****@*****.**"'''
            assert lines[
                2] == '''"Kev's Butties","Next Tuesday","£1.49","True","False","False","*****@*****.**"'''
    def framework(
            status='open',
            slug='g-cloud-7',
            is_e_signature_supported=False,
            name=None,
            clarification_questions_open=True,
            framework_agreement_version=None,
    ):
        if 'g-cloud-' in slug:
            if int(slug.split('-')[-1]) >= 9:
                lots = cloud_lots()
            else:
                lots = as_a_service_lots()
        elif 'digital-outcomes-and-specialists' in slug:
            lots = dos_lots()
        else:
            lots = []

        return FrameworkStub(
            status=status,
            name=name,
            slug=slug,
            clarification_questions_open=clarification_questions_open,
            lots=lots,
            framework_agreement_version=framework_agreement_version,
            applications_close_at=datetime(2015, 10, 6, 16),
            intention_to_award_at=datetime(2015, 10, 20, 12),
            clarifications_close_at=datetime(2015, 9, 22, 16),
            clarifications_publish_at=datetime(2015, 9, 29, 16),
            framework_live_at=datetime(2015, 11, 23, 12),
            framework_expires_at=datetime(2016, 11, 23, 12),
            isESignatureSupported=is_e_signature_supported
        ).single_result_response()
    def test_end_to_end_for_closed_awarded_cancelled_unsuccessful_briefs(
            self, brief_status):
        self.brief['status'] = brief_status
        if brief_status == 'awarded':
            self.brief['awardedBriefResponseId'] = 999
        for framework_status in ['live', 'expired']:
            self.data_api_client.find_brief_responses.return_value = {
                'briefResponses': self.responses
            }
            self.data_api_client.get_framework.return_value = FrameworkStub(
                framework_slug='digital-outcomes-and-specialists-4',
                status=framework_status,
                lots=[
                    LotStub(slug='digital-specialists',
                            allows_brief=True).response(),
                ]).single_result_response()
            self.data_api_client.get_brief.return_value = {
                'briefs': self.brief
            }

            with mock.patch.object(download_responses, 'data_api_client',
                                   self.data_api_client):
                self.login_as_buyer()
                res = self.client.get(
                    "/buyers/frameworks/digital-outcomes-and-specialists-4"
                    "/requirements/digital-specialists/1234/responses/download"
                )

            assert res.status_code == 200
            assert res.mimetype == 'application/vnd.oasis.opendocument.spreadsheet'
            assert len(res.data) > 100

            self._check_xml_files_in_zip_are_well_formed(res.data)
示例#22
0
    def test_raises_an_error_if_invalid_state(self, abort):
        abort.side_effect = CustomAbortException()

        with pytest.raises(CustomAbortException):
            get_saved_search_banner_message_status(
                {'lockedAt': '2018-06-25T13:39:54.167852Z'},
                FrameworkStub(slug='B-Cloud-1',
                              status='some-new-status').response(),
                FrameworkStub(status='live').response(),
            )

        assert self.current_app.logger.error.call_args_list == [
            mock.call(
                "Saved search banner messages invalid frameworks state: "
                "'B-Cloud-1' - 'some-new-status' and 'g-cloud-10' - 'live'")
        ]
    def setup_method(self, method):
        super().setup_method(method)

        self.data_api_client_patch = mock.patch(
            'app.main.views.buyers.data_api_client', autospec=True)
        self.data_api_client = self.data_api_client_patch.start()
        framework = FrameworkStub(slug=self.framework_slug,
                                  status='live',
                                  lots=[
                                      LotStub(slug='digital-outcomes',
                                              allows_brief=True).response(),
                                  ]).single_result_response()
        self.data_api_client.get_framework.return_value = framework

        closed_brief_stub = BriefStub(
            framework_slug=self.framework_slug,
            lot_slug="digital-outcomes",
            status='closed',
            user_id=123,
        ).single_result_response()
        closed_brief_stub['briefs'].update({
            "framework":
            framework["frameworks"],
            "publishedAt":
            self.brief_publishing_date,
        })
        self.data_api_client.get_brief.return_value = closed_brief_stub

        self.data_api_client.find_brief_responses.return_value = self.brief_responses
    def setup(self):
        self.data_api_client_mock = mock.create_autospec(DataAPIClient)
        self.data_api_client_mock.get_framework.return_value = FrameworkStub(
            applications_close_at="2025-07-01T16:00:00.000000Z",
            status="open").single_result_response()

        self.logging_mock = mock.create_autospec(Logger, instance=True)
    def test_draft_brief_requirements_task_list_cannot_start_tasks(
            self, lot_slug, task_name):
        self.data_api_client.get_framework.return_value = FrameworkStub(
            slug="digital-outcomes-and-specialists-4",
            status="live",
            lots=[LotStub(slug=lot_slug, allows_brief=True).response()],
        ).single_result_response()
        self.data_api_client.get_brief.return_value = BriefStub(
            framework_slug="digital-outcomes-and-specialists-4",
            lot_slug=lot_slug,
            status="draft",
        ).single_result_response()
        brief = self.data_api_client.get_brief.return_value["briefs"]

        document = self.get_requirements_task_list_page(brief)

        task_name_selector = f".dm-task-list__task-name:contains('{task_name}')"
        tag_selector = f"{task_name_selector} + .dm-task-list__tag"
        task_name = document.cssselect(task_name_selector)[0]
        tag = document.cssselect(tag_selector)[0]

        assert task_name.find(
            "a") is None, "task should not be a link when it cannot be started"
        assert tag.text.strip() == "Cannot start yet"

        brief.update({
            "specialistRole": "communicationsManager",
            "location": "London",
            "organisation": "Org Inc.",
            "specialistWork": "Werk.",
            "backgroundInformation": "Information.",
            "outcome": "Problem to be solved.",
            "endUsers": "Who the users are.",
            "phase": "Alpha",
            "existingTeam": "Team members.",
            "workplaceAddress": "Townsville",
            "workingArrangements": "Arrangements.",
            "startDate": "Tomorrow.",
            "summary": "Summary.",
            "numberOfSuppliers": 7,
            "technicalWeighting": 60,
            "culturalWeighting": 20,
            "priceWeighting": 20,
            "essentialRequirements": ["skills", "experience"],
            "culturalFitCriteria": ["cultural", "fit"],
            "successCriteria": ["proposal", "evaluation"],
            "priceCriteria": "fixedPrice",
            "requirementsLength": "1 week",
            "questionAndAnswerSessionDetails": "Q&A.",
        })

        document = self.get_requirements_task_list_page(brief)

        task_name = document.cssselect(task_name_selector)[0]
        tag = document.cssselect(tag_selector)[0]

        assert tag.text.strip() in ["Optional", "To do"]
        assert task_name.find(
            "a") is not None, "task should be a link when it can be started"
def mock_data_client():
    """Mock data client for use in tests. These can be overwritten in individual tests."""
    mock_data_client = Mock()
    mock_data_client.get_framework.return_value = FrameworkStub(lots=[
        LotStub(slug="test_lot_slug_1").response(),
        LotStub(slug="test_lot_slug_2").response(),
    ], ).single_result_response()

    mock_data_client.find_draft_services_iter.return_value = {}
    mock_data_client.export_users.return_value = {
        "users": [
            {
                "supplier_id": 12345,
                "application_status": "application",
                "email address": "1@12345",
                "extraneous_field": "foo",
            },
            {
                "supplier_id": 23456,
                "application_status": "no_application",
                "email address": "1@23456",
                "extraneous_field": "foo",
            },
            {
                "supplier_id": 123,
                "application_status": "application",
                "email address": "1@123",
                "extraneous_field": "foo",
            },
            {
                "supplier_id": 456,
                "application_status": "application",
                "email address": "1@456",
                "extraneous_field": "foo",
            },
            {
                "supplier_id": 789,
                "application_status": "no_application",
                "email address": "1@789",
                "extraneous_field": "foo",
            },
            {
                "supplier_id": 101,
                "application_status": "no_application",
                "email address": "1@101",
                "extraneous_field": "foo",
            },
        ]
    }

    with open(
            os.path.join(FIXTURES_DIR, "test_supplier_frameworks_response.json"
                         )) as supplier_frameworks_response:
        mock_data_client.find_framework_suppliers.return_value = json.loads(
            supplier_frameworks_response.read())
        mock_data_client.find_framework_suppliers_iter.return_value = iter(
            mock_data_client.find_framework_suppliers.
            return_value["supplierFrameworks"])
    return mock_data_client
    def test_dos_slug_kwarg_changes_all_related_framework_details(self):
        expected = FrameworkStub().response()
        expected.update({
            "name": "Digital Outcomes and Specialists",
            "slug": "digital-outcomes-and-specialists",
            "framework": "digital-outcomes-and-specialists",
            "family": "digital-outcomes-and-specialists",
            "lots": dos_lots(),
            "frameworkAgreementDetails": {
                "variations": {}
            },
            "hasDirectAward": False,
            "hasFurtherCompetition": True,
        })

        assert FrameworkStub(
            slug='digital-outcomes-and-specialists').response() == expected
示例#28
0
    def test_returns_the_view_function_if_framework_is_open(self):
        self.data_api_client_mock.get_framework.return_value = FrameworkStub(status='open').single_result_response()

        @return_404_if_applications_closed(lambda: self.data_api_client_mock)
        def view_function(framework_slug):
            return f'{framework_slug} - OK!'

        response = view_function(framework_slug='g-cloud-7')

        assert response == 'g-cloud-7 - OK!'
    def test_404_if_framework_status_is_not_live(self):
        self.data_api_client.get_framework.return_value = FrameworkStub(
            slug='digital-outcomes-and-specialists-4',
            status='open',
            lots=[
                LotStub(slug='user-research-studios').response(),
            ]).single_result_response()

        res = self.client.get(
            "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/user-research-studios"
        )
        assert res.status_code == 404
    def setup_method(self, method):
        super().setup_method(method)
        self.data_api_client_patch = mock.patch(
            'app.main.views.outcomes.data_api_client', autospec=True)
        self.data_api_client = self.data_api_client_patch.start()

        self.data_api_client.find_frameworks.return_value = {
            "frameworks": [
                FrameworkStub(slug="digital-outcomes-and-specialists-4",
                              status="live").response()
            ]
        }