def test_approved_coordinator_logged_in(self):
     '''
     This tests that informal chat contracts are visible to an approved coordinator logged in, whose community has been approved to participate
     '''
     scenario = scenarios.InternshipWeekScenario(week=11)
     self.client.force_login(scenario.coordinator.account)
     self.assert_permission_approved_on_informal_chat_contacts()
    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)
Esempio n. 3
0
    def submit_failed_community_signup(self, current_round):
        scenario = scenarios.InternshipWeekScenario(week = 10, community__name='Debian', community__slug='debian')

        self.client.force_login(scenario.coordinator.account)
        response = self.coordinator_signs_up_community_to_participate(
                reverse('participation-action', kwargs={'action': 'submit', 'round_slug': current_round.slug, 'community_slug': scenario.participation.community.slug, }),
                )
        with self.assertRaises(Participation.DoesNotExist):
            p = Participation.objects.get(community__slug=scenario.participation.community.slug, participating_round__slug=current_round.slug)
        self.assertNotEqual(response.status_code, 302)
    def test_community_read_only_submission_text_cfp_closed(self):
        """
        This tests how the page for coordinators and mentors of a community
        looks between rounds (after interns have been selected
        but before the next round has been announced).

        Test home/templates/home/community_read_only.html:
         - Create a community that has been approved to participate in a past round
         - No new RoundPage for the upcoming round
         - Check:
           - Warning card about CFP not being open is visible
           - The 'Submit a Project Proposal' button is not visible
           - The 'Submit an Outreachy Intern Project Proposal' heading is not visible
         - Ensure those checks are true for all visitor types
        """
        scenario = scenarios.InternshipWeekScenario(week=1,
                                                    community__name='Debian',
                                                    community__slug='debian')
        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': scenario.participation.participating_round.slug,
                'community_slug': scenario.participation.community.slug,
            })

        visitors = self.get_visitors_from_past_round(scenario)

        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,
                    '<div class="card-header text-white bg-warning">Project and community CFP is currently closed</div>',
                    html=True)
                self.assertNotContains(
                    response,
                    '<h2>Submit an Outreachy Intern Project Proposal</h2>',
                    html=True)
                self.assertNotContains(
                    response,
                    '<a class="btn btn-success" href="{}">Submit a Project Proposal</a>'
                    .format(project_submission_path),
                    html=True)
    def test_intern_in_good_standing_and_logged_in(self):
        """
        This tests that informal chat contracts are visible to an intern who is logged in, but not authorized to see them.
        """

        scenario = scenarios.InternshipWeekScenario(week=11)

        # Applicant 1 is an approved intern
        # and should be able to see the informal chat contacts
        self.client.force_login(scenario.applicant1.applicant.account)

        self.assert_permission_approved_on_informal_chat_contacts()
    def test_not_authorized_and_logged_in(self):
        """
        This tests that informal chat contracts are not visible to someone who is logged in, but not authorized to see them.
        """

        scenario = scenarios.InternshipWeekScenario(week=11)

        # Applicant 4 has a pending initial application
        # and should not be able to see the informal chat contacts
        self.client.force_login(scenario.applicant4.applicant.account)

        self.assert_permission_denied_on_informal_chat_contacts()
    def test_mentor_with_intern_and_logged_in(self):
        """
        This tests that informal chat contracts are visible to a mentor who is logged in, who does have an organizer approved intern.
        """

        scenario = scenarios.InternshipWeekScenario(week=11)

        # Mentor 1 is mentoring Applicant 1 (who is an approved intern)
        # and should be able to see the informal chat contacts
        mentors = models.MentorRelationship.objects.filter(
            intern_selection=scenario.intern_selection1)
        self.client.force_login(mentors[0].mentor.mentor.account)

        self.assert_permission_approved_on_informal_chat_contacts()
 def test_approved_coordinator_unapproved_community_logged_in(self):
     '''
     This tests that informal chat contracts are NOT visible to an approved coordinator logged in, whose community has NOT been approved to participate
     '''
     scenario = scenarios.InternshipWeekScenario(week=11)
     for community_approval_status in [
             models.ApprovalStatus.PENDING, models.ApprovalStatus.WITHDRAWN,
             models.ApprovalStatus.REJECTED
     ]:
         with self.subTest(
                 community_approval_status=community_approval_status):
             scenario.participation.approval_status = community_approval_status
             scenario.participation.save()
             self.client.force_login(scenario.coordinator.account)
             self.assert_permission_denied_on_informal_chat_contacts()
             self.client.logout()
    def test_mentor_with_no_intern_and_logged_in(self):
        """
        This tests that informal chat contracts are not visible to a mentor who is logged in, but does not have an organizer approved intern.
        """

        scenario = scenarios.InternshipWeekScenario(week=11)
        scenario.intern_selection = factories.InternSelectionFactory(
            round=scenario.round,
            funding_source=models.InternSelection.ORG_FUNDED,
            organizer_approved=False,
        )

        # The unapproved intern's mentor
        # should not be able to see the informal chat contacts
        mentors = models.MentorRelationship.objects.filter(
            intern_selection=scenario.intern_selection)
        self.client.force_login(mentors[0].mentor.mentor.account)

        self.assert_permission_denied_on_informal_chat_contacts()
    def test_community_read_only_submission_text_cfp_open_uncertain_participation(
            self):
        """
        This tests how the page for coordinators and mentors of a community
        looks after a new round has been announced,
        but before the community signs up to participate.

        Test home/templates/home/community_read_only.html:
         - Create a community that has been approved to participate in a past round
         - Create a new RoundPage for the upcoming round
         - Check:
           - The 'Not Participating' status is visible
           - The 'Coordinate for This Community' button is visible to anyone who is not a coordinator
           - The 'Community will participate' button is visible to a coordinator
           - The 'Community will not participate' button is visible to a coordinator
           - The 'Submit a Project Proposal' button is not visible
           - The 'Submit an Outreachy Intern Project Proposal' heading is not visible
        """
        scenario = scenarios.InternshipWeekScenario(week=10,
                                                    community__name='Debian',
                                                    community__slug='debian')
        community_read_only_path = reverse(
            'community-read-only',
            kwargs={
                'community_slug': scenario.participation.community.slug,
            })
        current_round = factories.RoundPageFactory(start_from='pingnew')

        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,
            })
        community_does_not_participate_path = reverse(
            'participation-action',
            kwargs={
                'action': 'withdraw',
                'round_slug': current_round.slug,
                'community_slug': scenario.participation.community.slug,
            })

        visitors = self.get_visitors_from_past_round(scenario)

        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-warning">Not Participating</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)
                else:
                    self.assertContains(
                        response,
                        '<a href="{}" class="btn btn-success">Community will participate</a>'
                        .format(community_does_participate_path),
                        html=True)
                    self.assertContains(
                        response,
                        '<a href="{}" class="btn btn-warning">Community will not participate</a>'
                        .format(community_does_not_participate_path),
                        html=True)
                self.assertNotContains(
                    response,
                    '<h2>Submit an Outreachy Intern Project Proposal</h2>',
                    html=True)
                self.assertNotContains(
                    response,
                    '<a class="btn btn-success" href="{}">Submit a Project Proposal</a>'
                    .format(project_submission_path),
                    html=True)
    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)
    def test_project_submission_no_community_participation(self):
        """
        This tests submitting a project when the community is not signed up to participate
         - Create a new RoundPage for the upcoming round with project submission open
         - Do not add the old community to participate in the round
         - 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=10,
                                                    community__name='Debian',
                                                    community__slug='debian')

        current_round = factories.RoundPageFactory(start_from='pingnew')

        # 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)

        # 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,
            '<span class="badge badge-pill badge-warning">Not Participating</span>',
            html=True)

        # Check that there is not a submit project button
        self.assertNotContains(
            response,
            '<h2>Submit an Outreachy Intern Project Proposal</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)

        # 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, 404)
Esempio n. 14
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)
Esempio n. 15
0
    def test_old_community_participation_signup(self):
        """
        This tests submitting an older community to participate in this round.
         - Create a community that has been approved to participate in a past round
         - Create a new RoundPage for the upcoming round
         - Submit the community to participate in the round through the form
         - There should be an email sent to the Outreachy organizers about the participation
         - There should be a Participation object for this community in the current round marked as PENDING

        Test home/templates/home/community_read_only.html:
         - Check:
           - The 'Pending Participation' status is visible
           - Funding for 2 interns 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,
            })
        community_does_not_participate_path = reverse(
            'participation-action',
            kwargs={
                'action': 'withdraw',
                'round_slug': current_round.slug,
                'community_slug': scenario.participation.community.slug,
            })
        sponsor_name = 'Software in the Public Interest - Debian'
        sponsor_amount = 13000

        visitors = self.get_visitors_from_past_round(scenario)
        # There should not be a Participation for Debian in the current round yet
        with self.assertRaises(Participation.DoesNotExist):
            p = Participation.objects.get(
                community__slug=scenario.participation.community.slug,
                participating_round__slug=current_round.slug)

        self.client.force_login(scenario.coordinator.account)
        response = self.coordinator_signs_up_community_to_participate(
            reverse('participation-action',
                    kwargs={
                        'action': 'submit',
                        'round_slug': current_round.slug,
                        'community_slug':
                        scenario.participation.community.slug,
                    }),
            sponsor_name,
            sponsor_amount,
        )
        self.assertEqual(response.status_code, 302)

        # Ensure the database reflects the community sign-up
        participation = Participation.objects.get(
            community__slug=scenario.participation.community.slug,
            participating_round__slug=current_round.slug,
            approval_status=ApprovalStatus.PENDING)
        sponsorship = Sponsorship.objects.get(participation=participation,
                                              coordinator_can_update=True,
                                              name=sponsor_name,
                                              amount=sponsor_amount,
                                              funding_secured=True)

        # Make sure the email to the Outreachy organizers was sent
        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(mail.outbox[0].subject,
                         'Approve community participation - Debian')
        self.assertEqual(mail.outbox[0].from_email, organizers)
        self.assertEqual(mail.outbox[0].to, [organizers])
        self.assertIn(community_read_only_path, mail.outbox[0].body)
        self.assertIn('Number of interns funded: 2', mail.outbox[0].body)
        self.assertIn(sponsor_name, mail.outbox[0].body)
        self.assertIn(str(sponsor_amount), mail.outbox[0].body)

        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-info">Pending Participation</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)