示例#1
0
    def create_surveys(self):
        tasklist_template = []

        survey1 = Survey.create(
            tasklist_template,
            program_label=self.program_label,
            organization_id='Organization_Foo',
            project_cohort_id='ProjectCohort_Foo',
            ordinal=1,
        )
        survey2 = Survey.create(
            tasklist_template,
            program_label=self.program_label,
            organization_id='Organization_Foo',
            project_cohort_id='ProjectCohort_Foo',
            ordinal=2,
        )
        survey1.put()
        survey2.put()

        # Simulate consistency.
        survey1.key.get()
        survey2.key.get()

        return survey1, survey2
示例#2
0
    def test_survey_task_body(self):
        """Tasks should get dynamic properties from their definition."""
        program_label = 'demo-program'
        task_label = 'task_foo'
        survey = Survey.create(
            [],
            program_label='demo-program',
            organization_id='Organization_Foo',
            ordinal=1,
        )

        task_template = {
            'label': task_label,
            'body': "<p>Demo body.</p>",
        }
        Program.mock_program_config(
            program_label, {
                'surveys': [{
                    'survey_tasklist_template': [{
                        'tasks': [task_template]
                    }]
                }]
            })

        t = Task.create(task_label,
                        1,
                        'checkpoint_foo',
                        parent=survey,
                        program_label=program_label)
        t_dict = t.to_client_dict()

        self.assertIsInstance(t_dict['body'], basestring)
        self.assertGreater(len(t_dict['body']), 0)
示例#3
0
    def test_metric_labels(self):
        """Client dict should have portal-friendly metric labels."""
        team_id = 'Team_foo'
        m1 = Metric.create(name='Foo Condition', label='foo_condition')
        m2 = Metric.create(name='Bar Condition', label='bar_condition')
        Metric.put_multi([m1, m2])
        survey = Survey.create(team_id=team_id, metrics=[m1.uid, m2.uid])
        survey.put()
        user = User.create(name='foo',
                           email='*****@*****.**',
                           owned_teams=[team_id])
        user.put()
        response = self.testapp.get(
            '/api/surveys/{}'.format(survey.uid),
            headers=self.login_headers(user),
        )

        logging.info(response.body)
        self.assertEqual(
            json.loads(response.body)['metric_labels'],
            {
                m1.uid: 'foo_condition',
                m2.uid: 'bar_condition'
            },
        )
示例#4
0
    def test_delete_removes_team(self):
        user = User.create(name='foo', email='*****@*****.**')

        team = Team.create(name='Team Foo', captain_id=user.uid,
                           program_id=self.demo_program.uid)
        team.put()

        user.owned_teams = [team.uid]
        user.put()

        survey = Survey.create(team_id=team.uid)
        survey.put()

        url = '/api/teams/{}'.format(team.uid)
        headers = self.login_headers(user)

        # Delete the team.
        self.testapp.delete(url, headers=headers, status=204)

        # Expect the team is gone from the db.
        self.assertIsNone(Team.get_by_id(team.uid))

        # Api should show a 404.
        self.testapp.get(url, headers=headers, status=404)
        self.testapp.delete(url, headers=headers, status=404)
示例#5
0
    def test_delete_removes_all_ownership(self):
        captain = User.create(name='cap', email='*****@*****.**')
        member = User.create(name='member', email='*****@*****.**')

        team = Team.create(name='Team Foo', captain_id=captain.uid,
                           program_id=self.demo_program.uid)
        team.put()

        captain.owned_teams = [team.uid]
        member.owned_teams = [team.uid]
        captain.put()
        member.put()

        survey = Survey.create(team_id=team.uid)
        survey.put()

        url = '/api/teams/{}'.format(team.uid)
        headers = self.login_headers(captain)

        # Delete the team.
        self.testapp.delete(url, headers=headers, status=204)

        # All users should now not be associated to the deleted team.
        self.assertNotIn(team.uid, User.get_by_id(captain.uid).owned_teams)
        self.assertNotIn(team.uid, User.get_by_id(member.uid).owned_teams)
示例#6
0
    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 test_nobody_done(self):
        """If no one finished the survey, counts are zero."""
        survey = Survey.create([], ordinal=1, program_label=self.program_label)
        survey.put()
        kwargs = {
            'key': 'progress',
            'program_label': self.program_label,
            'project_id': 'Project_12345678',
            'cohort_label': '2017_spring',
            'project_cohort_id': 'ProjectCohort_12345678',
            'code': 'trout viper',
            'survey_id': survey.uid,
            'survey_ordinal': survey.ordinal,
        }

        pd = [
            ParticipantData.create(participant_id='Participant_unfinished1',
                                   value=1,
                                   **kwargs),
            ParticipantData.create(participant_id='Participant_unfinished2',
                                   value=1,
                                   **kwargs),
        ]
        ParticipantData.put_multi(pd)

        result = ParticipantData.participation(survey_id=pd[0].survey_id)
        expected = [
            {
                'value': '1',
                'n': 2,
                'survey_ordinal': 1
            },
        ]

        self.assertEqual(result, expected)
