Пример #1
0
 def test_create_invalid_decisioning_method(self):
     options = {
         "client": "clientId",
         "organization_id": "orgId",
         "decisioning_method": "bad decisions"
     }
     with self.assertRaises(Exception) as err:
         TargetClient.create(options)
     self.assertEqual(
         str(err.exception),
         "Invalid Decisioning Method.  Must be set to one of: hybrid,on-device,server-side"
     )
Пример #2
0
    def test_get_offers_server_side(self):
        expected_result = deepcopy(EXPECTED_PREFETCH_RESULT)
        expected_result["response"]["edgeHost"] = "mboxedge28.tt.omtrdc.net"
        expected_result["target_location_hint_cookie"] = {
            "name": "mboxEdgeCluster",
            "value": "28",
            "maxAge": 1860
        }
        expected_result["meta"] = {
            "decisioning_method": DecisioningMethod.SERVER_SIDE.value
        }

        get_offers_opts = {
            "request": PREFETCH_REQUEST,
            "session_id": "dummy_session"
        }

        client_opts = dict(CONFIG)
        client_opts["decisioning_method"] = DecisioningMethod.SERVER_SIDE.value

        with patch.object(DeliveryApi, "execute", return_value=create_delivery_response(DELIVERY_API_RESPONSE)):
            client = TargetClient.create(client_opts)
            result = client.get_offers(get_offers_opts)
            result_dict = to_dict(result)
            expect_to_match_object(result_dict, expected_result)
Пример #3
0
    def test_get_offers_async_error(self):
        setup_mock("invalid_request", responses, 400)

        shared = {"has_response": False}
        client_options = {"client": "bad", "organization_id": "bad"}
        client = TargetClient.create(client_options)

        def callback():
            self.fail("Error callback should have been invoked")

        def err_callback(error):
            self.assertEqual(error.status, 400)
            self.assertEqual(
                json.loads(error.body), {
                    "status": 400,
                    "message": "Invalid request: Invalid imsOrg -  bad"
                })
            shared["has_response"] = True

        async_opts = deepcopy(self.get_offers_options)
        async_opts["request"] = create_delivery_request(async_opts["request"])
        async_opts["callback"] = callback
        async_opts["err_callback"] = err_callback
        thread = client.get_offers(async_opts)

        try:
            thread.get(
                timeout=5)  # Blocks current thread to keep test runner alive
        except multiprocessing.context.TimeoutError:
            self.fail("Test case timed out waiting for callback to be invoked")
        except delivery_api_client.exceptions.ApiException:
            pass  # thread.get re-throws exception, but we"ve already handled inside err_callback

        self.assertTrue(shared.get("has_response"))
Пример #4
0
    def test_get_offers_on_device_decisioning_emits_notifications(self):
        get_offers_opts = {
            "request": EXECUTE_REQUEST,
            "session_id": "dummy_session"
        }

        client_opts = dict(CONFIG)
        client_opts["decisioning_method"] = DecisioningMethod.ON_DEVICE.value
        client_opts["target_location_hint"] = "28"

        # send_notifications call
        with patch.object(DeliveryApi, "execute", return_value=create_delivery_response({})) \
                as mock_delivery_api:

            with patch("target_decisioning_engine.artifact_provider.urllib3.PoolManager") as mock_artifact_provider:
                artifact_instance = mock_artifact_provider.return_value
                artifact_response = HTTPResponse(status=OK, body=json.dumps(ARTIFACT_AB_SIMPLE))
                artifact_instance.request.return_value = artifact_response

                client = TargetClient.create(client_opts)
                self.assertEqual(mock_artifact_provider.call_count, 1)

                result = client.get_offers(get_offers_opts)
                self.assertIsNotNone(result.get("response"))
                self.assertEqual(result.get("response").status, OK)
                self.assertIsNotNone(result.get("response").execute)

                time.sleep(1)  # notifications sent async
                self.assertEqual(mock_delivery_api.call_count, 1)
                notification_request = to_dict(mock_delivery_api.call_args[0][2])
                expect_to_match_object(notification_request, EXPECTED_NOTIFICATION_REQUEST)
