Example #1
0
    def test_insights_start_dates_adjust_if_inside_window(self):
        input_date = pendulum.today().subtract(months=1)
        expected_date = input_date.subtract(days=28)
        insights = AdsInsights(name='insights',
                               account=None,
                               stream_alias="insights",
                               options={},
                               catalog_entry=self.fake_catalog_entry,
                               state={
                                   'bookmarks': {
                                       'insights': {
                                           'date_start':
                                           input_date.to_date_string()
                                       }
                                   }
                               })
        params = list(itertools.islice(insights.job_params(), 5))

        self.assertEqual(params[0]['time_ranges'],
                         [{
                             'since': expected_date.to_date_string(),
                             'until': expected_date.to_date_string()
                         }])

        expected_date = expected_date.add(days=4)
        self.assertEqual(params[4]['time_ranges'],
                         [{
                             'since': expected_date.to_date_string(),
                             'until': expected_date.to_date_string()
                         }])
Example #2
0
    def test_insights_start_dates(self):
        insights = AdsInsights(
            name='insights',
            account=None,
            stream_alias="insights",
            options={},
            annotated_schema=Schema.from_dict({
                'selected': True,
                'properties': {
                    'something': {
                        'type': 'object'
                    }
                }
            }),
            state={'bookmarks': {
                'insights': {
                    'date_start': '2017-01-31'
                }
            }})
        params = list(itertools.islice(insights.job_params(), 5))
        self.assertEqual(params[0]['time_ranges'], [{
            'since': '2017-01-03',
            'until': '2017-01-03'
        }])

        self.assertEqual(params[4]['time_ranges'], [{
            'since': '2017-01-07',
            'until': '2017-01-07'
        }])
Example #3
0
    def test_job_polling_retry(self):
        """AdInsights.api_get() polls the job status of an insights job we've requested
        that Facebook generate. This test makes a request with a mock response to
        raise a 400 status error that should be retried.

        We expect the tap to retry this request up to 5 times for each insights job attempted.
        """

        mocked_api_get = Mock()
        mocked_api_get.side_effect = FacebookRequestError(
            message='Unsupported get request; Object does not exist',
            request_context={"":Mock()},
            http_status=400,
            http_headers=Mock(),
            body={"error": {"error_subcode": 33}}
        )
        # Create the mock and force the function to throw an error
        mocked_account = Mock()
        mocked_account.get_insights = Mock()
        mocked_account.get_insights.return_value.api_get = mocked_api_get


        # Initialize the object and call `sync()`
        ad_insights_object = AdsInsights('', mocked_account, '', '', {}, {})
        with self.assertRaises(FacebookRequestError):
            ad_insights_object.run_job({})
        # 5 is the max tries specified in the tap
        self.assertEquals(25, mocked_account.get_insights.return_value.api_get.call_count)
        self.assertEquals(5, mocked_account.get_insights.call_count )
    def test_insights_job_params_stops(self):
        start_date = pendulum.today().subtract(days=2)
        insights = AdsInsights(name='insights',
                               account=None,
                               stream_alias="insights",
                               options={},
                               catalog_entry=CatalogEntry(schema={
                                   'properties': {
                                       'something': {
                                           'type': 'object'
                                       }
                                   }
                               },
                                                          metadata=[{
                                                              'breadcrumb':
                                                              ('properties',
                                                               'something'),
                                                              'metadata': {
                                                                  'selected':
                                                                  True
                                                              }
                                                          }]),
                               state={
                                   'bookmarks': {
                                       'insights': {
                                           'date_start':
                                           start_date.to_date_string()
                                       }
                                   }
                               })

        self.assertEqual(31, len(list(insights.job_params())))
    def test_insights_start_dates(self):
        insights = AdsInsights(
            name='insights',
            account=None,
            stream_alias="insights",
            options={},
            catalog_entry=CatalogEntry(
                schema={'properties': {
                    'something': {
                        'type': 'object'
                    }
                }},
                metadata=[{
                    'breadcrumb': ('properties', 'something'),
                    'metadata': {
                        'selected': True
                    }
                }]),
            state={'bookmarks': {
                'insights': {
                    'date_start': '2017-01-31'
                }
            }})
        params = list(itertools.islice(insights.job_params(), 5))
        self.assertEqual(params[0]['time_ranges'], [{
            'since': '2017-01-03',
            'until': '2017-01-03'
        }])

        self.assertEqual(params[4]['time_ranges'], [{
            'since': '2017-01-07',
            'until': '2017-01-07'
        }])
