Exemplo n.º 1
0
    def test_get_for_team(self):
        """You can list cycles for a team you own."""
        other, teammate, captain, team, cycles = self.create()

        # Forbidden for non-members.
        response = self.testapp.get(
            '/api/teams/{}/cycles'.format(team.uid),
            headers=jwt_headers(other),
            status=403
        )

        # Successful for members.
        response = self.testapp.get(
            '/api/teams/{}/cycles'.format(team.uid),
            headers=jwt_headers(teammate),
        )
        response_list = json.loads(response.body)
        self.assertEqual(len(response_list), 2)

        # Can filter by ordinal
        response = self.testapp.get(
            '/api/teams/{}/cycles?ordinal=1'.format(team.uid),
            headers=jwt_headers(teammate),
        )
        response_list = json.loads(response.body)
        self.assertEqual(len(response_list), 1)
        self.assertEqual(response_list[0]['ordinal'], 1)
Exemplo n.º 2
0
    def test_create(self):
        """Only captains can add cycles."""
        other, teammate, captain, team, cycles = self.create()
        last = cycles[-1]
        start_date = last.start_date + datetime.timedelta(weeks=5)
        end_date = last.end_date + datetime.timedelta(weeks=5)

        # Forbidden for non-captains.
        for user in (other, teammate):
            self.testapp.post_json(
                '/api/cycles',
                {
                    'team_id': team.uid,
                    'start_date': start_date.strftime(config.iso_date_format),
                    'end_date': end_date.strftime(config.iso_date_format),
                },
                headers=jwt_headers(user),
                status=403,
            )

        # Successful for captains.
        response = self.testapp.post_json(
            '/api/cycles',
            {
                'team_id': team.uid,
                'start_date': start_date.strftime(config.iso_date_format),
                'end_date': end_date.strftime(config.iso_date_format),
            },
            headers=jwt_headers(captain),
        )
        self.assertIsNotNone(Cycle.get_by_id(json.loads(response.body)['uid']))
Exemplo n.º 3
0
    def test_delete(self):
        other, teammate, team, cycles, responses = self.create()

        # Forbidden to delete other people's responses.
        self.testapp.delete(
            '/api/responses/{}'.format(responses['user_team_other'].uid),
            headers=jwt_headers(teammate),
            status=403,
        )

        # Successful to delete your own.
        self.testapp.delete(
            '/api/responses/{}'.format(responses['user_team_user1'].uid),
            headers=jwt_headers(teammate),
            status=204,
        )
        self.assertIsNone(Response.get_by_id(responses['user_team_user1'].uid))

        # Forbidden to delete other team's responses.
        self.testapp.delete(
            '/api/responses/{}'.format(responses['team_other'].uid),
            headers=jwt_headers(teammate),
            status=403,
        )

        # Successful to delete responses from your team.
        self.testapp.delete(
            '/api/responses/{}'.format(responses['team_team'].uid),
            headers=jwt_headers(teammate),
            status=204,
        )
        self.assertIsNone(Response.get_by_id(responses['team_team'].uid))
Exemplo n.º 4
0
    def test_delete(self):
        """Only team captains can delete cycles."""
        other, teammate, captain, team, cycles = self.create()
        other = User.create(name='other', email='*****@*****.**')
        other.put()

        # Forbidden by non-captains.
        for user in (teammate, other):
            self.testapp.delete(
                '/api/cycles/{}'.format(cycles[1].uid),
                headers=jwt_headers(user),
                status=403,
            )

        # Successful by captain.
        self.testapp.delete(
            '/api/cycles/{}'.format(cycles[1].uid),
            headers=jwt_headers(captain),
            status=204,
        )
        self.assertIsNone(Cycle.get_by_id(cycles[1].uid))

        # Forbidden if cycles are too few.
        self.testapp.delete(
            '/api/cycles/{}'.format(cycles[2].uid),
            headers=jwt_headers(captain),
            status=403,
        )
        # The last cycle wasn't deleted.
        self.assertIsNotNone(Cycle.get_by_id(cycles[2].uid))
