示例#1
0
    def test_sync_questions_categories(self, mock_logger, mock_poll_get_flow):
        self.org = factories.Org()
        self.poll_1 = factories.Poll(org=self.org, name='Poll 1')
        self.poll_2 = factories.Poll(org=self.org, name='Poll 2')
        # Create 2 questions locally:
        # one that is on RapidPro
        # and one that should be removed because it won't be on RapidPro
        self.question_1 = factories.Question(
            poll=self.poll_1,
            ruleset_uuid='goodquestion',
            question_type=models.Question.TYPE_MULTIPLE_CHOICE)
        self.question_2 = factories.Question(
            poll=self.poll_1,
            ruleset_uuid='oldquestion',
            question_type=models.Question.TYPE_MULTIPLE_CHOICE)

        # Data to pass to form for testing. Only select one poll
        self.data = [self.poll_1]
        # Patch the call to the API
        flow_1 = mock.Mock()
        flow_1.uuid = 'abcdefg123'
        flow_1.name = self.poll_1.name
        ruleset_existing = mock.Mock()
        ruleset_existing.uuid = 'goodquestion'
        ruleset_existing.label = 'good question'
        ruleset_new = mock.Mock()
        ruleset_new.uuid = 'newquestion'
        ruleset_new.label = 'new question'
        flow_1.rulesets = [ruleset_existing, ruleset_new]

        # Mock the call to the API to send back a single flow matching our first poll
        self.mock_temba_client.get_flows.return_value = [flow_1]
        # Mock this call to return an empty rule set so that RapidPro API is not called
        mock_poll_get_flow.return_value.rulesets = []

        # Assert that the 2 questions exist before we sync when one should be deleted
        self.assertEqual(models.Question.objects.count(), 2)

        # Call the task to sync questions...
        sync_questions_categories(self.org, self.data)
        # Two questions exist locally, one is new from the RapidPro API mock (flow_1.rulesets)
        self.assertEqual(models.Question.objects.count(), 2)
        self.assertEqual(models.Question.objects.first().ruleset_uuid,
                         'goodquestion')
        self.assertEqual(models.Question.objects.last().ruleset_uuid,
                         'newquestion')
        # Only 1 poll was reflected in the log message as only 1 poll was sent into the form data
        self.assertEqual(mock_logger.call_count, 2)
        self.assertIn("1 Poll(s)", mock_logger.call_args[0][0])
示例#2
0
    def test_from_temba__another_org(self):
        """Both uuid and Poll must match in order to update existing."""
        poll = factories.Poll()
        other_poll = factories.Poll()
        other_question = factories.Question(poll=other_poll)
        ruleset = factories.TembaRuleSet(uuid=other_question.ruleset_uuid)

        # Should return a Question that is distinct from the existing
        # Question for another poll.
        ret_val = models.Question.objects.from_temba(poll, ruleset, order=100)
        self.assertEqual(models.Question.objects.count(), 2)
        other_question.refresh_from_db()
        self.assertNotEqual(ret_val, other_question)
        self.assertNotEqual(ret_val.poll, other_question.poll)
        self.assertEqual(ret_val.ruleset_uuid, other_question.ruleset_uuid)
示例#3
0
    def test_active_poll_selection_and_question_sync(self, mock_sync_questions, mock_sync_poll):
        """ Test that the poll questions are being synced after the poll form is saved """
        self.org = factories.Org()
        self.poll_1 = factories.Poll(org=self.org)
        self.poll_2 = factories.Poll(org=self.org)

        # Data to pass to form for testing.
        self.data = {'polls': [self.poll_1.id]}
        self.form = forms.ActivePollsForm(org=self.org, data=self.data)

        self.assertTrue(self.form.is_valid())
        self.form.save()

        self.assertTrue(mock_sync_questions.delay.called)
        self.assertEqual(mock_sync_questions.delay.call_args_list[0][0][0], self.org)
        self.assertEqual(list(mock_sync_questions.delay.call_args_list[0][0][1]), [self.poll_1])
示例#4
0
    def test_sync__delete_non_existant_poll(self):
        """Sync should delete Polls that track a flow that does not exist."""
        org = factories.Org()
        poll = factories.Poll(org=org)  # noqa
        self.mock_temba_client.get_flows.return_value = []
        models.Poll.objects.sync(org)

        self.assertEqual(models.Poll.objects.count(), 0)
示例#5
0
    def test_set_active_for_org__invalid_uuids(self):
        """An error is raised when an invalid UUID for the org is passed."""
        org = factories.Org()
        poll = factories.Poll(org=org, is_active=False, flow_uuid='a')

        other_org = factories.Org()
        other_poll = factories.Poll(org=other_org,
                                    is_active=False,
                                    flow_uuid='b')

        with self.assertRaises(ValueError):
            Poll.objects.set_active_for_org(org, ['a', 'b'])

        poll.refresh_from_db()
        self.assertFalse(poll.is_active)
        other_poll.refresh_from_db()
        self.assertFalse(other_poll.is_active)