Пример #5
0
    def test_get_offers_does_remote_request_if_hybrid_request_and_decisioning_engine_not_ready(
            self):
        get_offers_opts = {
            "request": TARGET_REQUEST_DICT,
            "session_id": "dummy_session",
            "decisioning_method": DecisioningMethod.HYBRID.value
        }
        get_offers_opts["request"]["prefetch"] = {
            "mboxes": [{
                "name": "mbox-feature-flags",
                "index": 1
            }]
        }
        get_offers_opts["request"] = create_delivery_request(
            get_offers_opts["request"])

        client_opts = dict(CONFIG)
        client_opts["decisioning_method"] = DecisioningMethod.SERVER_SIDE.value

        with patch.object(DeliveryApi, "execute", return_value=create_delivery_response(DELIVERY_RESPONSE)) \
                as mock_delivery_api:
            client = TargetClient.create(client_opts)
            result = client.get_offers(get_offers_opts)
            self.assertEqual(mock_delivery_api.call_count, 1)
            self.assertEqual(result["response"].status, OK)
            self.assertIsNotNone(result["response"].prefetch)
            self.assertEqual(result["meta"]["decisioning_method"],
                             DecisioningMethod.SERVER_SIDE.value)
            self.assertEqual(result["meta"]["remote_mboxes"], [])
            self.assertEqual(result["meta"]["remote_views"], [])
Пример #6
0
    def test_create_decisioning_method_server_side(self):
        client_ready_mock = Mock()
        client_opts = dict(CONFIG)
        client_opts["decisioning_method"] = DecisioningMethod.SERVER_SIDE.value
        client_opts["events"] = {
            "client_ready": client_ready_mock
        }

        client = TargetClient.create(client_opts)
        time.sleep(1)
        self.assertIsNotNone(client)
        self.assertIsNone(client.decisioning_engine)
        self.assertEqual(client_ready_mock.call_count, 1)
Пример #7
0
    def test_get_offers_sync_error(self):
        setup_mock("invalid_request", responses, 400)
        client_options = {"client": "bad", "organization_id": "bad"}
        client = TargetClient.create(client_options)

        get_offers_opts = deepcopy(self.get_offers_options)
        get_offers_opts["request"] = create_delivery_request(
            get_offers_opts["request"])

        with self.assertRaises(
                delivery_api_client.exceptions.ApiException) as err:
            client.get_offers(get_offers_opts)
        self.assertEqual(json.loads(err.exception.body), {
            "status": 400,
            "message": "Invalid request: Invalid imsOrg -  bad"
        })
Пример #8
0
 def setUp(self):
     client_options = {
         "client": "someClientId",
         "organization_id": "someOrgId"
     }
     self.get_attributes_options = {
         "request": {
             "context": {"channel": ChannelType.WEB},
             "execute": {
                 "mboxes": [{"name": "one"}, {"name": "two"}]
             },
             "prefetch": {
                 "mboxes": [{"name": "three"}, {"name": "four"}]
             }
         }
     }
     self.client = TargetClient.create(client_options)
