Skip to content
Snippets Groups Projects
test_views.py 10.8 KiB
Newer Older
import urllib

from django.contrib.messages.storage.fallback import FallbackStorage
from django.contrib.sessions.middleware import SessionMiddleware
from django.test import RequestFactory
from django.urls import reverse_lazy

from opentech.apply.activity.models import Activity
from opentech.apply.determinations.models import ACCEPTED, REJECTED
from opentech.apply.determinations.views import BatchDeterminationCreateView
Fredrik Jonsson's avatar
Fredrik Jonsson committed
from opentech.apply.users.tests.factories import StaffFactory, UserFactory
from opentech.apply.funds.models import ApplicationSubmission
Dan Braghis's avatar
Dan Braghis committed
from opentech.apply.funds.tests.factories import ApplicationSubmissionFactory
from opentech.apply.utils.testing import BaseViewTestCase
Dan Braghis's avatar
Dan Braghis committed

from .factories import DeterminationFactory

Dan Braghis's avatar
Dan Braghis committed

class StaffDeterminationsTestCase(BaseViewTestCase):
Dan Braghis's avatar
Dan Braghis committed
    user_factory = StaffFactory
    url_name = 'funds:submissions:determinations:{}'
    base_view_name = 'detail'
Dan Braghis's avatar
Dan Braghis committed

    def get_kwargs(self, instance):
        return {'submission_pk': instance.submission.id, 'pk': instance.pk}
Dan Braghis's avatar
Dan Braghis committed

    def test_can_access_determination(self):
        submission = ApplicationSubmissionFactory(status='in_discussion')
        determination = DeterminationFactory(submission=submission, author=self.user, submitted=True)
Dan Braghis's avatar
Dan Braghis committed
        response = self.get_page(determination)
        self.assertContains(response, determination.submission.title)
        self.assertContains(response, self.user.full_name)
        self.assertContains(response, submission.get_absolute_url())
Dan Braghis's avatar
Dan Braghis committed

    def test_lead_can_access_determination(self):
        submission = ApplicationSubmissionFactory(status='in_discussion', lead=self.user)
        determination = DeterminationFactory(submission=submission, author=self.user, submitted=True)
        response = self.get_page(determination)
        self.assertContains(response, determination.submission.title)
        self.assertContains(response, self.user.full_name)
        self.assertContains(response, submission.get_absolute_url())
Dan Braghis's avatar
Dan Braghis committed

class DeterminationFormTestCase(BaseViewTestCase):
Dan Braghis's avatar
Dan Braghis committed
    user_factory = StaffFactory
    url_name = 'funds:submissions:determinations:{}'
    base_view_name = 'detail'
Dan Braghis's avatar
Dan Braghis committed

    def get_kwargs(self, instance):
        return {'submission_pk': instance.id, 'pk': instance.determinations.first().id}

    def get_form_kwargs(self, instance):
Dan Braghis's avatar
Dan Braghis committed
        return {'submission_pk': instance.id}

    def test_can_access_form_if_lead(self):
        submission = ApplicationSubmissionFactory(status='in_discussion', lead=self.user)
        response = self.get_page(submission, 'form')
        self.assertContains(response, submission.title)
        self.assertContains(response, submission.get_absolute_url())
Dan Braghis's avatar
Dan Braghis committed

    def test_cant_access_wrong_status(self):
        submission = ApplicationSubmissionFactory(status='rejected')
Dan Braghis's avatar
Dan Braghis committed
        response = self.get_page(submission, 'form')
        self.assertRedirects(response, self.absolute_url(submission.get_absolute_url()))
Dan Braghis's avatar
Dan Braghis committed

    def test_cant_resubmit_determination(self):
        submission = ApplicationSubmissionFactory(status='in_discussion', lead=self.user)
        determination = DeterminationFactory(submission=submission, author=self.user, accepted=True, submitted=True)