Exemplo n.º 5
0
    def test_overlap_forbidden(self):
        other, teammate, captain, team, cycles = self.create()

        # Try to create a new cycle that wraps the others.
        before = cycles[1].start_date - datetime.timedelta(days=1)
        after = cycles[2].end_date + datetime.timedelta(days=1)
        wrapping_params = {
            'team_id': team.uid,
            'ordinal': 1,
            'start_date': before.strftime(config.iso_date_format),
            'end_date': after.strftime(config.iso_date_format),
        }
        self.testapp.post_json(
            '/api/cycles',
            wrapping_params,
            headers=jwt_headers(captain),
            status=400,
        )

        # Nothing created in db.
        self.assertEqual(len(Cycle.get()), 3)

        # Same story for updating.
        self.testapp.put_json(
            '/api/cycles/{}'.format(cycles[1].uid),
            wrapping_params,
            headers=jwt_headers(captain),
            status=400,
        )

        # Cycle's dates haven't changed.
        fetched = Cycle.get_by_id(cycles[1].uid)
        self.assertEqual(fetched.start_date, cycles[1].start_date)
        self.assertEqual(fetched.end_date, cycles[1].end_date)
Exemplo n.º 6
0
    def test_get_for_team(self):
        """You can list participants for a team you own."""
        other, teammate, contact, captain, team, classroom, ppnt = self.create(
        )

        # Forbidden for non-members.
        response = self.testapp.get('/api/teams/{}/participants'.format(
            team.uid),
                                    headers=jwt_headers(other),
                                    status=403)

        # Make sure query excludes participants on other teams.
        other_ppnt = Participant.create(first_name='other',
                                        last_name='person',
                                        team_id='Team_foo',
                                        classroom_ids=['Classroom_foo'],
                                        student_id='STUDENTID001')
        other_ppnt.put()

        # Successful for members.
        response = self.testapp.get(
            '/api/teams/{}/participants'.format(team.uid),
            headers=jwt_headers(teammate),
        )
        response_list = json.loads(response.body)
        self.assertEqual(len(response_list), 1)
Exemplo n.º 7
0
    def test_update_question_level(self):
        """Question-level updates without conflicts."""
        other, teammate, team, cycles, responses = self.create()

        # New question. Added to the existing body (existing remain).
        response_id = responses['team_team'].uid
        self.testapp.put_json(
            '/api/responses/{}'.format(response_id),
            {'body': {
                'question_new': {
                    'value': 'foo',
                    'modified': None
                }
            }},
            headers=jwt_headers(teammate),
        )
        fetched = Response.get_by_id(response_id)
        self.assertIn('question', fetched.body)
        # New question was given a timestamp.
        self.assertIsNotNone(fetched.body['question_new']['modified'])

        # Question unchanged. Do nothing, even if timestamp is old.
        old_body = self.default_body()
        old_body['question']['modified'] = '2000-01-01T00:00:00Z'
        self.testapp.put_json(
            '/api/responses/{}'.format(response_id),
            {'body': old_body},
            headers=jwt_headers(teammate),
        )
        fetched = Response.get_by_id(response_id)
        self.assertEqual(
            fetched.body['question'],  # current value is...
            self.default_body()['question'],  # how it was originally created
        )

        # Non-stale update. Existing timestamp matches and value changes.
        new_body = self.default_body()
        new_body['question']['value'] = 'updated'
        self.testapp.put_json(
            '/api/responses/{}'.format(response_id),
            {'body': new_body},
            headers=jwt_headers(teammate),
        )
        fetched = Response.get_by_id(response_id)
        self.assertEqual(
            fetched.body['question']['value'],
            new_body['question']['value'],
        )
        # Timestamp should update.
        self.assertGreater(
            fetched.body['question']['modified'],
            new_body['question']['modified'],
        )
Exemplo n.º 8
0
    def test_update_force(self):
        """Force flag is set, override conflicts and save."""
        other, teammate, team, cycles, responses = self.create()

        # Value is changed and timestamp is old
        response_id = responses['team_team'].uid
        now = datetime.datetime.now().strftime(config.iso_datetime_format)
        old_time = '2000-01-01T00:00:00Z'
        body = {
            # based on stale data, but will be accepted anyway
            'question': {
                'value': 'bar',
                'modified': old_time
            },
            # this should be accepted also
            'question_new': {
                'value': 'foo',
                'modified': old_time
            },
        }
        self.testapp.put_json(
            '/api/responses/{}?force=true'.format(response_id),
            {'body': body},
            headers=jwt_headers(teammate),
        )
        fetched = Response.get_by_id(response_id)

        for k, info in body.items():
            self.assertIn(k, fetched.body)
            self.assertEqual(info['value'], fetched.body[k]['value'])
            self.assertTrue(fetched.body[k]['modified'] >= now)