Пример #9
0
    def test_get_offers_hybrid_does_remote_request_if_necessary(self):
        get_offers_opts = {
            "request": TARGET_REQUEST_DICT,
            "session_id": "dummy_session"
        }
        get_offers_opts["request"]["prefetch"] = {
            "mboxes": [{
                "name": "mbox-feature-flags",
                "index": 1
            }, {
                "name": "remote-only-mbox-a",
                "index": 2
            }, {
                "name": "remote-only-mbox-b",
                "index": 2
            }]
        }
        get_offers_opts["request"] = create_delivery_request(
            get_offers_opts["request"])

        client_opts = dict(CONFIG)
        client_opts["decisioning_method"] = DecisioningMethod.HYBRID.value

        with patch.object(DeliveryApi, "execute", return_value=create_delivery_response(DELIVERY_RESPONSE)) \
                as mock_delivery_api:
            with patch(
                    "target_decisioning_engine.artifact_provider.urllib3.PoolManager"
            ) as mock_artifact_provider:
                artifact_instance = mock_artifact_provider.return_value
                artifact_response = HTTPResponse(
                    status=OK, body=json.dumps(FEATURE_FLAG_ARTIFACT))
                artifact_instance.request.return_value = artifact_response

                client = TargetClient.create(client_opts)
                self.assertEqual(mock_artifact_provider.call_count, 1)

                result = client.get_offers(get_offers_opts)
                self.assertEqual(mock_delivery_api.call_count, 1)
                self.assertEqual(result["response"].status, OK)
                self.assertIsNotNone(result["response"].prefetch)
                self.assertEqual(result["meta"]["decisioning_method"],
                                 DecisioningMethod.HYBRID.value)
                self.assertSetEqual(
                    set(result["meta"]["remote_mboxes"]),
                    set(["remote-only-mbox-a", "remote-only-mbox-b"]))
                self.assertEqual(result["meta"]["remote_views"], [])
Пример #10
0
 def setUp(self):
     client_options = {
         "client": "someClientId",
         "organization_id": "someOrgId"
     }
     self.get_attributes_options = {
         "request": {
             "id": {
                 "tntId":
                 "338e3c1e51f7416a8e1ccba4f81acea0.28_0",
                 "marketingCloudVisitorId":
                 "07327024324407615852294135870030620007"
             },
             "context": {
                 "channel": ChannelType.WEB,
                 "mobilePlatform": None,
                 "application": None,
                 "screen": None,
                 "window": None,
                 "browser": None,
                 "address": {
                     "url": "http://adobe.com",
                     "referringUrl": None
                 },
                 "geo": None,
                 "timeOffsetInMinutes": None,
                 "userAgent":
                 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:73.0) Gecko/20100101 Firefox/73.0",
                 "beacon": False
             },
             "prefetch": {
                 "mboxes": [{
                     "name": "feature-flag-a",
                     "index": 1
                 }]
             },
             "execute": {
                 "mboxes": [{
                     "index": 1,
                     "name": "feature-flag-b"
                 }]
             }
         }
     }
     self.client = TargetClient.create(client_options)
Пример #11
0
    def test_create_decisioning_method_on_device(self):
        client_ready_mock = Mock()
        client_opts = dict(CONFIG)
        client_opts["decisioning_method"] = DecisioningMethod.ON_DEVICE.value
        client_opts["events"] = {
            "client_ready": client_ready_mock
        }

        with patch("target_decisioning_engine.artifact_provider.urllib3.PoolManager") as mock_pool_manager:
            instance = mock_pool_manager.return_value
            mock_response = HTTPResponse(status=OK, body=json.dumps(ARTIFACT_BLANK))
            instance.request.return_value = mock_response

            with patch.object(DeliveryApi, "execute", return_value=create_delivery_response(LOCATION_HINT_RESPONSE)):
                client = TargetClient.create(client_opts)
                self.assertIsNotNone(client.decisioning_engine)
                self.assertTrue(callable(client.decisioning_engine.get_offers))
                self.assertEqual(client_ready_mock.call_count, 1)
