コード例 #1
0
class TestCancelBrief(BaseApplicationTest):
    url = '/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-outcomes/{brief_id}/cancel'

    def setup_method(self, method):
        super(TestCancelBrief, 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.brief = BriefStub(
            user_id=123,
            framework_slug='digital-outcomes-and-specialists-4',
            lot_slug="digital-outcomes",
            status='closed'
        ).response()
        self.data_api_client.get_brief.return_value = {"briefs": self.brief}
        self.login_as_buyer()

    def teardown_method(self, method):
        self.data_api_client_patch.stop()
        super(TestCancelBrief, self).teardown_method(method)

    def test_cancel_brief_form_displays_default_title_correctly_when_accessed_through_cancel_url(self):
        """
        This form has a dynamic title dependent on the url it is accessed through.

        This test checks for the default "Why do you need to cancel <brief_name>? title when accessed
        through the '/cancel' url".
        """
        self.login_as_buyer()
        res = self.client.get(self.url.format(brief_id=1234))

        assert res.status_code == 200
        document = html.fromstring(res.get_data(as_text=True))
        self.assert_breadcrumbs(res, extra_breadcrumbs=[
            (
                'I need a thing to do a thing',
                '/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-outcomes/1234'
            ),
            (
                "Why do you need to cancel?",
            )
        ])

        page_title = document.xpath('//h1')[0].text_content()
        assert "Why do you need to cancel {}?".format(self.brief.get('title')) in page_title

        submit_button = document.xpath(
            '//button[normalize-space(string())=$t]',
            t="Update requirements",
        )
        assert len(submit_button) == 1

        expected_previous_page_link_text = 'Previous page'
        expected_previous_page_link_url = (
            '/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-outcomes/1234'
        )

        assert (
            document.xpath("//a[text()='{}']/@href".format(expected_previous_page_link_text))[0] ==
            expected_previous_page_link_url
        )

    def test_cancel_form_post_action_is_correct_when_accessed_from_cancel_url(self):
        url = (
            '/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/'
            'digital-outcomes/{brief_id}/cancel'
        )

        self.login_as_buyer()
        res = self.client.get(url.format(brief_id=1234))
        document = html.fromstring(res.get_data(as_text=True))
        assert document.xpath('//form[@action="{}"]'.format(url.format(brief_id=1234)))[0] is not None

        res = self.client.post(url.format(brief_id=1234))
        document = html.fromstring(res.get_data(as_text=True))
        assert document.xpath('//form[@action="{}"]'.format(url.format(brief_id=1234)))[0] is not None

    def test_cancel_form_displays_correctly_accessed_from_award_flow_url(self):
        url = (
            '/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/'
            'digital-outcomes/{brief_id}/cancel-award'
        )

        self.login_as_buyer()
        res = self.client.get(url.format(brief_id=1234))
        assert res.status_code == 200

        document = html.fromstring(res.get_data(as_text=True))
        page_title = document.xpath('//h1')[0].text_content()
        assert "Why didn’t you award a contract for {}?".format(self.brief.get('title')) in page_title

        submit_button = document.xpath(
            '//button[normalize-space(string())=$t]',
            t="Update requirements",
        )
        assert len(submit_button) == 1

        expected_previous_page_link_text = 'Previous page'
        expected_previous_page_link_url = (
            '/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-outcomes/1234/award'
        )

        assert (
            document.xpath("//a[text()='{}']/@href".format(expected_previous_page_link_text))[0] ==
            expected_previous_page_link_url
        )

    def test_cancel_form_post_action_is_correct_when_accessed_from_award_flow_url(self):
        url = (
            '/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/'
            'digital-outcomes/{brief_id}/cancel-award'
        )

        self.login_as_buyer()
        res = self.client.get(url.format(brief_id=1234))
        document = html.fromstring(res.get_data(as_text=True))
        assert document.xpath('//form[@action="{}"]'.format(url.format(brief_id=1234)))[0] is not None

        res = self.client.post(url.format(brief_id=1234))
        document = html.fromstring(res.get_data(as_text=True))
        assert document.xpath('//form[@action="{}"]'.format(url.format(brief_id=1234)))[0] is not None

    def test_404_if_user_is_not_brief_owner(self):
        self.data_api_client.get_brief.return_value['briefs']['users'][0]['id'] = 234

        res = self.client.get(self.url.format(brief_id=self.brief["id"]))

        assert res.status_code == 404

    @pytest.mark.parametrize('status', ['withdrawn', 'draft', 'live', 'cancelled', 'unsuccessful', 'awarded'])
    def test_404_if_brief_not_closed(self, status):
        self.data_api_client.get_brief.return_value['briefs']['status'] = status

        res = self.client.get(self.url.format(brief_id=self.brief["id"]))

        assert res.status_code == 404

    @pytest.mark.parametrize('framework_status', ['live', 'expired'])
    def test_200_for_acceptable_framework_statuses(self, framework_status):
        self.data_api_client.get_framework.return_value['frameworks']['status'] = framework_status

        res = self.client.get(self.url.format(brief_id=123))

        assert res.status_code == 200

    def test_that_no_option_chosen_triggers_error(self):
        res = self.client.post(self.url.format(brief_id=123))

        document = html.fromstring(res.get_data(as_text=True))
        error_message = document.xpath('//span[@class="govuk-error-message"]')[0].text_content()

        assert res.status_code == 400
        assert "Select a reason for cancelling the brief." in error_message

    def test_that_no_option_chosen_does_not_trigger_update(self):
        res = self.client.post(self.url.format(brief_id=123))

        assert res.status_code == 400
        self.data_api_client.cancel_brief.assert_not_called()

    def test_cancel_triggers_cancel_brief(self):
        res = self.client.post(
            self.url.format(brief_id=123), data={'cancel_reason': 'cancel'}
        )

        assert res.status_code == 302
        self.data_api_client.cancel_brief.assert_called_once_with('123', user='******')

    def test_unsuccessful_triggers_cancel_brief(self):
        res = self.client.post(
            self.url.format(brief_id=123), data={'cancel_reason': 'unsuccessful'}
        )

        assert res.status_code == 302
        self.data_api_client.update_brief_as_unsuccessful.assert_called_once_with('123', user='******')

    @pytest.mark.parametrize('status', ['withdrawn', 'draft', 'live', 'closed', 'awarded'])
    def test_400_if_incorrect_status_supplied(self, status):
        res = self.client.post(
            self.url.format(brief_id=123), data={'cancel_reason': status}
        )

        assert res.status_code == 400
        assert "Not a valid choice" in res.get_data(as_text=True)

    @pytest.mark.parametrize('status', ['withdrawn', 'draft', 'live', 'closed', 'awarded'])
    def test_update_methods_not_called_if_incorrect_status_supplied(self, status):
        res = self.client.post(
            self.url.format(brief_id=123), data={'cancel_reason': status}
        )

        assert res.status_code == 400
        self.data_api_client.update_brief_as_unsuccessful.assert_not_called()
        self.data_api_client.cancel_brief.assert_not_called()

    @pytest.mark.parametrize('status', ['cancel', 'unsuccessful'])
    def test_redirect_and_flash_on_successful_status_change(self, status):
        res = self.client.post(
            self.url.format(brief_id=123), data={'cancel_reason': status}
        )

        redirect_text = html.fromstring(res.get_data(as_text=True)).text_content().strip()
        expected_url = '/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-outcomes/123'

        assert res.status_code == 302
        assert expected_url in redirect_text

        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)
