def test_action_schedule_job(self):
        to_get_scheduled = JobFactory.create_batch(2, status=Job.DRAFT)
        already_scheduled = JobFactory(status=Job.SCHEDULED)
        already_published = JobFactory(status=Job.PUBLISHED)
        cancelled = JobFactory(status=Job.CANCELED)
        completed = JobFactory(status=Job.COMPLETED)
        JobFactory.create_batch(2, status=Job.DRAFT)

        queryset = Job.objects.filter(id__in=[
            to_get_scheduled[0].id,
            to_get_scheduled[1].id,
            already_scheduled.id,
            already_published.id,
            cancelled.id,
            completed.id,
        ])

        request = Mock()
        request.user = UserFactory.create()
        with patch.multiple('snippets.base.admin.adminmodels.messages',
                            warning=DEFAULT_MOCK,
                            success=DEFAULT_MOCK) as message_mocks:
            JobAdmin(Job, None).action_schedule_job(request, queryset)

        self.assertEqual(
            set(Job.objects.filter(status=Job.SCHEDULED)),
            set(to_get_scheduled + [already_scheduled])
        )
        self.assertTrue(message_mocks['warning'].called)
        self.assertTrue(message_mocks['success'].called)
    def test_change_status_to_completed(self):
        job = JobFactory.create(status=Job.DRAFT)
        with patch('snippets.base.models.datetime') as datetime_mock:
            datetime_mock.utcnow.return_value = datetime(2019, 1, 1, 0, 0)
            job.change_status(status=Job.COMPLETED,
                              user=None,
                              send_slack=False)

        job.refresh_from_db()
        self.assertEqual(job.status, Job.COMPLETED)
        self.assertEqual(job.completed_on, datetime(2019, 1, 1, 0, 0))
    def test_channels(self):
        job = JobFactory.create(targets=[
            TargetFactory.create(on_release=True),
            TargetFactory.create(on_beta=True, on_nightly=True),
            TargetFactory.create(on_release=False,
                                 on_esr=False,
                                 on_aurora=False,
                                 on_beta=False,
                                 on_nightly=False),
        ])

        self.assertTrue(job.channels, set(['release', 'beta', 'nightly']))
    def test_change_status(self):
        job = JobFactory.create(status=Job.DRAFT)
        with patch('snippets.base.models.slack') as slack_mock:
            with patch('snippets.base.models.LogEntry') as log_entry_mock:
                job.change_status(status=Job.SCHEDULED,
                                  user=job.creator,
                                  send_slack=True)

        job.refresh_from_db()

        self.assertEqual(job.status, Job.SCHEDULED)
        log_entry_mock.objects.log_action.assert_called()
        slack_mock._send_slack.assert_called()
