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"
                 }
             }]
         })
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
    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
                 }
             }
         })
Exemplo n.º 7
0
    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)
Exemplo n.º 8
0
    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)
Exemplo n.º 9
0
 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"
                 }
             }]
         })
Exemplo n.º 10
0
    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)
Exemplo n.º 11
0
    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)
Exemplo n.º 12
0
    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)
Exemplo n.º 13
0
    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)
Exemplo n.º 14
0
    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())
Exemplo n.º 15
0
    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")
Exemplo n.º 16
0
    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)
Exemplo n.º 17
0
    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)
Exemplo n.º 18
0
    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)
Exemplo n.º 19
0
    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)
Exemplo n.º 20
0
    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)
Exemplo n.º 21
0
    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)
Exemplo n.º 22
0
    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)