Example #6
0
    def test_insights_job_params_stops(self):
        start_date = pendulum.today().subtract(days=2)
        insights = AdsInsights(name='insights',
                               account=None,
                               stream_alias="insights",
                               options={},
                               catalog_entry=self.fake_catalog_entry,
                               state={
                                   'bookmarks': {
                                       'insights': {
                                           'date_start':
                                           start_date.to_date_string()
                                       }
                                   }
                               })

        self.assertEqual(31, len(list(insights.job_params())))
Example #7
0
    def test_retries_on_type_error(self):
        """`AdInsights.run_job()` calls a `facebook_business` method, `get_insights()`, to make a request to
        the API. We want to mock this to throw a `TypeError("string indices must be integers")` and
        assert that we retry this specific error.
        """

        # Create the mock and force the function to throw an error
        mocked_account = Mock()
        mocked_account.get_insights = Mock()
        mocked_account.get_insights.side_effect = TypeError("string indices must be integers")

        # Initialize the object and call `sync()`
        ad_creative_object = AdsInsights('', mocked_account, '', '', {}, {})
        with self.assertRaises(TypeError):
            ad_creative_object.run_job({})
        # 5 is the max tries specified in the tap
        self.assertEquals(5, mocked_account.get_insights.call_count )
Example #8
0
    def test_insights_job_params_stops(self):
        start_date = tap_facebook.TODAY.subtract(days=2)
        insights = AdsInsights(name='insights',
                               account=None,
                               breakdowns=[],
                               annotated_schema={
                                   'selected': True,
                                   'properties': {
                                       'something': {
                                           'type': 'object'
                                       }
                                   }
                               },
                               state=tap_facebook.State(
                                   start_date.to_date_string(), None))

        self.assertEqual(3, len(list(insights.job_params())))
Example #9
0
    def test_run_job(self, mocked_sleep):
        """ 
            AdsInsights.run_job calls a `facebook_business` method,`get_insights()`, to get a batch of insights. 
            We mock this method to raise a `AttributeError` and expect the tap to retry this that function up to 5 times,
            which is the current hard coded `max_tries` value.
        """

        # Mock get_insights function to throw AttributeError exception
        mocked_account = Mock()
        mocked_account.get_insights = Mock()
        mocked_account.get_insights.side_effect = AttributeError

        # Call run_job() function of Campaigns and verify AttributeError is raised
        ads_insights_object = AdsInsights('', mocked_account, '', '', '', {})
        with self.assertRaises(AttributeError):
            ads_insights_object.run_job('test')

        # verify get_insights() is called 5 times as max 5 reties provided for function
        self.assertEquals(mocked_account.get_insights.call_count, 5)
Example #10
0
    def test_retries_on_bad_data(self):
        """`AdInsights.run_job()` calls a `facebook_business` method,
        `get_insights()`, to make a request to the API. We mock this
        method to raise a `FacebookBadObjectError`

        We expect the tap to retry this request up to 5 times, which is
        the current hard coded `max_tries` value.
        """

        # Create the mock and force the function to throw an error
        mocked_account = Mock()
        mocked_account.get_insights = Mock()
        mocked_account.get_insights.side_effect = FacebookBadObjectError("Bad data to set object data")

        # Initialize the object and call `sync()`
        ad_creative_object = AdsInsights('', mocked_account, '', '', {}, {})
        with self.assertRaises(FacebookBadObjectError):
            ad_creative_object.run_job({})
        # 5 is the max tries specified in the tap
        self.assertEquals(5, mocked_account.get_insights.call_count )