Exemplo n.º 9
0
    def test_survey_participation(self):
        org_id = 'Org_foo'
        user = User.create(email='*****@*****.**',
                           owned_organizations=[org_id])
        user.put()

        pds = mock_one_finished_one_unfinished(
            1,
            'Participant_unfinished',
            'Participant_finished',
            program_label=self.program_label,
            cohort_label=self.cohort_label,
            organization_id=org_id,
        )

        result = self.testapp.get(
            '/api/surveys/{}/participation'.format(pds[0].survey_id),
            headers=jwt_headers(user),
        )
        expected = [
            {
                "survey_ordinal": 1,
                "value": "1",
                "n": 1
            },
            {
                "survey_ordinal": 1,
                "value": "100",
                "n": 1
            },
        ]
        self.assertEqual(json.loads(result.body), expected)
Exemplo n.º 10
0
    def test_update_with_conflicts(self):
        other, teammate, team, cycles, responses = self.create()

        # Value is changed and timestamp is old
        response_id = responses['team_team'].uid
        self.testapp.put_json(
            '/api/responses/{}'.format(response_id),
            {
                'body': {
                    # based on stale data
                    'question': {
                        'value': 'bar',
                        'modified': '2000-01-01T00:00:00Z',
                    },
                    # this should be ignored b/c of above
                    'question_new': {
                        'value': 'foo',
                        'modified': '2000-01-01T00:00:00Z',
                    },
                },
            },
            headers=jwt_headers(teammate),
            status=409,
        )
        fetched = Response.get_by_id(response_id)

        # Whole update is rejected, body unchanged.
        self.assertEqual(responses['team_team'].body, fetched.body)
Exemplo n.º 11
0
    def test_batch_rollback(self):
        (other, teammate, contact, captain, team, classroom,
         ppnt) = self.create()

        class1ppt1 = {
            'first_name': u'Je\u017cu',
            'last_name': u'Kl\u0105tw',
            'classroom_id': classroom.uid,
            'student_id': 'duplicateId',
        }
        class1ppt2 = {
            'first_name': u'Ppt',
            'last_name': u'One-Two',
            'classroom_id': classroom.uid,
            'student_id': 'duplicateId',
        }

        def postBody(ppt):
            return {'method': 'POST', 'path': '/api/participants', 'body': ppt}

        # Posting a duplicate should roll back the whole change.
        self.testapp.patch_json(
            '/api/participants',
            [postBody(class1ppt1), postBody(class1ppt2)],
            headers=jwt_headers(captain),
            status=400,
        )
        self.assertEqual(len(Participant.get()), 0)
Exemplo n.º 12
0
    def test_update_simple(self):
        """Check ownership-based update permission, no conflicts."""
        other, teammate, team, cycles, responses = self.create()

        new_body = self.default_body()
        new_body['question']['value'] = 'change'

        # Forbidden to update other people's responses.
        self.testapp.put_json(
            '/api/responses/{}'.format(responses['user_team_other'].uid),
            {'body': new_body},
            headers=jwt_headers(teammate),
            status=403,
        )

        # Successful to update your own.
        self.testapp.put_json(
            '/api/responses/{}'.format(responses['user_team_user1'].uid),
            {'body': new_body},
            headers=jwt_headers(teammate),
        )
        self.assertTrue(
            self.body_values_match(
                Response.get_by_id(responses['user_team_user1'].uid).body,
                new_body,
            ))

        # Forbidden to update other teams.
        self.testapp.put_json(
            '/api/responses/{}'.format(responses['team_other'].uid),
            {'body': new_body},
            headers=jwt_headers(teammate),
            status=403,
        )

        # Successful to update team-level.
        self.testapp.put_json(
            '/api/responses/{}'.format(responses['team_team'].uid),
            {'body': new_body},
            headers=jwt_headers(teammate),
        )
        self.assertTrue(
            self.body_values_match(
                Response.get_by_id(responses['team_team'].uid).body,
                new_body,
            ))