Dan Braghis's avatar
Dan Braghis committed
        response = self.post_page(submission, {'data': 'value', 'outcome': determination.outcome}, 'form')
        self.assertRedirects(response, self.absolute_url(submission.get_absolute_url()))
Dan Braghis's avatar
Dan Braghis committed

    def test_can_edit_draft_determination(self):
        submission = ApplicationSubmissionFactory(status='post_review_discussion', lead=self.user)
Dan Braghis's avatar
Dan Braghis committed
        response = self.post_page(submission, {
            'data': 'value',
            'outcome': ACCEPTED,
            'message': 'Accepted determination draft message',
            'save_draft': True,
Dan Braghis's avatar
Dan Braghis committed
        }, 'form')
Dan Braghis's avatar
Dan Braghis committed
        self.assertContains(response, '[Draft] Approved')
        self.assertContains(response, self.url(submission, 'form', absolute=False))
        self.assertNotContains(response, 'Accepted determination draft message')
Dan Braghis's avatar
Dan Braghis committed

    def test_cant_edit_submitted_more_info(self):
        submission = ApplicationSubmissionFactory(status='in_discussion', lead=self.user)
        DeterminationFactory(submission=submission, author=self.user, submitted=True)
        response = self.get_page(submission, 'form')
        self.assertNotContains(response, 'Update ')
    def test_can_edit_draft_determination_if_not_lead(self):
Dan Braghis's avatar
Dan Braghis committed
        submission = ApplicationSubmissionFactory(status='in_discussion')
        determination = DeterminationFactory(submission=submission, author=self.user, accepted=True)
Dan Braghis's avatar
Dan Braghis committed
        response = self.post_page(submission, {'data': 'value', 'outcome': determination.outcome}, 'form')
        self.assertContains(response, 'Approved')
        self.assertRedirects(response, self.absolute_url(submission.get_absolute_url()))
Dan Braghis's avatar
Dan Braghis committed

    def test_sends_message_if_requires_more_info(self):
        submission = ApplicationSubmissionFactory(status='in_discussion', lead=self.user)
        determination = DeterminationFactory(submission=submission, author=self.user)
        determination_message = 'This is the message'
            submission,
            {'data': 'value', 'outcome': determination.outcome, 'message': determination_message},
            'form',
        )
        self.assertEqual(Activity.comments.count(), 1)
        self.assertEqual(Activity.comments.first().message, determination_message)

    def test_can_progress_stage_via_determination(self):
        submission = ApplicationSubmissionFactory(status='concept_review_discussion', workflow_stages=2, lead=self.user)

        response = self.post_page(submission, {
            'data': 'value',
            'outcome': ACCEPTED,
            'message': 'You are invited to submit a proposal',
        }, 'form')

        # Cant use refresh from DB with FSM
        submission_original = self.refresh(submission)
        submission_next = submission_original.next

Dan Braghis's avatar
Dan Braghis committed
        # Cannot use self.url() as that uses a different base.
        url = submission_next.get_absolute_url()
Dan Braghis's avatar
Dan Braghis committed
        self.assertRedirects(response, self.factory.get(url, secure=True).build_absolute_uri(url))
        self.assertEqual(submission_original.status, 'invited_to_proposal')
        self.assertEqual(submission_next.status, 'draft_proposal')

Dan Braghis's avatar
Dan Braghis committed