示例#8
0
    def test_all_metrics_on_by_default(self):
        metric1 = Metric.create(name='Metric One', label='m1')
        metric2 = Metric.create(name='Metric One', label='m2')
        Metric.put_multi([metric1, metric2])

        survey = Survey.create(team_id='Team_foo', code='trout viper')
        self.assertEqual(set(survey.metrics), {metric1.uid, metric2.uid})
    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)
示例#10
0
    def test_should_notify(self):
        team_id = 'Team_foo'
        survey = Survey.create(team_id=team_id)

        cycle = Cycle.create(
            team_id=team_id,
            ordinal=1,
            start_date=datetime.date.today() - datetime.timedelta(days=1),
            end_date=datetime.date.today() + datetime.timedelta(days=1),
        )
        cycle.put()

        today = datetime.date.today()
        now = datetime.datetime.now()

        # Case 1: notified time is not set.
        self.assertEqual(survey.should_notify(today), cycle)

        # Case 2: sent within cycle
        survey.notified = now - datetime.timedelta(days=1)
        self.assertEqual(survey.should_notify(today), False)

        # Case 3: sent before cycle
        survey.notified = now - datetime.timedelta(days=10)
        self.assertEqual(survey.should_notify(today), cycle)

        # import pdb
        # pdb.set_trace()
        # Case 4: today is not in any cycle (there is no current cycle)
        self.assertEqual(
            survey.should_notify(today - datetime.timedelta(days=10)),
            False,
        )
示例#11
0
    def test_create_for_team(self):
        """Should populate only with metrics active by default."""
        metric1 = Metric.create(name="Community of Helpers",
                                label='community_of_helpers')
        metric1.put()
        metric2 = Metric.create(name="Feedback for Growth",
                                label='feedback_for_growth')
        metric2.put()

        program = Program.create(
            name='Test Program',
            label='test-program',
            metrics=[
                {
                    'uid': metric1.uid,
                    'default_active': True
                },
                {
                    'uid': metric2.uid,
                    'default_active': False
                },
            ],
            preview_url='foo.com',
        )
        program.put()

        team = Team.create(
            captain_id='User_captain',
            program_id=program.uid,
        )

        survey = Survey.create_for_team(team)
        self.assertEqual(survey.metrics, [metric1.uid])
        self.assertEqual(survey.open_responses, [metric1.uid])
        self.assertEqual(survey.meta, {})
示例#12
0
 def test_delete_not_implemented(self):
     user, team_dict = self.test_create_team_creates_survey()
     survey = Survey.get(team_id=team_dict['uid'])[0]
     self.testapp.delete(
         '/api/surveys/{}'.format(survey.uid),
         headers=self.login_headers(user),
         status=405,
     )
    def test_join_org(self):
        """Joining an org makes task reminders for all contained tasklists."""
        program_label = 'demo-program'
        cohort_label = 'demo-cohort'

        # Guarantee the dates will work by mocking the cohort config.
        cohort_config = {
            'label': cohort_label,
            'name': 'Demo Cohort',
            'open_date': str(datetime.date.today()),
            'close_date': str(datetime.date.today()),
        }
        Program.mock_program_config(
            program_label,
            {'cohorts': {
                cohort_label: cohort_config
            }},
        )

        program = Program.get_config(program_label)
        tasklist_template = program['surveys'][0]['survey_tasklist_template']

        owner = User.create(email='*****@*****.**', user_type='user')
        org = Organization.create(name="Foo Org", liaison_id=owner.uid)
        owner.owned_organizations = [org.uid]
        project = Project.create(program_label=program_label,
                                 organization_id=org.uid)
        survey = Survey.create(tasklist_template,
                               project_id=project.uid,
                               organization_id=org.uid,
                               program_label=program_label,
                               ordinal=1,
                               cohort_label=cohort_label)
        owner.put()
        org.put()
        project.put()
        survey.put()

        # The assumption here is the org and its contents are long-standing,
        # so force consistency with all.
        org.key.get()
        project.key.get()
        survey.key.get()

        joiner = User.create(email='*****@*****.**', user_type='user')
        joiner.put()

        self.testapp.post_json(
            '/api/users/{}/organizations'.format(joiner.uid),
            org.to_client_dict(),
            headers=login_headers(owner.uid),
        )

        # One TaskReminder for each of: org tasklist, project tasklist, survey
        # tasklist.
        self.assertEqual(len(TaskReminder.get(ancestor=joiner)), 3)

        return (org, project, survey, owner, joiner)