Пример #12
0
    def test_get_offers_on_device_partial_returns_206_and_remote_mbox_names(
            self):
        get_offers_opts = {
            "request": TARGET_REQUEST_DICT,
            "session_id": "dummy_session"
        }
        get_offers_opts["request"]["prefetch"] = {
            "mboxes": [{
                "name": "mbox-feature-flags",
                "index": 1
            }, {
                "name": "remote-only-mbox-a",
                "index": 2
            }, {
                "name": "remote-only-mbox-b",
                "index": 2
            }]
        }
        get_offers_opts["request"] = create_delivery_request(
            get_offers_opts["request"])

        client_opts = dict(CONFIG)
        client_opts["decisioning_method"] = DecisioningMethod.ON_DEVICE.value

        with patch(
                "target_decisioning_engine.artifact_provider.urllib3.PoolManager"
        ) as mock_artifact_provider:
            artifact_instance = mock_artifact_provider.return_value
            artifact_response = HTTPResponse(
                status=OK, body=json.dumps(FEATURE_FLAG_ARTIFACT))
            artifact_instance.request.return_value = artifact_response

            client = TargetClient.create(client_opts)
            self.assertEqual(mock_artifact_provider.call_count, 1)

            result = client.get_offers(get_offers_opts)
            self.assertEqual(result["response"].status, PARTIAL_CONTENT)
            self.assertIsNotNone(result["response"].prefetch)
            self.assertEqual(result["meta"]["decisioning_method"],
                             DecisioningMethod.ON_DEVICE.value)
            self.assertSetEqual(
                set(result["meta"]["remote_mboxes"]),
                set(["remote-only-mbox-a", "remote-only-mbox-b"]))
            self.assertEqual(result["meta"]["remote_views"], [])
Пример #13
0
    def test_get_offers_valid_on_device_decisioning_response(self):
        get_offers_opts = {
            "request": PREFETCH_REQUEST,
            "session_id": "dummy_session"
        }

        client_opts = dict(CONFIG)
        client_opts["decisioning_method"] = DecisioningMethod.ON_DEVICE.value
        client_opts["target_location_hint"] = "28"

        with patch("target_decisioning_engine.artifact_provider.urllib3.PoolManager") as mock_artifact_provider:
            artifact_instance = mock_artifact_provider.return_value
            artifact_response = HTTPResponse(status=OK, body=json.dumps(ARTIFACT_AB_SIMPLE))
            artifact_instance.request.return_value = artifact_response

            with patch.object(DeliveryApi, "execute", return_value=create_delivery_response(LOCATION_HINT_RESPONSE)):
                client = TargetClient.create(client_opts)
                result = client.get_offers(get_offers_opts)
                result_dict = to_dict(result)
                expect_to_match_object(result_dict, EXPECTED_PREFETCH_RESULT)
 def setUp(self):
     client_options = get_client_options()
     self.send_notifications_options = {
         "request": {
             "id": {
                 "tnt_id": "123"
             },
             "context": {
                 "channel": ChannelType.WEB
             },
             "notifications": [{
                 "id":
                 "SummerOfferNotification",
                 "timestamp":
                 1611954531 * 1000,
                 "type":
                 "display",
                 "mbox": {
                     "name": "SummerOffer"
                 },
                 "tokens": [
                     "GcvBXDhdJFNR9E9r1tgjfmqipfsIHvVzTQxHolz2IpSCnQ9Y9OaLL2gsdrWQTvE54PwSz67rmXWmSnkXpSSS2Q"
                 ]
             }, {
                 "id":
                 "SummerShoesOfferNotification",
                 "timestamp":
                 1611954531 * 1000,
                 "type":
                 "display",
                 "mbox": {
                     "name": "SummerShoesOffer"
                 },
                 "tokens": [
                     "GcvBXDhdJFNR9E9r1tgjfmqipfsIHvVzTQxHolz2IpSCnQ9Y9OaLL2gsdrWQTvE54PwSz67rmXWmSnkXpSSS2Q"
                 ]
             }]
         }
     }
     self.client = TargetClient.create(client_options)
Пример #15
0
    def test_client_preemptively_fetches_target_location_hint(self):
        get_offers_opts = {
            "request": TARGET_REQUEST,
            "session_id": "dummy_session"
        }

        client_opts = dict(CONFIG)
        client_opts["decisioning_method"] = DecisioningMethod.ON_DEVICE.value

        with patch("target_decisioning_engine.artifact_provider.urllib3.PoolManager") as mock_artifact_provider:
            artifact_instance = mock_artifact_provider.return_value
            artifact_response = HTTPResponse(status=OK, body=json.dumps(ARTIFACT_AB_SIMPLE))
            artifact_instance.request.return_value = artifact_response

            with patch.object(DeliveryApi, "execute", return_value=create_delivery_response(LOCATION_HINT_RESPONSE)):
                client = TargetClient.create(client_opts)
                result = client.get_offers(get_offers_opts)  # on-device
                self.assertEqual(result.get("target_location_hint_cookie"), {
                    "name": "mboxEdgeCluster",
                    "value": "28",
                    "maxAge": 1860
                })