コード例 #2
0
class TestWithdrawBriefSubmission(BaseApplicationTest):

    def setup_method(self, method):
        super().setup_method(method)
        self.data_api_client_patch = mock.patch(
            "app.main.views.withdraw_brief.data_api_client", autospec=True
        )
        self.data_api_client = self.data_api_client_patch.start()

        self.data_api_client.get_brief.return_value = BriefStub().single_result_response()
        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()

        self.brief = BriefStub(
            user_id=123,
            framework_slug='digital-outcomes-and-specialists-4',
            lot_slug="digital-specialists",
            status='draft'
        ).response()

        self.login_as_buyer()

    def teardown_method(self, method):
        self.data_api_client_patch.stop()
        super().teardown_method(method)

    @pytest.mark.parametrize('framework_status', ['live', 'expired'])
    def test_withdraw_brief_warning_page_displays_correctly(self, framework_status):
        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()
        self.data_api_client.get_brief.return_value = BriefStub(
            framework_slug='digital-outcomes-and-specialists-4',
            status='live',
        ).single_result_response()

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

        assert res.status_code == 200
        document = html.fromstring(res.get_data(as_text=True))
        self.assert_breadcrumbs(res, extra_breadcrumbs=[
            (
                'I need a thing to do a thing',
                '/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234'
            ),
            (
                "Are you sure you want to withdraw these requirements?",
            )
        ])

        page_title = document.xpath('//h1')[0].text_content()
        title_caption = document.cssselect('span.govuk-caption-xl')[0].text_content()
        assert title_caption == self.brief.get('title')
        assert page_title == "Are you sure you want to withdraw these requirements?"

        assert document.xpath(
            '//form[@action="/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234/withdraw"]' # noqa
        )[0] is not None

        submit_button = document.cssselect('button[name="withdraw_confirmed"]')
        cancel_link = document.xpath("//a[normalize-space()='Cancel']")

        assert len(submit_button) == 1
        assert len(cancel_link) == 1

        assert cancel_link[0].attrib['href'] == "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234" # noqa

    @pytest.mark.parametrize('framework_status', ['live', 'expired'])
    def test_withdraw_brief_submission(self, framework_status):
        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()
        self.data_api_client.get_brief.return_value = BriefStub(
            framework_slug='digital-outcomes-and-specialists-4',
            status='live',
        ).single_result_response()

        res = self.client.post(
            "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234/withdraw",
            data={"withdraw_confirmed": True}
        )

        assert res.status_code == 302
        assert self.data_api_client.delete_brief.call_args_list == []
        assert res.location == "http://localhost{}".format(self.briefs_dashboard_url)

        expected_flash_message = ("You’ve withdrawn your requirements for ‘I need a thing to do a thing’", "success")
        self.assert_flashes(*expected_flash_message)
        self.assert_flashes_with_dm_alert(*expected_flash_message)

    @pytest.mark.parametrize('framework_status', ['coming', 'open', 'pending', 'standstill'])
    def test_404_if_framework_is_not_live_or_expired(self, framework_status):
        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()

        res = self.client.post(
            "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234/withdraw",
            data={"withdraw_confirmed": True}
        )
        assert res.status_code == 404
        assert not self.data_api_client.delete_brief.called

    @pytest.mark.parametrize('status', ['draft', 'closed', 'awarded', 'cancelled', 'unsuccessful', 'withdrawn'])
    def test_cannot_withdraw_non_live_brief(self, status):
        self.data_api_client.get_brief.return_value = BriefStub(status=status).single_result_response()

        res = self.client.post(
            "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234/withdraw",
            data={"withdraw_confirmed": True}
        )

        assert res.status_code == 404
        assert self.data_api_client.delete_brief.call_args_list == []

    def test_404_if_brief_does_not_belong_to_user(self):
        self.data_api_client.get_brief.return_value = BriefStub(user_id=234, status='live').single_result_response()

        res = self.client.post(
            "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234/withdraw",
            data={"withdraw_confirmed": True}
        )

        assert res.status_code == 404

    def test_404_if_brief_has_wrong_lot(self):
        self.data_api_client.get_brief.return_value = BriefStub(status='live').single_result_response()

        res = self.client.post(
            "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-outcomes/1234/withdraw",
            data={"withdraw_confirmed": True})

        assert res.status_code == 404
