def test_project_submission_to_approved_community(self):
        """
        This tests submitting a project to a community that is approved to participate in this round.
         - Create a new RoundPage for the upcoming round, with an approved community
         - Go to the community read-only page
         - Log in as a mentor from the previous round for this community
         - Click the 'Submit Project' button, fill out project description
         - Be redirected to the MentorApproval form, fill that out
         - Be redirected to the ProjectSkills form, fill that out
         - Be redirected to the ProjectCommunicationChannels form, fill that out
         - Finally be done! \o/
         - Coordinator receives email about the pending project
         - The community read-only page should not reflect the project was submitted, except to the mentor who submitted it
        """
        scenario = scenarios.InternshipWeekScenario(week=10,
                                                    community__name='Debian',
                                                    community__slug='debian')

        current_round = factories.RoundPageFactory(start_from='pingnew')
        participation = factories.ParticipationFactory(
            community=scenario.community,
            participating_round=current_round,
            approval_status=ApprovalStatus.APPROVED)

        self.check_project_submission(scenario, current_round, participation)
 def test_unapproved_coordinator_unapproved_community_logged_in(self):
     '''
     This tests that informal chat contracts are NOT visible to an unapproved coordinator logged in, whose community has NOT been approved to participate
     '''
     scenario = scenarios.NewRoundScenario(round__start_from='internends',
                                           round__days_after_today=-185)
     for community_approval_status in [
             models.ApprovalStatus.PENDING, models.ApprovalStatus.WITHDRAWN,
             models.ApprovalStatus.REJECTED
     ]:
         with self.subTest(
                 community_approval_status=community_approval_status):
             for coordinator_approval_status in [
                     models.ApprovalStatus.PENDING,
                     models.ApprovalStatus.WITHDRAWN,
                     models.ApprovalStatus.REJECTED
             ]:
                 with self.subTest(coordinator_approval_status=
                                   coordinator_approval_status):
                     participation = factories.ParticipationFactory(
                         participating_round=scenario.round,
                         approval_status=community_approval_status,
                     )
                     coordinator_approval = factories.CoordinatorApprovalFactory(
                         community=participation.community,
                         approval_status=coordinator_approval_status,
                     )
                     self.client.force_login(
                         coordinator_approval.coordinator.account)
                     self.assert_permission_denied_on_informal_chat_contacts(
                     )
                     self.client.logout()
    def test_project_hard_deadline(self):
        """
        This tests submitting a project after the deadline for project approval fails:
         - Create a new RoundPage for the upcoming round with the project submission deadline passed
         - Create an approved community
         - Go to the community read-only page
         - There should not be a 'Submit Project' button
         - Submitting a project directly via the URL should fail
        """
        scenario = scenarios.InternshipWeekScenario(week=15,
                                                    community__name='Debian',
                                                    community__slug='debian')

        current_round = factories.RoundPageFactory(start_from='lateprojects')
        participation = factories.ParticipationFactory(
            community=scenario.community,
            participating_round=current_round,
            approval_status=ApprovalStatus.APPROVED)

        # Check community CFP page to ensure the message about the CFP being closed is displayed
        response = self.client.get(reverse('community-cfp'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(
            response,
            '<div class="card-header text-white bg-warning">Project and community CFP is currently closed</div>',
            html=True)

        # Check community CFP page to ensure the message about the CFP being closed is displayed
        response = self.client.get(
            reverse('community-read-only',
                    kwargs={
                        'community_slug':
                        scenario.participation.community.slug,
                    }))
        self.assertContains(
            response,
            '<div class="card-header text-white bg-warning">Project and community CFP is currently closed</div>',
            html=True)

        # Check that there is not a submit project button
        self.assertNotContains(
            response,
            '<h2>Submit an Outreachy Intern Project Proposal</h2>',
            html=True)
        self.assertContains(response,
                            '<h2>Project Submission Deadline Passed</h2>',
                            html=True)
        project_submission_path = reverse(
            'project-action',
            kwargs={
                'action': 'submit',
                'round_slug': current_round.slug,
                'community_slug': scenario.participation.community.slug,
            })
        self.assertNotContains(
            response,
            '<a class="btn btn-success" href="{}">Submit a Project Proposal</a>'
            .format(project_submission_path),
            html=True)

        sponsorship = factories.SponsorshipFactory(
            participation=participation,
            name='Software in the Public Interest - Debian',
            amount=13000)
        visitors = self.get_visitors_from_past_round(scenario)

        # Submit project description
        self.client.force_login(scenario.mentor.account)
        response = self.client.post(
            project_submission_path,
            {
                'approved_license': 'on',
                'no_proprietary_software': 'on',
                'longevity': '2Y',
                'community_size': '20',
                'short_title':
                'Improve Debian bioinformatics packages test coverage',
                'long_description':
                'The Debian Med project has packaged a lot of <a href="http://blends.debian.org/med/tasks/bio">applications for bioinformatics</a>. You will be improving the test coverage of those packages.',
                'minimum_system_requirements': 'A system running Debian Linux',
                'contribution_tasks':
                'Look at issues marked newcomers-welcome.',
                'repository': 'https://salsa.debian.org/med-team',
                'issue_tracker': 'https://bugs.debian.org/',
                'newcomer_issue_tag': 'newcomers-welcome',
                'intern_tasks':
                'Interns will work on new tests for <a href="http://blends.debian.org/med/tasks/bio">Debian bioinformatics packages</a>.',
                'intern_benefits':
                'Interns will develop skills in quality assurance testing, learn Linux command-line tools, and gain knowledge in how Linux distributions like Debian package software.',
                'community_benefits':
                'Debian maintainers will spend less time tracking down bugs in newly released software.',
                'new_contributors_welcome': True,
            },
            # This says we're supposed to follow any and all redirects to other pages after the post
            # This will allow us to record a history of where the redirect went to
            follow=True,
        )
        self.assertEqual(response.status_code, 403)
        self.assertContains(
            response,
            'Not allowed to submit a project after its submission and approval deadline ({})'
            .format(current_round.lateprojects),
            status_code=403)
    def test_project_soft_deadline(self):
        """
        Mentors are told that projects are due one week before they're actually due.
        This is a "soft" project submission deadline.
        It's seven days before lateprojects - can be found by calling RoundPage.project_soft_deadline().

        After the soft project submission deadline,
        the community CFP page shows project submission is closed.
        The community read-only page doesn't show the submit project button.
        *But* mentors can still submit if they know the URL.
        This allows us to deal with the few mentors who always miss the deadline.

        This tests submitting a project after the soft deadline succeeds:
         - Create a new RoundPage for the upcoming round with the project submission deadline passed
         - Create an approved community
         - Go to the community read-only page
         - There should not be a 'Submit Project' button
         - Submitting a project directly via the URL should still work
        """
        scenario = scenarios.InternshipWeekScenario(week=14,
                                                    community__name='Debian',
                                                    community__slug='debian')

        current_round = factories.RoundPageFactory(start_from='lateprojects',
                                                   days_after_today=6)
        participation = factories.ParticipationFactory(
            community=scenario.community,
            participating_round=current_round,
            approval_status=ApprovalStatus.APPROVED)

        # Check community CFP page to ensure the message about the CFP being closed is displayed
        response = self.client.get(reverse('community-cfp'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(
            response,
            '<div class="card-header text-white bg-warning">Project and community CFP is currently closed</div>',
            html=True)

        # Check community CFP page to ensure the message about the CFP being closed is displayed
        response = self.client.get(
            reverse('community-read-only',
                    kwargs={
                        'community_slug':
                        scenario.participation.community.slug,
                    }))
        self.assertContains(
            response,
            '<div class="card-header text-white bg-warning">Project and community CFP is currently closed</div>',
            html=True)

        # Check that there is not a submit project button
        self.assertNotContains(
            response,
            '<h2>Submit an Outreachy Intern Project Proposal</h2>',
            html=True)
        self.assertContains(response,
                            '<h2>Project Submission Deadline Passed</h2>',
                            html=True)
        project_submission_path = reverse(
            'project-action',
            kwargs={
                'action': 'submit',
                'round_slug': current_round.slug,
                'community_slug': scenario.participation.community.slug,
            })
        self.assertNotContains(
            response,
            '<a class="btn btn-success" href="{}">Submit a Project Proposal</a>'
            .format(project_submission_path),
            html=True)

        self.check_project_submission(scenario, current_round, participation)
Ejemplo n.º 5
0
    def test_community_participation_approval(self):
        """
        This tests approving a community to participate in this round.
         - Create a new RoundPage for the upcoming round, with a pending community
         - Go to the community read-only page
         - Log in as an organizer
         - The community read-only page should have an 'Approve Community' and a 'Reject Community' button
         - Post to the Participation approval URL
         - This should redirect back to community read-only page
         - Participation should now marked as approved in the database
         - Coordinator receives email that the community was approved to participate
         - The community read-only page should now reflect that the community has been approved
           - Community status box should read 'Participating'
         - There should still be a way to submit projects

        Test home/templates/home/community_read_only.html:
         - Check:
           - The 'Participating' status is visible
           - Funding for 1 intern is visible
           - The 'Coordinate for This Community' button is visible to anyone who is not a coordinator
           - The 'Submit a Project Proposal' button is visible
           - The 'Submit an Outreachy Intern Project Proposal' heading is visible
           - The 'Community will participate' button is visible to a coordinator
           - The 'Community will not participate' button is visible to a coordinator
        """
        scenario = scenarios.InternshipWeekScenario(week=10,
                                                    community__name='Debian',
                                                    community__slug='debian')
        current_round = factories.RoundPageFactory(start_from='pingnew')

        community_read_only_path = reverse(
            'community-read-only',
            kwargs={
                'community_slug': scenario.participation.community.slug,
            })
        project_submission_path = reverse(
            'project-action',
            kwargs={
                'action': 'submit',
                'round_slug': current_round.slug,
                'community_slug': scenario.participation.community.slug,
            })
        coordinator_signup_path = reverse(
            'coordinatorapproval-action',
            kwargs={
                'action': 'submit',
                'community_slug': scenario.participation.community.slug,
            })
        community_does_participate_path = reverse(
            'participation-action',
            kwargs={
                'action': 'submit',
                'round_slug': current_round.slug,
                'community_slug': scenario.participation.community.slug,
            })
        approve_participation_path = reverse(
            'participation-action',
            kwargs={
                'action': 'approve',
                'round_slug': current_round.slug,
                'community_slug': scenario.participation.community.slug,
            })
        reject_participation_path = reverse(
            'participation-action',
            kwargs={
                'action': 'reject',
                'round_slug': current_round.slug,
                'community_slug': scenario.participation.community.slug,
            })
        visitors = self.get_visitors_from_past_round(scenario)

        # Set up the community with a pending participation in the current round
        participation = factories.ParticipationFactory(
            community=scenario.community,
            participating_round=current_round,
            approval_status=ApprovalStatus.PENDING)
        sponsorship = factories.SponsorshipFactory(
            participation=participation,
            name='Software in the Public Interest - Debian',
            amount=13000)

        organizer_account = User.objects.get(is_staff=True)
        self.client.force_login(organizer_account)

        # Double check that the community read-only page has links to approve or reject
        response = self.client.get(community_read_only_path)
        self.assertEqual(response.status_code, 200)
        self.assertContains(
            response,
            '<span class="badge badge-pill badge-info">Pending Participation</span>',
            html=True)
        self.assertContains(
            response,
            '<input type="submit" class="btn btn-success m-2" value="Approve Community" />',
            html=True)
        self.assertContains(
            response,
            '<a href="{}" class="btn btn-warning m-2">Reject Community</a>'.
            format(reject_participation_path),
            html=True)

        # Approve the community
        response = self.client.post(approve_participation_path)
        self.assertEqual(response.status_code, 302)

        # Check the database status
        approved_participation = Participation.objects.get(
            community__slug=participation.community.slug,
            participating_round__slug=current_round.slug,
            approval_status=ApprovalStatus.APPROVED)

        # Check that the email to the community coordinator was sent
        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(
            mail.outbox[0].subject, '{} is participating in Outreachy!'.format(
                scenario.community.name))
        self.assertEqual(mail.outbox[0].from_email, organizers)
        self.assertEqual(mail.outbox[0].to,
                         scenario.community.get_coordinator_email_list())
        self.assertIn(
            'The Outreachy organizers have approved {} to participate in the current round of Outreachy!'
            .format(scenario.community.name), mail.outbox[0].body)
        # TODO: we should probably check that other information is correct,
        # like the round dates, but this is enough for now.

        # Check that the community read-only page reflects the database status
        for visitor_type, visitor in visitors:
            with self.subTest(visitor_type=visitor_type):
                self.client.logout()
                if visitor:
                    self.client.force_login(visitor)
                response = self.client.get(community_read_only_path)
                self.assertEqual(response.status_code, 200)
                self.assertContains(
                    response,
                    '<span class="badge badge-pill badge-success">Participating</span>',
                    html=True)
                self.assertContains(
                    response,
                    '<span class="badge badge-pill badge-success">Funded</span>',
                    html=True)
                self.assertContains(
                    response,
                    '<td>This community has funding for 2 interns.</td>',
                    html=True)
                self.assertContains(
                    response,
                    '<span class="badge badge-pill badge-warning">No Projects</span>',
                    html=True)
                self.assertContains(
                    response,
                    '<span class="badge badge-pill badge-info">Open to New Projects</span>',
                    html=True)
                if visitor_type != 'coordinator':
                    self.assertContains(
                        response,
                        '<a href="{}" class="btn btn-success">Coordinate for This Community</a>'
                        .format(coordinator_signup_path),
                        html=True)
                self.assertContains(
                    response,
                    '<h2>Submit an Outreachy Intern Project Proposal</h2>',
                    html=True)
                self.assertContains(
                    response,
                    '<a class="btn btn-success" href="{}">Submit a Project Proposal</a>'
                    .format(project_submission_path),
                    html=True)