def mock_participants(self): unfinished_id = Participant.convert_uid(self.unfinished_id) finished_id = Participant.convert_uid(self.finished_id) participants = [ Participant.create(id=unfinished_id, name='unfinished', organization_id='Org_foo'), Participant.create(id=finished_id, name='finished', organization_id='Org_foo'), ] Participant.put_multi(participants) return participants
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)
def test_status_code_not_found_returned_when_student_id(self): """404 Not Found is returned when class exists but student_id doesn't.""" code = 'forest temple' student_id = 'zelda' bad_student_id = 'NOTzelda' team = Team.create( name="Foo Team", captain_id="User_cap", program_id=self.program.uid, ) team.put() classroom = Classroom.create( code=code, name='Adventuring 101', contact_id='User_LINK', team_id=team.uid, ) classroom.put() participant = Participant.create( student_id=student_id, team_id=team.uid, classroom_ids=[classroom.uid], ) participant.put() self.testapp.get( '/api/codes/{}/participants/{}'.format(code, bad_student_id), status=404, )
def create_pd_context(self): program_label = 'demo-program' program_config = Program.get_config(program_label) template = program_config['surveys'][0]['survey_tasklist_template'] project_cohort = ProjectCohort.create( program_label=program_label, organization_id='Organization_foo', project_id='Project_foo', cohort_label='2018', ) project_cohort.put() survey = Survey.create( template, program_label=program_label, organization_id='Organization_foo', project_cohort_id=project_cohort.uid, ordinal=1, ) survey.put() participant = Participant.create(name='Pascal', organization_id='PERTS') participant.put() return (project_cohort, survey, participant)
def test_get_participant_by_id(self): p = Participant.create( name= 'f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7', organization_id='Organization_12345678', ) p.put() fetched_p = Participant.get_by_id(p.uid) # Test that hashes up to 128 characters will fit. self.assertEqual(fetched_p.name, p.name)
def create(self): team_id = 'Team_001' p1 = Participant.create( student_id='4321', team_id=team_id, classroom_ids=['Classroom_001'], ) p2 = Participant.create( student_id='4322', team_id=team_id, classroom_ids=['Classroom_001', 'Classroom_002'], ) p3 = Participant.create( student_id='4323', team_id=team_id, classroom_ids=['Classroom_003'], ) Participant.put_multi([p1, p2, p3]) return p1, p2, p3
def test_completion_ids_exclude_testing(self): """Don't count testing pd as that participant being done.""" pid = self.test_create_portal_pd(testing=True) participant = Participant.create( id=SqlModel.convert_uid(pid), name='Pascal', organization_id='Organization_PERTS', ) participant.put() results = ParticipantData.completion_ids( project_cohort_id='ProjectCohort_12345678') self.assertEqual(results, [])
def test_delete_disassociates_participants(self): captain, contact, classroom1, report1, report2 = \ self.create_for_delete() # Create another classroom, so we check that participants remain on it # afterward. classroom2 = Classroom.create( name='Classroom Bar', code='steel snake', team_id=classroom1.team_id, contact_id=contact.uid, num_students=22, ) classroom2.put() ppt_on_one = Participant.create( student_id='on_one', team_id=classroom1.team_id, classroom_ids=[classroom1.uid], ) ppt_on_two = Participant.create( student_id='on_two', team_id=classroom1.team_id, classroom_ids=[classroom1.uid, classroom2.uid], ) Participant.put_multi([ppt_on_one, ppt_on_two]) url = '/api/classrooms/{}'.format(classroom1.uid) headers = self.login_headers(captain) # Delete the classroom. self.testapp.delete(url, headers=headers, status=204) # Both participants are still there, but neither is associated with # the deleted classroom. self.assertEqual( Participant.get_by_id(ppt_on_one.uid).classroom_ids, []) self.assertEqual( Participant.get_by_id(ppt_on_two.uid).classroom_ids, [classroom2.uid])
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, )
def create(self): team = Team.create(name='foo', program_id=self.program.uid) classroom = Classroom.create( name="CompSci 101", team_id=team.uid, code="foo", ) teammate = User.create(name='teammate', email='*****@*****.**', owned_teams=[team.uid]) contact = User.create(name='contact', email='*****@*****.**', owned_teams=[team.uid]) captain = User.create(name='captain', email='*****@*****.**', owned_teams=[team.uid]) other = User.create(name='other', email='*****@*****.**') team.captain_id = captain.uid classroom.contact_id = contact.uid # O hedgehog of curses, generate for the Finns a part of the game of # ignominies! # http://clagnut.com/blog/2380/ participant = Participant.create( first_name=u'Je\u017cu', last_name=u'Kl\u0105tw', team_id=team.uid, classroom_ids=[classroom.uid], student_id=u'Kl\[email protected]', ) participant.put() User.put_multi((other, teammate, contact, captain)) team.put() classroom.num_students = 1 classroom.put() return (other, teammate, contact, captain, team, classroom, participant)
def test_status_code_found_returned(self): """200 OK returned when student_id is found in classroom roster.""" code = 'forest temple' student_id = 'Zelda 77!' team = Team.create( name="Foo Team", captain_id="User_cap", program_id=self.program.uid, ) team.put() classroom = Classroom.create( code=code, name='Adventuring 101', contact_id='User_LINK', team_id=team.uid, ) classroom.put() participant = Participant.create( student_id=student_id, team_id=team.uid, classroom_ids=[classroom.uid], ) participant.put() # Exact match. self.testapp.get( '/api/codes/{}/participants/{}'.format(code, student_id), status=200, ) # Stripped. self.testapp.get( '/api/codes/{}/participants/{}'.format( code, Participant.strip_token(student_id)), status=200, )
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)
def test_completion_ids(self): pid = self.test_create_portal_pd() participant = Participant.create( id=SqlModel.convert_uid(pid), name='Pascal', organization_id='Organization_PERTS', ) participant.put() results = ParticipantData.completion_ids( project_cohort_id='ProjectCohort_12345678') expected = [ { 'module': 1, 'percent_progress': '100', 'token': 'Pascal' }, { 'module': 2, 'percent_progress': '33', 'token': 'Pascal' }, ] self.assertEqual(results, expected)
def test_check_roster_cycle_data(self): team = Team.create(name='foo', captain_id="User_cap", program_id=self.program.uid) classroom = Classroom.create( name="CompSci 101", team_id=team.uid, contact_id="User_contact", code="foo bar", num_students=1, ) ppt = Participant.create(team_id=team.uid, classroom_ids=[classroom.uid], student_id='STUDENTID001') today = datetime.date.today() cycle1 = Cycle.create( team_id=team.uid, ordinal=1, # schedule to not be current (starts and ends in the past) start_date=today - datetime.timedelta(days=3), end_date=today - datetime.timedelta(days=2), ) cycle1.put() team.put() classroom.put() ppt.put() # Without a current cycle, no cycle data response = self.testapp.get( '/api/codes/{}/participants/{}'.format(classroom.url_code, ppt.student_id), status=200, ) self.assertEqual( json.loads(response.body), { 'uid': ppt.uid, 'team_id': ppt.team_id }, ) # Add a new cycle that is current. cycle2 = Cycle.create( team_id=team.uid, ordinal=2, # schedule to not be current (starts and ends in the past) start_date=today - datetime.timedelta(days=1), end_date=today + datetime.timedelta(days=1), ) cycle2.put() # Cycle data present. response = self.testapp.get( '/api/codes/{}/participants/{}'.format(classroom.url_code, ppt.student_id), status=200, ) expected = { 'uid': ppt.uid, 'team_id': ppt.team_id, 'cycle': { 'uid': cycle2.uid, 'team_id': cycle2.team_id, 'ordinal': cycle2.ordinal, 'start_date': util.datelike_to_iso_string(cycle2.start_date), 'end_date': util.datelike_to_iso_string(cycle2.end_date), } } self.assertEqual(json.loads(response.body), expected)
def test_check_roster(self): # Other apps (neptune) should be able to check the existence of # participants by name, and it should work on stripped versions. other, teammate, contact, captain, team, classroom, ppnt = self.create( ) ppnt.student_id = u'ABC-123-def' ppnt.stripped_student_id = 'abc123def' ppnt.put() url_code = classroom.code.replace(' ', '-') # Unstripped name found. self.testapp.get( '/api/codes/{}/participants/{}'.format(url_code, ppnt.student_id), status=200, ) # Stripped name (expected neptune behavior) found. self.testapp.get( '/api/codes/{}/participants/{}'.format(url_code, ppnt.stripped_student_id), status=200, ) # Unknown name not found. self.testapp.get( '/api/codes/{}/participants/{}'.format(url_code, 'dne'), status=404, ) # Known name, unknown classroom code => not found. self.testapp.get( '/api/codes/{}/participants/{}'.format('bad-code', ppnt.stripped_student_id), status=404, ) # Known name and code, but student not on that classroom => not found. other_class = Classroom.create( name="Other Class", team_id=team.uid, contact_id='User_contact', code="bar", ) other_class.put() self.testapp.get( '/api/codes/{}/participants/{}'.format('bar', ppnt.stripped_student_id), status=404, ) # Known name, but not on any classrooms => not found. disassociated = Participant.create( team_id=team.uid, classroom_ids=[], student_id='disassociated', ) disassociated.put() self.testapp.get( '/api/codes/{}/participants/{}'.format( url_code, disassociated.stripped_student_id), status=404, )
def create_participant(self): p = Participant.create(name='Rene', organization_id='Org_Eruditorum') p.put() return p