Пример #16
0
    def test_client_recovers_if_location_hint_request_fails(self):
        get_offers_opts = {
            "request": TARGET_REQUEST,
            "session_id": "dummy_session"
        }

        client_opts = dict(CONFIG)
        client_opts["decisioning_method"] = DecisioningMethod.ON_DEVICE.value

        with patch("delivery_api_client.rest.urllib3.PoolManager") as mock_delivery_api:
            delivery_instance = mock_delivery_api.return_value
            delivery_response = HTTPResponse(status=503)
            delivery_instance.request.return_value = delivery_response

            with patch("target_decisioning_engine.artifact_provider.urllib3.PoolManager") as mock_artifact_provider:
                artifact_instance = mock_artifact_provider.return_value
                artifact_response = HTTPResponse(status=OK, body=json.dumps(ARTIFACT_AB_SIMPLE))
                artifact_instance.request.return_value = artifact_response

                client = TargetClient.create(client_opts)
                result = client.get_offers(get_offers_opts)  # on-device
                self.assertIsNone(result.get("target_location_hint_cookie"))
Пример #17
0
    def test_client_uses_location_hint_from_config(self):
        get_offers_opts = {
            "request": TARGET_REQUEST,
            "session_id": "dummy_session"
        }

        client_opts = dict(CONFIG)
        client_opts["decisioning_method"] = DecisioningMethod.ON_DEVICE.value
        client_opts["target_location_hint"] = "28"

        with patch("target_decisioning_engine.artifact_provider.urllib3.PoolManager") as mock_artifact_provider:
            artifact_instance = mock_artifact_provider.return_value
            artifact_response = HTTPResponse(status=OK, body=json.dumps(ARTIFACT_AB_SIMPLE))
            artifact_instance.request.return_value = artifact_response

            client = TargetClient.create(client_opts)
            result = client.get_offers(get_offers_opts)
            self.assertEqual(result.get("target_location_hint_cookie"), {
                "name": "mboxEdgeCluster",
                "value": "28",
                "maxAge": 1860
            })
Пример #18
0
    def test_get_offers_raises_exception_if_client_configured_as_server_side_but_request_made_with_on_device(
            self):
        get_offers_opts = {
            "request": TARGET_REQUEST_DICT,
            "session_id": "dummy_session",
            "decisioning_method": DecisioningMethod.ON_DEVICE.value
        }
        get_offers_opts["request"]["prefetch"] = {
            "mboxes": [{
                "name": "mbox-feature-flags",
                "index": 1
            }]
        }
        get_offers_opts["request"] = create_delivery_request(
            get_offers_opts["request"])

        client_opts = dict(CONFIG)
        client_opts["decisioning_method"] = DecisioningMethod.SERVER_SIDE.value
        client = TargetClient.create(client_opts)

        with self.assertRaises(Exception) as err:
            client.get_offers(get_offers_opts)
            self.assertEqual(str(err.exception), DECISIONING_ENGINE_NOT_READY)
