UNPKG

@snowplow/javascript-tracker

Version:
765 lines (693 loc) 21.7 kB
/* * Copyright (c) 2021 Snowplow Analytics Ltd, 2010 Anthon Pang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ import util from 'util'; import F from 'lodash/fp'; import { fetchResults, start, stop, DockerWrapper } from '../micro'; const dumpLog = (log: Array<unknown>) => console.log(util.inspect(log, true, null, true)); const isMatchWithCallback = F.isMatchWith((lt, rt) => (F.isFunction(rt) ? rt(lt) : undefined)); const SAFARI_EXPECTED_FIRST_NAME = 'Alex'; const SAFARI_EXPECTED_MESSAGE = 'Changed message'; describe('Auto tracking', () => { if (F.isMatch({ browserName: 'internet explorer', version: '9' }, browser.capabilities)) { fit('Skip IE9', () => {}); // Automated tests for IE autotracking features } let log: Array<unknown> = []; let docker: DockerWrapper; const logContains = (ev: unknown) => F.some(isMatchWithCallback(ev as object), log); const loadUrlAndWait = (url: string) => { browser.url(url); browser.waitUntil(() => $('#init').getText() === 'true', { timeout: 5000, timeoutMsg: 'expected init after 5s', interval: 250, }); }; beforeAll(() => { browser.call(() => { return start().then((container) => { docker = container; }); }); browser.url('/index.html'); browser.setCookies({ name: 'container', value: docker.url }); }); afterAll(() => { browser.call(() => { return stop(docker.container); }); }); it('should send a link click events', () => { loadUrlAndWait('/link-tracking.html'); $('#link-to-click').click(); loadUrlAndWait('/link-tracking.html?filter=exclude'); $('#link-to-not-track').click(); $('#link-to-click').click(); loadUrlAndWait('/link-tracking.html?filter=filter'); $('#link-to-filter').click(); $('#link-to-click').click(); loadUrlAndWait('/link-tracking.html?filter=include'); $('#link-to-filter').click(); $('#link-to-click').click(); // time for activity to register and request to arrive browser.pause(5000); browser.call(() => fetchResults(docker.url).then((result) => { log = result; }) ); }); it('should send a link click event', () => { expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', page_url: 'http://snowplow-js-tracker.local:8080/link-tracking.html', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1', data: { targetUrl: 'http://snowplow-js-tracker.local:8080/link-tracking.html#click', elementId: 'link-to-click', elementClasses: ['example'], elementTarget: '_self', }, }, }, contexts: { data: [ { schema: 'iglu:org.schema/WebPage/jsonschema/1-0-0', data: { keywords: ['tester'] }, }, ], }, }, }) ).toBe(true); }); it('should not send a blocked link click event', () => { expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1', data: { elementId: 'link-to-not-track', }, }, }, }, }) ).toBe(false); expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1', data: { targetUrl: 'http://snowplow-js-tracker.local:8080/link-tracking.html?filter=exclude#click', elementId: 'link-to-click', elementClasses: ['example'], elementContent: 'Click here', elementTarget: '_self', }, }, }, }, }) ).toBe(true); }); it('should not send a filtered link click event', () => { expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1', data: { elementId: 'link-to-filter', }, }, }, }, }) ).toBe(false); expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1', data: { targetUrl: 'http://snowplow-js-tracker.local:8080/link-tracking.html?filter=filter#click', elementId: 'link-to-click', elementClasses: ['example'], elementContent: 'Click here', elementTarget: '_self', }, }, }, }, }) ).toBe(true); }); it('should not send a non-included link click event', () => { expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1', data: { elementId: 'link-to-filter', }, }, }, }, }) ).toBe(false); expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1', data: { targetUrl: 'http://snowplow-js-tracker.local:8080/link-tracking.html?filter=include#click', elementId: 'link-to-click', elementClasses: ['example'], elementContent: 'Click here', elementTarget: '_self', }, }, }, }, }) ).toBe(true); }); it('should send form events', () => { loadUrlAndWait('/form-tracking.html'); $('#fname').click(); // Safari 12.1 doesn't fire onchange events when clearing // However some browsers don't support setValue if (F.isMatch({ browserName: 'Safari', browserVersion: '12.1.1' }, browser.capabilities)) { $('#fname').setValue(SAFARI_EXPECTED_FIRST_NAME); } else { $('#fname').clearValue(); } $('#lname').click(); browser.pause(250); $('#bike').click(); browser.pause(250); $('#cars').click(); $('#cars').selectByAttribute('value', 'saab'); $('#cars').click(); browser.pause(250); $('#message').click(); // Safari 12.1 doesn't fire onchange events when clearing // However some browsers don't support setValue if (F.isMatch({ browserName: 'Safari', browserVersion: '12.1.1' }, browser.capabilities)) { $('#message').setValue(SAFARI_EXPECTED_MESSAGE); } else { $('#message').clearValue(); } browser.pause(250); $('#terms').click(); browser.pause(2000); $('#submit').click(); browser.pause(1000); loadUrlAndWait('/form-tracking.html?filter=exclude'); $('#fname').click(); $('#lname').click(); browser.pause(1000); loadUrlAndWait('/form-tracking.html?filter=include'); $('#lname').click(); browser.pause(1000); loadUrlAndWait('/form-tracking.html?filter=filter'); $('#fname').click(); $('#lname').click(); browser.pause(1000); loadUrlAndWait('/form-tracking.html?filter=excludedForm'); $('#excluded-fname').click(); $('#excluded-submit').click(); // time for activity to register and request to arrive browser.pause(2500); browser.call(() => fetchResults(docker.url).then((result) => { log = result; }) ); }); it('should send focus_form and change_form on text input', () => { // Safari 12.1 doesn't fire onchange events when clearing // However some browsers don't support setValue let expectedFirstName = ''; if (F.isMatch({ browserName: 'Safari', browserVersion: '12.1.1' }, browser.capabilities)) { expectedFirstName = SAFARI_EXPECTED_FIRST_NAME; } expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0', data: { formId: 'myForm', elementId: 'fname', nodeName: 'INPUT', elementType: 'text', elementClasses: ['test'], value: 'John', }, }, }, }, }) ).toBe(true); expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0', data: { formId: 'myForm', elementId: 'fname', nodeName: 'INPUT', type: 'text', elementClasses: ['test'], value: expectedFirstName, }, }, }, }, }) ).toBe(true); expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0', data: { formId: 'myForm', elementId: 'lname', nodeName: 'INPUT', elementType: 'text', elementClasses: [], value: 'Doe', }, }, }, }, }) ).toBe(true); }); it('should send change_form on radio input', () => { expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0', data: { formId: 'myForm', elementId: 'vehicle', nodeName: 'INPUT', type: 'radio', elementClasses: [], value: 'Bike', }, }, }, }, }) ).toBe(true); }); it('should send focus_form and change_form on select change', () => { // MS Edge <= 18 doesn't fire change events on select elements via Edge WebDriver if (F.isMatch({ browserName: 'MicrosoftEdge', browserVersion: '25.10586.0.0' }, browser.capabilities)) { return; } expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0', data: { formId: 'myForm', elementId: 'cars', nodeName: 'SELECT', elementClasses: [], value: 'volvo', }, }, }, }, }) ).toBe(true); expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0', data: { formId: 'myForm', elementId: 'cars', nodeName: 'SELECT', elementClasses: [], value: 'saab', }, }, }, }, }) ).toBe(true); }); it('should send focus_form and change_form on textarea input', () => { // Safari 12.1 doesn't fire onchange events when clearing // However some browsers don't support setValue let expectedMessage = ''; if (F.isMatch({ browserName: 'Safari', browserVersion: '12.1.1' }, browser.capabilities)) { expectedMessage = SAFARI_EXPECTED_MESSAGE; } expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0', data: { formId: 'myForm', elementId: 'message', nodeName: 'TEXTAREA', elementClasses: [], value: 'This is a message', }, }, }, }, }) ).toBe(true); expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0', data: { formId: 'myForm', elementId: 'message', nodeName: 'TEXTAREA', elementClasses: [], value: expectedMessage, }, }, }, }, }) ).toBe(true); }); it('should send change_form on checkbox', () => { expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0', data: { formId: 'myForm', elementId: 'terms', nodeName: 'INPUT', type: 'checkbox', elementClasses: [], value: 'agree', }, }, }, }, }) ).toBe(true); }); it('should send submit_form on form submission', () => { // Safari 12.1 doesn't fire onchange events when clearing // However some browsers don't support setValue let expectedFirstName = '', expectedMessage = ''; if (F.isMatch({ browserName: 'Safari', browserVersion: '12.1.1' }, browser.capabilities)) { expectedFirstName = SAFARI_EXPECTED_FIRST_NAME; expectedMessage = SAFARI_EXPECTED_MESSAGE; } expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/submit_form/jsonschema/1-0-0', data: { formId: 'myForm', formClasses: ['formy-mcformface'], elements: [ { name: 'message', value: expectedMessage, nodeName: 'TEXTAREA', }, { name: 'fname', value: expectedFirstName, nodeName: 'INPUT', type: 'text', }, { name: 'lname', value: 'Doe', nodeName: 'INPUT', type: 'text', }, { name: 'vehicle', value: 'Bike', nodeName: 'INPUT', type: 'radio', }, { name: 'terms', value: 'agree', nodeName: 'INPUT', type: 'checkbox', }, { name: 'cars', value: 'saab', nodeName: 'SELECT', }, ], }, }, }, contexts: { data: [ { schema: 'iglu:org.schema/WebPage/jsonschema/1-0-0', data: { keywords: ['tester'] }, }, ], }, }, }) ).toBe(true); }); it('should not send focus_form on excluded element', () => { expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', page_url: 'http://snowplow-js-tracker.local:8080/form-tracking.html?filter=exclude', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0', data: { elementId: 'fname', }, }, }, }, }) ).toBe(false); expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', page_url: 'http://snowplow-js-tracker.local:8080/form-tracking.html?filter=exclude', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0', data: { elementId: 'lname', }, }, }, }, }) ).toBe(true); }); it('should send focus_form on included element', () => { expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', page_url: 'http://snowplow-js-tracker.local:8080/form-tracking.html?filter=include', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0', data: { elementId: 'lname', }, }, }, }, }) ).toBe(true); }); it('should send focus_form on element included by filter', () => { expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', page_url: 'http://snowplow-js-tracker.local:8080/form-tracking.html?filter=filter', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0', data: { elementId: 'fname', }, }, }, }, }) ).toBe(true); expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', page_url: 'http://snowplow-js-tracker.local:8080/form-tracking.html?filter=filter', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0', data: { elementId: 'lname', }, }, }, }, }) ).toBe(false); }); it('should not send focus_form on elements', () => { expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0', data: { elementId: 'excluded-fname', }, }, }, }, }) ).toBe(false); }); it('should not send submit_form', () => { expect( logContains({ event: { event: 'unstruct', app_id: 'autotracking', unstruct_event: { data: { schema: 'iglu:com.snowplowanalytics.snowplow/submit_form/jsonschema/1-0-0', data: { formId: 'excludedForm', formClasses: ['excluded-form'], }, }, }, }, }) ).toBe(false); }); });