Exemple #5
0
    def test_delete(self):
        distribution = DistributionFactory()
        distribution_bundle = DistributionBundleFactory(
            code_name='foo',
            enabled=False,
        )
        distribution_bundle.distributions.add(distribution)

        target = TargetFactory(on_release=False,
                               on_beta=False,
                               on_nightly=True,
                               on_esr=False,
                               on_aurora=False)
        JobFactory(
            status=models.Job.COMPLETED,
            snippet__locale=',fr,',
            targets=[target],
        )

        # Still published, but belongs to a disabled distribution
        JobFactory(
            status=models.Job.PUBLISHED,
            snippet__locale=',fr,',
            targets=[target],
            distribution=distribution,
        )

        with patch(
                'snippets.base.management.commands.generate_bundles.default_storage'
        ) as ds_mock:
            # Test that only removes if file exists.
            ds_mock.exists.return_value = True
            call_command('generate_bundles', stdout=Mock())

        ds_mock.delete.assert_has_calls([
            call('pregen/Firefox/nightly/fr/default.json'),
            call('pregen/Firefox/nightly/fr/foo.json')
        ])
        ds_mock.save.assert_not_called()
    def test_modified_date_updates_when_target_updates(self):
        target = TargetFactory()
        job = JobFactory(targets=[target])
        snippet = job.snippet
        # Must refresh from db to get the actual datetime stored in db which
        # may be different by milliseconds from the original python datetime.
        snippet.refresh_from_db()
        old_modified = snippet.modified

        target.name = 'new name'
        target.save()
        snippet.refresh_from_db()
        new_modified = snippet.modified

        self.assertNotEqual(old_modified, new_modified)
 def test_render_always_eval_to_false(self):
     job = JobFactory.create(weight=10,
                             campaign__slug='demo-campaign',
                             targets=[
                                 TargetFactory(on_release=False,
                                               on_beta=False,
                                               on_esr=False,
                                               on_aurora=False,
                                               on_nightly=True,
                                               jexl_expr='(la==lo)'),
                             ])
     job.snippet.render = Mock()
     job.snippet.render.return_value = {}
     generated_output = job.render(always_eval_to_false=True)
     self.assertEqual(generated_output['targeting'], '(la==lo) && false')
    def test_modified_date_updates_when_campaign_updates(self):
        job = JobFactory()
        snippet = job.snippet
        # Must refresh from db to get the actual datetime stored in db which
        # may be different by milliseconds from the original python datetime.
        snippet.refresh_from_db()
        old_modified = snippet.modified

        campaign = job.campaign
        campaign.name = 'new name'
        campaign.save()

        snippet.refresh_from_db()
        new_modified = snippet.modified

        self.assertNotEqual(old_modified, new_modified)
    def test_modified_date_updates_when_distribution_bundle_updates(self):
        job = JobFactory()
        distribution_bundle = DistributionBundleFactory()
        distribution_bundle.distributions.add(job.distribution)
        snippet = job.snippet
        # Must refresh from db to get the actual datetime stored in db which
        # may be different by milliseconds from the original python datetime.
        snippet.refresh_from_db()
        old_modified = snippet.modified

        distribution_bundle.code_name = 'bar'
        distribution_bundle.save()

        snippet.refresh_from_db()
        new_modified = snippet.modified
        self.assertNotEqual(old_modified, new_modified)
    def test_render(self):
        self.maxDiff = None
        job = JobFactory.create(weight=10,
                                campaign__slug='demo-campaign',
                                targets=[
                                    TargetFactory(on_release=False,
                                                  on_beta=False,
                                                  on_esr=False,
                                                  on_aurora=False,
                                                  on_nightly=True,
                                                  jexl_expr='(la==lo)'),
                                    TargetFactory(on_release=False,
                                                  on_beta=True,
                                                  on_esr=False,
                                                  on_aurora=False,
                                                  on_nightly=True),
                                    TargetFactory(on_release=False,
                                                  on_beta=True,
                                                  on_esr=False,
                                                  on_aurora=False,
                                                  on_nightly=True,
                                                  jexl_expr='foo==bar'),
                                ])
        snippet_render = {
            'template': 'simple_snippet',
            'template_version': 'xx.xx',
            'content': {
                'block_button_text': 'Block me',
                'text': 'This is text [[job_id]]',
            }
        }
        expected_output = copy.deepcopy(snippet_render)
        expected_output.update({
            'id': str(job.id),
            'weight': 10,
            'campaign': 'demo-campaign',
            'targeting': '(la==lo) && foo==bar',
            'content': {
                'block_button_text': 'Block me',
                'text': f'This is text {job.id}',
            }
        })
        job.snippet.render = Mock()
        job.snippet.render.return_value = snippet_render
        generated_output = job.render()

        self.assertEqual(generated_output, expected_output)
    def test_duplicate(self):
        user = UserFactory.create()
        job = JobFactory.create(status=Job.PUBLISHED,
                                metric_impressions=500,
                                metric_clicks=500,
                                metric_blocks=500,
                                completed_on=datetime.utcnow())
        duplicate_job = job.duplicate(user)
        job.refresh_from_db()

        for attr in ['id', 'creator', 'created', 'modified', 'uuid']:
            self.assertNotEqual(getattr(job, attr),
                                getattr(duplicate_job, attr))

        self.assertEqual(duplicate_job.status, Job.DRAFT)
        self.assertEqual(duplicate_job.metric_impressions, 0)
        self.assertEqual(duplicate_job.metric_clicks, 0)
        self.assertEqual(duplicate_job.metric_blocks, 0)
        self.assertEqual(duplicate_job.completed_on, None)
Exemple #12
0
    def test_delete_does_not_exist(self):
        target = TargetFactory(on_release=False,
                               on_beta=False,
                               on_nightly=True,
                               on_esr=False,
                               on_aurora=False)
        JobFactory(
            status=models.Job.COMPLETED,
            snippet__locale=',fr,',
            targets=[target],
        )

        with patch(
                'snippets.base.management.commands.generate_bundles.default_storage'
        ) as ds_mock:
            # Test that only removes if file exists.
            ds_mock.exists.return_value = False
            call_command('generate_bundles', stdout=Mock())

        ds_mock.delete.assert_not_called()
        ds_mock.save.assert_not_called()