class TestDeleteBriefSubmission(BaseApplicationTest):
    def setup_method(self, method):
        super().setup_method(method)
        self.data_api_client_patch = mock.patch(
            "app.main.views.create_a_brief.delete.data_api_client",
            autospec=True)
        self.data_api_client = self.data_api_client_patch.start()

        self.data_api_client.get_brief.return_value = BriefStub(
            framework_slug="digital-outcomes-and-specialists-4",
        ).single_result_response()
        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()
        self.brief = BriefStub(
            user_id=123,
            framework_slug='digital-outcomes-and-specialists-4',
            lot_slug="digital-specialists",
            status='draft').response()
        self.data_api_client.get_brief.return_value = {"briefs": self.brief}
        self.login_as_buyer()

    def teardown_method(self, method):
        self.data_api_client_patch.stop()
        super().teardown_method(method)

    def test_delete_brief_warning_page_displays_correctly(self):
        res = self.client.get(
            "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234/delete"
        )

        assert res.status_code == 200
        document = html.fromstring(res.get_data(as_text=True))
        self.assert_breadcrumbs(
            res,
            extra_breadcrumbs=
            [('I need a thing to do a thing',
              '/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234'
              ), ("Are you sure you want to delete these requirements?", )])

        page_title = document.xpath('//h1')[0].text_content()
        title_caption = document.cssselect(
            'span.govuk-caption-xl')[0].text_content()
        assert title_caption == self.brief.get('title')
        assert page_title == "Are you sure you want to delete these requirements?"

        url = (
            '/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/'
            'digital-specialists/1234/delete')
        assert document.xpath('//form[@action="{}"]'.format(
            url.format(brief_id=1234)))[0] is not None

        submit_button = document.cssselect('button[name="delete_confirmed"]')
        cancel_link = document.xpath("//a[normalize-space()='Cancel']")

        assert len(submit_button) == 1
        assert len(cancel_link) == 1

        assert cancel_link[0].attrib[
            'href'] == "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234"  # noqa

    def test_delete_brief_submission(self):
        for framework_status in ['live', 'expired']:
            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()

        res = self.client.post(
            "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234/delete",
            data={"delete_confirmed": "True"})

        assert res.status_code == 302
        assert self.data_api_client.delete_brief.called
        assert res.location == "http://localhost{}".format(
            self.briefs_dashboard_url)

        expected_message = "Your requirements ‘I need a thing to do a thing’ were deleted"
        expected_category = "success"
        self.assert_flashes(expected_message, expected_category)
        self.assert_flashes_with_dm_alert(expected_message, expected_category)

    def test_404_if_framework_is_not_live_or_expired(self):
        for framework_status in ['coming', 'open', 'pending', 'standstill']:
            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()

            res = self.client.post(
                "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234/delete",
            )
            assert res.status_code == 404
            assert not self.data_api_client.delete_brief.called

    def test_cannot_delete_live_brief(self):
        self.data_api_client.get_brief.return_value = BriefStub(
            status='live').single_result_response()

        res = self.client.post(
            "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-specialists/1234/delete",
        )

        assert res.status_code == 404
        assert not self.data_api_client.delete_brief.called

    def test_404_if_brief_does_not_belong_to_user(self):
        self.data_api_client.get_brief.return_value = BriefStub(
            user_id=234).single_result_response()

        res = self.client.post(
            "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/"
            "digital-specialists/1234/delete",
            data={"delete_confirmed": True})

        assert res.status_code == 404

    def test_404_if_brief_has_wrong_lot(self):
        res = self.client.post(
            "/buyers/frameworks/digital-outcomes-and-specialists-4/requirements/digital-outcomes/1234/delete",
            data={"delete_confirmed": True})

        assert res.status_code == 404