diff --git a/package.json b/package.json index d2b95fe..8550cc4 100644 --- a/package.json +++ b/package.json @@ -47,23 +47,8 @@ "typescript": "^3.0" }, "jest": { - "testEnvironment": "node", + "preset": "ts-jest", "coverageDirectory": "./coverage", - "collectCoverage": true, - "moduleFileExtensions": [ - "ts", - "js" - ], - "transform": { - "^.+\\.ts$": "ts-jest" - }, - "globals": { - "ts-jest": { - "tsConfigFile": "tsconfig.json" - } - }, - "testMatch": [ - "**/__tests__/*.+(ts)" - ] + "collectCoverage": true } } diff --git a/src/__snapshots__/index.spec.ts.snap b/src/__snapshots__/index.spec.ts.snap new file mode 100644 index 0000000..07e623f --- /dev/null +++ b/src/__snapshots__/index.spec.ts.snap @@ -0,0 +1,119 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`transform should be transformed 1`] = ` +Object { + "app_id": "angry-birds", + "br_features_flash": false, + "br_features_pdf": true, + "collector_tstamp": "2013-11-26T00:02:05Z", + "contexts_com_snowplowanalytics_snowplow_ua_parser_context_1": Array [ + Object { + "deviceFamily": "Other", + "osFamily": "Windows XP", + "osMajor": null, + "osMinor": null, + "osPatch": null, + "osPatchMinor": null, + "osVersion": "Windows XP", + "useragentFamily": "IE", + "useragentMajor": "7", + "useragentMinor": "0", + "useragentPatch": null, + "useragentVersion": "IE 7.0", + }, + ], + "contexts_org_schema_web_page_1": Array [ + Object { + "author": "Fred Blundun", + "breadcrumb": Array [ + "blog", + "releases", + ], + "datePublished": "2014-11-06T00:00:00Z", + "genre": "blog", + "inLanguage": "en-US", + "keywords": Array [ + "snowplow", + "javascript", + "tracker", + "event", + ], + }, + ], + "contexts_org_w3_performance_timing_1": Array [ + Object { + "connectEnd": 1415358090183, + "connectStart": 1415358090103, + "domComplete": 0, + "domContentLoadedEventEnd": 1415358091309, + "domContentLoadedEventStart": 1415358090968, + "domInteractive": 1415358090886, + "domLoading": 1415358090270, + "domainLookupEnd": 1415358090102, + "domainLookupStart": 1415358090102, + "fetchStart": 1415358089870, + "loadEventEnd": 0, + "loadEventStart": 0, + "navigationStart": 1415358089861, + "redirectEnd": 0, + "redirectStart": 0, + "requestStart": 1415358090183, + "responseEnd": 1415358090265, + "responseStart": 1415358090265, + "unloadEventEnd": 1415358090287, + "unloadEventStart": 1415358090270, + }, + ], + "derived_tstamp": "2013-11-26T00:03:57.886Z", + "domain_sessionid": "2b15e5c8-d3b1-11e4-b9d6-1681e6b88ec1", + "domain_sessionidx": 3, + "domain_userid": "bc2e92ec6c204a14", + "dvce_created_tstamp": "2013-11-26T00:03:57.885Z", + "etl_tstamp": "2017-01-26T00:01:25.292Z", + "event": "page_view", + "event_fingerprint": "e3dbfa9cca0412c3d4052863cefb547f", + "event_format": "jsonschema", + "event_id": "c6ef3124-b53a-4b13-a233-0088f79dcbcb", + "event_name": "link_click", + "event_vendor": "com.snowplowanalytics.snowplow", + "event_version": "1-0-0", + "geo_city": "New York", + "geo_country": "US", + "geo_latitude": 37.443604, + "geo_location": "37.443604,-122.4124", + "geo_longitude": -122.4124, + "geo_region": "TX", + "geo_region_name": "Florida", + "geo_zipcode": "94109", + "ip_domain": "nuvox.net", + "ip_isp": "FDN Communications", + "ip_netspeed": "Cable/DSL", + "ip_organization": "Bouygues Telecom", + "name_tracker": "cloudfront-1", + "network_userid": "ecdff4d0-9175-40ac-a8bb-325c49733607", + "page_title": "On Analytics", + "page_url": "http://www.snowplowanalytics.com", + "page_urlfragment": "4-conclusion", + "page_urlhost": "www.snowplowanalytics.com", + "page_urlpath": "/product/index.html", + "page_urlport": 80, + "page_urlquery": "id=GTM-DLRG", + "page_urlscheme": "http", + "platform": "web", + "true_tstamp": "2013-11-26T00:03:57.886Z", + "txn_id": 41828, + "unstruct_event_com_snowplowanalytics_snowplow_link_click_1": Object { + "elementClasses": Array [ + "foreground", + ], + "elementId": "exampleLink", + "targetUrl": "http://www.example.com", + }, + "user_fingerprint": "2161814971", + "user_id": "jon.doe@email.com", + "user_ipaddress": "92.231.54.234", + "v_collector": "clj-tomcat-0.1.0", + "v_etl": "serde-0.5.2", + "v_tracker": "js-2.1.0", +} +`; diff --git a/src/__tests__/types.test.ts b/src/__tests__/types.test.ts deleted file mode 100644 index dab511e..0000000 --- a/src/__tests__/types.test.ts +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2018-2019 dokmic, Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -import * as Types from '../types'; - -it('should parse string', () => { - expect(Types.String('key', 'value')).toEqual([{ key: 'key', value: 'value' }]); -}); - -it('should parse integer', () => { - expect(Types.Integer('key', '123.456')).toEqual([{ key: 'key', value: 123 }]); - expect(() => Types.Integer('key', 'string')).toThrow(); -}); - -it('should parse float', () => { - expect(Types.Double('key', '123.456')).toEqual([{ key: 'key', value: 123.456 }]); - expect(() => Types.Double('key', 'string')).toThrow(); -}); - -it('should parse boolean', () => { - expect(Types.Boolean('key', '0')).toEqual([{ key: 'key', value: false }]); - expect(Types.Boolean('key', '1')).toEqual([{ key: 'key', value: true }]); - expect(() => Types.Boolean('key', '2')).toThrow(); -}); - -it('should parse timestamp', () => { - expect(Types.Timestamp('key', '2017-01-11 10:20:17')).toEqual([{ key: 'key', value: '2017-01-11T10:20:17Z' }]); -}); - -it('should parse contexts', () => { - expect(Types.Contexts('', JSON.stringify({ - data: [ - { - data: { unique: true }, - schema: 'iglu:com.acme/unduplicated/jsonschema/1-0-0', - }, - { - data: { value: 1 }, - schema: 'iglu:com.acme/duplicated/jsonschema/1-0-0', - }, - { - data: { value: 2 }, - schema: 'iglu:com.acme/duplicated/jsonschema/1-0-0', - }, - ], - schema: 'iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0', - }))).toEqual([ - { - key: 'contexts_com_acme_unduplicated_1', - value: [ - { unique: true }, - ], - }, - { - key: 'contexts_com_acme_duplicated_1', - value: [ - { value: 1 }, - { value: 2 }, - ], - }, - ]); -}); - -it('should parse unstruct', () => { - expect(Types.Unstruct('', JSON.stringify({ - data: { - data: { key: 'value' }, - schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1', - }, - schema: 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0', - }))).toEqual([{ - key: 'unstruct_event_com_snowplowanalytics_snowplow_link_click_1', - value: { key: 'value' }, - }]); - - expect(() => Types.Unstruct('', JSON.stringify({ - schema: 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0', - data: {}, - }))).toThrow(); -}); - -it('should fail on schema', () => { - expect(() => Types.Unstruct('', JSON.stringify({ - data: { - data: { key: 'value' }, - schema: 'something', - }, - schema: 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0', - }))).toThrow(); -}); diff --git a/src/__tests__/index.test.ts b/src/index.fixture.ts similarity index 56% rename from src/__tests__/index.test.ts rename to src/index.fixture.ts index 32f7f7f..2a16d29 100644 --- a/src/__tests__/index.test.ts +++ b/src/index.fixture.ts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 dokmic, Snowplow Analytics Ltd. All rights reserved. + * Copyright (c) 2019 dokmic, Snowplow Analytics Ltd. All rights reserved. * * This program is licensed to you under the Apache License Version 2.0, * and you may not use this file except in compliance with the Apache License Version 2.0. @@ -10,20 +10,8 @@ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ -import { transform } from '../index'; -const unstruct = JSON.stringify({ - schema: 'iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0', - data: { - schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1', - data: { - targetUrl: 'http://www.example.com', - elementClasses: ['foreground'], - elementId: 'exampleLink', - }, - }, -}); -const contexts = JSON.stringify({ +const contexts = { schema: 'iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0', data: [ { @@ -63,8 +51,9 @@ const contexts = JSON.stringify({ }, }, ], -}); -const derivedContexts = JSON.stringify({ +}; + +const derivedContexts = { schema: 'iglu:com.snowplowanalytics.snowplow\/contexts\/jsonschema\/1-0-1', data: [{ schema: 'iglu:com.snowplowanalytics.snowplow\/ua_parser_context\/jsonschema\/1-0-0', @@ -81,11 +70,23 @@ const derivedContexts = JSON.stringify({ osPatchMinor: null, osVersion: 'Windows XP', deviceFamily: 'Other', - }, + } as any, }], -}); -const event = { - contexts, +}; + +const unstructEvent = { + schema: 'iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0', + data: { + schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1', + data: { + targetUrl: 'http://www.example.com', + elementClasses: ['foreground'], + elementId: 'exampleLink', + }, + }, +}; + +export const event = { app_id: 'angry-birds', platform: 'web', etl_tstamp: '2017-01-26 00:01:25.292', @@ -138,12 +139,13 @@ const event = { mkt_term: '', mkt_content: '', mkt_campaign: '', + contexts: JSON.stringify(contexts), se_category: '', se_action: '', se_label: '', se_property: '', se_value: '', - unstruct_event: unstruct, + unstruct_event: JSON.stringify(unstructEvent), tr_orderid: '', tr_affiliation: '', tr_total: '', @@ -207,7 +209,7 @@ const event = { dvce_sent_tstamp: '', refr_domain_userid: '', refr_device_tstamp: '', - derived_contexts: derivedContexts, + derived_contexts: JSON.stringify(derivedContexts), domain_sessionid: '2b15e5c8-d3b1-11e4-b9d6-1681e6b88ec1', derived_tstamp: '2013-11-26 00:03:57.886', event_vendor: 'com.snowplowanalytics.snowplow', @@ -217,142 +219,3 @@ const event = { event_fingerprint: 'e3dbfa9cca0412c3d4052863cefb547f', true_tstamp: '2013-11-26 00:03:57.886', }; -const expected = { - geo_location: '37.443604,-122.4124', - app_id: 'angry-birds', - platform: 'web', - etl_tstamp: '2017-01-26T00:01:25.292Z', - collector_tstamp: '2013-11-26T00:02:05Z', - dvce_created_tstamp: '2013-11-26T00:03:57.885Z', - event: 'page_view', - event_id: 'c6ef3124-b53a-4b13-a233-0088f79dcbcb', - txn_id: 41828, - name_tracker: 'cloudfront-1', - v_tracker: 'js-2.1.0', - v_collector: 'clj-tomcat-0.1.0', - v_etl: 'serde-0.5.2', - user_id: 'jon.doe@email.com', - user_ipaddress: '92.231.54.234', - user_fingerprint: '2161814971', - domain_userid: 'bc2e92ec6c204a14', - domain_sessionidx: 3, - network_userid: 'ecdff4d0-9175-40ac-a8bb-325c49733607', - geo_country: 'US', - geo_region: 'TX', - geo_city: 'New York', - geo_zipcode: '94109', - geo_latitude: 37.443604, - geo_longitude: -122.4124, - geo_region_name: 'Florida', - ip_isp: 'FDN Communications', - ip_organization: 'Bouygues Telecom', - ip_domain: 'nuvox.net', - ip_netspeed: 'Cable/DSL', - page_url: 'http://www.snowplowanalytics.com', - page_title: 'On Analytics', - page_urlscheme: 'http', - page_urlhost: 'www.snowplowanalytics.com', - page_urlport: 80, - page_urlpath: '/product/index.html', - page_urlquery: 'id=GTM-DLRG', - page_urlfragment: '4-conclusion', - contexts_org_schema_web_page_1: [{ - genre: 'blog', - inLanguage: 'en-US', - datePublished: '2014-11-06T00:00:00Z', - author: 'Fred Blundun', - breadcrumb: ['blog', 'releases'], - keywords: ['snowplow', 'javascript', 'tracker', 'event'], - }], - contexts_org_w3_performance_timing_1: [{ - navigationStart: 1415358089861, - unloadEventStart: 1415358090270, - unloadEventEnd: 1415358090287, - redirectStart: 0, - redirectEnd: 0, - fetchStart: 1415358089870, - domainLookupStart: 1415358090102, - domainLookupEnd: 1415358090102, - connectStart: 1415358090103, - connectEnd: 1415358090183, - requestStart: 1415358090183, - responseStart: 1415358090265, - responseEnd: 1415358090265, - domLoading: 1415358090270, - domInteractive: 1415358090886, - domContentLoadedEventStart: 1415358090968, - domContentLoadedEventEnd: 1415358091309, - domComplete: 0, - loadEventStart: 0, - loadEventEnd: 0, - }], - unstruct_event_com_snowplowanalytics_snowplow_link_click_1: { - targetUrl: 'http://www.example.com', - elementClasses: ['foreground'], - elementId: 'exampleLink', - }, - br_features_pdf: true, - br_features_flash: false, - contexts_com_snowplowanalytics_snowplow_ua_parser_context_1: [{ - useragentFamily: 'IE', - useragentMajor: '7', - useragentMinor: '0', - useragentPatch: null, - useragentVersion: 'IE 7.0', - osFamily: 'Windows XP', - osMajor: null, - osMinor: null, - osPatch: null, - osPatchMinor: null, - osVersion: 'Windows XP', - deviceFamily: 'Other', - }], - domain_sessionid: '2b15e5c8-d3b1-11e4-b9d6-1681e6b88ec1', - derived_tstamp: '2013-11-26T00:03:57.886Z', - event_vendor: 'com.snowplowanalytics.snowplow', - event_name: 'link_click', - event_format: 'jsonschema', - event_version: '1-0-0', - event_fingerprint: 'e3dbfa9cca0412c3d4052863cefb547f', - true_tstamp: '2013-11-26T00:03:57.886Z', -}; - -function encode(event) { - return Object.keys(event) - .map(key => event[key]) - .join('\t'); -} - -it('should be transformed', () => { - expect(transform(encode(event))).toEqual(expected); -}); - -it('should fail on fields number', () => { - expect(() => transform(encode({ - a: '1', - b: '2', - }))).toThrow('Wrong event fields number.'); -}); - -it('should fail on one field', () => { - expect(() => transform(encode(Object.assign({}, event, { - tr_tax_base: 'bad_tax_base', - })))).toThrow("Invalid value for field 'tr_tax_base'."); -}); - -it('should fail on multiple fields', () => { - expect(() => transform(encode(Object.assign({}, event, { - dvce_ismobile: 'bad_dvce_ismobile', - tr_tax_base: 'bad_tax_base', - })))).toThrow([ - "Invalid value for field 'dvce_ismobile'.", - "Invalid value for field 'tr_tax_base'.", - ].join('\n')); -}); - -it('should not return geo_location', () => { - expect(() => transform(encode(Object.assign({}, event, { - geo_latitude: '', - geo_longitude: '', - })))).not.toHaveProperty('geo_location'); -}); diff --git a/src/index.spec.ts b/src/index.spec.ts new file mode 100644 index 0000000..8e1addf --- /dev/null +++ b/src/index.spec.ts @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018-2019 dokmic, Snowplow Analytics Ltd. All rights reserved. + * + * This program is licensed to you under the Apache License Version 2.0, + * and you may not use this file except in compliance with the Apache License Version 2.0. + * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the Apache License Version 2.0 is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. + */ + +import { transform } from './index'; +import { event } from './index.fixture'; + +function encode(event: object) { + return Object.keys(event) + .map(key => event[key]) + .join('\t'); +} + +describe('transform', () => { + it('should be transformed', () => { + expect(transform(encode(event))).toMatchSnapshot(); + }); + + it('should fail on fields number', () => { + expect(() => transform(encode({ a: '1', b: '2' }))) + .toThrow('Wrong event fields number.'); + }); + + it('should fail on one field', () => { + expect(() => transform(encode({ ...event, tr_tax_base: 'bad_tax_base' }))) + .toThrow("Invalid value for field 'tr_tax_base'."); + }); + + it('should fail on multiple fields', () => { + expect(() => transform(encode({ ...event, dvce_ismobile: 'bad_dvce_ismobile', tr_tax_base: 'bad_tax_base' }))) + .toThrow([ + "Invalid value for field 'dvce_ismobile'.", + "Invalid value for field 'tr_tax_base'.", + ].join('\n')); + }); + + it('should not return geo_location', () => { + expect(() => transform(encode({ ...event, geo_latitude: '', geo_longitude: '' }))) + .not.toHaveProperty('geo_location'); + }); +}); diff --git a/src/types.spec.ts b/src/types.spec.ts new file mode 100644 index 0000000..e7ddaa1 --- /dev/null +++ b/src/types.spec.ts @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2018-2019 dokmic, Snowplow Analytics Ltd. All rights reserved. + * + * This program is licensed to you under the Apache License Version 2.0, + * and you may not use this file except in compliance with the Apache License Version 2.0. + * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the Apache License Version 2.0 is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. + */ + +import { Boolean, Contexts, Double, Integer, String, Timestamp, Unstruct } from './types'; + +describe('String', () => { + it('should parse string', () => { + expect(String('key', 'value')).toEqual([{ key: 'key', value: 'value' }]); + }); +}); + +describe('Integer', () => { + it('should parse integer', () => { + expect(Integer('key', '123.456')).toEqual([{ key: 'key', value: 123 }]); + }); + + it('should throw an error', () => { + expect(() => Integer('key', 'string')).toThrow(); + }); +}); + +describe('Double', () => { + it('should parse float', () => { + expect(Double('key', '123.456')).toEqual([{ key: 'key', value: 123.456 }]); + }); + + it('should throw an error', () => { + expect(() => Double('key', 'string')).toThrow(); + }); +}); + +describe('Boolean', () => { + it('should parse true', () => { + expect(Boolean('key', '1')).toEqual([{ key: 'key', value: true }]); + }); + + it('should parse false', () => { + expect(Boolean('key', '0')).toEqual([{ key: 'key', value: false }]); + }); + + it('should throw an error', () => { + expect(() => Boolean('key', '2')).toThrow(); + }); +}); + +describe('Timestamp', () => { + it('should parse timestamp', () => { + expect(Timestamp('key', '2017-01-11 10:20:17')).toEqual([{ key: 'key', value: '2017-01-11T10:20:17Z' }]); + }); +}); + +describe('Contexts', () => { + it('should parse contexts', () => { + expect(Contexts('', JSON.stringify({ + data: [ + { + data: { unique: true }, + schema: 'iglu:com.acme/unduplicated/jsonschema/1-0-0', + }, + { + data: { value: 1 }, + schema: 'iglu:com.acme/duplicated/jsonschema/1-0-0', + }, + { + data: { value: 2 }, + schema: 'iglu:com.acme/duplicated/jsonschema/1-0-0', + }, + ], + schema: 'iglu:com.snowplowanalytics.snowplow/contexts/jsonschema/1-0-0', + }))).toEqual([ + { + key: 'contexts_com_acme_unduplicated_1', + value: [ + { unique: true }, + ], + }, + { + key: 'contexts_com_acme_duplicated_1', + value: [ + { value: 1 }, + { value: 2 }, + ], + }, + ]); + }); +}); + +describe('Unstruct', () => { + it('should parse unstruct', () => { + expect(Unstruct('', JSON.stringify({ + data: { + data: { key: 'value' }, + schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1', + }, + schema: 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0', + }))).toEqual([{ + key: 'unstruct_event_com_snowplowanalytics_snowplow_link_click_1', + value: { key: 'value' }, + }]); + }); + + it('should throw an error on missing data', () => { + expect(() => Unstruct('', JSON.stringify({ + schema: 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0', + data: {}, + }))).toThrow(); + }); + + it('should throw an error on invalid schema', () => { + expect(() => Unstruct('', JSON.stringify({ + data: { + data: { key: 'value' }, + schema: 'something', + }, + schema: 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0', + }))).toThrow(); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index d63b018..e5437a9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,16 +13,9 @@ "target": "es6" }, "exclude": [ - "node_modules", - "**/*.test.ts" - ], - "include": [ - "**/*.ts" + "node_modules" ], "typeRoots": [ "node_modules/@types" - ], - "types": [ - "jest" ] }