Exemplo n.º 13
0
    def test_get_for_team(self):
        """You can list responses for a team you own."""
        other, teammate, team, cycles, responses = self.create()

        # Forbidden for non-members.
        response = self.testapp.get('/api/teams/{}/responses'.format(team.uid),
                                    headers=jwt_headers(other),
                                    status=403)

        # Successful for members.
        response = self.testapp.get(
            '/api/teams/{}/responses'.format(team.uid),
            headers=jwt_headers(teammate),
        )
        response_list = json.loads(response.body)

        def get_by_type(typ, response_list):
            return next(rd for rd in response_list
                        if rd['uid'] == responses[typ].uid)

        # Responses from yourself or your team should have bodies.
        for typ in ('user_team_user1', 'user_team_user2', 'team_team'):
            self.assertEqual(
                get_by_type(typ, response_list)['body'],
                responses[typ].body,
            )

        # Responses from other users should be present but have empty bodies.
        self.assertEqual(
            get_by_type('user_team_other', response_list)['body'],
            {},
        )

        # Any responses from other teams should not be returned.
        self.assertEqual(len(response_list), 4)

        # Can filter by cycle.
        cycle_id = cycles[0].uid
        response = self.testapp.get(
            '/api/teams/{}/responses?parent_id={}'.format(team.uid, cycle_id),
            headers=jwt_headers(teammate),
        )
        response_list = json.loads(response.body)
        self.assertEqual(len(response_list), 2)
        self.assertEqual(set(r['parent_id'] for r in response_list),
                         {cycle_id})
Exemplo n.º 14
0
 def test_get(self):
     other, teammate, captain, team, cycles = self.create()
     current = cycles[-1]
     response = self.testapp.get(
         '/api/cycles/{}'.format(current.uid),
         headers=jwt_headers(teammate),
     )
     self.assertEqual(current.uid, json.loads(response.body)['uid'])
Exemplo n.º 15
0
    def test_delete_not_supported(self):
        other, teammate, contact, captain, team, classroom, ppnt = self.create(
        )

        # Not supported.
        for user in (other, teammate, contact, captain):
            self.testapp.delete(
                '/api/participants/{}'.format(ppnt.uid),
                headers=jwt_headers(user),
                status=405,
            )
    def query_pc_participation(self, user, project_cohort):
        """Populates memcache w/ participation (even if blank) for this pc."""

        start = datetime.datetime.now() - datetime.timedelta(days=1)
        end = datetime.datetime.now() + datetime.timedelta(days=1)
        url = '/api/project_cohorts/{}/participation?start={}&end={}'.format(
            project_cohort.uid,
            start.strftime(config.iso_datetime_format),
            end.strftime(config.iso_datetime_format),
        )

        self.testapp.get(url, headers=jwt_headers(user))
Exemplo n.º 17
0
    def test_batch_participation(self):
        user = User.create(email='*****@*****.**')
        user.put()

        pc_kwargs = {
            'program_label': self.program_label,
            'cohort_label': self.cohort_label,
        }
        pcs = [
            ProjectCohort.create(**pc_kwargs),
            ProjectCohort.create(**pc_kwargs),
        ]
        ndb.put_multi(pcs)

        all_pds = []
        for pc in pcs:
            pds = mock_one_finished_one_unfinished(
                1,
                'Participant_unfinished',
                'Participant_finished',
                pc_id=pc.uid,
                code=pc.code,
                program_label=self.program_label,
                cohort_label=self.cohort_label,
            )
            all_pds += pds

        # Forbidden without allowed endpoints.
        pc_ids = [pc.uid for pc in pcs]
        self.testapp.get(
            '/api/project_cohorts/participation?uid={}&uid={}'.format(*pc_ids),
            headers=jwt_headers(user),
            status=403)

        # Running various queries works as expected.
        self.batch_participation(user, pcs)

        # Simulate a new pd being written to the first pc by clearing that
        # memcache key. The server should fall back to sql and still give the
        # same results.
        id_key = ParticipantData.participation_by_pc_cache_key(pcs[0].uid)
        code_key = ParticipantData.participation_by_pc_cache_key(pcs[0].code)
        self.assertIsNotNone(memcache.get(id_key))
        self.assertIsNotNone(memcache.get(code_key))
        memcache.delete(id_key)
        memcache.delete(code_key)
        self.batch_participation(user, pcs)

        # Now with everything cached, clearing the db and running the same
        # queries again should have the same result.
        ParticipantData.delete_multi(all_pds)
        self.batch_participation(user, pcs)