Exemple #13
0
    def test_name(self):
        JobFactory.create(id=2990, snippet__id=20000, snippet__name='foo 1')
        JobFactory.create(id=2991, snippet__id=20001, snippet__name='foo 2')
        job = JobFactory.create(id=2992,
                                snippet__id=20002,
                                snippet__name='bar 1')
        JobFactory.create(id=2993, snippet__name='foo lala foo')
        filtr = JobFilter(
            QueryDict(query_string='only_scheduled=all&name=bar'),
            queryset=models.Job.objects.all())
        self.assertEqual(set([job]), set(filtr.qs))

        # Test search with Job ID
        filtr = JobFilter(
            QueryDict(query_string=f'only_scheduled=all&name={job.id}'),
            queryset=models.Job.objects.all())

        self.assertEqual(set([job]), set(filtr.qs))

        # Test search with Snippet ID
        filtr = JobFilter(QueryDict(
            query_string=f'only_scheduled=all&name={job.snippet.id}'),
                          queryset=models.Job.objects.all())
        self.assertEqual(set([job]), set(filtr.qs))
Exemple #14
0
 def test_only_scheduled_false(self):
     job1 = JobFactory.create(publish_start=None, publish_end=None)
     JobFactory.create(publish_end=datetime(2019, 2, 2))
     filtr = JobFilter(QueryDict(query_string='only_scheduled=false'),
                       queryset=models.Job.objects.all())
     self.assertEqual(set([job1]), set(filtr.qs))
    def test_render_client_limits(self):
        # Combined
        job = JobFactory.create(
            client_limit_lifetime=100,
            client_limit_per_hour=10,
            client_limit_per_month=100,
            campaign__slug='demo_campaign',
        )
        expected_output = {
            'id': str(job.id),
            'weight': 100,
            'campaign': 'demo_campaign',
            'targeting': '',
            'frequency': {
                'lifetime':
                100,
                'custom': [{
                    'period': 3600000,
                    'cap': 10
                }, {
                    'period': 2592000000,
                    'cap': 100
                }]
            }
        }
        job.snippet.render = Mock()
        job.snippet.render.return_value = {}
        generated_output = job.render()
        self.assertEqual(generated_output, expected_output)

        # Lifetime limit only
        job = JobFactory.create(
            client_limit_lifetime=100,
            campaign__slug='demo_campaign_1',
        )
        expected_output = {
            'id': str(job.id),
            'weight': 100,
            'campaign': 'demo_campaign_1',
            'targeting': '',
            'frequency': {
                'lifetime': 100,
            }
        }
        job.snippet.render = Mock()
        job.snippet.render.return_value = {}
        generated_output = job.render()
        self.assertEqual(generated_output, expected_output)

        # Custom limits only

        # Lifetime limit only
        job = JobFactory.create(
            client_limit_per_week=9,
            client_limit_per_fortnight=99,
            campaign__slug='demo_campaign_2',
        )
        expected_output = {
            'id': str(job.id),
            'weight': 100,
            'campaign': 'demo_campaign_2',
            'targeting': '',
            'frequency': {
                'custom': [{
                    'period': 604800000,
                    'cap': 9
                }, {
                    'period': 1296000000,
                    'cap': 99
                }]
            }
        }
        job.snippet.render = Mock()
        job.snippet.render.return_value = {}
        generated_output = job.render()
        self.assertEqual(generated_output, expected_output)
