def test_integration_context_base64(self): t = tracker.Tracker([default_emitter], default_subject, encode_base64=True) with HTTMock(pass_response_content): t.track_unstruct_event( SelfDescribingJson( "iglu:com.acme/viewed_product/jsonschema/2-0-2", { "product_id": "ASO01043", "price$flt": 49.95, "walrus$tms": 1000 }), context=[ SelfDescribingJson( "iglu:com.example/user/jsonschema/2-0-3", {"user_type": "tester"}) ]) envelope_string = unquote_plus(from_querystring( "cx", querystrings[-1])) envelope = json.loads( (base64.urlsafe_b64decode(bytearray(envelope_string, "utf-8"))).decode("utf-8")) self.assertEquals( envelope, { "schema": "iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-1", "data": [{ "schema": "iglu:com.example/user/jsonschema/2-0-3", "data": { "user_type": "tester" } }] })
def test_complete_payload_co(self, mok_uuid, mok_track): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_uuid.side_effect = mocked_uuid mok_track.side_effect = mocked_track t = Tracker(e, encode_base64=False) p = Payload() geo_ctx = SelfDescribingJson(geoSchema, geoData) mov_ctx = SelfDescribingJson(movSchema, movData) ctx_array = [geo_ctx, mov_ctx] t.complete_payload(p, ctx_array, None, None) self.assertEqual(mok_track.call_count, 1) trackArgsTuple = mok_track.call_args_list[0][0] self.assertEqual(len(trackArgsTuple), 1) passed_nv_pairs = trackArgsTuple[0].nv_pairs expected_co = { "schema": CONTEXT_SCHEMA, "data": [{ "schema": geoSchema, "data": geoData }, { "schema": movSchema, "data": movData }] } self.assertIn("co", passed_nv_pairs) self.assertDictEqual(json.loads(passed_nv_pairs["co"]), expected_co)
def test_track_screen_view(self, mok_track_unstruct): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_track_unstruct.side_effect = mocked_track_unstruct t = Tracker(e) ctx = SelfDescribingJson("test.context.schema", {"user": "******"}) evTstamp = 1399021242030 t.track_screen_view("screenName", "screenId", context=[ctx], tstamp=evTstamp) expected = { "schema": SCREEN_VIEW_SCHEMA, "data": { "name": "screenName", "id": "screenId" } } callArgs = mok_track_unstruct.call_args_list[0][0] self.assertEqual(len(callArgs), 4) self.assertDictEqual(callArgs[0].to_json(), expected) self.assertIs(callArgs[1][0], ctx) self.assertEqual(callArgs[2], evTstamp)
def test_track_site_search(self, mok_track_unstruct): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_track_unstruct.side_effect = mocked_track_unstruct t = Tracker(e) ctx = SelfDescribingJson("test.context.schema", {"user": "******"}) evTstamp = 1399021242030 t.track_site_search(["track", "search"], {"new": True}, 100, 10, context=[ctx], tstamp=evTstamp) expected = { "schema": SITE_SEARCH_SCHEMA, "data": { "terms": ["track", "search"], "filters": { "new": True }, "totalResults": 100, "pageResults": 10 } } callArgs = mok_track_unstruct.call_args_list[0][0] self.assertEqual(len(callArgs), 4) self.assertDictEqual(callArgs[0].to_json(), expected) self.assertIs(callArgs[1][0], ctx) self.assertEqual(callArgs[2], evTstamp)
def send_events(self, evts): """ :param evts: Array of events to be sent :type evts: list(dict(string:*)) """ if len(evts) > 0: logger.info("Attempting to send %s events" % len(evts)) Emitter.attach_sent_timestamp(evts) success_events = [] failure_events = [] if self.method == 'post': data = SelfDescribingJson(PAYLOAD_DATA_SCHEMA, evts).to_string() request_succeeded = self.http_post(data) if request_succeeded: success_events += evts else: failure_events += evts elif self.method == 'get': for evt in evts: request_succeeded = self.http_get(evt) if request_succeeded: success_events += [evt] else: failure_events += [evt] if self.on_success is not None and len(success_events) > 0: self.on_success(success_events) if self.on_failure is not None and len(failure_events) > 0: self.on_failure(len(success_events), failure_events) else: logger.info("Skipping flush since buffer is empty")
def test_integration_unstruct_event_non_base64(self): t = tracker.Tracker([default_emitter], default_subject, encode_base64=False) with HTTMock(pass_response_content): t.track_unstruct_event( SelfDescribingJson( "iglu:com.acme/viewed_product/jsonschema/2-0-2", { "product_id": "ASO01043", "price$flt": 49.95, "walrus$tms": 1000 })) expected_fields = {"e": "ue"} for key in expected_fields: self.assertEquals(from_querystring(key, querystrings[-1]), expected_fields[key]) envelope_string = from_querystring("ue_pr", querystrings[-1]) envelope = json.loads(unquote_plus(envelope_string)) self.assertEquals( envelope, { "schema": "iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0", "data": { "schema": "iglu:com.acme/viewed_product/jsonschema/2-0-2", "data": { "product_id": "ASO01043", "price$flt": 49.95, "walrus$tms": 1000 } } })
def test_unicode_get(self): t = tracker.Tracker([default_emitter], default_subject, encode_base64=False) unicode_a = u'\u0107' unicode_b = u'test.\u0107om' test_ctx = SelfDescribingJson('iglu:a.b/c/jsonschema/1-0-0', {'test': unicode_a}) with HTTMock(pass_response_content): t.track_page_view(unicode_b, context=[test_ctx]) t.track_screen_view(unicode_b, context=[test_ctx]) url_string = unquote_plus(from_querystring("url", querystrings[-2])) try: self.assertEqual(url_string.decode('utf-8'), unicode_b) except AttributeError: # in python 3: str type contains unicode (so no 'decode') self.assertEqual(url_string, unicode_b) context_string = unquote_plus(from_querystring("co", querystrings[-1])) actual_a = json.loads(context_string)['data'][0]['data']['test'] self.assertEqual(actual_a, unicode_a) uepr_string = unquote_plus(from_querystring("ue_pr", querystrings[-1])) actual_b = json.loads(uepr_string)['data']['data']['name'] self.assertEqual(actual_b, unicode_b)
def test_track_link_click(self, mok_track_unstruct): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_track_unstruct.side_effect = mocked_track_unstruct t = Tracker(e) ctx = SelfDescribingJson("test.context.schema", {"user": "******"}) evTstamp = 1399021242030 t.track_link_click("example.com", "elemId", ["elemClass1", "elemClass2"], "_blank", "elemContent", context=[ctx], tstamp=evTstamp) expected = { "schema": LINK_CLICK_SCHEMA, "data": { "targetUrl": "example.com", "elementId": "elemId", "elementClasses": ["elemClass1", "elemClass2"], "elementTarget": "_blank", "elementContent": "elemContent" } } callArgs = mok_track_unstruct.call_args_list[0][0] self.assertEqual(len(callArgs), 4) self.assertDictEqual(callArgs[0].to_json(), expected) self.assertIs(callArgs[1][0], ctx) self.assertEqual(callArgs[2], evTstamp)
def test_integration_context_base64(self): t = tracker.Tracker([default_emitter], default_subject, encode_base64=True) with HTTMock(pass_response_content): t.track_page_view("localhost", "local host", None, [ SelfDescribingJson("iglu:com.example/user/jsonschema/2-0-3", {"user_type": "tester"}) ]) envelope_string = unquote_plus(from_querystring( "cx", querystrings[-1])) envelope = json.loads( (base64.urlsafe_b64decode(bytearray(envelope_string, "utf-8"))).decode("utf-8")) self.assertEquals( envelope, { "schema": "iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-1", "data": [{ "schema": "iglu:com.example/user/jsonschema/2-0-3", "data": { "user_type": "tester" } }] })
def test_track_page_view(self, mok_complete_payload): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_complete_payload.side_effect = mocked_complete_payload t = Tracker(e) ctx = SelfDescribingJson("test.context.schema", {"user": "******"}) evTstamp = 1399021242030 t.track_page_view("example.com", "Example", "docs.snowplowanalytics.com", context=[ctx], tstamp=evTstamp) self.assertEqual(mok_complete_payload.call_count, 1) completeArgsList = mok_complete_payload.call_args_list[0][0] self.assertEqual(len(completeArgsList), 4) actualPayloadArg = completeArgsList[0] actualContextArg = completeArgsList[1] actualTstampArg = completeArgsList[2] actualPairs = actualPayloadArg.nv_pairs expectedPairs = { "e": "pv", "url": "example.com", "page": "Example", "refr": "docs.snowplowanalytics.com" } self.assertDictEqual(actualPairs, expectedPairs) self.assertIs(actualContextArg[0], ctx) self.assertEqual(actualTstampArg, evTstamp)
def test_alias_of_track_unstruct_event(self, mok_track): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_track.side_effect = mocked_track t = Tracker(e) evJson = SelfDescribingJson("test.schema", {"n": "v"}) # call the alias t.track_self_describing_event(evJson) self.assertEqual(mok_track.call_count, 1)
def test_track_unstruct_event_all_args(self, mok_complete_payload): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_complete_payload.side_effect = mocked_complete_payload t = Tracker(e, encode_base64=False) evJson = SelfDescribingJson("test.schema", {"n": "v"}) ctx = SelfDescribingJson("test.context.schema", {"user": "******"}) evContext = [ctx] evTstamp = 1399021242030 t.track_unstruct_event(evJson, evContext, evTstamp) self.assertEqual(mok_complete_payload.call_count, 1) completeArgsList = mok_complete_payload.call_args_list[0][0] self.assertEqual(len(completeArgsList), 4) # payload actualPayloadArg = completeArgsList[0] actualPairs = actualPayloadArg.nv_pairs actualUePr = json.loads(actualPairs["ue_pr"]) # context actualContextArg = completeArgsList[1] # tstamp actualTstampArg = completeArgsList[2] expectedUePr = { "data": { "data": { "n": "v" }, "schema": "test.schema" }, "schema": UNSTRUCT_SCHEMA } self.assertDictEqual(actualUePr, expectedUePr) self.assertEqual(actualPairs["e"], "ue") self.assertIs(actualContextArg[0], ctx) self.assertEqual(actualTstampArg, evTstamp)
def test_complete_payload_cx(self, mok_uuid, mok_track): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_uuid.side_effect = mocked_uuid mok_track.side_effect = mocked_track t = Tracker(e, encode_base64=True) p = Payload() geo_ctx = SelfDescribingJson(geoSchema, geoData) mov_ctx = SelfDescribingJson(movSchema, movData) ctx_array = [geo_ctx, mov_ctx] t.complete_payload(p, ctx_array, None, None) self.assertEqual(mok_track.call_count, 1) trackArgsTuple = mok_track.call_args_list[0][0] self.assertEqual(len(trackArgsTuple), 1) passed_nv_pairs = trackArgsTuple[0].nv_pairs self.assertIn("cx", passed_nv_pairs)
def test_track_unstruct_event_encode(self, mok_complete_payload): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_complete_payload.side_effect = mocked_complete_payload t = Tracker(e, encode_base64=True) evJson = SelfDescribingJson("test.sde.schema", {"n": "v"}) t.track_unstruct_event(evJson) self.assertEqual(mok_complete_payload.call_count, 1) completeArgsList = mok_complete_payload.call_args_list[0][0] self.assertEqual(len(completeArgsList), 4) actualPayloadArg = completeArgsList[0] actualPairs = actualPayloadArg.nv_pairs self.assertTrue("ue_px" in actualPairs.keys())
def send_events(self, evts): """ :param evts: Array of events to be sent :type evts: list(dict(string:*)) """ if len(evts) > 0: logger.info("Attempting to send %s requests" % len(evts)) Emitter.attach_sent_timestamp(evts) if self.method == 'post': data = SelfDescribingJson(PAYLOAD_DATA_SCHEMA, evts).to_string() post_succeeded = False try: status_code = self.http_post(data).status_code post_succeeded = self.is_good_status_code(status_code) except requests.RequestException as e: logger.warn(e) if post_succeeded: if self.on_success is not None: self.on_success(len(evts)) elif self.on_failure is not None: self.on_failure(0, evts) elif self.method == 'get': success_count = 0 unsent_requests = [] for evt in evts: get_succeeded = False try: status_code = self.http_get(evt).status_code get_succeeded = self.is_good_status_code(status_code) except requests.RequestException as e: logger.warn(e) if get_succeeded: success_count += 1 else: unsent_requests.append(evt) if len(unsent_requests) == 0: if self.on_success is not None: self.on_success(success_count) elif self.on_failure is not None: self.on_failure(success_count, unsent_requests) else: logger.info("Skipping flush since buffer is empty")
def test_track_ecommerce_transaction_no_items(self, mok_complete_payload): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_complete_payload.side_effect = mocked_complete_payload t = Tracker(e) ctx = SelfDescribingJson("test.context.schema", {"user": "******"}) evTstamp = 1399021242030 t.track_ecommerce_transaction("1234", 10, "transAffiliation", 2.5, 1.5, "transCity", "transState", "transCountry", "transCurrency", context=[ctx], tstamp=evTstamp) self.assertEqual(mok_complete_payload.call_count, 1) completeArgsList = mok_complete_payload.call_args_list[0][0] self.assertEqual(len(completeArgsList), 4) actualPayloadArg = completeArgsList[0] actualContextArg = completeArgsList[1] actualTstampArg = completeArgsList[2] actualPairs = actualPayloadArg.nv_pairs expectedPairs = { "e": "tr", "tr_id": "1234", "tr_tt": 10, "tr_af": "transAffiliation", "tr_tx": 2.5, "tr_sh": 1.5, "tr_ci": "transCity", "tr_st": "transState", "tr_co": "transCountry", "tr_cu": "transCurrency" } self.assertDictEqual(actualPairs, expectedPairs) self.assertIs(actualContextArg[0], ctx) self.assertEqual(actualTstampArg, evTstamp)
def test_track_ecommerce_transaction_item(self, mok_complete_payload): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_complete_payload.side_effect = mocked_complete_payload t = Tracker(e) ctx = SelfDescribingJson("test.context.schema", {"user": "******"}) evTstamp = 1399021242030 t.track_ecommerce_transaction_item("1234", "sku1234", 3.14, 1, "itemName", "itemCategory", "itemCurrency", context=[ctx], tstamp=evTstamp) self.assertEqual(mok_complete_payload.call_count, 1) completeArgsList = mok_complete_payload.call_args_list[0][0] self.assertEqual(len(completeArgsList), 4) actualPayloadArg = completeArgsList[0] actualContextArg = completeArgsList[1] actualTstampArg = completeArgsList[2] actualPairs = actualPayloadArg.nv_pairs expectedPairs = { "e": "ti", "ti_id": "1234", "ti_sk": "sku1234", "ti_nm": "itemName", "ti_ca": "itemCategory", "ti_pr": 3.14, "ti_qu": 1, "ti_cu": "itemCurrency" } self.assertDictEqual(actualPairs, expectedPairs) self.assertIs(actualContextArg[0], ctx) self.assertEqual(actualTstampArg, evTstamp)
def test_unicode_post(self): t = tracker.Tracker([post_emitter], default_subject, encode_base64=False) unicode_a = u'\u0107' unicode_b = u'test.\u0107om' test_ctx = SelfDescribingJson('iglu:a.b/c/jsonschema/1-0-0', {'test': unicode_a}) with HTTMock(pass_post_response_content): t.track_page_view(unicode_b, context=[test_ctx]) t.track_screen_view(unicode_b, context=[test_ctx]) pv_event = querystrings[-2] self.assertEqual(pv_event['data'][0]['url'], unicode_b) in_test_ctx = json.loads( pv_event['data'][0]['co'])['data'][0]['data']['test'] self.assertEqual(in_test_ctx, unicode_a) sv_event = querystrings[-1] in_uepr_name = json.loads( sv_event['data'][0]['ue_pr'])['data']['data']['name'] self.assertEqual(in_uepr_name, unicode_b)
def test_track_struct_event(self, mok_complete_payload): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_complete_payload.side_effect = mocked_complete_payload t = Tracker(e) ctx = SelfDescribingJson("test.context.schema", {"user": "******"}) evTstamp = 1399021242030 t.track_struct_event("Mixes", "Play", "Test", "TestProp", value=3.14, context=[ctx], tstamp=evTstamp) self.assertEqual(mok_complete_payload.call_count, 1) completeArgsList = mok_complete_payload.call_args_list[0][0] self.assertEqual(len(completeArgsList), 4) actualPayloadArg = completeArgsList[0] actualContextArg = completeArgsList[1] actualTstampArg = completeArgsList[2] actualPairs = actualPayloadArg.nv_pairs expectedPairs = { "e": "se", "se_ca": "Mixes", "se_ac": "Play", "se_la": "Test", "se_pr": "TestProp", "se_va": 3.14 } self.assertDictEqual(actualPairs, expectedPairs) self.assertIs(actualContextArg[0], ctx) self.assertEqual(actualTstampArg, evTstamp)
def test_track_add_to_cart(self, mok_track_unstruct): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_track_unstruct.side_effect = mocked_track_unstruct t = Tracker(e) ctx = SelfDescribingJson("test.context.schema", {"user": "******"}) evTstamp = 1399021242030 t.track_add_to_cart("sku1234", 3, "testName", "testCategory", 3.14, "testCurrency", context=[ctx], tstamp=evTstamp) expected = { "schema": ADD_TO_CART_SCHEMA, "data": { "sku": "sku1234", "quantity": 3, "name": "testName", "category": "testCategory", "unitPrice": 3.14, "currency": "testCurrency" } } callArgs = mok_track_unstruct.call_args_list[0][0] self.assertEqual(len(callArgs), 4) self.assertDictEqual(callArgs[0].to_json(), expected) self.assertIs(callArgs[1][0], ctx) self.assertEqual(callArgs[2], evTstamp)
def test_track_form_submit(self, mok_track_unstruct): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_track_unstruct.side_effect = mocked_track_unstruct t = Tracker(e) ctx = SelfDescribingJson("test.context.schema", {"user": "******"}) evTstamp = 1399021242030 elems = [{ "name": "user_email", "value": "*****@*****.**", "nodeName": "INPUT", "type": "email" }] t.track_form_submit("testFormId", ["testClass1", "testClass2"], elems, context=[ctx], tstamp=evTstamp) expected = { "schema": FORM_SUBMIT_SCHEMA, "data": { "formId": "testFormId", "formClasses": ["testClass1", "testClass2"], "elements": elems } } callArgs = mok_track_unstruct.call_args_list[0][0] self.assertEqual(len(callArgs), 4) self.assertDictEqual(callArgs[0].to_json(), expected) self.assertIs(callArgs[1][0], ctx) self.assertEqual(callArgs[2], evTstamp)
def test_track_ecommerce_transaction_with_items(self, mok_complete_payload, mok_track_trans_item): mokEmitter = self.create_patch('snowplow_tracker.Emitter') e = mokEmitter() with ContractsDisabled(): mok_complete_payload.side_effect = mocked_complete_payload mok_track_trans_item.side_effect = mocked_track_trans_item t = Tracker(e) ctx = SelfDescribingJson("test.context.schema", {"user": "******"}) evTstamp = 1399021242030 transItems = [{ "sku": "sku1234", "quantity": 3, "price": 3.14 }, { "sku": "sku5678", "quantity": 1, "price": 2.72 }] t.track_ecommerce_transaction("1234", 10, "transAffiliation", 2.5, 1.5, "transCity", "transState", "transCountry", "transCurrency", items=transItems, context=[ctx], tstamp=evTstamp) # Transaction callCompleteArgsList = mok_complete_payload.call_args_list firstCallArgsList = callCompleteArgsList[0][0] self.assertEqual(len(firstCallArgsList), 4) actualPayloadArg = firstCallArgsList[0] actualContextArg = firstCallArgsList[1] actualTstampArg = firstCallArgsList[2] actualPairs = actualPayloadArg.nv_pairs expectedTransPairs = { "e": "tr", "tr_id": "1234", "tr_tt": 10, "tr_af": "transAffiliation", "tr_tx": 2.5, "tr_sh": 1.5, "tr_ci": "transCity", "tr_st": "transState", "tr_co": "transCountry", "tr_cu": "transCurrency" } self.assertDictEqual(actualPairs, expectedTransPairs) self.assertIs(actualContextArg[0], ctx) self.assertEqual(actualTstampArg, evTstamp) # Items calls_to_track_trans_item = mok_track_trans_item.call_count self.assertEqual(calls_to_track_trans_item, 2) callTrackItemsArgsList = mok_track_trans_item.call_args_list # 1st item firstItemCallArgs = callTrackItemsArgsList[0][0] self.assertEqual((), firstItemCallArgs) firstItemCallKwargs = callTrackItemsArgsList[0][1] expectedFirstItemPairs = { 'tstamp': evTstamp, 'order_id': '1234', 'currency': 'transCurrency', 'sku': 'sku1234', 'quantity': 3, "price": 3.14, 'event_subject': None } self.assertDictEqual(firstItemCallKwargs, expectedFirstItemPairs) # 2nd item secItemCallArgs = callTrackItemsArgsList[1][0] self.assertEqual((), secItemCallArgs) secItemCallKwargs = callTrackItemsArgsList[1][1] expectedSecItemPairs = { 'tstamp': evTstamp, 'order_id': '1234', 'currency': 'transCurrency', 'sku': 'sku5678', 'quantity': 1, "price": 2.72, 'event_subject': None } self.assertDictEqual(secItemCallKwargs, expectedSecItemPairs)