From 3b28ae48cdd2e0c0437d2e74a629ca5d6f5b1992 Mon Sep 17 00:00:00 2001 From: Simon Bennetts Date: Tue, 19 Sep 2023 14:09:27 +0200 Subject: [PATCH] Fix no storage events Signed-off-by: Simon Bennetts --- CHANGELOG.md | 3 + source/Background/index.ts | 2 +- source/ContentScript/index.ts | 12 ++-- source/types/ReportedModel.ts | 7 ++- test/ContentScript/integrationTests.test.ts | 56 +++++++++++++++++-- test/ContentScript/unitTests.test.ts | 13 ++++- test/ContentScript/webpages/localStorage.html | 11 ++++ .../webpages/sessionStorage.html | 11 ++++ 8 files changed, 99 insertions(+), 16 deletions(-) create mode 100644 test/ContentScript/webpages/localStorage.html create mode 100644 test/ContentScript/webpages/sessionStorage.html diff --git a/CHANGELOG.md b/CHANGELOG.md index e25933b..ba81f49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,3 +4,6 @@ All notable changes to this add-on will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased + +### Fixed +- Storage events not being reported. \ No newline at end of file diff --git a/source/Background/index.ts b/source/Background/index.ts index 7a0f5a0..ce2c80c 100644 --- a/source/Background/index.ts +++ b/source/Background/index.ts @@ -196,7 +196,7 @@ async function handleMessage( case REPORT_OBJECT: { const repObj = JSON.parse(request.data); if (repObj.type === LOCAL_STORAGE || repObj.type === SESSION_STORAGE) { - const repStorage = new ReportedStorage('', '', '', '', ''); + const repStorage = new ReportedStorage('', '', '', '', '', ''); Object.assign(repStorage, repObj); const repStorStr = repStorage.toShortString(); if (reportedStorage.has(repStorStr)) { diff --git a/source/ContentScript/index.ts b/source/ContentScript/index.ts index 86b2247..01833a5 100644 --- a/source/ContentScript/index.ts +++ b/source/ContentScript/index.ts @@ -47,8 +47,9 @@ function reportStorage( storage: Storage, fn: (re: ReportedStorage) => void ): void { + const url = window.location.href; for (const key of Object.keys(storage)) { - fn(new ReportedStorage(name, '', key, '', storage.getItem(key))); + fn(new ReportedStorage(name, '', key, '', storage.getItem(key), url)); } } @@ -131,8 +132,9 @@ function reportPageForms( doc: Document, fn: (re: ReportedObject) => void ): void { + const url = window.location.href; Array.prototype.forEach.call(doc.forms, (form: HTMLFormElement) => { - fn(new ReportedElement(form)); + fn(new ReportedElement(form, url)); }); } @@ -140,10 +142,11 @@ function reportPageLinks( doc: Document, fn: (re: ReportedObject) => void ): void { + const url = window.location.href; Array.prototype.forEach.call( doc.links, (link: HTMLAnchorElement | HTMLAreaElement) => { - fn(new ReportedElement(link)); + fn(new ReportedElement(link, url)); } ); } @@ -152,8 +155,9 @@ function reportElements( collection: HTMLCollection, fn: (re: ReportedObject) => void ): void { + const url = window.location.href; Array.prototype.forEach.call(collection, (element: Element) => { - fn(new ReportedElement(element)); + fn(new ReportedElement(element, url)); }); } diff --git a/source/types/ReportedModel.ts b/source/types/ReportedModel.ts index c35fa90..df539a6 100644 --- a/source/types/ReportedModel.ts +++ b/source/types/ReportedModel.ts @@ -42,7 +42,7 @@ class ReportedObject { id: string, nodeName: string, text: string | null, - url: string = window.location.href + url: string ) { this.timestamp = Date.now(); this.type = type; @@ -96,13 +96,14 @@ class ReportedStorage extends ReportedObject { } class ReportedElement extends ReportedObject { - public constructor(element: Element) { + public constructor(element: Element, url: string) { super( 'nodeAdded', element.tagName, element.id, element.nodeName, - element.textContent + element.textContent, + url ); if (element.tagName === 'A') { // This gets the full URL rather than a relative one diff --git a/test/ContentScript/integrationTests.test.ts b/test/ContentScript/integrationTests.test.ts index b93ee78..c697f02 100644 --- a/test/ContentScript/integrationTests.test.ts +++ b/test/ContentScript/integrationTests.test.ts @@ -65,7 +65,8 @@ function integrationTests( await page.close(); // Then const expectedData = - '["{\\"action\\":{\\"action\\":\\"reportEvent\\"},\\"body\\":{\\"eventJson\\":\\"{TIMESTAMP,\\"eventName\\":\\"pageLoad\\",\\"url\\":\\"http://localhost:1801/webpages/integrationTest.html\\",\\"count\\":1}\\",\\"apikey\\":\\"not set\\"}}","{\\"action\\":{\\"action\\":\\"reportObject\\"},\\"body\\":{\\"objectJson\\":\\"{TIMESTAMP,\\"type\\":\\"nodeAdded\\",\\"tagName\\":\\"A\\",\\"id\\":\\"\\",\\"nodeName\\":\\"A\\",\\"url\\":\\"http://localhost:1801/webpages/integrationTest.html\\",\\"href\\":\\"http://localhost:1801/webpages/integrationTest.html#test\\",\\"text\\":\\"Link\\"}\\",\\"apikey\\":\\"not set\\"}}"]'; + '["{\\"action\\":{\\"action\\":\\"reportEvent\\"},\\"body\\":{\\"eventJson\\":\\"{TIMESTAMP,\\"eventName\\":\\"pageLoad\\",\\"url\\":\\"http://localhost:1801/webpages/integrationTest.html\\",\\"count\\":1}\\",\\"apikey\\":\\"not set\\"}}",' + + '"{\\"action\\":{\\"action\\":\\"reportObject\\"},\\"body\\":{\\"objectJson\\":\\"{TIMESTAMP,\\"type\\":\\"nodeAdded\\",\\"tagName\\":\\"A\\",\\"id\\":\\"\\",\\"nodeName\\":\\"A\\",\\"url\\":\\"http://localhost:1801/webpages/integrationTest.html\\",\\"href\\":\\"http://localhost:1801/webpages/integrationTest.html#test\\",\\"text\\":\\"Link\\"}\\",\\"apikey\\":\\"not set\\"}}"]'; expect(JSON.stringify(Array.from(actualData))).toBe(expectedData); }); @@ -121,7 +122,9 @@ function integrationTests( await page.close(); // Then const expectedData = - '["{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"input-1\\",\\"index\\":1,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClear\\"}\\",\\"apikey\\":\\"not set\\"}}","{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"value\\":\\"testinput\\",\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"input-1\\",\\"index\\":2,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementSendKeys\\"}\\",\\"apikey\\":\\"not set\\"}}","{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"click\\",\\"index\\":3,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClick\\"}\\",\\"apikey\\":\\"not set\\"}}"]'; + '["{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"input-1\\",\\"index\\":1,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClear\\"}\\",\\"apikey\\":\\"not set\\"}}",' + + '"{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"value\\":\\"testinput\\",\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"input-1\\",\\"index\\":2,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementSendKeys\\"}\\",\\"apikey\\":\\"not set\\"}}",' + + '"{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"click\\",\\"index\\":3,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClick\\"}\\",\\"apikey\\":\\"not set\\"}}"]'; expect(JSON.stringify(Array.from(actualData))).toBe(expectedData); }); @@ -189,7 +192,10 @@ function integrationTests( await page.close(); // Then const expectedData = - '["{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"input-1\\",\\"index\\":1,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClear\\"}\\",\\"apikey\\":\\"not set\\"}}","{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"value\\":\\"testinput\\",\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"input-1\\",\\"index\\":2,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementSendKeys\\"}\\",\\"apikey\\":\\"not set\\"}}","{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"click\\",\\"index\\":3,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClick\\"}\\",\\"apikey\\":\\"not set\\"}}","{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"index\\":4,\\"sleepInSeconds\\":0,\\"enabled\\":true,\\"elementType\\":\\"ZestClientWindowClose\\"}\\",\\"apikey\\":\\"not set\\"}}"]'; + '["{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"input-1\\",\\"index\\":1,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClear\\"}\\",\\"apikey\\":\\"not set\\"}}",' + + '"{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"value\\":\\"testinput\\",\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"input-1\\",\\"index\\":2,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementSendKeys\\"}\\",\\"apikey\\":\\"not set\\"}}",' + + '"{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"click\\",\\"index\\":3,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClick\\"}\\",\\"apikey\\":\\"not set\\"}}",' + + '"{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"index\\":4,\\"sleepInSeconds\\":0,\\"enabled\\":true,\\"elementType\\":\\"ZestClientWindowClose\\"}\\",\\"apikey\\":\\"not set\\"}}"]'; expect(JSON.stringify(Array.from(actualData))).toBe(expectedData); }); @@ -211,7 +217,10 @@ function integrationTests( await page.close(); // Then const expectedData = - '["{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"input-1\\",\\"index\\":1,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClear\\"}\\",\\"apikey\\":\\"not set\\"}}","{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"value\\":\\"testinput\\",\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"input-1\\",\\"index\\":2,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementSendKeys\\"}\\",\\"apikey\\":\\"not set\\"}}","{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"click\\",\\"index\\":3,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClick\\"}\\",\\"apikey\\":\\"not set\\"}}","{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"index\\":4,\\"sleepInSeconds\\":0,\\"enabled\\":true,\\"elementType\\":\\"ZestClientWindowClose\\"}\\",\\"apikey\\":\\"not set\\"}}"]'; + '["{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"input-1\\",\\"index\\":1,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClear\\"}\\",\\"apikey\\":\\"not set\\"}}",' + + '"{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"value\\":\\"testinput\\",\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"input-1\\",\\"index\\":2,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementSendKeys\\"}\\",\\"apikey\\":\\"not set\\"}}",' + + '"{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"click\\",\\"index\\":3,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClick\\"}\\",\\"apikey\\":\\"not set\\"}}",' + + '"{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"index\\":4,\\"sleepInSeconds\\":0,\\"enabled\\":true,\\"elementType\\":\\"ZestClientWindowClose\\"}\\",\\"apikey\\":\\"not set\\"}}"]'; expect(JSON.stringify(Array.from(actualData))).toBe(expectedData); }); @@ -257,7 +266,8 @@ function integrationTests( await page.close(); // Then expect(JSON.stringify(Array.from(actualData))).toBe( - '["{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"frameIndex\\":0,\\"frameName\\":\\"\\",\\"parent\\":false,\\"index\\":1,\\"enabled\\":true,\\"elementType\\":\\"ZestClientSwitchToFrame\\"}\\",\\"apikey\\":\\"not set\\"}}","{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"test-btn\\",\\"index\\":2,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClick\\"}\\",\\"apikey\\":\\"not set\\"}}"]' + '["{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"frameIndex\\":0,\\"frameName\\":\\"\\",\\"parent\\":false,\\"index\\":1,\\"enabled\\":true,\\"elementType\\":\\"ZestClientSwitchToFrame\\"}\\",\\"apikey\\":\\"not set\\"}}",' + + '"{\\"action\\":{\\"action\\":\\"reportZestStatement\\"},\\"body\\":{\\"statementJson\\":\\"{\\"windowHandle\\":\\"windowHandle1\\",\\"type\\":\\"id\\",\\"element\\":\\"test-btn\\",\\"index\\":2,\\"enabled\\":true,\\"elementType\\":\\"ZestClientElementClick\\"}\\",\\"apikey\\":\\"not set\\"}}"]' ); }); @@ -277,6 +287,42 @@ function integrationTests( // Then expect(JSON.stringify(Array.from(actualData))).toBe('[]'); }); + + test('Should record set localStorage', async () => { + // Given / When + server = getFakeZapServer(actualData, _JSONPORT); + const context = await driver.getContext(_JSONPORT); + const page = await context.newPage(); + await page.goto( + `http://localhost:${_HTTPPORT}/webpages/localStorage.html` + ); + await page.waitForLoadState('networkidle'); + await page.waitForTimeout(1000); + await page.close(); + // Then + const expectedData = + '["{\\"action\\":{\\"action\\":\\"reportEvent\\"},\\"body\\":{\\"eventJson\\":\\"{TIMESTAMP,\\"eventName\\":\\"pageLoad\\",\\"url\\":\\"http://localhost:1801/webpages/localStorage.html\\",\\"count\\":1}\\",\\"apikey\\":\\"not set\\"}}",' + + '"{\\"action\\":{\\"action\\":\\"reportObject\\"},\\"body\\":{\\"objectJson\\":\\"{TIMESTAMP,\\"type\\":\\"localStorage\\",\\"tagName\\":\\"\\",\\"id\\":\\"test\\",\\"nodeName\\":\\"\\",\\"url\\":\\"http://localhost:1801/webpages/localStorage.html\\",\\"text\\":\\"localData\\"}\\",\\"apikey\\":\\"not set\\"}}"]'; + expect(JSON.stringify(Array.from(actualData))).toBe(expectedData); + }); + + test('Should record set sessionStorage', async () => { + // Given / When + server = getFakeZapServer(actualData, _JSONPORT); + const context = await driver.getContext(_JSONPORT); + const page = await context.newPage(); + await page.goto( + `http://localhost:${_HTTPPORT}/webpages/sessionStorage.html` + ); + await page.waitForLoadState('networkidle'); + await page.waitForTimeout(1000); + await page.close(); + // Then + const expectedData = + '["{\\"action\\":{\\"action\\":\\"reportEvent\\"},\\"body\\":{\\"eventJson\\":\\"{TIMESTAMP,\\"eventName\\":\\"pageLoad\\",\\"url\\":\\"http://localhost:1801/webpages/sessionStorage.html\\",\\"count\\":1}\\",\\"apikey\\":\\"not set\\"}}",' + + '"{\\"action\\":{\\"action\\":\\"reportObject\\"},\\"body\\":{\\"objectJson\\":\\"{TIMESTAMP,\\"type\\":\\"sessionStorage\\",\\"tagName\\":\\"\\",\\"id\\":\\"test\\",\\"nodeName\\":\\"\\",\\"url\\":\\"http://localhost:1801/webpages/sessionStorage.html\\",\\"text\\":\\"sessionData\\"}\\",\\"apikey\\":\\"not set\\"}}"]'; + expect(JSON.stringify(Array.from(actualData))).toBe(expectedData); + }); } } diff --git a/test/ContentScript/unitTests.test.ts b/test/ContentScript/unitTests.test.ts index fda8d71..d6a4713 100644 --- a/test/ContentScript/unitTests.test.ts +++ b/test/ContentScript/unitTests.test.ts @@ -47,7 +47,8 @@ test('ReportedObject toString as expected', () => { 'b', 'c', 'd', - 'e' + 'e', + 'http://localhost/' ); // Then @@ -59,7 +60,10 @@ test('ReportedObject toString as expected', () => { test('ReportedElement P toString as expected', () => { // Given / When const el: Element = document.createElement('p'); - const ro: src.ReportedElement = new src.ReportedElement(el); + const ro: src.ReportedElement = new src.ReportedElement( + el, + 'http://localhost/' + ); // Then expect(ro.toNonTimestampString()).toBe( @@ -73,7 +77,10 @@ test('ReportedElement A toString as expected', () => { const linkText = document.createTextNode('Title'); a.appendChild(linkText); a.setAttribute('href', 'https://example.com'); - const ro: src.ReportedElement = new src.ReportedElement(a); + const ro: src.ReportedElement = new src.ReportedElement( + a, + 'http://localhost/' + ); // Then expect(ro.toNonTimestampString()).toBe( diff --git a/test/ContentScript/webpages/localStorage.html b/test/ContentScript/webpages/localStorage.html new file mode 100644 index 0000000..e94612e --- /dev/null +++ b/test/ContentScript/webpages/localStorage.html @@ -0,0 +1,11 @@ + + + + Document + + + + + \ No newline at end of file diff --git a/test/ContentScript/webpages/sessionStorage.html b/test/ContentScript/webpages/sessionStorage.html new file mode 100644 index 0000000..33cc2e1 --- /dev/null +++ b/test/ContentScript/webpages/sessionStorage.html @@ -0,0 +1,11 @@ + + + + Document + + + + + \ No newline at end of file