From 8dd819d14eb72b07910950210c353a9442fc4d58 Mon Sep 17 00:00:00 2001 From: Stanislav A Date: Mon, 7 Nov 2022 19:09:56 +0300 Subject: [PATCH] add trusted-set-local-storage-item scriptelt --- src/scriptlets/scriptlets-list.js | 1 + .../trusted-set-local-storage-item.js | 71 +++++++++++++ tests/scriptlets/index.test.js | 1 + .../scriptlets/set-local-storage-item.test.js | 60 +++++------ .../trusted-set-local-storage-item.test.js | 99 +++++++++++++++++++ 5 files changed, 202 insertions(+), 30 deletions(-) create mode 100644 src/scriptlets/trusted-set-local-storage-item.js create mode 100644 tests/scriptlets/trusted-set-local-storage-item.test.js diff --git a/src/scriptlets/scriptlets-list.js b/src/scriptlets/scriptlets-list.js index f00ab89f7..9a14ecf04 100644 --- a/src/scriptlets/scriptlets-list.js +++ b/src/scriptlets/scriptlets-list.js @@ -51,3 +51,4 @@ export * from './no-topics'; export * from './trusted-replace-xhr-response'; export * from './xml-prune'; export * from './trusted-replace-fetch-response'; +export * from './trusted-set-local-storage-item'; diff --git a/src/scriptlets/trusted-set-local-storage-item.js b/src/scriptlets/trusted-set-local-storage-item.js new file mode 100644 index 000000000..b0979370f --- /dev/null +++ b/src/scriptlets/trusted-set-local-storage-item.js @@ -0,0 +1,71 @@ +import { + hit, + nativeIsNaN, +} from '../helpers/index'; + +/* eslint-disable max-len */ +/** + * @scriptlet trusted-set-local-storage-item + * + * @description + * Adds specified key and its value to localStorage object, or updates the value of the key if it already exists. + * + * **Syntax** + * ``` + * example.com#%#//scriptlet('trusted-set-local-storage-item', 'key', 'value') + * ``` + * + * - `key` — required, key name to be set. + * - `value` - required, key value; possible values: + * - positive decimal integer `<= 32767` + * - one of the predefined constants: + * - `undefined` + * - `false` + * - `true` + * - `null` + * - `emptyObj` - empty object + * - `emptyArr` - empty array + * - `''` - empty string + * - `yes` + * - `no` + * + * **Examples** + * ``` + * example.org#%#//scriptlet('trusted-set-local-storage-item', 'player.live.current.mute', 'false') + * + * example.org#%#//scriptlet('trusted-set-local-storage-item', 'exit-intent-marketing', '1') + * ``` + */ +/* eslint-enable max-len */ + +export function trustedSetLocalStorageItem(source, key, value) { + if (!key || (!value && value !== '')) { + return; + } + + const setItem = (key, value) => { + const { localStorage } = window; + // setItem() may throw an exception if the storage is full. + try { + localStorage.setItem(key, value); + hit(source); + } catch (e) { + if (source.verbose) { + // eslint-disable-next-line no-console + console.log(`Was unable to set localStorage item due to: ${e.message}`); + } + } + }; + + setItem(key, value); +} + +trustedSetLocalStorageItem.names = [ + 'trusted-set-local-storage-item', + // trusted scriptlets support no aliases +]; + +trustedSetLocalStorageItem.injections = [ + hit, + nativeIsNaN, +]; diff --git a/tests/scriptlets/index.test.js b/tests/scriptlets/index.test.js index 865db978d..90e785e1a 100644 --- a/tests/scriptlets/index.test.js +++ b/tests/scriptlets/index.test.js @@ -48,3 +48,4 @@ import './trusted-replace-xhr-response.test'; import './xml-prune.test'; import './trusted-click-element.test'; import './trusted-replace-fetch-response.test'; +import './trusted-set-local-storage-item.test'; diff --git a/tests/scriptlets/set-local-storage-item.test.js b/tests/scriptlets/set-local-storage-item.test.js index 1a11244a1..b180ea884 100644 --- a/tests/scriptlets/set-local-storage-item.test.js +++ b/tests/scriptlets/set-local-storage-item.test.js @@ -97,34 +97,34 @@ if (isSafariBrowser()) { assert.strictEqual(window.localStorage.getItem(cName), 'no', 'localStorage item has been set'); clearStorageItem(cName); }); -} -test('Set localStorage key with invalid value', (assert) => { - let cName = '__test-item_arrayItem'; - let cValue = '["item"]'; - runScriptlet(name, [cName, cValue]); - assert.strictEqual(window.hit, undefined, 'Hit was not fired'); - assert.strictEqual(window.localStorage.getItem(cName), null, 'localStorage item has not been set'); - clearStorageItem(cName); - - cName = '__test-item_object'; - cValue = '{"key":value"}'; - runScriptlet(name, [cName, cValue]); - assert.strictEqual(window.hit, undefined, 'Hit was not fired'); - assert.strictEqual(window.localStorage.getItem(cName), null, 'localStorage item has not been set'); - clearStorageItem(cName); - - cName = '__test-item_str'; - cValue = 'test_string'; - runScriptlet(name, [cName, cValue]); - assert.strictEqual(window.hit, undefined, 'Hit was not fired'); - assert.strictEqual(window.localStorage.getItem(cName), null, 'localStorage item has not been set'); - clearStorageItem(cName); - - cName = '__test-item_bigInt'; - cValue = '999999'; - runScriptlet(name, [cName, cValue]); - assert.strictEqual(window.hit, undefined, 'Hit was not fired'); - assert.strictEqual(window.localStorage.getItem(cName), null, 'localStorage item has not been set'); - clearStorageItem(cName); -}); + test('Set localStorage key with invalid value', (assert) => { + let cName = '__test-item_arrayItem'; + let cValue = '["item"]'; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, undefined, 'Hit was not fired'); + assert.strictEqual(window.localStorage.getItem(cName), null, 'localStorage item has not been set'); + clearStorageItem(cName); + + cName = '__test-item_object'; + cValue = '{"key":value"}'; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, undefined, 'Hit was not fired'); + assert.strictEqual(window.localStorage.getItem(cName), null, 'localStorage item has not been set'); + clearStorageItem(cName); + + cName = '__test-item_str'; + cValue = 'test_string'; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, undefined, 'Hit was not fired'); + assert.strictEqual(window.localStorage.getItem(cName), null, 'localStorage item has not been set'); + clearStorageItem(cName); + + cName = '__test-item_bigInt'; + cValue = '999999'; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, undefined, 'Hit was not fired'); + assert.strictEqual(window.localStorage.getItem(cName), null, 'localStorage item has not been set'); + clearStorageItem(cName); + }); +} diff --git a/tests/scriptlets/trusted-set-local-storage-item.test.js b/tests/scriptlets/trusted-set-local-storage-item.test.js new file mode 100644 index 000000000..dded24d6f --- /dev/null +++ b/tests/scriptlets/trusted-set-local-storage-item.test.js @@ -0,0 +1,99 @@ +/* eslint-disable no-underscore-dangle */ +import { runScriptlet, clearGlobalProps, isSafariBrowser } from '../helpers'; + +const { test, module } = QUnit; +const name = 'trusted-set-local-storage-item'; + +const beforeEach = () => { + window.__debug = () => { + window.hit = 'FIRED'; + }; +}; + +const afterEach = () => { + clearGlobalProps('hit', '__debug'); +}; + +module(name, { beforeEach, afterEach }); + +const clearStorageItem = (cName) => { + window.localStorage.removeItem(cName); +}; + +if (isSafariBrowser()) { + test('unsupported', (assert) => { + assert.ok(true, 'does not work in Safari 10 while browserstack auto tests run'); + }); +} else { + test('Set localStorage key with valid value', (assert) => { + let cName = '__test-item_true'; + let cValue = 'true'; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, 'FIRED', 'Hit was fired'); + assert.strictEqual(window.localStorage.getItem(cName), 'true', 'localStorage item has been set'); + clearStorageItem(cName); + + cName = '__test-item_false'; + cValue = 'false'; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, 'FIRED', 'Hit was fired'); + assert.strictEqual(window.localStorage.getItem(cName), 'false', 'localStorage item has been set'); + clearStorageItem(cName); + + cName = '__test-item_null'; + cValue = 'null'; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, 'FIRED', 'Hit was fired'); + assert.strictEqual(window.localStorage.getItem(cName), 'null', 'localStorage item has been set'); + clearStorageItem(cName); + + cName = '__test-item_undefined'; + cValue = 'undefined'; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, 'FIRED', 'Hit was fired'); + assert.strictEqual(window.localStorage.getItem(cName), 'undefined', 'localStorage item has been set'); + clearStorageItem(cName); + + cName = '__test-item_emptyStr'; + cValue = ''; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, 'FIRED', 'Hit was fired'); + assert.strictEqual(window.localStorage.getItem(cName), '', 'localStorage item has been set'); + clearStorageItem(cName); + + cName = '__test-item_int'; + cValue = '15'; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, 'FIRED', 'Hit was fired'); + assert.strictEqual(window.localStorage.getItem(cName), '15', 'localStorage item has been set'); + clearStorageItem(cName); + + cName = '__test-item_yes'; + cValue = 'yes'; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, 'FIRED', 'Hit was fired'); + assert.strictEqual(window.localStorage.getItem(cName), 'yes', 'localStorage item has been set'); + clearStorageItem(cName); + + cName = '__test-item_no'; + cValue = 'no'; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, 'FIRED', 'Hit was fired'); + assert.strictEqual(window.localStorage.getItem(cName), 'no', 'localStorage item has been set'); + clearStorageItem(cName); + + cName = '__test-item_arrayItem'; + cValue = '["item"]'; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, 'FIRED', 'Hit was fired'); + assert.strictEqual(window.localStorage.getItem(cName), cValue, 'localStorage item has not been set'); + clearStorageItem(cName); + + cName = '__test-item_object'; + cValue = '{"key":value"}'; + runScriptlet(name, [cName, cValue]); + assert.strictEqual(window.hit, 'FIRED', 'Hit was fired'); + assert.strictEqual(window.localStorage.getItem(cName), cValue, 'localStorage item has not been set'); + clearStorageItem(cName); + }); +}