Exemple #16
0
 def test_only_scheduled_all(self):
     job1, job2 = JobFactory.create_batch(2)
     job3 = JobFactory.create(publish_end=datetime(2019, 2, 2))
     filtr = JobFilter(QueryDict(query_string='only_scheduled=all'),
                       queryset=models.Job.objects.all())
     self.assertEqual(set([job1, job2, job3]), set(filtr.qs))
    def test_base(self):
        JobFactory.create(
            id=1000,
            status=Job.COMPLETED,
            publish_start=date(2020, 1, 1),
            completed_on=date(2020, 1, 10),
        )
        JobFactory.create(id=2000)
        JobDailyPerformance(date=date(2020, 1, 9),
                            impression=100,
                            job=Job.objects.get(id=1000)).save()

        rows = [
            [
                {
                    'message_id': '1000',
                    'event_context': '{}',
                    'event': 'CLICK_BUTTON',
                    'channel': 'release',
                    'country_code': 'GR',
                    'counts': 5,
                    'no_clients': 2,
                    'no_clients_total': 0,
                },
                {
                    'message_id': '1000',
                    'event_context': '{}',
                    'event': 'IMPRESSION',
                    'channel': 'release',
                    'country_code': 'ES',
                    'counts': 30,
                    'no_clients': 10,
                    'no_clients_total': 0,
                },
                {
                    'message_id': '1000',
                    'event_context': '{}',
                    'event': 'IMPRESSION',
                    'channel': 'release',
                    'country_code': 'IT',
                    'counts': 50,
                    'no_clients': 20,
                    'no_clients_total': 0,
                },
                {
                    'message_id': '1000',
                    'event_context': '{}',
                    'event': 'BLOCK',
                    'channel': 'releases',
                    'country_code': 'UK',
                    'counts': 23,
                    'no_clients': 9,
                    'no_clients_total': 0,
                },
                {
                    'message_id': '1000',
                    'event_context': '{}',
                    'event': 'BLOCK',
                    'channel': 'beta-test',
                    'country_code': 'SW',
                    'counts': 27,
                    'no_clients': 50,
                    'no_clients_total': 0,
                },
                # To be discarded
                {
                    'message_id': '500',
                    'event_context': '{}',
                    'event': 'CLICK',
                    'channel': 'demo',
                    'country_code': 'GR',
                    'counts': 5,
                    'no_clients': 10,
                    'no_clients_total': 0,
                },
                {
                    'message_id': '1000',
                    'event_context': '',
                    'event': 'CLICK',
                    'channel': 'release',
                    'country_code': 'GR',
                    'counts': 6,
                    'no_clients': 10,
                    'no_clients_total': 0,
                },
                {
                    'message_id': '2000',
                    'event_context': '{}',
                    'event': 'CLICK_BUTTON',
                    'additional_properties':
                    '{"value": "scene1-button-learn-more", "foo": "bar"}',
                    'channel': 'release',
                    'country_code': 'GR',
                    'counts': 44,
                    'no_clients': 33,
                    'no_clients_total': 0,
                },
                {
                    'message_id': '2000',
                    'event_context': '{}',
                    'event': 'CLICK_BUTTON',
                    'channel': 'release',
                    'country_code': 'BG',
                    'counts': 3,
                    'no_clients': 10,
                    'no_clients_total': 0,
                },
                {
                    'message_id': '2000',
                    'event_context': '{}',
                    'event': 'CLICK_BUTTON',
                    'channel': 'release',
                    'country_code': 'AL',
                    'counts': 1,
                    'no_clients': 10,
                    'no_clients_total': 0,
                },
                {
                    'message_id': '2000',
                    'event_context': 'conversion-subscribe-activation',
                    'event': 'CLICK_BUTTON',
                    'additional_properties': '{"foo": "bar"}',
                    'channel': 'release',
                    'country_code': 'GR',
                    'counts': 5,
                    'no_clients': 8,
                    'no_clients_total': 0,
                },
                {
                    'message_id': '2000',
                    'event_context': 'subscribe-error',
                    'event': 'CLICK_BUTTON',
                    'additional_properties': '{"foo": "bar"}',
                    'channel': 'release',
                    'country_code': 'GR',
                    'counts': 3,
                    'no_clients': 4,
                    'no_clients_total': 0,
                },
                {
                    'message_id': '2000',
                    'event_context': 'subscribe-success',
                    'event': 'CLICK_BUTTON',
                    'channel': 'release',
                    'country_code': 'ERROR',
                    'counts': 9,
                    'no_clients': 57,
                    'no_clients_total': 0,
                },
                {
                    'message_id': '2000',
                    'event_context': '',
                    'event': 'DISMISS',
                    'channel': 'beta',
                    'country_code': 'ERROR',
                    'counts': 1,
                    'no_clients': 1,
                    'no_clients_total': 0,
                },
            ],
            [
                {
                    'message_id': '1000',
                    'event_context': '',
                    'event': 'IMPRESSION',
                    'channel': 'release',
                    'country_code': 'ES',
                    'counts': 0,
                    'no_clients': 0,
                    'no_clients_total': 232,
                },
                {
                    'message_id': '1000',
                    'event_context': '',
                    'event': 'IMPRESSION',
                    'channel': 'release',
                    'country_code': 'IT',
                    'counts': 0,
                    'no_clients': 0,
                    'no_clients_total': 421,
                },
            ],
        ]

        with patch('snippets.base.etl.redash_rows') as redash_rows_mock:
            redash_rows_mock.side_effect = rows
            result = etl.update_job_metrics(date(2020, 1, 10))

        self.assertEqual(redash_rows_mock.call_count, 2)
        self.assertTrue(result)
        self.assertEqual(JobDailyPerformance.objects.count(), 3)

        jdp1 = JobDailyPerformance.objects.filter(
            job_id=1000).order_by('-id')[0]
        self.assertEqual(jdp1.impression, 80)
        self.assertEqual(jdp1.impression_no_clients, 30)
        self.assertEqual(jdp1.impression_no_clients_total, 653)
        self.assertEqual(jdp1.click, 11)
        self.assertEqual(jdp1.click_no_clients, 12)
        self.assertEqual(jdp1.click_no_clients_total, 0)
        self.assertEqual(jdp1.block, 50)
        self.assertEqual(jdp1.block_no_clients, 59)
        self.assertEqual(jdp1.block_no_clients_total, 0)
        self.assertEqual(jdp1.dismiss, 0)
        self.assertEqual(jdp1.dismiss_no_clients, 0)
        self.assertEqual(jdp1.dismiss_no_clients_total, 0)
        self.assertEqual(jdp1.go_to_scene2, 0)
        self.assertEqual(jdp1.go_to_scene2_no_clients, 0)
        self.assertEqual(jdp1.go_to_scene2_no_clients_total, 0)
        self.assertEqual(jdp1.subscribe_error, 0)
        self.assertEqual(jdp1.subscribe_error_no_clients, 0)
        self.assertEqual(jdp1.subscribe_error_no_clients_total, 0)
        self.assertEqual(jdp1.subscribe_success, 0)
        self.assertEqual(jdp1.subscribe_success_no_clients, 0)
        self.assertEqual(jdp1.subscribe_success_no_clients_total, 0)
        self.assertEqual(jdp1.other_click, 0)
        self.assertEqual(jdp1.other_click_no_clients, 0)
        self.assertEqual(jdp1.other_click_no_clients_total, 0)
        self.assertEqual(len(jdp1.details), 5)
        for detail in [{
                'event': 'click',
                'counts': 11,
                'channel': 'release',
                'country': 'GR',
                'no_clients': 12,
                'no_clients_total': 0
        }, {
                'event': 'impression',
                'counts': 30,
                'channel': 'release',
                'country': 'ES',
                'no_clients': 10,
                'no_clients_total': 232
        }, {
                'event': 'impression',
                'counts': 50,
                'channel': 'release',
                'country': 'IT',
                'no_clients': 20,
                'no_clients_total': 421
        }, {
                'event': 'block',
                'counts': 23,
                'channel': 'release',
                'country': 'UK',
                'no_clients': 9,
                'no_clients_total': 0
        }, {
                'event': 'block',
                'counts': 27,
                'channel': 'beta',
                'country': 'SW',
                'no_clients': 50,
                'no_clients_total': 0
        }]:
            self.assertTrue(detail in jdp1.details)

        jdp2 = JobDailyPerformance.objects.get(job_id=2000)
        self.assertEqual(jdp2.impression, 0)
        self.assertEqual(jdp2.impression_no_clients, 0)
        self.assertEqual(jdp2.impression_no_clients_total, 0)
        self.assertEqual(jdp2.click, 5)
        self.assertEqual(jdp2.click_no_clients, 8)
        self.assertEqual(jdp2.click_no_clients_total, 0)
        self.assertEqual(jdp2.block, 0)
        self.assertEqual(jdp2.block_no_clients, 0)
        self.assertEqual(jdp2.block_no_clients_total, 0)
        self.assertEqual(jdp2.dismiss, 1)
        self.assertEqual(jdp2.dismiss_no_clients, 1)
        self.assertEqual(jdp2.dismiss_no_clients_total, 0)
        self.assertEqual(jdp2.go_to_scene2, 44)
        self.assertEqual(jdp2.go_to_scene2_no_clients, 33)
        self.assertEqual(jdp2.go_to_scene2_no_clients_total, 0)
        self.assertEqual(jdp2.subscribe_error, 3)
        self.assertEqual(jdp2.subscribe_error_no_clients, 4)
        self.assertEqual(jdp2.subscribe_error_no_clients_total, 0)
        self.assertEqual(jdp2.subscribe_success, 9)
        self.assertEqual(jdp2.subscribe_success_no_clients, 57)
        self.assertEqual(jdp2.subscribe_success_no_clients_total, 0)
        self.assertEqual(jdp2.other_click, 4)
        self.assertEqual(jdp2.other_click_no_clients, 20)
        self.assertEqual(jdp2.other_click_no_clients_total, 0)
        self.assertEqual(len(jdp2.details), 7)
        for detail in [{
                'event': 'go_to_scene2',
                'counts': 44,
                'channel': 'release',
                'country': 'GR',
                'no_clients': 33,
                'no_clients_total': 0
        }, {
                'event': 'other_click',
                'counts': 3,
                'channel': 'release',
                'country': 'BG',
                'no_clients': 10,
                'no_clients_total': 0
        }, {
                'event': 'other_click',
                'counts': 1,
                'channel': 'release',
                'country': 'AL',
                'no_clients': 10,
                'no_clients_total': 0
        }, {
                'event': 'click',
                'counts': 5,
                'channel': 'release',
                'country': 'GR',
                'no_clients': 8,
                'no_clients_total': 0
        }, {
                'event': 'subscribe_error',
                'counts': 3,
                'channel': 'release',
                'country': 'GR',
                'no_clients': 4,
                'no_clients_total': 0
        }, {
                'event': 'subscribe_success',
                'counts': 9,
                'channel': 'release',
                'country': 'XX',
                'no_clients': 57,
                'no_clients_total': 0
        }, {
                'event': 'dismiss',
                'counts': 1,
                'channel': 'beta',
                'country': 'XX',
                'no_clients': 1,
                'no_clients_total': 0
        }]:
            self.assertTrue(detail in jdp2.details)