示例#14
0
    def assert_created_with_program(self, team_dict, program):
        # Survey should have program's metrics.
        survey = Survey.get(team_id=team_dict['uid'])[0]
        self.assertEqual(survey.metrics, program.metrics)
        self.assertEqual(survey.open_responses, program.metrics)

        # Correct number of cycles created.
        cycles = Cycle.get(team_id=team_dict['uid'])
        self.assertEqual(len(cycles), program.min_cycles or 0)
示例#15
0
 def get(self, id=None):
     # convert short_uid to uid if needed
     if id is not None:
         id = Survey.get_long_uid(id)
         response = self.api.get_by_id(id)
     else:
         params = self.get_params()
         response = self.api.get('Survey', ancestor=self.api.user, **params)
     self.write(response)
示例#16
0
    def test_get_metrics(self):
        metric1 = Metric.create(name="Community of Helpers",
                                label='community_of_helpers')
        metric1.put()
        metric2 = Metric.create(name="Feedback for Growth",
                                label='feedback_for_growth')
        metric2.put()

        survey = Survey.create(team_id='Team_foo',
                               metrics=[metric1.uid, metric2.uid])
        self.assertEqual(set(survey.get_metrics()), {metric1, metric2})
示例#17
0
def makeANewSurvey(name, description, question, body, note, start_date,
                   end_date):
    survey = Survey(name=name,
                    description=description,
                    question=question,
                    body=body,
                    note=note,
                    start_date=start_date,
                    end_date=end_date)
    session.add(survey)
    session.commit()
    return jsonify(survey=survey.serialize)
示例#18
0
    def set_up(self):
        # Let ConsistencyTestCase set up the datastore testing stub.
        super(TestSurveys, self).set_up()

        with mysql_connection.connect() as sql:
            sql.reset({
                'cycle': Cycle.get_table_definition(),
                'metric': Metric.get_table_definition(),
                'program': Program.get_table_definition(),
                'survey': Survey.get_table_definition(),
                'team': Team.get_table_definition(),
            })
示例#19
0
    def test_program_access(self):
        """Should be able to look up program config through project."""
        tasklist_template = []
        survey = Survey.create(
            tasklist_template,
            program_label='demo-program',
            organization_id='Organization_Foo',
            ordinal=1,
        )
        s_dict = survey.to_client_dict()

        self.assertEqual(s_dict['name'], 'Intervention')
示例#20
0
    def test_put_artifact_url_sends_email(self):
        """PUT response has special jwt giving permission on Neptune."""
        user = User.create(name='foo', email='*****@*****.**')
        team = Team.create(name="Foo Team",
                           captain_id=user.uid,
                           program_id="Program_foo")
        survey = Survey.create(team_id=team.uid)
        user.owned_teams = [team.uid]

        team.put()
        survey.put()
        user.put()

        artifact_url = 'https://www.example.com/artifact'

        # Not changing the artifact does NOT trigger an email.
        self.testapp.put_json(
            '/api/surveys/{}'.format(survey.uid),
            {'meta': {
                'artifact_url': ''
            }},
            headers=self.login_headers(user),
        )
        self.assertEqual(Email.count(), 0)

        # Changing it triggers an email.
        self.testapp.put_json(
            '/api/surveys/{}'.format(survey.uid),
            {'meta': {
                'artifact_use': 'true',
                'artifact_url': artifact_url
            }},
            headers=self.login_headers(user),
        )

        emails = Email.get()
        self.assertEqual(len(emails), 1)
        email = emails[0]
        self.assertIn(artifact_url, email.html)
        self.assertIn(team.name, email.html)

        # Sending a PUT **without** changing it does NOT trigger an email.
        self.testapp.put_json(
            '/api/surveys/{}'.format(survey.uid),
            {'meta': {
                'artifact_use': 'true',
                'artifact_url': artifact_url
            }},
            headers=self.login_headers(user),
        )

        self.assertEqual(Email.count(), 1)  # same as before
示例#21
0
 def test_checkpoint_creation(self):
     program_label = 'demo-program'
     program_config = Program.get_config(program_label)
     template = program_config['surveys'][0]['survey_tasklist_template']
     survey = Survey.create(
         template,
         program_label=program_label,
         organization_id='Organization_Foo',
         ordinal=1,
     )
     survey.put()
     checkpoints = Checkpoint.get(parent_id=survey.uid)
     self.assertEqual(len(checkpoints), len(template))
示例#22
0
    def test_config_enabled(self):
        program = Program.create(
            name='Program Foo',
            label='TP1',
            survey_config_enabled=True,
            preview_url='foo.com',
        )
        program.put()

        team = Team.create(captain_id='User_captain', program_id=program.uid)
        team.put()

        survey = Survey.create(team_id=team.uid)
        survey.put()

        # Enabled by program.
        self.assertEqual(Survey.config_enabled(survey.uid), True)

        # Disabled by program.
        program.survey_config_enabled = False
        program.put()
        self.assertEqual(Survey.config_enabled(survey.uid), False)