class BatchDeterminationTestCase(BaseViewTestCase):
    user_factory = StaffFactory
    url_name = 'funds:submissions:determinations:{}'
    base_view_name = 'batch'

    def dummy_request(self, path):
        request = RequestFactory().get(path)
        middleware = SessionMiddleware()
        middleware.process_request(request)
        request.session.save()
        request.user = StaffFactory()
        request._messages = FallbackStorage(request)
        return request

    def test_cant_access_without_submissions(self):
        url = self.url(None) + '?action=rejected'
        response = self.client.get(url, follow=True, secure=True)
        self.assertRedirects(response, self.url_from_pattern('apply:submissions:list'))
        self.assertEqual(len(response.context['messages']), 1)

    def test_cant_access_without_action(self):
        submission = ApplicationSubmissionFactory()
        url = self.url(None) + '?submissions=' + str(submission.id)
        response = self.client.get(url, follow=True, secure=True)
        self.assertRedirects(response, self.url_from_pattern('apply:submissions:list'))
        self.assertEqual(len(response.context['messages']), 1)

    def test_can_submit_batch_determination(self):
        submissions = ApplicationSubmissionFactory.create_batch(4)

        url = self.url(None) + '?submissions=' + ','.join([str(submission.id) for submission in submissions]) + '&action=rejected'
        data = {
            'submissions': [submission.id for submission in submissions],
            'data': 'some data',
            'outcome': REJECTED,
            'message': 'Sorry',
            'author': self.user.id,
        }

        response = self.client.post(url, data, secure=True, follow=True)

        for submission in submissions:
            submission = self.refresh(submission)
            self.assertEqual(submission.status, 'rejected')
            self.assertEqual(submission.determinations.count(), 1)

        self.assertRedirects(response, self.url_from_pattern('apply:submissions:list'))

    def test_sets_next_on_redirect(self):
        test_path = '/a/path/?with=query&a=sting'
        request = RequestFactory().get('', PATH_INFO=test_path)
        redirect = BatchDeterminationCreateView.should_redirect(
            request,
            ApplicationSubmission.objects.none(),
            ['rejected'],
        )
        url = urllib.parse.urlparse(redirect.url)
        query = urllib.parse.parse_qs(url.query)
        next_path = urllib.parse.unquote_plus(query['next'][0])
        self.assertEqual(next_path, test_path)

    def test_success_redirects_if_exists(self):
        test_path = '/a/path/?with=query&a=sting'
        view = BatchDeterminationCreateView()
        view.request = self.dummy_request('?next=' + urllib.parse.quote_plus(test_path))
        redirect_url = view.get_success_url()
        self.assertEqual(redirect_url, test_path)

    def test_success_if_no_next(self):
        view = BatchDeterminationCreateView()
        view.request = self.dummy_request('')
        redirect_url = view.get_success_url()
        self.assertEqual(redirect_url, reverse_lazy('apply:submissions:list'))

    def test_message_created_if_determination_exists(self):
        submissions = ApplicationSubmissionFactory.create_batch(2)

        DeterminationFactory(submission=submissions[0], accepted=True, is_draft=False)

        url = self.url(None) + '?submissions=' + ','.join([str(submission.id) for submission in submissions]) + '&action=rejected'
        data = {
            'submissions': [submission.id for submission in submissions],
            'data': 'some data',
            'outcome': REJECTED,
            'message': 'Sorry',
            'author': self.user.id,
        }

        response = self.client.post(url, data, secure=True, follow=True)

        self.assertEqual(submissions[0].determinations.count(), 1)
        self.assertEqual(submissions[0].determinations.first().outcome, ACCEPTED)

        self.assertEqual(submissions[1].determinations.count(), 1)
        self.assertEqual(submissions[1].determinations.first().outcome, REJECTED)

        # 5 base - 2 x django messages, 1 x activity feed, 1 x email, 1 x slack
        # plus 1 extra for unable to determine
        self.assertEqual(len(response.context['messages']), 6)

class UserDeterminationFormTestCase(BaseViewTestCase):
Dan Braghis's avatar
Dan Braghis committed
    user_factory = UserFactory
    url_name = 'funds:submissions:determinations:{}'
    base_view_name = 'detail'
Dan Braghis's avatar
Dan Braghis committed

    def get_kwargs(self, instance):
        return {'submission_pk': instance.id}

    def test_cant_access_form(self):
        submission = ApplicationSubmissionFactory(status='in_discussion')
        response = self.get_page(submission, 'form')
        self.assertEqual(response.status_code, 403)