Exemple #18
0
    def test_base(self):
        now = datetime.utcnow()
        job_without_end_date = JobFactory(status=models.Job.PUBLISHED,
                                          publish_end=None)
        job_that_has_ended = JobFactory(status=models.Job.PUBLISHED,
                                        publish_end=now)
        job_ending_in_the_future = JobFactory(status=models.Job.PUBLISHED,
                                              limit_impressions=10000,
                                              metric_last_update=now,
                                              publish_end=now +
                                              timedelta(days=1))
        job_scheduled_not_ready_to_go = JobFactory(status=models.Job.SCHEDULED,
                                                   publish_start=now)
        job_scheduled_ready_to_go = JobFactory(status=models.Job.SCHEDULED,
                                               publish_start=now -
                                               timedelta(minutes=10))
        job_scheduled_in_the_future = JobFactory(status=models.Job.SCHEDULED,
                                                 publish_start=now +
                                                 timedelta(days=1))
        job_impression_limit_reached = JobFactory(status=models.Job.PUBLISHED,
                                                  limit_impressions=10000,
                                                  metric_impressions=10000,
                                                  metric_last_update=now,
                                                  publish_end=now +
                                                  timedelta(days=1))
        job_click_limit_reached = JobFactory(status=models.Job.PUBLISHED,
                                             limit_impressions=10000,
                                             metric_impressions=1000,
                                             limit_clicks=1000,
                                             metric_clicks=1001,
                                             metric_last_update=now,
                                             publish_end=now +
                                             timedelta(days=1))
        job_block_limit_reached = JobFactory(
            status=models.Job.PUBLISHED,
            limit_blocks=10,
            metric_blocks=1000,
            metric_last_update=now - timedelta(minutes=30),
            publish_end=now + timedelta(days=1))
        job_impression_limit_not_reached = JobFactory(
            status=models.Job.PUBLISHED,
            limit_impressions=100,
            metric_impressions=10,
            metric_last_update=now - timedelta(hours=12),
            publish_end=now + timedelta(days=1))
        job_click_limit_not_reached = JobFactory(
            status=models.Job.PUBLISHED,
            limit_clicks=100,
            metric_clicks=10,
            metric_last_update=now - timedelta(hours=1),
            publish_end=now + timedelta(days=1))
        job_block_limit_not_reached = JobFactory(status=models.Job.PUBLISHED,
                                                 limit_blocks=100,
                                                 metric_blocks=10,
                                                 metric_last_update=now,
                                                 publish_end=now +
                                                 timedelta(days=1))
        job_impression_limit_not_reached_but_no_data = JobFactory(
            status=models.Job.PUBLISHED,
            limit_impressions=100,
            metric_impressions=10,
            metric_last_update=now - timedelta(hours=26),
            publish_end=now + timedelta(days=1))
        job_click_limit_not_reached_but_no_data = JobFactory(
            status=models.Job.PUBLISHED,
            limit_clicks=100,
            metric_clicks=10,
            metric_last_update=now - timedelta(hours=30),
            publish_end=now + timedelta(days=1))
        job_block_limit_not_reached_but_no_data = JobFactory(
            status=models.Job.PUBLISHED,
            limit_blocks=100,
            metric_blocks=10,
            metric_last_update=now - timedelta(hours=40),
            publish_end=now + timedelta(days=1))
        job_block_limit_not_reached_just_created = JobFactory(
            status=models.Job.PUBLISHED,
            limit_blocks=100,
            metric_blocks=10,
            publish_end=now + timedelta(days=1))

        job_cancelled = JobFactory(status=models.Job.CANCELED)
        job_completed = JobFactory(status=models.Job.COMPLETED)

        call_command('update_jobs', stdout=Mock())

        job_without_end_date.refresh_from_db()
        job_that_has_ended.refresh_from_db()
        job_ending_in_the_future.refresh_from_db()
        job_scheduled_not_ready_to_go.refresh_from_db()
        job_scheduled_ready_to_go.refresh_from_db()
        job_scheduled_in_the_future.refresh_from_db()
        job_cancelled.refresh_from_db()
        job_completed.refresh_from_db()
        job_impression_limit_reached.refresh_from_db()
        job_click_limit_reached.refresh_from_db()
        job_block_limit_reached.refresh_from_db()
        job_impression_limit_not_reached.refresh_from_db()
        job_click_limit_not_reached.refresh_from_db()
        job_block_limit_not_reached.refresh_from_db()
        job_impression_limit_not_reached_but_no_data.refresh_from_db()
        job_click_limit_not_reached_but_no_data.refresh_from_db()
        job_block_limit_not_reached_but_no_data.refresh_from_db()
        job_block_limit_not_reached_just_created.refresh_from_db()

        self.assertEqual(job_without_end_date.status, models.Job.PUBLISHED)
        self.assertEqual(job_that_has_ended.status, models.Job.COMPLETED)
        self.assertEqual(job_ending_in_the_future.status, models.Job.PUBLISHED)
        self.assertEqual(job_scheduled_not_ready_to_go.status,
                         models.Job.SCHEDULED)
        self.assertEqual(job_scheduled_ready_to_go.status,
                         models.Job.PUBLISHED)
        self.assertEqual(job_scheduled_in_the_future.status,
                         models.Job.SCHEDULED)
        self.assertEqual(job_cancelled.status, models.Job.CANCELED)
        self.assertEqual(job_completed.status, models.Job.COMPLETED)
        self.assertEqual(job_impression_limit_reached.status,
                         models.Job.COMPLETED)
        self.assertEqual(job_click_limit_reached.status, models.Job.COMPLETED)
        self.assertEqual(job_block_limit_reached.status, models.Job.COMPLETED)
        self.assertEqual(job_impression_limit_not_reached.status,
                         models.Job.PUBLISHED)
        self.assertEqual(job_click_limit_not_reached.status,
                         models.Job.PUBLISHED)
        self.assertEqual(job_block_limit_not_reached.status,
                         models.Job.PUBLISHED)
        self.assertEqual(job_impression_limit_not_reached_but_no_data.status,
                         models.Job.COMPLETED)
        self.assertEqual(job_click_limit_not_reached_but_no_data.status,
                         models.Job.COMPLETED)
        self.assertEqual(job_block_limit_not_reached_but_no_data.status,
                         models.Job.COMPLETED)
        self.assertEqual(job_block_limit_not_reached_just_created.status,
                         models.Job.PUBLISHED)
