From b759f4a290fc5f9683c06b4e2f0e425962d2e465 Mon Sep 17 00:00:00 2001 From: Nina Ciocanu Date: Thu, 7 Nov 2024 12:13:48 +0200 Subject: [PATCH 1/3] mark applied items and do not re-apply them --- bundlesize.json | 12 +++---- .../Personalization/createFetchDataHandler.js | 13 +++++++- .../Personalization/dom-actions/action.js | 22 ++++++------- .../Personalization/dom-actions/appendHtml.js | 4 +-- .../dom-actions/dom/addCssClass.js | 7 ++++ .../dom-actions/dom/hasCssClass.js | 8 +++++ .../dom-actions/insertHtmlAfter.js | 4 +-- .../dom-actions/insertHtmlBefore.js | 4 +-- .../dom-actions/prependHtml.js | 4 +-- .../dom-actions/rearrangeChildren.js | 3 +- .../dom-actions/replaceHtml.js | 4 +-- .../dom-actions/setAttributes.js | 3 +- .../Personalization/dom-actions/setHtml.js | 4 +-- .../Personalization/dom-actions/setStyles.js | 3 +- .../Personalization/dom-actions/setText.js | 3 +- .../Personalization/dom-actions/swapImage.js | 3 +- .../handlers/createProcessDomAction.js | 7 +++- .../handlers/createRenderedHandler.js | 33 +++++++++++++++++++ .../handlers/injectCreateProposition.js | 8 +++-- .../specs/Personalization/C5805676.js | 14 +++++--- 20 files changed, 121 insertions(+), 42 deletions(-) create mode 100644 src/components/Personalization/dom-actions/dom/addCssClass.js create mode 100644 src/components/Personalization/dom-actions/dom/hasCssClass.js create mode 100644 src/components/Personalization/handlers/createRenderedHandler.js diff --git a/bundlesize.json b/bundlesize.json index 4256f8f83..37e9aa379 100644 --- a/bundlesize.json +++ b/bundlesize.json @@ -5,13 +5,13 @@ "brotiliSize": 133 }, "dist/alloy.js": { - "uncompressedSize": 589421, - "gzippedSize": 89564, - "brotiliSize": 69620 + "uncompressedSize": 594046, + "gzippedSize": 90339, + "brotiliSize": 70202 }, "dist/alloy.min.js": { - "uncompressedSize": 123486, - "gzippedSize": 40839, - "brotiliSize": 35412 + "uncompressedSize": 124422, + "gzippedSize": 41166, + "brotiliSize": 35699 } } \ No newline at end of file diff --git a/src/components/Personalization/createFetchDataHandler.js b/src/components/Personalization/createFetchDataHandler.js index 587d50447..310ab5392 100644 --- a/src/components/Personalization/createFetchDataHandler.js +++ b/src/components/Personalization/createFetchDataHandler.js @@ -11,6 +11,7 @@ governing permissions and limitations under the License. */ import { groupBy, isNonEmptyArray } from "../../utils/index.js"; import PAGE_WIDE_SCOPE from "../../constants/pageWideScope.js"; +import uuid from "../../utils/uuid.js"; const DECISIONS_HANDLE = "personalization:decisions"; @@ -56,7 +57,17 @@ export default ({ }, }); } - const propositions = handles.map((handle) => createProposition(handle)); + const propositions = handles.map(handle => { + const proposition = { + items: handle.items.map(item => { + item.id = (!item.id || item.id === "0" ) ? uuid() : item.id; + return item; + }), + ...handle + }; + return createProposition(proposition); + }); + const { page: pagePropositions = [], view: viewPropositions = [], diff --git a/src/components/Personalization/dom-actions/action.js b/src/components/Personalization/dom-actions/action.js index 5de0ad718..50b291d9a 100644 --- a/src/components/Personalization/dom-actions/action.js +++ b/src/components/Personalization/dom-actions/action.js @@ -12,8 +12,7 @@ governing permissions and limitations under the License. import { awaitSelector } from "../../../utils/dom/index.js"; import { hideElements, showElements } from "../flicker/index.js"; -import { selectNodesWithEq } from "./dom/index.js"; - +import { selectNodesWithEq} from "./dom/index.js"; export { default as setText } from "./setText.js"; export { default as setHtml } from "./setHtml.js"; export { default as appendHtml } from "./appendHtml.js"; @@ -26,24 +25,25 @@ export { default as setAttributes } from "./setAttributes.js"; export { default as swapImage } from "./swapImage.js"; export { default as rearrangeChildren } from "./rearrangeChildren.js"; -const renderContent = (elements, content, decorateProposition, renderFunc) => { - const executions = elements.map((element) => - renderFunc(element, content, decorateProposition), - ); +const renderContent = (elements, content, decorateProposition, renderFunc, renderedHandler) => { + const executions = elements.map((element) => { + if(renderedHandler.shouldRender(element)) { + return renderFunc(element, content, decorateProposition, renderedHandler.markAsRendered); + } + }); return Promise.all(executions); }; export const createAction = (renderFunc) => { - return (itemData, decorateProposition) => { + return (itemData, decorateProposition, renderedHandler) => { const { selector, prehidingSelector, content } = itemData; - hideElements(prehidingSelector); return awaitSelector(selector, selectNodesWithEq) - .then((elements) => - renderContent(elements, content, decorateProposition, renderFunc), - ) + .then((elements) => { + return renderContent(elements, content, decorateProposition, renderFunc, renderedHandler); + }) .then( () => { // if everything is OK, show elements diff --git a/src/components/Personalization/dom-actions/appendHtml.js b/src/components/Personalization/dom-actions/appendHtml.js index 0efe70c83..45581228d 100644 --- a/src/components/Personalization/dom-actions/appendHtml.js +++ b/src/components/Personalization/dom-actions/appendHtml.js @@ -21,7 +21,7 @@ import { getRemoteScriptsUrls, } from "./scripts.js"; -export default (container, html, decorateProposition) => { +export default (container, html, decorateProposition, markAsRendered) => { const fragment = createFragment(html); addNonceToInlineStyleElements(fragment); const elements = getChildNodes(fragment); @@ -35,7 +35,7 @@ export default (container, html, decorateProposition) => { }); decorateProposition(container); - + markAsRendered(container); executeInlineScripts(container, scripts); return executeRemoteScripts(scriptsUrls); diff --git a/src/components/Personalization/dom-actions/dom/addCssClass.js b/src/components/Personalization/dom-actions/dom/addCssClass.js new file mode 100644 index 000000000..c6bbd4d33 --- /dev/null +++ b/src/components/Personalization/dom-actions/dom/addCssClass.js @@ -0,0 +1,7 @@ +import {isNonEmptyString} from "../../../../utils/index.js"; + +export default (element, name) => { + if (name && isNonEmptyString(name)) { + element.classList.add(name); + } +}; diff --git a/src/components/Personalization/dom-actions/dom/hasCssClass.js b/src/components/Personalization/dom-actions/dom/hasCssClass.js new file mode 100644 index 000000000..13b7948ab --- /dev/null +++ b/src/components/Personalization/dom-actions/dom/hasCssClass.js @@ -0,0 +1,8 @@ +import {isNonEmptyString} from "../../../../utils/index.js"; + +export default (element, name) => { + if (name && isNonEmptyString(name)) { + return element.classList.contains(name); + } + return false; +}; diff --git a/src/components/Personalization/dom-actions/insertHtmlAfter.js b/src/components/Personalization/dom-actions/insertHtmlAfter.js index 0a72d0ea5..3c0670f3e 100644 --- a/src/components/Personalization/dom-actions/insertHtmlAfter.js +++ b/src/components/Personalization/dom-actions/insertHtmlAfter.js @@ -20,7 +20,7 @@ import { executeRemoteScripts, } from "./scripts.js"; -export default (container, html, decorateProposition) => { +export default (container, html, decorateProposition, markRendered) => { const fragment = createFragment(html); addNonceToInlineStyleElements(fragment); const elements = getChildNodes(fragment); @@ -36,7 +36,7 @@ export default (container, html, decorateProposition) => { insertAfter(insertionPoint, element); insertionPoint = element; }); - + markRendered(container); executeInlineScripts(container, scripts); return executeRemoteScripts(scriptsUrls); diff --git a/src/components/Personalization/dom-actions/insertHtmlBefore.js b/src/components/Personalization/dom-actions/insertHtmlBefore.js index 2ab4d28eb..71ae1e4f1 100644 --- a/src/components/Personalization/dom-actions/insertHtmlBefore.js +++ b/src/components/Personalization/dom-actions/insertHtmlBefore.js @@ -20,7 +20,7 @@ import { getRemoteScriptsUrls, } from "./scripts.js"; -export default (container, html, decorateProposition) => { +export default (container, html, decorateProposition, markRendered) => { const fragment = createFragment(html); addNonceToInlineStyleElements(fragment); const elements = getChildNodes(fragment); @@ -33,7 +33,7 @@ export default (container, html, decorateProposition) => { decorateProposition(element); insertBefore(container, element); }); - + markRendered(container); executeInlineScripts(container, scripts); return executeRemoteScripts(scriptsUrls); diff --git a/src/components/Personalization/dom-actions/prependHtml.js b/src/components/Personalization/dom-actions/prependHtml.js index c91748e56..e3ee9ea29 100644 --- a/src/components/Personalization/dom-actions/prependHtml.js +++ b/src/components/Personalization/dom-actions/prependHtml.js @@ -26,7 +26,7 @@ import { getRemoteScriptsUrls, } from "./scripts.js"; -export default (container, html, decorateProposition) => { +export default (container, html, decorateProposition, markRendered) => { const fragment = createFragment(html); addNonceToInlineStyleElements(fragment); const elements = getChildNodes(fragment); @@ -53,7 +53,7 @@ export default (container, html, decorateProposition) => { i -= 1; } - + markRendered(container); executeInlineScripts(container, scripts); return executeRemoteScripts(scriptsUrls); diff --git a/src/components/Personalization/dom-actions/rearrangeChildren.js b/src/components/Personalization/dom-actions/rearrangeChildren.js index 3071930ec..7186c5507 100644 --- a/src/components/Personalization/dom-actions/rearrangeChildren.js +++ b/src/components/Personalization/dom-actions/rearrangeChildren.js @@ -12,7 +12,7 @@ governing permissions and limitations under the License. import { getChildren, insertAfter, insertBefore } from "./dom/index.js"; -export default (container, { from, to }, decorateProposition) => { +export default (container, { from, to }, decorateProposition, markRendered) => { const children = getChildren(container); const elementFrom = children[from]; const elementTo = children[to]; @@ -31,4 +31,5 @@ export default (container, { from, to }, decorateProposition) => { decorateProposition(elementTo); decorateProposition(elementFrom); + markRendered(container); }; diff --git a/src/components/Personalization/dom-actions/replaceHtml.js b/src/components/Personalization/dom-actions/replaceHtml.js index da5eea767..402d3ae9c 100644 --- a/src/components/Personalization/dom-actions/replaceHtml.js +++ b/src/components/Personalization/dom-actions/replaceHtml.js @@ -13,8 +13,8 @@ governing permissions and limitations under the License. import { removeNode } from "../../../utils/dom/index.js"; import insertHtmlBefore from "./insertHtmlBefore.js"; -export default (container, html, decorateProposition) => { - return insertHtmlBefore(container, html, decorateProposition).then(() => { +export default (container, html, decorateProposition, markRendered) => { + return insertHtmlBefore(container, html, decorateProposition, markRendered).then(() => { removeNode(container); }); }; diff --git a/src/components/Personalization/dom-actions/setAttributes.js b/src/components/Personalization/dom-actions/setAttributes.js index 0b588d835..cc5e70c24 100644 --- a/src/components/Personalization/dom-actions/setAttributes.js +++ b/src/components/Personalization/dom-actions/setAttributes.js @@ -12,10 +12,11 @@ governing permissions and limitations under the License. import { setAttribute } from "./dom/index.js"; -export default (container, attributes, decorateProposition) => { +export default (container, attributes, decorateProposition, markRendered) => { Object.keys(attributes).forEach((key) => { setAttribute(container, key, attributes[key]); }); decorateProposition(container); + markRendered(container); }; diff --git a/src/components/Personalization/dom-actions/setHtml.js b/src/components/Personalization/dom-actions/setHtml.js index 3fb0817b8..3d57580e1 100644 --- a/src/components/Personalization/dom-actions/setHtml.js +++ b/src/components/Personalization/dom-actions/setHtml.js @@ -21,7 +21,7 @@ const clear = (container) => { childNodes.forEach(removeNode); }; -export default (container, html, decorateProposition) => { +export default (container, html, decorateProposition, markRendered) => { clear(container); - return appendHtml(container, html, decorateProposition); + return appendHtml(container, html, decorateProposition, markRendered); }; diff --git a/src/components/Personalization/dom-actions/setStyles.js b/src/components/Personalization/dom-actions/setStyles.js index 821495987..4faf19454 100644 --- a/src/components/Personalization/dom-actions/setStyles.js +++ b/src/components/Personalization/dom-actions/setStyles.js @@ -12,7 +12,7 @@ governing permissions and limitations under the License. import { setStyle } from "./dom/index.js"; -export default (container, styles, decorateProposition) => { +export default (container, styles, decorateProposition, markRendered) => { const { priority, ...style } = styles; Object.keys(style).forEach((key) => { @@ -20,4 +20,5 @@ export default (container, styles, decorateProposition) => { }); decorateProposition(container); + markRendered(container); }; diff --git a/src/components/Personalization/dom-actions/setText.js b/src/components/Personalization/dom-actions/setText.js index 63108582d..8fa2b7659 100644 --- a/src/components/Personalization/dom-actions/setText.js +++ b/src/components/Personalization/dom-actions/setText.js @@ -10,7 +10,8 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -export default (container, text, decorateProposition) => { +export default (container, text, decorateProposition, markRendered) => { decorateProposition(container); container.textContent = text; + markRendered(container); }; diff --git a/src/components/Personalization/dom-actions/swapImage.js b/src/components/Personalization/dom-actions/swapImage.js index abaf1bfc0..769c2a6f4 100644 --- a/src/components/Personalization/dom-actions/swapImage.js +++ b/src/components/Personalization/dom-actions/swapImage.js @@ -14,7 +14,7 @@ import { SRC } from "../../../constants/elementAttribute.js"; import { removeAttribute, setAttribute } from "./dom/index.js"; import { isImage, loadImage } from "./images.js"; -export default (container, url, decorateProposition) => { +export default (container, url, decorateProposition, markRendered) => { if (!isImage(container)) { return; } @@ -29,4 +29,5 @@ export default (container, url, decorateProposition) => { // Replace the image "src" setAttribute(container, SRC, url); + markRendered(container); }; diff --git a/src/components/Personalization/handlers/createProcessDomAction.js b/src/components/Personalization/handlers/createProcessDomAction.js index a2da4dd41..243ba1cb2 100644 --- a/src/components/Personalization/handlers/createProcessDomAction.js +++ b/src/components/Personalization/handlers/createProcessDomAction.js @@ -12,6 +12,7 @@ governing permissions and limitations under the License. import createDecorateProposition from "./createDecorateProposition.js"; import { DOM_ACTION_CLICK } from "../dom-actions/initDomActionsModules.js"; +import createRenderedHandler from "./createRenderedHandler.js"; export default ({ modules, @@ -64,9 +65,13 @@ export default ({ item.getProposition().getNotification(), storeInteractionMeta, ); + const renderedHandler = createRenderedHandler( + item.getProposition().getScopeType(), + item.getIdentifier() + ); return { - render: () => modules[type](item.getData(), decorateProposition), + render: () => modules[type](item.getData(), decorateProposition, renderedHandler), setRenderAttempted: true, includeInNotification: true, }; diff --git a/src/components/Personalization/handlers/createRenderedHandler.js b/src/components/Personalization/handlers/createRenderedHandler.js new file mode 100644 index 000000000..66490807b --- /dev/null +++ b/src/components/Personalization/handlers/createRenderedHandler.js @@ -0,0 +1,33 @@ +/* +Copyright 2024 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ +import { noop } from "../../../utils/index.js"; +import hasCssClass from "../dom-actions/dom/hasCssClass.js"; +import addCssClass from "../dom-actions/dom/addCssClass.js"; + +export default ( + scopeType, + itemIdentifier, +) => { + return { + shouldRender: (element) => { + if (scopeType === "view") { + return !hasCssClass(element, itemIdentifier); + } + return true; + }, + markAsRendered: (element) => { + if (scopeType === "view") { + addCssClass(element, itemIdentifier); + } + } + }; +}; \ No newline at end of file diff --git a/src/components/Personalization/handlers/injectCreateProposition.js b/src/components/Personalization/handlers/injectCreateProposition.js index a91c0df06..f15e9a130 100644 --- a/src/components/Personalization/handlers/injectCreateProposition.js +++ b/src/components/Personalization/handlers/injectCreateProposition.js @@ -18,7 +18,7 @@ import { } from "../constants/scopeType.js"; export default ({ preprocess, isPageWideSurface }) => { - const createItem = (item, proposition) => { + const createItem = (item, proposition, itemIdentifier) => { const { id, schema, data, characteristics: { trackingLabel } = {} } = item; const schemaType = data ? data.type : undefined; @@ -29,6 +29,9 @@ export default ({ preprocess, isPageWideSurface }) => { getId() { return id; }, + getIdentifier() { + return itemIdentifier; + }, getSchema() { return schema; }, @@ -63,6 +66,7 @@ export default ({ preprocess, isPageWideSurface }) => { ) => { const { id, scope, scopeDetails, items = [] } = payload; const { characteristics: { scopeType } = {} } = scopeDetails || {}; + const keyedItems = items.map((item, index) => ({key: `alloy-${item.id}`, item})); return { getScope() { @@ -78,7 +82,7 @@ export default ({ preprocess, isPageWideSurface }) => { return PROPOSITION_SCOPE_TYPE; }, getItems() { - return items.map((item) => createItem(item, this)); + return keyedItems.map((keyedItem) => createItem(keyedItem.item, this, keyedItem.key)); }, getNotification() { return { id, scope, scopeDetails }; diff --git a/test/functional/specs/Personalization/C5805676.js b/test/functional/specs/Personalization/C5805676.js index 28ce72419..402abb0eb 100644 --- a/test/functional/specs/Personalization/C5805676.js +++ b/test/functional/specs/Personalization/C5805676.js @@ -103,7 +103,8 @@ test("Test C5805676: Merged metric propositions should be delivered", async () = await t.expect(responseBodyProposition.items.length).eql(2); - await t.expect(responseBodyProposition.items[0]).eql(DEFAULT_CONTENT_ITEM); + await t.expect(responseBodyProposition.items[0].schema).eql(DEFAULT_CONTENT_ITEM.schema); + await t.expect(responseBodyProposition.items[0].meta).eql(DEFAULT_CONTENT_ITEM.meta); await t.expect(responseBodyProposition.items[1]).eql(MEASUREMENT_ITEM); const formBasedScopePropositions = eventResult.propositions.filter( @@ -114,7 +115,12 @@ test("Test C5805676: Merged metric propositions should be delivered", async () = await t.expect(formBasedScopePropositions[0].items.length).eql(2); await t.expect(formBasedScopePropositions[0].renderAttempted).eql(false); await t - .expect(formBasedScopePropositions[0].items[0]) - .eql(DEFAULT_CONTENT_ITEM); - await t.expect(formBasedScopePropositions[0].items[1]).eql(MEASUREMENT_ITEM); + .expect(formBasedScopePropositions[0].items[0].schema) + .eql(DEFAULT_CONTENT_ITEM.schema); + await t + .expect(formBasedScopePropositions[0].items[0].meta) + .eql(DEFAULT_CONTENT_ITEM.meta); + + await t.expect(formBasedScopePropositions[0].items[1].data).eql(MEASUREMENT_ITEM.data); + await t.expect(formBasedScopePropositions[0].items[1].schema).eql(MEASUREMENT_ITEM.schema); }); From a295d90084c7b06de41ce14b9f14fcbc4bb5dd7f Mon Sep 17 00:00:00 2001 From: Nina Ciocanu Date: Thu, 7 Nov 2024 12:49:51 +0200 Subject: [PATCH 2/3] formating --- bundlesize.json | 12 +++++------ .../Personalization/createFetchDataHandler.js | 8 +++---- .../Personalization/dom-actions/action.js | 21 +++++++++++++++---- .../dom-actions/dom/addCssClass.js | 2 +- .../dom-actions/dom/hasCssClass.js | 2 +- .../dom-actions/replaceHtml.js | 7 ++++++- .../handlers/createProcessDomAction.js | 5 +++-- .../handlers/createRenderedHandler.js | 12 ++++------- .../handlers/injectCreateProposition.js | 9 ++++++-- .../StreamingMedia/createTrackMediaSession.js | 2 +- .../validateMediaSessionOptions.js | 4 ++-- src/utils/request/createRequestParams.js | 7 +++++-- .../specs/Personalization/C5805676.js | 16 ++++++++++---- 13 files changed, 69 insertions(+), 38 deletions(-) diff --git a/bundlesize.json b/bundlesize.json index 37e9aa379..623d49f10 100644 --- a/bundlesize.json +++ b/bundlesize.json @@ -5,13 +5,13 @@ "brotiliSize": 133 }, "dist/alloy.js": { - "uncompressedSize": 594046, - "gzippedSize": 90339, - "brotiliSize": 70202 + "uncompressedSize": 593980, + "gzippedSize": 90304, + "brotiliSize": 70171 }, "dist/alloy.min.js": { - "uncompressedSize": 124422, - "gzippedSize": 41166, - "brotiliSize": 35699 + "uncompressedSize": 124393, + "gzippedSize": 41151, + "brotiliSize": 35684 } } \ No newline at end of file diff --git a/src/components/Personalization/createFetchDataHandler.js b/src/components/Personalization/createFetchDataHandler.js index 310ab5392..bae90b150 100644 --- a/src/components/Personalization/createFetchDataHandler.js +++ b/src/components/Personalization/createFetchDataHandler.js @@ -57,13 +57,13 @@ export default ({ }, }); } - const propositions = handles.map(handle => { + const propositions = handles.map((handle) => { const proposition = { - items: handle.items.map(item => { - item.id = (!item.id || item.id === "0" ) ? uuid() : item.id; + items: handle.items.map((item) => { + item.id = !item.id || item.id === "0" ? uuid() : item.id; return item; }), - ...handle + ...handle, }; return createProposition(proposition); }); diff --git a/src/components/Personalization/dom-actions/action.js b/src/components/Personalization/dom-actions/action.js index 50b291d9a..890141b87 100644 --- a/src/components/Personalization/dom-actions/action.js +++ b/src/components/Personalization/dom-actions/action.js @@ -12,7 +12,7 @@ governing permissions and limitations under the License. import { awaitSelector } from "../../../utils/dom/index.js"; import { hideElements, showElements } from "../flicker/index.js"; -import { selectNodesWithEq} from "./dom/index.js"; +import { selectNodesWithEq } from "./dom/index.js"; export { default as setText } from "./setText.js"; export { default as setHtml } from "./setHtml.js"; export { default as appendHtml } from "./appendHtml.js"; @@ -25,11 +25,18 @@ export { default as setAttributes } from "./setAttributes.js"; export { default as swapImage } from "./swapImage.js"; export { default as rearrangeChildren } from "./rearrangeChildren.js"; -const renderContent = (elements, content, decorateProposition, renderFunc, renderedHandler) => { +const renderContent = ( + elements, + content, + decorateProposition, + renderFunc, + renderedHandler, +) => { const executions = elements.map((element) => { if(renderedHandler.shouldRender(element)) { return renderFunc(element, content, decorateProposition, renderedHandler.markAsRendered); } + return Promise.resolve(); }); return Promise.all(executions); @@ -42,8 +49,14 @@ export const createAction = (renderFunc) => { return awaitSelector(selector, selectNodesWithEq) .then((elements) => { - return renderContent(elements, content, decorateProposition, renderFunc, renderedHandler); - }) + return renderContent( + elements, + content, + decorateProposition, + renderFunc, + renderedHandler, + ); + }) .then( () => { // if everything is OK, show elements diff --git a/src/components/Personalization/dom-actions/dom/addCssClass.js b/src/components/Personalization/dom-actions/dom/addCssClass.js index c6bbd4d33..401cbe83c 100644 --- a/src/components/Personalization/dom-actions/dom/addCssClass.js +++ b/src/components/Personalization/dom-actions/dom/addCssClass.js @@ -1,4 +1,4 @@ -import {isNonEmptyString} from "../../../../utils/index.js"; +import { isNonEmptyString } from "../../../../utils/index.js"; export default (element, name) => { if (name && isNonEmptyString(name)) { diff --git a/src/components/Personalization/dom-actions/dom/hasCssClass.js b/src/components/Personalization/dom-actions/dom/hasCssClass.js index 13b7948ab..6616b13ec 100644 --- a/src/components/Personalization/dom-actions/dom/hasCssClass.js +++ b/src/components/Personalization/dom-actions/dom/hasCssClass.js @@ -1,4 +1,4 @@ -import {isNonEmptyString} from "../../../../utils/index.js"; +import { isNonEmptyString } from "../../../../utils/index.js"; export default (element, name) => { if (name && isNonEmptyString(name)) { diff --git a/src/components/Personalization/dom-actions/replaceHtml.js b/src/components/Personalization/dom-actions/replaceHtml.js index 402d3ae9c..484f159bc 100644 --- a/src/components/Personalization/dom-actions/replaceHtml.js +++ b/src/components/Personalization/dom-actions/replaceHtml.js @@ -14,7 +14,12 @@ import { removeNode } from "../../../utils/dom/index.js"; import insertHtmlBefore from "./insertHtmlBefore.js"; export default (container, html, decorateProposition, markRendered) => { - return insertHtmlBefore(container, html, decorateProposition, markRendered).then(() => { + return insertHtmlBefore( + container, + html, + decorateProposition, + markRendered, + ).then(() => { removeNode(container); }); }; diff --git a/src/components/Personalization/handlers/createProcessDomAction.js b/src/components/Personalization/handlers/createProcessDomAction.js index 243ba1cb2..547c6aa41 100644 --- a/src/components/Personalization/handlers/createProcessDomAction.js +++ b/src/components/Personalization/handlers/createProcessDomAction.js @@ -67,11 +67,12 @@ export default ({ ); const renderedHandler = createRenderedHandler( item.getProposition().getScopeType(), - item.getIdentifier() + item.getIdentifier(), ); return { - render: () => modules[type](item.getData(), decorateProposition, renderedHandler), + render: () => + modules[type](item.getData(), decorateProposition, renderedHandler), setRenderAttempted: true, includeInNotification: true, }; diff --git a/src/components/Personalization/handlers/createRenderedHandler.js b/src/components/Personalization/handlers/createRenderedHandler.js index 66490807b..433a35f7c 100644 --- a/src/components/Personalization/handlers/createRenderedHandler.js +++ b/src/components/Personalization/handlers/createRenderedHandler.js @@ -9,25 +9,21 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import { noop } from "../../../utils/index.js"; import hasCssClass from "../dom-actions/dom/hasCssClass.js"; import addCssClass from "../dom-actions/dom/addCssClass.js"; -export default ( - scopeType, - itemIdentifier, -) => { +export default (scopeType, itemIdentifier) => { return { shouldRender: (element) => { if (scopeType === "view") { return !hasCssClass(element, itemIdentifier); } - return true; + return true; }, markAsRendered: (element) => { if (scopeType === "view") { addCssClass(element, itemIdentifier); } - } + }, }; -}; \ No newline at end of file +}; diff --git a/src/components/Personalization/handlers/injectCreateProposition.js b/src/components/Personalization/handlers/injectCreateProposition.js index f15e9a130..5dafda56e 100644 --- a/src/components/Personalization/handlers/injectCreateProposition.js +++ b/src/components/Personalization/handlers/injectCreateProposition.js @@ -66,7 +66,10 @@ export default ({ preprocess, isPageWideSurface }) => { ) => { const { id, scope, scopeDetails, items = [] } = payload; const { characteristics: { scopeType } = {} } = scopeDetails || {}; - const keyedItems = items.map((item, index) => ({key: `alloy-${item.id}`, item})); + const keyedItems = items.map((item) => ({ + key: `alloy-${item.id}`, + item, + })); return { getScope() { @@ -82,7 +85,9 @@ export default ({ preprocess, isPageWideSurface }) => { return PROPOSITION_SCOPE_TYPE; }, getItems() { - return keyedItems.map((keyedItem) => createItem(keyedItem.item, this, keyedItem.key)); + return keyedItems.map((keyedItem) => + createItem(keyedItem.item, this, keyedItem.key), + ); }, getNotification() { return { id, scope, scopeDetails }; diff --git a/src/components/StreamingMedia/createTrackMediaSession.js b/src/components/StreamingMedia/createTrackMediaSession.js index 22f9f713c..f82aca490 100644 --- a/src/components/StreamingMedia/createTrackMediaSession.js +++ b/src/components/StreamingMedia/createTrackMediaSession.js @@ -38,7 +38,7 @@ export default ({ getPlayerDetails, legacy, }, - edgeConfigOverrides + edgeConfigOverrides, }); mediaSessionCacheManager.storeSession({ diff --git a/src/components/StreamingMedia/validateMediaSessionOptions.js b/src/components/StreamingMedia/validateMediaSessionOptions.js index 08f61b3fd..89c608d87 100644 --- a/src/components/StreamingMedia/validateMediaSessionOptions.js +++ b/src/components/StreamingMedia/validateMediaSessionOptions.js @@ -30,7 +30,7 @@ export default ({ options }) => { sessionDetails: objectOf(anything()).required(), }), }), - edgeConfigOverrides: objectOf({}) + edgeConfigOverrides: objectOf({}), }).required(), objectOf({ @@ -40,7 +40,7 @@ export default ({ options }) => { sessionDetails: objectOf(anything()).required(), }), }), - edgeConfigOverrides: objectOf({}) + edgeConfigOverrides: objectOf({}), }).required(), ], diff --git a/src/utils/request/createRequestParams.js b/src/utils/request/createRequestParams.js index 6c091a9e3..aed49132d 100644 --- a/src/utils/request/createRequestParams.js +++ b/src/utils/request/createRequestParams.js @@ -9,7 +9,7 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import {isEmptyObject} from "../index.js"; +import { isEmptyObject } from "../index.js"; /** * @typedef {{ datastreamId: string, [k: string]: Object }} Override @@ -33,7 +33,10 @@ export default ({ localConfigOverrides, globalConfigOverrides, payload }) => { payload.mergeConfigOverride(globalConfigOverrides); } - if (localConfigOverridesWithoutDatastreamId && !isEmptyObject(localConfigOverridesWithoutDatastreamId)) { + if ( + localConfigOverridesWithoutDatastreamId && + !isEmptyObject(localConfigOverridesWithoutDatastreamId) + ) { payload.mergeConfigOverride(localConfigOverridesWithoutDatastreamId); } return requestParams; diff --git a/test/functional/specs/Personalization/C5805676.js b/test/functional/specs/Personalization/C5805676.js index 402abb0eb..3e1826608 100644 --- a/test/functional/specs/Personalization/C5805676.js +++ b/test/functional/specs/Personalization/C5805676.js @@ -103,8 +103,12 @@ test("Test C5805676: Merged metric propositions should be delivered", async () = await t.expect(responseBodyProposition.items.length).eql(2); - await t.expect(responseBodyProposition.items[0].schema).eql(DEFAULT_CONTENT_ITEM.schema); - await t.expect(responseBodyProposition.items[0].meta).eql(DEFAULT_CONTENT_ITEM.meta); + await t + .expect(responseBodyProposition.items[0].schema) + .eql(DEFAULT_CONTENT_ITEM.schema); + await t + .expect(responseBodyProposition.items[0].meta) + .eql(DEFAULT_CONTENT_ITEM.meta); await t.expect(responseBodyProposition.items[1]).eql(MEASUREMENT_ITEM); const formBasedScopePropositions = eventResult.propositions.filter( @@ -121,6 +125,10 @@ test("Test C5805676: Merged metric propositions should be delivered", async () = .expect(formBasedScopePropositions[0].items[0].meta) .eql(DEFAULT_CONTENT_ITEM.meta); - await t.expect(formBasedScopePropositions[0].items[1].data).eql(MEASUREMENT_ITEM.data); - await t.expect(formBasedScopePropositions[0].items[1].schema).eql(MEASUREMENT_ITEM.schema); + await t + .expect(formBasedScopePropositions[0].items[1].data) + .eql(MEASUREMENT_ITEM.data); + await t + .expect(formBasedScopePropositions[0].items[1].schema) + .eql(MEASUREMENT_ITEM.schema); }); From f5ada5a7e94c2402e3e10d85126f443312d748ec Mon Sep 17 00:00:00 2001 From: Nina Ciocanu Date: Mon, 18 Nov 2024 18:21:17 +0200 Subject: [PATCH 3/3] addding tests --- .../Personalization/createFetchDataHandler.js | 2 +- .../createDecoratePropositionForTest2.js | 53 +++++++++++++++++++ .../dom-actions/dom/addCssClass.spec.js | 0 .../dom-actions/dom/hasCssClass.spec.js | 0 .../handlers/createRenderedHandler.spec.js | 0 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 test/unit/helpers/createDecoratePropositionForTest2.js create mode 100644 test/unit/specs/components/Personalization/dom-actions/dom/addCssClass.spec.js create mode 100644 test/unit/specs/components/Personalization/dom-actions/dom/hasCssClass.spec.js create mode 100644 test/unit/specs/components/Personalization/handlers/createRenderedHandler.spec.js diff --git a/src/components/Personalization/createFetchDataHandler.js b/src/components/Personalization/createFetchDataHandler.js index bae90b150..4a9f47a2b 100644 --- a/src/components/Personalization/createFetchDataHandler.js +++ b/src/components/Personalization/createFetchDataHandler.js @@ -59,11 +59,11 @@ export default ({ } const propositions = handles.map((handle) => { const proposition = { + ...handle, items: handle.items.map((item) => { item.id = !item.id || item.id === "0" ? uuid() : item.id; return item; }), - ...handle, }; return createProposition(proposition); }); diff --git a/test/unit/helpers/createDecoratePropositionForTest2.js b/test/unit/helpers/createDecoratePropositionForTest2.js new file mode 100644 index 000000000..43528d0d9 --- /dev/null +++ b/test/unit/helpers/createDecoratePropositionForTest2.js @@ -0,0 +1,53 @@ +/* +Copyright 2024 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ +import { + ADOBE_JOURNEY_OPTIMIZER, + ADOBE_TARGET, +} from "../../../src/constants/decisionProvider.js"; +import createInteractionStorage from "../../../src/components/Personalization/createInteractionStorage.js"; +import createDecorateProposition from "../../../src/components/Personalization/handlers/createDecorateProposition.js"; +import { + ALWAYS, + NEVER, +} from "../../../src/constants/propositionInteractionType.js"; + +export default ({ + autoCollectPropositionInteractions = { + [ADOBE_JOURNEY_OPTIMIZER]: ALWAYS, + [ADOBE_TARGET]: NEVER, + }, + type, + propositionId = "propositionID", + itemId = "itemId", + trackingLabel = "trackingLabel", + scopeType = "page", + notification = { + id: "notifyId", + scope: "web://mywebsite.com", + scopeDetails: { + something: true, + decisionProvider: ADOBE_JOURNEY_OPTIMIZER, + }, + }, +} = {}) => { + const { storeInteractionMeta } = createInteractionStorage(); + return createDecorateProposition( + autoCollectPropositionInteractions, + type, + propositionId, + itemId, + trackingLabel, + scopeType, + notification, + storeInteractionMeta, + ); +}; diff --git a/test/unit/specs/components/Personalization/dom-actions/dom/addCssClass.spec.js b/test/unit/specs/components/Personalization/dom-actions/dom/addCssClass.spec.js new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/specs/components/Personalization/dom-actions/dom/hasCssClass.spec.js b/test/unit/specs/components/Personalization/dom-actions/dom/hasCssClass.spec.js new file mode 100644 index 000000000..e69de29bb diff --git a/test/unit/specs/components/Personalization/handlers/createRenderedHandler.spec.js b/test/unit/specs/components/Personalization/handlers/createRenderedHandler.spec.js new file mode 100644 index 000000000..e69de29bb