示例#6
0
    def setUp(self):
        """Set up common resources."""
        super(BaseMapsTest, self).setUp()

        self.org = factories.Org()
        self.poll = factories.Poll()
        self.pollrun = factories.PollRun(poll=self.poll)

        self.boundary_a = factories.Boundary(org=self.org)
        self.boundary_b = factories.Boundary(org=self.org)
示例#7
0
    def test_set_active_for_org(self):
        """Set which org polls are active."""
        polls = []

        org = factories.Org()
        polls.append(factories.Poll(org=org, is_active=True, flow_uuid='0'))
        polls.append(factories.Poll(org=org, is_active=True, flow_uuid='1'))
        polls.append(factories.Poll(org=org, is_active=False, flow_uuid='2'))
        polls.append(factories.Poll(org=org, is_active=False, flow_uuid='3'))

        other_org = factories.Org()
        polls.append(
            factories.Poll(org=other_org, is_active=True, flow_uuid='4'))
        polls.append(
            factories.Poll(org=other_org, is_active=False, flow_uuid='5'))

        models.Poll.objects.set_active_for_org(org, ['0', '2'])

        # Refresh from database.
        polls = [models.Poll.objects.get(pk=p.pk) for p in polls]

        # Specified org Polls should be active.
        self.assertTrue(polls[0].is_active)
        self.assertTrue(polls[2].is_active)

        # All other org polls should be inactive.
        self.assertFalse(polls[1].is_active)
        self.assertFalse(polls[3].is_active)

        # Polls for other orgs should be unaffected.
        self.assertTrue(polls[4].is_active)
        self.assertFalse(polls[5].is_active)
示例#8
0
    def test_from_temba__new(self):
        """Should create a new Question to match the Poll and uuid."""
        poll = factories.Poll()
        ruleset = factories.TembaRuleSet()

        # Should create a new Question object that matches the incoming data.
        question = models.Question.objects.from_temba(poll, ruleset, order=100)
        self.assertEqual(models.Question.objects.count(), 1)
        self.assertEqual(question.ruleset_uuid, ruleset.uuid)
        self.assertEqual(question.poll, poll)
        self.assertEqual(question.rapidpro_name, ruleset.label)
        self.assertEqual(question.question_type, models.Question.TYPE_OPEN)
        self.assertEqual(question.order, 100)
示例#9
0
    def test_get_flow_definition(self):
        """Flow definition should be retrieved from the API and cached on the poll."""
        definition = factories.TembaFlowDefinition()
        self.mock_temba_client.get_flow_definition.return_value = definition
        poll = factories.Poll()
        self.assertFalse(hasattr(poll, '_flow_definition'))
        for i in range(2):
            # The result of the method should be cached on the poll.
            self.assertEqual(poll.get_flow_definition(), definition)
            self.assertEqual(poll._flow_definition, definition)

            # API call count should not go up.
            self.assertEqual(
                self.mock_temba_client.get_flow_definition.call_count, 1)
示例#10
0
    def test_from_temba__existing(self):
        """Fields on an existing Poll should be updated from RapidPro."""
        org = factories.Org()
        poll = factories.Poll(org=org,
                              flow_uuid='abc',
                              rapidpro_name='old',
                              name='custom',
                              is_active=True)
        flow = factories.TembaFlow(uuid='abc', name='new')

        updated = Poll.objects.from_temba(org, flow)

        poll.refresh_from_db()
        self.assertEqual(poll.pk, updated.pk)
        self.assertEqual(poll.rapidpro_name, 'new')
        self.assertEqual(poll.name, 'custom')
        self.assertTrue(poll.is_active)
示例#11
0
    def test_sync__update_existing(self):
        """Sync should update existing objects if they have changed on RapidPro."""
        self.mock_temba_client.get_flow_definition.return_value = factories.TembaFlowDefinition(
        )

        org = factories.Org()
        poll = factories.Poll(org=org, is_active=True)
        flow = factories.TembaFlow(uuid=poll.flow_uuid)
        self.mock_temba_client.get_flows.return_value = [flow]
        models.Poll.objects.sync(org)

        self.assertEqual(models.Poll.objects.count(), 1)
        poll = models.Poll.objects.get()
        self.assertEqual(poll.org, org)
        self.assertEqual(poll.flow_uuid, flow.uuid)
        self.assertEqual(poll.rapidpro_name, flow.name)
        self.assertEqual(poll.name, flow.name)
        self.assertTrue(poll.is_active)