Exemple #19
0
    def test_generation(self):
        target = TargetFactory(on_release=True,
                               on_beta=True,
                               on_nightly=False,
                               on_esr=False,
                               on_aurora=False)
        # Draft, completed, scheduled or cancelled
        JobFactory(
            status=models.Job.DRAFT,
            snippet__locale=',en,',
            targets=[target],
        )
        JobFactory(
            status=models.Job.COMPLETED,
            snippet__locale=',en,',
            targets=[target],
        )
        JobFactory(
            status=models.Job.SCHEDULED,
            snippet__locale=',en,',
            targets=[target],
        )
        JobFactory(
            status=models.Job.CANCELED,
            snippet__locale=',en,',
            targets=[target],
        )
        JobFactory(
            status=models.Job.PUBLISHED,
            snippet__locale=',en,',
            targets=[target],
            distribution__name='not-default',
        )

        # Jobs to be included in the bundle
        published_job_1 = JobFactory(
            status=models.Job.PUBLISHED,
            snippet__locale=',en,',
            targets=[target],
        )
        published_job_2 = JobFactory(
            status=models.Job.PUBLISHED,
            snippet__locale=',en,',
            targets=[target],
            distribution__name='other-distribution-part-of-default-bundle',
        )

        # Add Distribution to the Default DistributionBundle
        models.DistributionBundle.objects.get(
            name='Default').distributions.add(
                models.Distribution.objects.get(
                    name='other-distribution-part-of-default-bundle'))

        with patch.multiple(
                'snippets.base.management.commands.generate_bundles',
                json=DEFAULT,
                product_details=DEFAULT,
                default_storage=DEFAULT) as mock:
            mock['json'].dumps.return_value = ''
            mock['product_details'].languages.keys.return_value = [
                'fr', 'en-us', 'en-au'
            ]
            call_command('generate_bundles', stdout=Mock())

        self.assertEqual(mock['default_storage'].save.call_count, 4)

        mock['default_storage'].save.assert_has_calls([
            call('pregen/Firefox/release/en-us/default.json', ANY),
            call('pregen/Firefox/release/en-au/default.json', ANY),
            call('pregen/Firefox/beta/en-us/default.json', ANY),
            call('pregen/Firefox/beta/en-au/default.json', ANY),
        ],
                                                      any_order=True)

        # Check that there's only one job included in the bundle and that it's
        # the correct one.
        self.assertEqual(
            len(mock['json'].dumps.call_args_list[0][0][0]['messages']), 2)
        self.assertEqual(
            set([
                mock['json'].dumps.call_args_list[0][0][0]['messages'][0]
                ['id'],
                mock['json'].dumps.call_args_list[0][0][0]['messages'][1]['id']
            ]), set([str(published_job_1.id),
                     str(published_job_2.id)]))