Exemplo n.º 18
0
    def test_get(self):
        other, teammate, team, cycles, responses = self.create()

        # Forbidden to see all responses.
        response = self.testapp.get(
            '/api/responses',
            headers=jwt_headers(other),
            status=403,
        )

        # Forbidden to see other user's responses.
        response = self.testapp.get(
            '/api/responses/{}'.format(responses['user_team_other'].uid),
            headers=jwt_headers(other),
            status=403,
        )

        # Forbidden to see other team's responses.
        response = self.testapp.get(
            '/api/responses/{}'.format(responses['team_other'].uid),
            headers=jwt_headers(other),
            status=403,
        )

        # Success for own resposnes.
        user_resp = self.testapp.get(
            '/api/responses/{}'.format(responses['user_team_user1'].uid),
            headers=jwt_headers(teammate),
        )
        self.assertEqual(responses['user_team_user1'].uid,
                         json.loads(user_resp.body)['uid'])

        # Success for team resposnes.
        team_resp = self.testapp.get(
            '/api/responses/{}'.format(responses['team_team'].uid),
            headers=jwt_headers(teammate),
        )
        self.assertEqual(responses['team_team'].uid,
                         json.loads(team_resp.body)['uid'])
Exemplo n.º 19
0
    def test_patch_with_disassociated_participant(self):
        """If a participant exists with no classrooms, they are found."""
        other, teammate, contact, captain, team, classroom, _ = self.create()

        student_id = 'disassociated'

        # Add an participant who is disassociated from all classrooms.
        ppt = Participant.create(
            team_id=team.uid,
            classroom_ids=[],
            student_id=student_id,
        )
        ppt.put()

        def postBody(ppt, id_modifier=''):
            ppt = ppt.copy()
            ppt['student_id'] += id_modifier
            return {'method': 'POST', 'path': '/api/participants', 'body': ppt}

        response = self.testapp.patch_json(
            '/api/participants',
            [{
                'method': 'POST',
                'path': '/api/participants',
                'body': {
                    'team_id': team.uid,
                    'classroom_id': classroom.uid,
                    'student_id': student_id,
                },
            }],
            headers=jwt_headers(contact),
        )
        response_list = json.loads(response.body)

        # The provided student id matched the disassociated user and the
        # db used that uid.
        self.assertEqual(len(response_list), 1)
        self.assertEqual(response_list[0]['uid'], ppt.uid)
        self.assertEqual(
            Participant.get_by_id(ppt.uid).classroom_ids,
            [classroom.uid],
        )

        # `num_students` has incremented after adding new participant to
        # classroom.
        updated_classroom = Classroom.get_by_id(classroom.uid)
        self.assertEqual(
            updated_classroom.num_students,
            classroom.num_students + 1,
        )
Exemplo n.º 20
0
    def test_update(self):
        other, teammate, contact, captain, team, classroom, ppnt = self.create(
        )

        # Can't update for other classrooms.
        for user in (other, teammate):
            self.testapp.put_json(
                '/api/participants/{}'.format(ppnt.uid),
                {'student_id': 'Dave'},
                headers=jwt_headers(user),
                status=403,
            )

        # Success for contacts and captains.
        for user in (contact, captain):
            new_first = 'Dave-new'
            response = self.testapp.put_json(
                '/api/participants/{}'.format(ppnt.uid),
                {'student_id': new_first},
                headers=jwt_headers(user),
            )
            fetched = Participant.get_by_id(json.loads(response.body)['uid'])
            self.assertEqual(fetched.student_id, new_first)
Exemplo n.º 21
0
    def test_get(self):
        other, teammate, contact, captain, team, classroom, ppnt = self.create(
        )

        # Forbidden to see all participants.
        response = self.testapp.get(
            '/api/participants',
            headers=jwt_headers(other),
            status=403,
        )

        # Forbidden to see other-team participants.
        response = self.testapp.get(
            '/api/participants/{}'.format(ppnt.uid),
            headers=jwt_headers(other),
            status=403,
        )

        # Success for on-team participants.
        response = self.testapp.get(
            '/api/participants/{}'.format(ppnt.uid),
            headers=jwt_headers(teammate),
        )
        self.assertEqual(ppnt.uid, json.loads(response.body)['uid'])