Example #11
0
    def test_job_polling_retry_succeeds_eventually(self):
        """AdInsights.api_get() polls the job status of an insights job we've requested
        that Facebook generate. This test makes a request with a mock response to
        raise a 400 status error that should be retried.

        We expect the tap to retry this request up to 5 times for each insights job attempted.
        """

        mocked_bad_response = FacebookRequestError(
                message='Unsupported get request; Object does not exist',
                request_context={"":Mock()},
                http_status=400,
                http_headers=Mock(),
                body={"error": {"error_subcode": 33}}
            )

        mocked_good_response = {
            "async_status": "Job Completed",
            "async_percent_completion": 100,
            "id": "2134"
        }

        mocked_api_get = Mock()
        mocked_api_get.side_effect = [
            mocked_bad_response,
            mocked_bad_response,
            mocked_good_response
        ]

        # Create the mock and force the function to throw an error
        mocked_account = Mock()
        mocked_account.get_insights = Mock()
        mocked_account.get_insights.return_value.api_get = mocked_api_get

        # Initialize the object and call `sync()`
        ad_insights_object = AdsInsights('', mocked_account, '', '', {}, {})
        ad_insights_object.run_job({})
        self.assertEquals(3, mocked_account.get_insights.return_value.api_get.call_count)
        self.assertEquals(1, mocked_account.get_insights.call_count)
Example #12
0
    def test_insights_start_dates(self):
        insights = AdsInsights(name='insights',
                               account=None,
                               breakdowns=[],
                               annotated_schema={
                                   'selected': True,
                                   'properties': {
                                       'something': {
                                           'type': 'object'
                                       }
                                   }
                               },
                               state=tap_facebook.State('2017-01-31', None))
        params = list(itertools.islice(insights.job_params(), 5))
        self.assertEqual(params[0]['time_ranges'], [{
            'since': '2017-01-03',
            'until': '2017-01-31'
        }])

        self.assertEqual(params[4]['time_ranges'], [{
            'since': '2017-01-07',
            'until': '2017-02-04'
        }])
Example #13
0
    def test_insights_job_params_stops(self):
        start_date = tap_facebook.TODAY.subtract(days=2)
        insights = AdsInsights(name='insights',
                               account=None,
                               stream_alias="insights",
                               options={},
                               annotated_schema=Schema.from_dict({
                                   'selected': True,
                                   'properties': {
                                       'something': {
                                           'type': 'object'
                                       }
                                   }
                               }),
                               state={
                                   'bookmarks': {
                                       'insights': {
                                           'date_start':
                                           start_date.to_date_string()
                                       }
                                   }
                               })

        self.assertEqual(31, len(list(insights.job_params())))
Example #14
0
    def test_retries_and_good_response(self):
        """Facebook has a class called `FacebookResponse` and it is created from a `requests.Response`. Some
        `facebook_business` functions depend on calling `FacebookResponse.json()`, which sometimes returns a
        string instead of a dictionary. This leads to a `TypeError("string indices must be integers")` and
        we want to retry these.

        This test will return a "bad" API response the first time the function is called, then a
        "good" response that can be `json.loads()`. We check that the resulting object has our
        expected value in it.
        """
        FacebookAdsApi.init(access_token='access_token')

        expected_value = {"foo": "bar"}

        account = AdAccount('abc_123')
        patcher = patch('requests.Session.request')
        mocked_request = patcher.start()

        mocked_bad_response = Response()
        mocked_bad_response._content = b'images'

        mocked_good_response = Response()

        # Convert our expected value into a JSON string, and then into bytes
        byte_string = json.dumps(expected_value).encode()

        mocked_good_response._content = byte_string

        mocked_request.side_effect = [
            mocked_bad_response, mocked_good_response
        ]

        ad_creative_object = AdsInsights('', account, '', '', {}, {})
        with self.assertRaises(TypeError):
            ad_creative_object.account.get_insights(params={}, is_async=True)

        actual_response = ad_creative_object.account.get_insights(
            params={}, is_async=True)

        self.assertDictEqual(expected_value, actual_response._json)

        # Clean up tests
        patcher.stop()