def test_rserve_ru_override(self): """Can specify reporting unit ids to limit RServe request.""" team = Team.create(name='Team Foo', captain_id='User_captain', program_id=self.ep_program.uid) classroom1 = Classroom.create(name='Classroom One', team_id=team.uid, contact_id='User_contact', code='foo 1') classroom2 = Classroom.create(name='Classroom Two', team_id=team.uid, contact_id='User_contact', code='foo 2') classroom3 = Classroom.create(name='Classroom Three', team_id=team.uid, contact_id='User_contact', code='foo 3') team.put() Classroom.put_multi((classroom1, classroom2, classroom3)) response = self.testapp.get( '/cron/rserve/reports/ep?ru={}&ru={}&really_send=false'.format( classroom1.uid, classroom2.uid)) payload = json.loads(response.body)['payload'] # Only specified ids are present (class 1 and 2). self.assertEqual( set(ru['id'] for ru in payload['reporting_units']), {classroom1.uid, classroom2.uid}, )
def test_delete_issues_allowed_endpoints_jwt(self): """DELETE response has special jwt giving permission on Neptune.""" user, team_dict = self.create() # Add some classrooms. c1 = Classroom.create( name='C1', team_id=team_dict['uid'], contact_id='User_contact', code='a a', ) c2 = Classroom.create( name='C2', team_id=team_dict['uid'], contact_id='User_contact', code='b b', ) Classroom.put_multi([c1, c2]) response = self.testapp.delete( '/api/teams/{}'.format(team_dict['uid']), headers=self.login_headers(user), ) jwt = response.headers['Authorization'][7:] # drop "Bearer " payload, error = jwt_helper.decode(jwt) # Should include an endpoint for each classroom. self.assertEqual( set(payload['allowed_endpoints']), { 'DELETE //neptune/api/codes/a-a', 'DELETE //neptune/api/codes/b-b', }, )
def resolve_id_mismatch(klass, user, new_id): """Change all references to user's id to a new id. N.B. this is obviously brittle; when the relationship schema changes, this will also have to change. """ # The auth server has a different id for this user; defer to it. teams = Team.get(captain_id=user.uid) for t in teams: t.captain_id = new_id Team.put_multi(teams) classrooms = Classroom.get(contact_id=user.uid) for c in classrooms: c.contact_id = new_id Classroom.put_multi(classrooms) params = {'uid': new_id, 'short_uid': SqlModel.convert_uid(new_id)} with mysql_connection.connect() as sql: sql.update_row(klass.table, 'uid', user.uid, **params) for k, v in params.items(): setattr(user, k, v) return user
def test_rserve_skips_existing(self): program = Program.create( name="The Engagement Project", label="ep19", preview_url='foo.com', ) week = util.datelike_to_iso_string(datetime.date.today()) org = Organization.create(name="Organization", captain_id="User_cap", program_id=program.uid) org_to_skip = Organization.create(name="Organization", captain_id="User_cap", program_id=program.uid) Organization.put_multi([org, org_to_skip]) team = Team.create(name="Team", captain_id="User_cap", program_id=program.uid) team_to_skip = Team.create(name="Team", captain_id="User_cap", program_id=program.uid) Team.put_multi([team, team_to_skip]) cl = Classroom.create(name="Classroom", team_id=team.uid, code="foo", contact_id="User_contact") cl_to_skip = Classroom.create(name="Classroom", team_id=team.uid, code="foo", contact_id="User_contact") Classroom.put_multi([cl, cl_to_skip]) Report.put_multi([ Report.create(parent_id=org_to_skip.uid, filename="foo", issue_date=week), Report.create(parent_id=team_to_skip.uid, filename="foo", issue_date=week), Report.create(parent_id=cl_to_skip.uid, filename="foo", issue_date=week), ]) # Skips all the parents who have reports already this week. orgs, teams, classes = cron_rserve.get_report_parents( program, week, False) self.assertEqual(len(orgs), 1) self.assertEqual(len(teams), 1) self.assertEqual(len(classes), 1) # ...unless you force it, then they're all there. orgs, teams, classes = cron_rserve.get_report_parents( program, week, True) self.assertEqual(len(orgs), 2) self.assertEqual(len(teams), 2) self.assertEqual(len(classes), 2)
def test_rserve_payload(self): org = Organization.create(name='Org', program_id=self.ep_program.uid) team = Team.create(name='Team Foo', captain_id='User_captain', program_id=self.ep_program.uid) classroom = Classroom.create(name='Classroom Bar', team_id=team.uid, contact_id='User_contact') # Orphaned classrooms shouldn't appear in the payload. other_classroom = Classroom.create(name='Classroom Other', team_id='Team_other', contact_id='User_other') payload = cron_rserve.build_payload( [org], [team], [classroom, other_classroom], { 'neptune_sql_credentials': 'fake secret 1', 'triton_sql_credentials': 'fake secret 2', 'saturn_sql_credentials': 'fake secret 3', 'qualtrics_credentials': 'fake secret 4', 'mandrill_api_key': 'fake secret 5', 'rserve_service_account_credentials': 'fake secret 6', }, ) self.assertIn('neptune_sql_credentials', payload) self.assertIn('triton_sql_credentials', payload) self.assertIn('saturn_sql_credentials', payload) self.assertIn('qualtrics_credentials', payload) self.assertIn('mandrill_api_key', payload) self.assertIn('rserve_service_account_credentials', payload) team_found = False classroom_found = False other_classroom_found = False for ru in payload['reporting_units']: if ru['id'] == org.uid and ru['organization_id'] == org.uid: org_found = True if ru['id'] == team.uid and ru['team_id'] == team.uid: team_found = True if (ru['id'] == classroom.uid and ru['classroom_id'] == classroom.uid and ru['team_id'] == team.uid): classroom_found = True if ru['id'] == other_classroom.uid: other_classroom_found = True self.assertEqual(org_found, True) self.assertEqual(team_found, True) self.assertEqual(classroom_found, True) self.assertEqual(other_classroom_found, False)
def create(self, program_label): program = Program.create( name="Foo", label=program_label, active=True, preview_url='foo.com', ) program.put() captain = User.create(email='*****@*****.**', name="Captain PERTS") team = Team.create(name='Team Foo', program_id=program.uid, captain_id=captain.uid) team.put() classrooms = [ Classroom.create(name='Class A', team_id=team.uid, num_students=5, contact_id='User_contact', code='foo'), Classroom.create(name='Class B', team_id=team.uid, num_students=5, contact_id='User_contact', code='bar'), Classroom.create(name='Class C', team_id=team.uid, num_students=5, contact_id='User_contact', code='baz'), ] Classroom.put_multi(classrooms) survey = Survey.create(team_id=team.uid) survey.put() captain.owned_teams = [team.uid] captain.put() start_date = datetime.date.today() - datetime.timedelta(days=7) end_date = datetime.date.today() + datetime.timedelta(days=7) cycle = Cycle.create(team_id=team.uid, ordinal=1, start_date=start_date, end_date=end_date) cycle.put() return (program, captain, team, classrooms, cycle)
def test_resolve_mismatch(self): team, classroom, captain, contact = self.create() old_captain_id = captain.uid old_contact_id = contact.uid new_captain_id = 'User_newcaptain' new_contact_id = 'User_newcontact' captain = User.resolve_id_mismatch(captain, new_captain_id) contact = User.resolve_id_mismatch(contact, new_contact_id) self.assertEqual(captain.uid, new_captain_id) self.assertEqual(contact.uid, new_contact_id) fetched_captain = User.get_by_id(new_captain_id) fetched_contact = User.get_by_id(new_contact_id) self.assertIsNotNone(fetched_captain) self.assertIsNotNone(fetched_contact) fetched_team = Team.get_by_id(team.uid) self.assertEqual(fetched_team.captain_id, new_captain_id) fetched_classroom = Classroom.get_by_id(classroom.uid) self.assertEqual(fetched_classroom.contact_id, new_contact_id)
def create(self): """Team owners can create classrooms with themselves as contact.""" captain = User.create(email='*****@*****.**') contact = User.create(email='*****@*****.**') # other = User.create(email='*****@*****.**') team = Team.create(name='Foo Team', captain_id=captain.uid, program_id=self.program.uid) team.put() classroom = Classroom.create(name='Foo Classroom', team_id=team.uid, code='trout viper', contact_id=contact.uid) classroom.put() captain.owned_teams = [team.uid] captain.put() contact.owned_teams = [team.uid] contact.put() # other.put() # return team, classroom, captain, contact, other return team, classroom, captain, contact
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 get_team_reports(self, team_id): user = self.get_current_user() team = Team.get_by_id(team_id) if not team: return self.http_not_found() if not owns(user, team) and not has_captain_permission(user, team): return self.http_forbidden("Only team members can list reports.") # Limit access to preview reports, super admin only. show_preview_reports = True if user.super_admin else False # Returns both team- and class-level reports. all_reports = Report.get_for_team(team.uid, show_preview_reports) # Any team member can see the team reports... allowed_reports = [r for r in all_reports if not r.classroom_id] # ...but limit access to classroom reports. classroom_reports = [r for r in all_reports if r.classroom_id] classroom_ids = [r.classroom_id for r in classroom_reports] classrooms = {c.uid: c for c in Classroom.get_by_id(classroom_ids)} for report in classroom_reports: if has_contact_permission(user, classrooms[report.classroom_id]): allowed_reports.append(report) # Add a custom link for users to access each report. self.write([ dict(r.to_client_dict(), link=self.report_link(r)) for r in allowed_reports ])
def get(self, program_id_or_label): user = self.get_current_user() if not user.super_admin: return self.http_forbidden() program = Program.get_by_id(program_id_or_label) if not program: program = Program.get_by_label(program_id_or_label) if not program: return self.http_not_found() search_str = self.get_param('q', unicode, None) if not search_str: return self.write([]) if search_str.startswith('user:'******'t have team r orgs = Organization.query_by_name(search_str, program.uid) teams = Team.query_by_name(search_str, program.uid) classrooms = Classroom.query_by_name(search_str, program.uid) users = User.query_by_name_or_email(search_str) self.write({ 'organizations': [e.to_client_dict() for e in orgs], 'teams': [e.to_client_dict() for e in teams], 'classrooms': [e.to_client_dict() for e in classrooms], 'users': [e.to_client_dict() for e in users], })
def test_create(self): """Team owners can create classrooms with themselves as contact.""" team = Team.create(name='Team Foo', captain_id='User_cap', program_id=self.program.uid) team.put() user = User.create(name='User Foo', email='*****@*****.**', owned_teams=[team.uid]) user.put() response = self.testapp.post_json( '/api/classrooms', { 'name': 'Classroom Foo', 'team_id': team.uid, 'code': 'a a', 'contact_id': user.uid }, headers=self.login_headers(user), ) # Make sure the response is right. response_dict = json.loads(response.body) classroom = Classroom.get_by_id(response_dict['uid']) self.assertEqual( response.body, json.dumps(classroom.to_client_dict(), default=util.json_dumps_default), ) # Make sure the contact is set. self.assertEqual(classroom.contact_id, user.uid) # Clear the user's cookie so we can use the app as other people. self.testapp.reset() return user, classroom
def set_up(self): # Let ConsistencyTestCase set up the datastore testing stub. super(TestApiParticipants, self).set_up() application = self.patch_webapp(webapp2.WSGIApplication)( api_routes, config={ 'webapp2_extras.sessions': { 'secret_key': self.cookie_key } }, debug=True) self.testapp = webtest.TestApp(application) with mysql_connection.connect() as sql: sql.reset({ 'classroom': Classroom.get_table_definition(), 'cycle': Cycle.get_table_definition(), 'participant': Participant.get_table_definition(), 'program': Program.get_table_definition(), 'team': Team.get_table_definition(), 'user': User.get_table_definition(), }) self.program = Program.create( name="Engagement Project", label='ep18', min_cycles=3, active=True, preview_url='foo.com', ) self.program.put()
def test_delete_forbidden(self): """Only team captains can delete classrooms.""" teammate = User.create(name='teammate', email='*****@*****.**') other = User.create(name='other', email='*****@*****.**') team = Team.create(name='Team Foo', captain_id='User_captain', program_id=self.program.uid) team.put() teammate.owned_teams = [team.uid] User.put_multi([teammate, other]) classroom = Classroom.create( name='Classroom Foo', code='trout viper', team_id=team.uid, contact_id='User_contact', num_students=22, grade_level='9-12', ) classroom.put() for user in (teammate, other): self.testapp.delete( '/api/classrooms/{}'.format(classroom.uid), headers=self.login_headers(user), status=403, )
def test_disallow_classroom_move(self): """Update the team_id of all class reports when class moves.""" user = User.create(name='foo', email='*****@*****.**') team1 = Team.create(name='Team Foo', captain_id=user.uid, program_id=self.program.uid) team1.put() team2 = Team.create(name='Team Bar', captain_id=user.uid, program_id=self.program.uid) team2.put() user.owned_teams = [team1.uid, team2.uid] user.put() classroom = Classroom.create( name='Classroom Foo', code='trout viper', team_id=team1.uid, contact_id=user.uid, num_students=22, grade_level='9-12', ) classroom.put() # move class to new team self.testapp.put_json( '/api/classrooms/{}'.format(classroom.uid), {'team_id': team2.uid}, headers=self.login_headers(user), status=403, )
def create(self): other = User.create(name='other', email='*****@*****.**') teammate = User.create(name='teammate', email='*****@*****.**') contact = User.create(name='contact', email='*****@*****.**') captain = User.create(name='captain', email='*****@*****.**') super_admin = User.create(name='super', email='*****@*****.**', user_type='super_admin') team = Team.create(name='Team foo', captain_id=captain.uid, program_id=self.program.uid) team.put() classroom = Classroom.create(name='Class foo', team_id=team.uid, code='trout viper', contact_id=contact.uid) classroom.put() teammate.owned_teams.append(team.uid) contact.owned_teams.append(team.uid) captain.owned_teams.append(team.uid) User.put_multi((other, teammate, contact, captain, super_admin)) return (other, teammate, contact, captain, super_admin, team, classroom)
def set_up(self): # Let ConsistencyTestCase set up the datastore testing stub. super(TestApiSurveys, self).set_up() application = webapp2.WSGIApplication(api_routes, config={ 'webapp2_extras.sessions': { 'secret_key': self.cookie_key } }, debug=True) self.testapp = webtest.TestApp(application) with mysql_connection.connect() as sql: sql.reset({ 'classroom': Classroom.get_table_definition(), 'metric': Metric.get_table_definition(), 'program': Program.get_table_definition(), 'survey': Survey.get_table_definition(), 'team': Team.get_table_definition(), 'user': User.get_table_definition(), }) self.ep_program = Program.create( name="Engagement Project", label='ep18', active=True, preview_url='foo.com', ) self.ep_program.put()
def post(self, team_id, date_str=None): if date_str: today = datetime.strptime(date_str, config.iso_date_format).date() else: today = date.today() # Guaranteed to have start and end dates. cycle = Cycle.get_current_for_team(team_id, today) if not cycle: logging.info( "Either the team doesn't exist, or they don't have a cycle " "matching the current date. Doing nothing.") return team = Team.get_by_id(team_id) classrooms = Classroom.get(team_id=team_id) if len(classrooms) == 0: logging.info("No classrooms, setting participation to 0.") cycle.students_completed = 0 else: ppn = get_participation(cycle, classrooms) num_complete = 0 for code, counts in ppn.items(): complete_count = next( (c for c in counts if c['value'] == '100'), None) num_complete += complete_count['n'] if complete_count else 0 cycle.students_completed = num_complete cycle.put()
def test_get_main_contacts(self): contact1 = User.create(email="*****@*****.**") contact2 = User.create(email="*****@*****.**") contact1.put() contact2.put() classroom1 = Classroom.create(name="Foo", team_id="foo", code='a a', contact_id=contact1.uid) classroom2 = Classroom.create(name="Bar", team_id="bar", code='b b', contact_id=contact2.uid) contacts = User.get_main_contacts([classroom1, classroom2]) self.assertEqual(set(contacts), {contact1, contact2})
def set_up(self): # Let ConsistencyTestCase set up the datastore testing stub. super(TestClassrooms, self).set_up() with mysql_connection.connect() as sql: sql.reset({ 'user': User.get_table_definition(), 'classroom': Classroom.get_table_definition(), })
def test_post_empty_report(self): """RServe posts "empty" reports to note why it hasn't produced a visible report. Test that the API accepts these for each kind of parent. """ rserve_user = User.create( id='rserve', email='*****@*****.**', user_type='super_admin', ) rserve_user.put() org = Organization.create(name='Organization', captain_id='User_cap', program_id=self.program.uid) org.put() team = Team.create( name='Team Foo', captain_id='User_cap', organization_ids=[org.uid], program_id=self.program.uid, ) team.put() classroom = Classroom.create(name='Class foo', team_id=team.uid, code='trout viper', contact_id='User_contact') classroom.put() url = '/api/reports' report_date = datetime.date.today().strftime('%Y-%m-%d') self.testapp.post_json( url, dict(self.empty_report_params(report_date, org.uid), organization_id=org.uid), headers=self.login_headers(rserve_user), ) self.testapp.post_json( url, dict(self.empty_report_params(report_date, team.uid), team_id=team.uid), headers=self.login_headers(rserve_user), ) self.testapp.post_json( url, dict(self.empty_report_params(report_date, classroom.uid), team_id=team.uid, classroom_id=classroom.uid), headers=self.login_headers(rserve_user), ) reports = Report.get() self.assertEqual(len(reports), 3) self.assertEqual(all(r.template == 'empty' for r in reports), True)
def create_for_search(self): # Test that users can be matched on either name or email. admin_foo = User.create(name="Admin Foo", email="*****@*****.**") user_foo1 = User.create(name="User Foo", email="*****@*****.**") user_foo2 = User.create(name="Generic Name", email="*****@*****.**") user_bar = User.create(name="User Bar", email="*****@*****.**") org_foo = Organization.create(name="Org Foo", program_id=self.ep.uid) org_bar = Organization.create(name="Org Bar", program_id=self.ep.uid) team_foo = Team.create(name="Team Foo", program_id=self.ep.uid, captain_id=user_foo1.uid) team_bar = Team.create(name="Team Bar", program_id=self.ep.uid, captain_id=user_bar.uid) cl_foo = Classroom.create( name="Class Foo", code="foo", team_id=team_foo.uid, contact_id=user_foo2.uid, ) cl_bar = Classroom.create( name="Class Bar", code="bar", team_id=team_bar.uid, contact_id="User_contact", ) # Test that users can be matched on either name or email. admin_foo.owned_organizations = [org_foo.uid] user_foo1.owned_teams = [team_foo.uid] user_foo2.owned_teams = [team_foo.uid] user_bar.owned_teams = [team_bar.uid] Organization.put_multi([org_foo, org_bar]) Team.put_multi([team_foo, team_bar]) Classroom.put_multi([cl_foo, cl_bar]) User.put_multi([admin_foo, user_foo1, user_foo2, user_bar]) return (org_foo, org_bar, team_foo, team_bar, cl_foo, cl_bar, admin_foo, user_foo1, user_foo2, user_bar)
def classroom_manager(): classrooms = list(map(lambda c: Classroom(c[0], c[1]), sorted_classrooms)) def get_minimum_essential_classroom(slot, capacity): nonlocal classrooms current_classrooms = list(map(lambda c: c.classroom.name, slot)) for classroom in classrooms: if classroom.capacity >= capacity and classroom.name not in current_classrooms: return classroom return None return get_minimum_essential_classroom
def get_membership(self, email, program_id): user = User.get_by_auth('email', email) orgs = Organization.query_by_user(user, program_id) teams = Team.query_by_user(user, program_id) classrooms = Classroom.query_by_contact(user, program_id) return { 'organizations': [e.to_client_dict() for e in orgs], 'teams': [e.to_client_dict() for e in teams], 'classrooms': [e.to_client_dict() for e in classrooms], 'users': [user.to_client_dict()], }
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 post(self, team_id, date_str=None): survey = Survey.get(team_id=team_id)[0] if date_str: today = datetime.strptime(date_str, config.iso_date_format).date() else: today = date.today() # Cycle ultimately comes from Cycle.get_current_for_team() and so is # guaranteed to have start and end dates. cycle = survey.should_notify(today) if not cycle: # This task is run every week, but only actually send notifications # if the date matches the survey interval. return team = Team.get_by_id(survey.team_id) program = Program.get_by_id(team.program_id) classrooms = Classroom.get(team_id=team_id) users = User.query_by_team(team_id) if len(classrooms) == 0: pct_complete_by_id = {} else: ppn = get_participation(cycle, classrooms) pct_complete_by_id = self.participation_to_pct(ppn, classrooms) # Get all the responses once to save trips to the db. Redact them later # according to the relevate user. unsafe_responses = Response.get_for_teams_unsafe([team_id], parent_id=cycle.uid) to_put = [] for user in users: if user.receive_email: safe_responses = Response.redact_private_responses( unsafe_responses, user) email = cycle_emailers.create_cycle_email( program.label, user, # recipient users, team, classrooms, safe_responses, cycle, pct_complete_by_id, ) to_put.append(email) ndb.put_multi(to_put)
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 test_client_dict_has_default_contact_name(self): # Should work whether the contact is saved to the db or not. cl = Classroom.create(name="Classroom", team_id="Team_foo", code="foo", contact_id="User_contact") # No matching user or unsaved class fails gracefully. before_dict = cl.to_client_dict() self.assertEqual(before_dict['contact_name'], '') cl.put() after_dict = cl.to_client_dict() self.assertEqual(after_dict['contact_name'], '')
def set_up(self): # Let ConsistencyTestCase set up the datastore testing stub. super(TestTasks, self).set_up() with mysql_connection.connect() as sql: sql.reset({ 'classroom': Classroom.get_table_definition(), 'cycle': Cycle.get_table_definition(), 'metric': Metric.get_table_definition(), 'program': Program.get_table_definition(), 'response': Response.get_table_definition(), 'survey': Survey.get_table_definition(), 'team': Team.get_table_definition(), 'user': User.get_table_definition(), })
def test_initial_contact_name(self): cl = Classroom.create(name="Classroom", team_id="Team_foo", code="foo") user = User.create(email="*****@*****.**", name="Cleopatra") cl.contact_id = user.uid cl.put() user.put() # Handling the class for the client should populate memcache. self.assertEqual(cl.to_client_dict()['contact_name'], user.name) # Should see the value in the cache directly. cached = memcache.get(util.cached_properties_key(cl.uid)) self.assertEqual(cached['contact_name'], user.name) return (cl, user)