Exemplo n.º 22
0
    def test_batch_participation_subqueries(self):
        """Shouldn't fail if requested >30 pcs.

        See https://cloud.google.com/appengine/docs/standard/python/datastore/queries#Python_Property_filters
        """
        user = User.create(email='*****@*****.**')
        user.put()

        url = '/api/project_cohorts/participation?{}'.format('&'.join(
            r'uid=cool%20cat{}'.format(x) for x in range(31)))

        self.testapp.get(
            url,
            headers=jwt_headers(user),
            status=404,  # breaking subqueries would respond with a 500
        )
Exemplo n.º 23
0
    def test_get_for_team_super(self):
        """Super admins should be able to see full responses for anyone."""
        other, teammate, team, cycles, responses = self.create()

        admin = User.create(email='*****@*****.**',
                            name="Super",
                            user_type='super_admin')
        admin.put()
        response = self.testapp.get(
            '/api/teams/{}/responses'.format(team.uid),
            headers=jwt_headers(admin),
        )
        response_list = json.loads(response.body)

        for r in response_list:
            self.assertGreater(len(r['body']), 0)
Exemplo n.º 24
0
    def test_update_privacy_ignored(self):
        other, teammate, team, cycles, responses = self.create()

        # Starts private.
        to_update = responses['user_team_user1']
        self.assertTrue(to_update.private)

        # Try to make it non-private.
        self.testapp.put_json(
            '/api/responses/{}'.format(to_update.uid),
            dict(to_update.to_client_dict(), private=False),
            headers=jwt_headers(teammate),
        )

        # Privacy unchanged.
        fetched = Response.get_by_id(to_update.uid)
        self.assertEqual(to_update.private, fetched.private)
Exemplo n.º 25
0
    def test_invalid_timestamp(self):
        """Timestamp is somehow _newer_ than the db. Indicates bigger error."""
        other, teammate, team, cycles, responses = self.create()

        # Value is changed and timestamp is old
        response_id = responses['team_team'].uid
        self.testapp.put_json(
            '/api/responses/{}'.format(response_id),
            {
                'body': {
                    'question': {
                        'value': 'bar',
                        'modified': '2020-01-01T00:00:00Z',
                    },
                },
            },
            headers=jwt_headers(teammate),
            status=500,
        )
Exemplo n.º 26
0
    def test_update_remove_from_all(self):
        other, teammate, contact, captain, team, classroom, ppnt = self.create(
        )

        # Updating to have no classrooms DOES NOT delete the participant and
        # updates classroom counts. We keep participants even if they're not on
        # any classrooms so that if they're re-added their uid (which must be
        # synced with Neptune) remains the same.
        self.testapp.put_json(
            '/api/participants/{}'.format(ppnt.uid),
            {'classroom_ids': []},
            headers=jwt_headers(captain),
        )
        fetched_ppnt = Participant.get_by_id(ppnt.uid)
        self.assertIsNotNone(fetched_ppnt)
        self.assertEqual(fetched_ppnt.classroom_ids, [])

        fetched_classroom = Classroom.get_by_id(classroom.uid)
        self.assertEqual(fetched_classroom.num_students,
                         classroom.num_students - 1)