Пример #19
0
    def test_get_offers_artifact_retrieval_failed(self):
        client_ready_mock = Mock()
        artifact_failed_mock = Mock()
        artifact_success_mock = Mock()

        client_opts = dict(CONFIG)
        client_opts["decisioning_method"] = DecisioningMethod.ON_DEVICE.value
        client_opts["events"] = {
            "client_ready": client_ready_mock,
            "artifact_download_failed": artifact_failed_mock,
            "artifact_download_succeeded": artifact_success_mock
        }

        with patch("target_decisioning_engine.artifact_provider.urllib3.PoolManager") as mock_pool_manager:
            instance = mock_pool_manager.return_value
            mock_response = HTTPResponse(status=403)
            instance.request.return_value = mock_response

            with patch.object(DeliveryApi, "execute", return_value=create_delivery_response(LOCATION_HINT_RESPONSE)):
                client = TargetClient.create(client_opts)

                self.assertEqual(client_ready_mock.call_count, 0)
                self.assertEqual(artifact_success_mock.call_count, 0)
                self.assertEqual(artifact_failed_mock.call_count, 1)
                self.assertEqual(artifact_failed_mock.call_args[0][0].get("type"), "artifact_download_failed")
                self.assertIsNotNone(artifact_failed_mock.call_args[0][0].get("artifact_location"))
                self.assertIsNotNone(artifact_failed_mock.call_args[0][0].get("error"))

                get_offers_opts = {
                    "request": TARGET_REQUEST,
                    "session_id": "dummy_session"
                }

            with self.assertRaises(Exception) as err:
                client.get_offers(get_offers_opts)
                self.assertEqual(str(err.exception), DECISIONING_ENGINE_NOT_READY)
Пример #20
0
 def setUp(self):
     client_options = get_client_options()
     self.get_offers_options = {
         "request": {
             "id": {
                 "tnt_id": "123"
             },
             "execute": {
                 "mboxes": [{
                     "name": "cart",
                     "index": 1
                 }]
             },
             "prefetch": {
                 "mboxes": [{
                     "name": "homepage",
                     "index": 1
                 }]
             },
             "context": {
                 "channel": ChannelType.WEB,
                 "application": {
                     "id": "123",
                     "name": "unit testing python"
                 },
                 "screen": {
                     "width": 512,
                     "height": 512,
                     "color_depth": 100,
                     "orientation": ScreenOrientationType.PORTRAIT
                 },
                 "window": {
                     "width": 512,
                     "height": 512
                 },
                 "browser": {
                     "host": "targetpythonsdk"
                 },
                 "address": {
                     "url": "http://www.targetpythonsdk.com"
                 },
                 "geo": {
                     "latitude": 38.8,
                     "longitude": -77.0
                 }
             },
             "property": {
                 "token": "08b62abd-c3e7-dfb2-da93-96b3aa724d81"
             },
             "experience_cloud": {
                 "analytics": {
                     "supplemental_data_id":
                     "234234987325982342342349873259823",
                     "tracking_server": "ags041.sc.omtrdc.net",
                     "logging": "server_side"
                 },
                 "audience_manager": {
                     "location_hint": 9,
                     "blob": "32fdghkjh34kj5h43"
                 }
             }
         }
     }
     self.client = TargetClient.create(client_options)
Пример #21
0
 def test_create_return_client(self):
     options = {"client": "clientId", "organization_id": "orgId"}
     client = TargetClient.create(options)
     self.assertIsNotNone(client)
Пример #22
0
 def test_create_missing_organization_id(self):
     options = {"client": "clientId"}
     with self.assertRaises(Exception) as err:
         TargetClient.create(options)
     self.assertEqual(str(err.exception), "Organization Id is required")
Пример #23
0
 def test_create_missing_options(self):
     with self.assertRaises(Exception) as err:
         TargetClient.create()
     self.assertEqual(str(err.exception), "Options are required")
Пример #24
0

def client_ready_callback(ready_event):
    print("Server is now ready to start handling requests")


client_options = {
    "client": "acmeclient",
    "organization_id": "1234567890@AdobeOrg",
    "decisioning_method": "on-device",
    "events": {
        "client_ready": client_ready_callback
    }
}

target_client = TargetClient.create(client_options)
target_service = TargetClientService(target_client)
results = {}


@app.route('/executePageLoad', methods=['GET'])
def execute_page_load():
    """
    Make an execute pageload request to get all initial offers at page load time, get cookies for request if they exist,
    and on response set Target cookie for use with next request
    """
    get_offers_options = initialize_options(request)
    target_delivery_response = target_service.get_page_load_target_delivery_response(request, get_offers_options)
    response = Response(target_delivery_response.get("response").to_str(), status=200, mimetype='application/json')
    set_target_cookies(response, target_delivery_response)
    return response