示例#23
0
    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)
示例#24
0
    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)
示例#25
0
 def test_task_creation(self):
     program_label = 'demo-program'
     program_config = Program.get_config(program_label)
     template = program_config['surveys'][0]['survey_tasklist_template']
     survey = Survey.create(
         template,
         program_label=program_label,
         organization_id='Organization_Foo',
         ordinal=1,
     )
     survey.put()
     tasks = Task.get(ancestor=survey)
     num_tasks = sum([len(checkpoint['tasks']) for checkpoint in template])
     self.assertEqual(len(tasks), num_tasks)
示例#26
0
def add_survey_ids_to_project_cohorts(project_cohort):
    """To make batch querying of dashboard views easier, we want to be able to
    get surveys by id, given project cohorts. This is a change to how pcs are
    created, so legacy data needs updating.

    Configure this job in map_reduce.yaml and initiate it from /mapreduce. You
    must be signed in as a project admin.

    See: https://sookocheff.com/post/appengine/mapreduce/mapreduce-yaml/
    """
    if len(project_cohort.survey_ids) > 0:
        return

    keys = Survey.get(project_cohort_id=project_cohort.uid, keys_only=True)
    project_cohort.survey_ids = [k.id() for k in keys]
    yield op.db.Put(project_cohort)
示例#27
0
    def test_change_team_ignored(self):
        team_id = 'Team_foo'
        survey = Survey.create(team_id=team_id)
        survey.put()
        user = User.create(name='foo',
                           email='*****@*****.**',
                           owned_teams=[team_id])
        user.put()
        response = self.testapp.put_json(
            '/api/surveys/{}'.format(survey.uid),
            {'team_id': 'Team_other'},
            headers=self.login_headers(user),
        )

        # team id shoud be unchanged
        self.assertEqual(json.loads(response.body)['team_id'], team_id)
    def test_survey_creation(self):
        """Creating a project cohort should create surveys."""

        # Hack eventual consistency for just this test because we don't
        # expect surveys to be available instantly upon creation, unlike the
        # project cohort itself.
        self.policy = datastore_stub_util.PseudoRandomHRConsistencyPolicy(
            probability=1)
        self.testbed.init_datastore_v3_stub(consistency_policy=self.policy)

        pc, user = self.test_join_cohort()

        program_label = 'demo-program'
        program = Program.get_config(program_label)

        surveys = Survey.get(project_cohort_id=pc.uid)
        self.assertEqual(len(surveys), len(program['surveys']))
示例#29
0
    def set_up(self):
        # Let ConsistencyTestCase set up the datastore testing stub.
        super(TestApiTeams, 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(),
                'cycle': Cycle.get_table_definition(),
                'program': Program.get_table_definition(),
                'organization': Organization.get_table_definition(),
                'report': Report.get_table_definition(),
                'survey': Survey.get_table_definition(),
                'team': Team.get_table_definition(),
                'user': User.get_table_definition(),
            })

        # See #848. Remove once resolved.
        self.demo_program = Program.create(
            name="Demo Program",
            label='demoprogram',
            min_cycles=3,
            active=True,
            preview_url='foo.com',
        )
        self.demo_program.put()

        self.ep_program = Program.create(
            name="Engagement Project",
            label='ep19',
            min_cycles=3,
            active=True,
            preview_url='foo.com',
        )
        self.ep_program.put()
示例#30
0
    def test_put_clears_dashboard_queries(self):
        org_id = 'Organization_Foo'
        program_label = 'demo-program'
        pc = ProjectCohort.create(
            program_label='demo-program',
            organization_id=org_id,
            project_id='Project_Foo',
            cohort_label='2018',
        )
        pc.put()
        program_config = Program.get_config(program_label)
        template = program_config['surveys'][0]['survey_tasklist_template']
        survey = Survey.create(
            template,
            program_label=program_label,
            organization_id=org_id,
            project_cohort_id=pc.uid,
            ordinal=1,
        )
        survey.put()

        org_key = util.cached_query_key(
            'SuperDashboard',
            organization_id=pc.organization_id,
        )
        program_cohort_key = util.cached_query_key(
            'SuperDashboard',
            program_label=pc.program_label,
            cohort_label=pc.cohort_label,
        )

        memcache.set(org_key, {'foo': 1})
        memcache.set(program_cohort_key, {'foo': 1})

        # Re-fetch the org so it doesn't have an associated tasklist, which
        # saves checkpoints. This should clear memcache without relying on those
        # checkpoints.
        survey = survey.key.get()
        survey.status = 'ready'
        survey.put()

        self.assertIsNone(memcache.get(org_key))
        self.assertIsNone(memcache.get(program_cohort_key))