Exemplo n.º 27
0
    def test_create_insert(self):
        """Server reorders team cycles and returns them in an envelope."""
        other, teammate, captain, team, cycles = self.create()

        # Move the last cycle ahead one month so we have room to insert.
        last = cycles[-1]
        orig_start_date = last.start_date
        orig_end_date = last.end_date
        last.start_date = orig_start_date + datetime.timedelta(weeks=5)
        last.end_date = orig_end_date + datetime.timedelta(weeks=5)
        last.put()

        # Now insert a penultimate cycle.
        response = self.testapp.post_json(
            '/api/cycles?envelope=team_cycles',
            {
                'team_id': team.uid,
                'ordinal': last.ordinal + 1,
                'start_date': orig_start_date.strftime(config.iso_date_format),
                'end_date': orig_end_date.strftime(config.iso_date_format),
            },
            headers=jwt_headers(captain),
        )
        response_dict = json.loads(response.body)

        # New cycle is in the 'data' property.
        self.assertIsNotNone(Cycle.get_by_id(response_dict['data']['uid']))

        # Other metadata is present in the envelope.
        self.assertEqual(response_dict['status'], 200)
        # Specifically the list of other cycles for this team.
        team_cycles = response_dict['team_cycles']
        self.assertEqual(len(team_cycles), 3)

        # The one we created should be second-to-last.
        self.assertEqual(team_cycles[-2]['uid'], response_dict['data']['uid'])
        # All the ordinals should be updated and sorted.
        self.assertEqual(
            [c['ordinal'] for c in team_cycles],
            [1, 2, 3]
        )
    def test_invite_triton_exists(self):
        inviter = User.create(email='*****@*****.**')
        inviter.put()
        invitee = User.create(email='*****@*****.**', hashed_password='******')
        invitee.put()

        response = self.testapp.post_json(
            '/api/invitations',
            {
                'email': invitee.email,
                'platform': 'triton',
                'template_content': {
                    'foo': 'bar'
                },
                'domain': 'https://copilot.perts.net',
                'from_address': '*****@*****.**',
                'from_name': 'Copilot',
                'reply_to': '*****@*****.**',
            },
            headers=jwt_headers(inviter),
        )
        response_user = json.loads(response.body)
        self.assertRegexpMatches(response_user['uid'], r'^User_')

        # One email queued.
        emails = Email.get()
        self.assertEqual(len(emails), 1)
        email = emails[0]

        # To the right person.
        email.to = invitee.email

        # With the right template.
        self.assertEqual(email.mandrill_template, 'triton-invite-exists')

        # And right template params.
        self.assertEqual(type(email.mandrill_template_content['foo']), unicode)
        self.assertGreater(len(email.mandrill_template_content['foo']), 0)

        self.assertIn('/login', email.mandrill_template_content['link'])
Exemplo n.º 29
0
    def test_update_remove_from_multiple_rosters(self):
        """When ppt is updated to have one fewer classroom id."""
        other, teammate, contact, captain, team, classroom, _ = self.create()

        # Make a second classroom to associate with.
        classroom2 = Classroom.create(
            name="Second Classroom",
            team_id=team.uid,
            contact_id='User_contact',
            code="bar",
        )

        # Start with a ppt on two classrooms.
        ppnt = Participant.create(
            team_id=team.uid,
            classroom_ids=[classroom.uid, classroom2.uid],
            student_id='toremove',
        )
        ppnt.put()

        # Make sure count of students starts out correct.
        classroom2.num_students = 1
        classroom2.put()

        # Remove them from just one of their classrooms.
        response = self.testapp.put_json(
            '/api/participants/{}'.format(ppnt.uid),
            {'classroom_ids': [classroom.uid]},  # classroom2 removed
            headers=jwt_headers(contact),
        )

        # Check they're still on the other classroom.
        fetched = Participant.get_by_id(ppnt.uid)
        self.assertEqual(fetched.classroom_ids, [classroom.uid])

        # Check that classroom size is updated.
        fetched_classroom2 = Classroom.get_by_id(classroom2.uid)
        self.assertEqual(fetched_classroom2.num_students,
                         classroom2.num_students - 1)
Exemplo n.º 30
0
    def test_get_for_team_supervisor(self):
        """What organization supervisors can see...

        * Full responses for team-level
        * No body for user-level
        """
        other, teammate, team, cycles, responses = self.create()

        supervisor = User.create(email='*****@*****.**',
                                 name="Supervisor",
                                 owned_organizations=team.organization_ids)
        supervisor.put()

        response = self.testapp.get(
            '/api/teams/{}/responses'.format(team.uid),
            headers=jwt_headers(supervisor),
        )
        response_list = json.loads(response.body)

        for r in response_list:
            if r['type'] == Response.TEAM_LEVEL_SYMBOL:
                self.assertGreater(len(r['body']), 0)
            if r['type'] == Response.USER_LEVEL_SYMBOL:
                self.assertEqual(len(r['body']), 0)