Exemple #20
0
    def test_base(self):
        job_running = JobFactory(
            status=models.Job.PUBLISHED,
            publish_start='2050-01-05 01:00',
            publish_end='2050-01-08 02:00',
            limit_impressions=1000,
        )
        # Without end date
        job_running2 = JobFactory(
            status=models.Job.PUBLISHED,
            publish_start='2050-01-04 01:00',
            publish_end=None,
            limit_blocks=1000,
        )
        request_data_first = {
            'start_date': '2050-01-05',
            'end_date': '2050-01-06',
            'message_id': job_running.id,
        }
        request_data_second = {
            'start_date': '2050-01-04',
            'end_date': '2050-01-06',
            'message_id': job_running2.id,
        }
        return_data_first = {
            'query_result': {
                'data': {
                    'rows': [{
                        'event': 'IMPRESSION',
                        'counts': 100,
                    }, {
                        'event': 'BLOCK',
                        'counts': 10,
                    }, {
                        'event': 'CLICK',
                        'counts': 50,
                    }, {
                        'event': 'CLICK_BUTTON',
                        'counts': 60,
                    }]
                }
            }
        }
        return_data_second = {
            'query_result': {
                'data': {
                    'rows': [{
                        'event': 'IMPRESSION',
                        'counts': 250,
                    }, {
                        'event': 'BLOCK',
                        'counts': 100,
                    }, {
                        'event': 'CLICK',
                        'counts': 25,
                    }, {
                        'event': 'CLICK_BUTTON',
                        'counts': 10,
                    }]
                }
            }
        }

        with patch(
                'snippets.base.management.commands.fetch_metrics.RedashDynamicQuery'
        ) as rdq:
            with patch(
                    'snippets.base.management.commands.fetch_metrics.datetime',
                    wraps=datetime) as datetime_mock:  # noqa
                datetime_mock.utcnow.return_value = datetime(2050, 1, 6)
                rdq.return_value.query.side_effect = [
                    return_data_first, return_data_second
                ]
                call_command('fetch_metrics', stdout=Mock())

        rdq.return_value.query.assert_has_calls([
            call(settings.REDASH_JOB_QUERY_BIGQUERY_ID, request_data_first),
            call(settings.REDASH_JOB_QUERY_BIGQUERY_ID, request_data_second),
        ])

        job_running.refresh_from_db()
        self.assertEqual(job_running.metric_impressions, 100)
        self.assertEqual(job_running.metric_blocks, 10)
        self.assertEqual(job_running.metric_clicks, 110)

        job_running2.refresh_from_db()
        self.assertEqual(job_running2.metric_impressions, 250)
        self.assertEqual(job_running2.metric_blocks, 100)
        self.assertEqual(job_running2.metric_clicks, 35)
 def test_base(self):
     JobFactory.create_batch(2)
     client = Client()
     response = client.get(reverse('ical-feed'), follow=True)
     self.assertEqual(response.status_code, 200)
 def setUp(self):
     self.job1, self.job2 = JobFactory.create_batch(2)