示例#12
0
    def test_from_temba__existing(self):
        """Should update an existing Question for the Poll and uuid."""
        poll = factories.Poll()
        question = factories.Question(poll=poll,
                                      question_type=models.Question.TYPE_OPEN)
        ruleset = factories.TembaRuleSet(
            uuid=question.ruleset_uuid,
            response_type=models.Question.TYPE_MULTIPLE_CHOICE)

        # Should return the existing Question object.
        ret_val = models.Question.objects.from_temba(poll, ruleset, order=100)
        self.assertEqual(ret_val, question)
        self.assertEqual(ret_val.ruleset_uuid, question.ruleset_uuid)
        self.assertEqual(models.Question.objects.count(), 1)

        # Existing Question should be updated to match the incoming data.
        question.refresh_from_db()
        self.assertEqual(question.ruleset_uuid, ruleset.uuid)
        self.assertEqual(question.poll, poll)
        self.assertEqual(question.rapidpro_name, ruleset.label)
        self.assertEqual(question.order, 100)

        # Question type should not be updated.
        self.assertEqual(question.question_type, models.Question.TYPE_OPEN)
示例#13
0
    def setUp(self):
        super(PollChartTest, self).setUp()

        self.org = factories.Org()

        self.poll = factories.Poll(org=self.org)

        self.region1 = factories.Region(org=self.org, name="Beta")
        self.region2 = factories.Region(org=self.org, name="Acme")

        self.question1 = factories.Question(
            poll=self.poll, question_type=models.Question.TYPE_MULTIPLE_CHOICE)
        self.question2 = factories.Question(
            poll=self.poll, question_type=models.Question.TYPE_OPEN)
        self.question3 = factories.Question(
            poll=self.poll, question_type=models.Question.TYPE_NUMERIC)

        self.pollrun = factories.UniversalPollRun(poll=self.poll)

        self.contact1 = factories.Contact(org=self.org, region=self.region1)
        self.response1 = factories.Response(
            contact=self.contact1, pollrun=self.pollrun,
            status=models.Response.STATUS_COMPLETE)
        factories.Answer(
            response=self.response1, question=self.question1,
            value="4.00000", category="1 - 5")
        factories.Answer(
            response=self.response1, question=self.question2,
            value="It's very rainy", category="All Responses")
        factories.Answer(
            response=self.response1, question=self.question3,
            value="4.00000", category="1 - 5")

        self.contact2 = factories.Contact(org=self.org, region=self.region1)
        self.response2 = factories.Response(
            contact=self.contact2, pollrun=self.pollrun,
            status=models.Response.STATUS_COMPLETE)
        factories.Answer(
            response=self.response2, question=self.question1,
            value="3.00000", category="1 - 5")
        factories.Answer(
            response=self.response2, question=self.question2,
            value="rainy and rainy", category="All Responses")
        factories.Answer(
            response=self.response2, question=self.question3,
            value="3.00000", category="1 - 5")

        self.contact3 = factories.Contact(org=self.org, region=self.region2)
        self.response3 = factories.Response(
            contact=self.contact3, pollrun=self.pollrun,
            status=models.Response.STATUS_COMPLETE)
        factories.Answer(
            response=self.response3, question=self.question1,
            value="8.00000", category="6 - 10")
        factories.Answer(
            response=self.response3, question=self.question2,
            value="Sunny sunny", category="All Responses")
        factories.Answer(
            response=self.response3, question=self.question3,
            value="8.00000", category="6 - 10")

        self.pollruns = models.PollRun.objects.filter(pk=self.pollrun.pk)
        self.responses = models.Response.objects.filter(pollrun=self.pollrun)
示例#14
0
 def test_by_org(self):
     """by_org filter should return only Polls for the given org."""
     org = factories.Org()
     poll = factories.Poll(org=org)
     factories.Poll()
     self.assertEqual(list(models.Poll.objects.by_org(org)), [poll])
示例#15
0
 def test_ruleset_uuid_can_repeat_between_polls(self):
     """ruleset_uuid can be repeated with different Polls."""
     factories.Question(poll=factories.Poll(), ruleset_uuid='abc')
     factories.Question(poll=factories.Poll(), ruleset_uuid='abc')
示例#16
0
 def test_ruleset_uuid_unique_to_poll(self):
     """ruleset_uuid should be unique for a particular Poll."""
     poll = factories.Poll()
     factories.Question(poll=poll, ruleset_uuid='abc')
     with self.assertRaises(IntegrityError):
         factories.Question(poll=poll, ruleset_uuid='abc')
示例#17
0
 def test_str(self):
     """Smoke test for string representation."""
     poll = factories.Poll(name='hello')
     self.assertEqual(str(poll), 'hello')
示例#18
0
 def test_active(self):
     """active filter shouldn't return Polls where is_active is False."""
     poll = factories.Poll(is_active=True)
     factories.Poll(is_active=False)
     self.assertEqual(list(models.Poll.objects.active()), [poll])
示例#19
0
 def test_flow_uuid_unique_to_org(self):
     """flow_uuid should be unique for a given Org."""
     org = factories.Org()
     factories.Poll(org=org, flow_uuid='abc')
     with self.assertRaises(IntegrityError):
         factories.Poll(org=org, flow_uuid='abc')
示例#20
0
 def test_flow_uuid_can_repeat_between_orgs(self):
     """flow_uuid can be repeated with different Orgs."""
     factories.Poll(org=factories.Org(), flow_uuid='abc')
     factories.Poll(org=factories.Org(), flow_uuid='abc')