diff --git a/package-lock.json b/package-lock.json index 25fef56f8..a1f2443f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "2.19.0-beta.0", "license": "Apache-2.0", "dependencies": { - "@adobe/aep-rules-engine": "^2.0.1", + "@adobe/aep-rules-engine": "^2.0.2", "@adobe/reactor-cookie": "^1.0.0", "@adobe/reactor-load-script": "^1.1.1", "@adobe/reactor-object-assign": "^1.0.0", @@ -87,9 +87,9 @@ } }, "node_modules/@adobe/aep-rules-engine": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@adobe/aep-rules-engine/-/aep-rules-engine-2.0.1.tgz", - "integrity": "sha512-lcnxd8SN4D7/4A9pOivH9BGzhWjCkcDimI97vhlqWkA0nP2/NzScbG1OR4W2adXUcMYkB18suad9vXmpwqa4YA==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@adobe/aep-rules-engine/-/aep-rules-engine-2.0.2.tgz", + "integrity": "sha512-y5B1LcLo1xbUtRZLe4FRGiburzLu6kgY2VgLutgjoz0bpsKFxb21mqJ1axemsTfpJawYEvuP23+No1ud1ZsP2A==" }, "node_modules/@adobe/alloy": { "version": "2.19.0-beta.0", @@ -19387,9 +19387,9 @@ }, "dependencies": { "@adobe/aep-rules-engine": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@adobe/aep-rules-engine/-/aep-rules-engine-2.0.1.tgz", - "integrity": "sha512-lcnxd8SN4D7/4A9pOivH9BGzhWjCkcDimI97vhlqWkA0nP2/NzScbG1OR4W2adXUcMYkB18suad9vXmpwqa4YA==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@adobe/aep-rules-engine/-/aep-rules-engine-2.0.2.tgz", + "integrity": "sha512-y5B1LcLo1xbUtRZLe4FRGiburzLu6kgY2VgLutgjoz0bpsKFxb21mqJ1axemsTfpJawYEvuP23+No1ud1ZsP2A==" }, "@adobe/alloy": { "version": "2.19.0-beta.0", diff --git a/package.json b/package.json index 89e05fe9f..ad0ef9994 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ } ], "dependencies": { - "@adobe/aep-rules-engine": "^2.0.1", + "@adobe/aep-rules-engine": "^2.0.2", "@adobe/reactor-cookie": "^1.0.0", "@adobe/reactor-load-script": "^1.1.1", "@adobe/reactor-object-assign": "^1.0.0", diff --git a/sandbox/src/components/MessageFeedDemo/MessageFeed.js b/sandbox/src/components/MessageFeedDemo/MessageFeed.js index 1aef05a1d..09a04a9a6 100644 --- a/sandbox/src/components/MessageFeedDemo/MessageFeed.js +++ b/sandbox/src/components/MessageFeedDemo/MessageFeed.js @@ -34,7 +34,7 @@ const mockResponse = { ], activity: { id: - "39ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d183" + "8e24e51d-5203-4d0b-99c9-2b3c95ff48f2#05885219-ea84-43bc-874e-1ef4a85b6fbb" }, correlationID: "02c77ea8-7c0e-4d33-8090-4a5bfd3d7503" }, @@ -148,7 +148,7 @@ const mockResponse = { ], activity: { id: - "39ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d183" + "cf087a6e-131d-4147-adc7-bc1ea947f09c#ff64e6e6-e43f-479d-b5c0-f5568c771b3b" }, correlationID: "02c77ea8-7c0e-4d33-8090-4a5bfd3d7503" }, @@ -179,9 +179,9 @@ const mockResponse = { definition: { events: [ { - type: "decisioning.propositionDisplay", - id: - "1ae11bc5-96dc-41c7-8f71-157c57a5290e" + "iam.eventType": "display", + "iam.id": + "cf087a6e-131d-4147-adc7-bc1ea947f09c#ff64e6e6-e43f-479d-b5c0-f5568c771b3b" } ], matcher: "ge", @@ -251,7 +251,7 @@ const mockResponse = { ], activity: { id: - "39ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d183" + "57712381-1690-4d19-9469-0a35ea5bd4e3#74f8e5cf-d770-41c3-b595-557b3ee00ba3" }, correlationID: "02c77ea8-7c0e-4d33-8090-4a5bfd3d7503" }, @@ -282,9 +282,9 @@ const mockResponse = { definition: { events: [ { - type: "decisioning.propositionDisplay", - id: - "d1f7d411-a549-47bc-a4d8-c8e638b0a46b" + "iam.eventType": "trigger", + "iam.id": + "57712381-1690-4d19-9469-0a35ea5bd4e3#74f8e5cf-d770-41c3-b595-557b3ee00ba3" } ], matcher: "ge", @@ -424,7 +424,6 @@ export default function MessageFeed() { surface: "web://target.jasonwaters.dev/aep.html", callback: ({ items = [], rendered, clicked }) => { setClickHandler(() => clicked); - setMessageFeedItems(items); rendered(items); } diff --git a/src/components/DecisioningEngine/createContextProvider.js b/src/components/DecisioningEngine/createContextProvider.js index 8c183aa3f..303465a4d 100644 --- a/src/components/DecisioningEngine/createContextProvider.js +++ b/src/components/DecisioningEngine/createContextProvider.js @@ -43,8 +43,10 @@ export default ({ eventRegistry, window }) => { pageLoadTimestamp, currentTimestamp, currentDate: now.getDate(), - currentDay: now.getDay(), - currentHour: now.getHours(), + // Day of the week starts on Monday as is practiced in ISO 8601, but we want it to start on Sunday to match the authoring UI rule + "~state.com.adobe.module.lifecycle/lifecyclecontextdata.dayofweek": + now.getDay() + 1, + "~state.com.adobe.module.lifecycle/lifecyclecontextdata.hourofday": now.getHours(), currentMinute: now.getMinutes(), currentMonth: now.getMonth(), currentYear: now.getFullYear(), diff --git a/src/components/DecisioningEngine/createDecisionHistory.js b/src/components/DecisioningEngine/createDecisionHistory.js index 85bb5e4d2..1360c3f99 100644 --- a/src/components/DecisioningEngine/createDecisionHistory.js +++ b/src/components/DecisioningEngine/createDecisionHistory.js @@ -9,16 +9,14 @@ 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. */ - -const QUALIFIED_EVENT_TYPE = "decisioning.propositionQualified"; +import { PropositionEventType } from "../../constants/propositionEventType"; export default ({ eventRegistry }) => { - const recordQualified = item => { - const { id } = item; + const recordQualified = id => { if (!id) { return undefined; } - return eventRegistry.addEvent(item, QUALIFIED_EVENT_TYPE, id); + return eventRegistry.addEvent({}, PropositionEventType.TRIGGER, id); }; return { recordQualified }; diff --git a/src/components/DecisioningEngine/createDecisionProvider.js b/src/components/DecisioningEngine/createDecisionProvider.js index da01cc4ad..77beb7245 100644 --- a/src/components/DecisioningEngine/createDecisionProvider.js +++ b/src/components/DecisioningEngine/createDecisionProvider.js @@ -11,14 +11,16 @@ governing permissions and limitations under the License. */ import createEvaluableRulesetPayload from "./createEvaluableRulesetPayload"; import createDecisionHistory from "./createDecisionHistory"; +import { getActivityId } from "./utils"; export default ({ eventRegistry }) => { - const payloads = {}; + const payloadsBasedOnActivityId = {}; const decisionHistory = createDecisionHistory({ eventRegistry }); const addPayload = payload => { - if (!payload.id) { + const activityId = getActivityId(payload); + if (!activityId) { return; } @@ -29,12 +31,12 @@ export default ({ eventRegistry }) => { ); if (evaluableRulesetPayload.isEvaluable) { - payloads[payload.id] = evaluableRulesetPayload; + payloadsBasedOnActivityId[activityId] = evaluableRulesetPayload; } }; const evaluate = (context = {}) => - Object.values(payloads) + Object.values(payloadsBasedOnActivityId) .map(payload => payload.evaluate(context)) .filter(payload => payload.items.length > 0); diff --git a/src/components/DecisioningEngine/createEvaluableRulesetPayload.js b/src/components/DecisioningEngine/createEvaluableRulesetPayload.js index 6b7aff4cc..59a24ff65 100644 --- a/src/components/DecisioningEngine/createEvaluableRulesetPayload.js +++ b/src/components/DecisioningEngine/createEvaluableRulesetPayload.js @@ -14,7 +14,8 @@ import { JSON_CONTENT_ITEM, RULESET_ITEM } from "../Personalization/constants/schema"; -import { DISPLAY } from "../Personalization/constants/eventType"; +import { DISPLAY } from "../../constants/eventType"; +import { getActivityId } from "./utils"; import flattenArray from "../../utils/flattenArray"; import createConsequenceAdapter from "./createConsequenceAdapter"; @@ -42,6 +43,7 @@ const isRulesetItem = item => { export default (payload, eventRegistry, decisionHistory) => { const consequenceAdapter = createConsequenceAdapter(); + const activityId = getActivityId(payload); const items = []; const addItem = item => { @@ -59,7 +61,7 @@ export default (payload, eventRegistry, decisionHistory) => { }; const evaluate = context => { - const displayEvent = eventRegistry.getEvent(DISPLAY, payload.id); + const displayEvent = eventRegistry.getEvent(DISPLAY, activityId); const displayedDate = displayEvent ? displayEvent.firstTimestamp @@ -72,7 +74,7 @@ export default (payload, eventRegistry, decisionHistory) => { .map(item => { const { firstTimestamp: qualifiedDate - } = decisionHistory.recordQualified(item); + } = decisionHistory.recordQualified(activityId); return { ...item, diff --git a/src/components/DecisioningEngine/createEventRegistry.js b/src/components/DecisioningEngine/createEventRegistry.js index 84c158a43..22a060a2b 100644 --- a/src/components/DecisioningEngine/createEventRegistry.js +++ b/src/components/DecisioningEngine/createEventRegistry.js @@ -12,14 +12,17 @@ governing permissions and limitations under the License. import { createRestoreStorage, createSaveStorage, - getExpirationDate + getExpirationDate, + getActivityId } from "./utils"; +import { EVENT_TYPE_TRUE } from "../../constants/eventType"; const STORAGE_KEY = "events"; const MAX_EVENT_RECORDS = 1000; const DEFAULT_SAVE_DELAY = 500; const RETENTION_PERIOD = 30; +const prefixed = key => `iam.${key}`; export const createEventPruner = ( limit = MAX_EVENT_RECORDS, retentionPeriod = RETENTION_PERIOD @@ -36,7 +39,7 @@ export const createEventPruner = ( .sort((a, b) => a.firstTimestamp - b.firstTimestamp) .slice(-1 * limit) .forEach(entry => { - pruned[eventType][entry.event.id] = entry; + pruned[eventType][entry.event[prefixed("id")]] = entry; }); }); return pruned; @@ -53,11 +56,10 @@ export default ({ storage, saveDelay = DEFAULT_SAVE_DELAY }) => { ); const events = restore({}); - const addEvent = (event, eventType, eventId) => { + const addEvent = (event, eventType, eventId, action) => { if (!events[eventType]) { events[eventType] = {}; } - const existingEvent = events[eventType][eventId]; const count = existingEvent ? existingEvent.count : 0; @@ -67,7 +69,12 @@ export default ({ storage, saveDelay = DEFAULT_SAVE_DELAY }) => { : timestamp; events[eventType][eventId] = { - event: { ...event, id: eventId, type: eventType }, + event: { + ...event, + [prefixed("id")]: eventId, + [prefixed("eventType")]: eventType, + [prefixed("action")]: action + }, firstTimestamp, timestamp, count: count + 1 @@ -90,13 +97,34 @@ export default ({ storage, saveDelay = DEFAULT_SAVE_DELAY }) => { ) { return; } - const { decisioning = {} } = _experience; - const { propositions = [] } = decisioning; + const { + propositionEventType: propositionEventTypeObj = {}, + propositionAction = {}, + propositions = [] + } = decisioning; + + const propositionEventTypesList = Object.keys(propositionEventTypeObj); + + // https://wiki.corp.adobe.com/pages/viewpage.action?spaceKey=CJM&title=Proposition+Event+Types + if (propositionEventTypesList.length === 0) { + return; + } - propositions.forEach(proposition => - addEvent({ proposition }, eventType, proposition.id) - ); + const { id: action } = propositionAction; + + propositionEventTypesList.forEach(propositionEventType => { + if (propositionEventTypeObj[propositionEventType] === EVENT_TYPE_TRUE) { + propositions.forEach(proposition => { + addEvent( + {}, + propositionEventType, + getActivityId(proposition), + action + ); + }); + } + }); }; const getEvent = (eventType, eventId) => { if (!events[eventType]) { diff --git a/src/components/DecisioningEngine/utils.js b/src/components/DecisioningEngine/utils.js index 5b7f5338c..9048661c8 100644 --- a/src/components/DecisioningEngine/utils.js +++ b/src/components/DecisioningEngine/utils.js @@ -52,3 +52,11 @@ export const ensureSchemaBasedRulesetConsequences = event => { } }); }; + +export const getActivityId = proposition => { + const { scopeDetails = {} } = proposition; + const { activity = {} } = scopeDetails; + const { id } = activity; + + return id; +}; diff --git a/src/components/Personalization/createCollect.js b/src/components/Personalization/createCollect.js index 9b8b2a218..54bc6fad1 100644 --- a/src/components/Personalization/createCollect.js +++ b/src/components/Personalization/createCollect.js @@ -9,8 +9,8 @@ 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 { DISPLAY } from "./constants/eventType"; -import { getPropositionEventType } from "./constants/propositionEventType"; +import { DISPLAY } from "../../constants/eventType"; +import { getPropositionEventType } from "../../constants/propositionEventType"; import { isNonEmptyArray } from "../../utils"; export default ({ eventManager, mergeDecisionsMeta }) => { diff --git a/src/components/Personalization/createOnClickHandler.js b/src/components/Personalization/createOnClickHandler.js index 719a2ce49..cbf51f7d6 100644 --- a/src/components/Personalization/createOnClickHandler.js +++ b/src/components/Personalization/createOnClickHandler.js @@ -11,8 +11,8 @@ governing permissions and limitations under the License. */ import { isNonEmptyArray, isNonEmptyString } from "../../utils"; -import { INTERACT } from "./constants/eventType"; -import { PropositionEventType } from "./constants/propositionEventType"; +import { INTERACT } from "../../constants/eventType"; +import { PropositionEventType } from "../../constants/propositionEventType"; import PAGE_WIDE_SCOPE from "../../constants/pageWideScope"; export default ({ diff --git a/src/components/Personalization/createPendingNotificationsHandler.js b/src/components/Personalization/createPendingNotificationsHandler.js index c161a8024..6fa3b488b 100644 --- a/src/components/Personalization/createPendingNotificationsHandler.js +++ b/src/components/Personalization/createPendingNotificationsHandler.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 { PropositionEventType } from "./constants/propositionEventType"; +import { PropositionEventType } from "../../constants/propositionEventType"; export default ({ pendingDisplayNotifications, mergeDecisionsMeta }) => ({ event diff --git a/src/components/Personalization/createSubscribeMessageFeed.js b/src/components/Personalization/createSubscribeMessageFeed.js index be2dfba30..bb67cb97d 100644 --- a/src/components/Personalization/createSubscribeMessageFeed.js +++ b/src/components/Personalization/createSubscribeMessageFeed.js @@ -15,7 +15,7 @@ import { string } from "../../utils/validation"; import { MESSAGE_FEED_ITEM } from "./constants/schema"; -import { DISPLAY, INTERACT } from "./constants/eventType"; +import { DISPLAY, INTERACT } from "../../constants/eventType"; const validateOptions = ({ options }) => { const validator = objectOf({ diff --git a/src/components/Personalization/createViewChangeHandler.js b/src/components/Personalization/createViewChangeHandler.js index 2f68cd8eb..f745223a4 100644 --- a/src/components/Personalization/createViewChangeHandler.js +++ b/src/components/Personalization/createViewChangeHandler.js @@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import { PropositionEventType } from "./constants/propositionEventType"; +import { PropositionEventType } from "../../constants/propositionEventType"; export default ({ mergeDecisionsMeta, processPropositions, viewCache }) => { return ({ personalizationDetails, event, onResponse }) => { diff --git a/src/components/Personalization/event.js b/src/components/Personalization/event.js index fe7e565fe..c7fa19e7a 100644 --- a/src/components/Personalization/event.js +++ b/src/components/Personalization/event.js @@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const EVENT_TYPE_TRUE = 1; +import { EVENT_TYPE_TRUE } from "../../constants/eventType"; /* eslint-disable no-underscore-dangle */ export const mergeDecisionsMeta = ( diff --git a/src/components/Personalization/in-app-message-actions/actions/displayIframeContent.js b/src/components/Personalization/in-app-message-actions/actions/displayIframeContent.js index 8d149e497..4a768eb26 100644 --- a/src/components/Personalization/in-app-message-actions/actions/displayIframeContent.js +++ b/src/components/Personalization/in-app-message-actions/actions/displayIframeContent.js @@ -14,7 +14,7 @@ import { getNonce } from "../../dom-actions/dom"; import { createElement, parseAnchor, removeElementById } from "../utils"; import { TEXT_HTML } from "../../constants/contentType"; import { assign } from "../../../../utils"; -import { getEventType } from "../../constants/propositionEventType"; +import { getEventType } from "../../../../constants/propositionEventType"; const ALLOY_MESSAGING_CONTAINER_ID = "alloy-messaging-container"; const ALLOY_OVERLAY_CONTAINER_ID = "alloy-overlay-container"; diff --git a/src/components/Personalization/constants/eventType.js b/src/constants/eventType.js similarity index 96% rename from src/components/Personalization/constants/eventType.js rename to src/constants/eventType.js index a61c15bcb..e379a5198 100644 --- a/src/components/Personalization/constants/eventType.js +++ b/src/constants/eventType.js @@ -14,3 +14,4 @@ export const DISPLAY = "decisioning.propositionDisplay"; export const INTERACT = "decisioning.propositionInteract"; export const TRIGGER = "decisioning.propositionTrigger"; export const DISMISS = "decisioning.propositionDismiss"; +export const EVENT_TYPE_TRUE = 1; diff --git a/src/components/Personalization/constants/propositionEventType.js b/src/constants/propositionEventType.js similarity index 100% rename from src/components/Personalization/constants/propositionEventType.js rename to src/constants/propositionEventType.js diff --git a/test/unit/specs/components/DecisioningEngine/contextTestUtils.js b/test/unit/specs/components/DecisioningEngine/contextTestUtils.js index a99492b8f..322d7e191 100644 --- a/test/unit/specs/components/DecisioningEngine/contextTestUtils.js +++ b/test/unit/specs/components/DecisioningEngine/contextTestUtils.js @@ -16,6 +16,11 @@ import createDecisionProvider from "../../../../../src/components/DecisioningEng export const proposition = { id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", + scopeDetails: { + activity: { + id: "abc#xyz" + } + }, items: [ { schema: "https://ns.adobe.com/personalization/mock-action", @@ -55,6 +60,11 @@ export const mockWindow = ({ export const payloadWithCondition = condition => { return { id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", + scopeDetails: { + activity: { + id: "abc#xyz" + } + }, items: [ { id: "79129ecf-6430-4fbd-955a-b4f1dfdaa6fe", diff --git a/test/unit/specs/components/DecisioningEngine/createDecisionProvider.spec.js b/test/unit/specs/components/DecisioningEngine/createDecisionProvider.spec.js index 82c78f28e..3a4b48109 100644 --- a/test/unit/specs/components/DecisioningEngine/createDecisionProvider.spec.js +++ b/test/unit/specs/components/DecisioningEngine/createDecisionProvider.spec.js @@ -24,6 +24,8 @@ describe("DecisioningEngine:createDecisionProvider", () => { decisionProvider = createDecisionProvider({ eventRegistry }); decisionProvider.addPayloads([ { + id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", + scope: "web://mywebsite.com", scopeDetails: { decisionProvider: "AJO", characteristics: { @@ -41,7 +43,6 @@ describe("DecisioningEngine:createDecisionProvider", () => { }, correlationID: "02c77ea8-7c0e-4d33-8090-4a5bfd3d7503" }, - id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", items: [ { id: "79129ecf-6430-4fbd-955a-b4f1dfdaa6fe", @@ -124,10 +125,11 @@ describe("DecisioningEngine:createDecisionProvider", () => { ] } } - ], - scope: "web://mywebsite.com" + ] }, { + id: "3d5d69cd-acde-4eca-b43b-a54574b67bb0", + scope: "web://mywebsite.com", scopeDetails: { decisionProvider: "AJO", characteristics: { @@ -141,11 +143,10 @@ describe("DecisioningEngine:createDecisionProvider", () => { ], activity: { id: - "39ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d183" + "48ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d168" }, correlationID: "02c77ea8-7c0e-4d33-8090-4a5bfd3d7503" }, - id: "3d5d69cd-acde-4eca-b43b-a54574b67bb0", items: [ { id: "5229f502-38d6-40c3-9a3a-b5b1a6adc441", @@ -214,8 +215,7 @@ describe("DecisioningEngine:createDecisionProvider", () => { ] } } - ], - scope: "web://mywebsite.com" + ] } ]); }); @@ -224,6 +224,8 @@ describe("DecisioningEngine:createDecisionProvider", () => { decisionProvider.evaluate({ color: "blue", action: "lipstick" }) ).toEqual([ { + id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", + scope: "web://mywebsite.com", scopeDetails: { decisionProvider: "AJO", characteristics: { @@ -241,7 +243,6 @@ describe("DecisioningEngine:createDecisionProvider", () => { }, correlationID: "02c77ea8-7c0e-4d33-8090-4a5bfd3d7503" }, - id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", items: [ { schema: "https://ns.adobe.com/personalization/dom-action", @@ -271,8 +272,7 @@ describe("DecisioningEngine:createDecisionProvider", () => { }, id: "10da709c-aa1a-40e5-84dd-966e2e8a1d5f" } - ], - scope: "web://mywebsite.com" + ] } ]); }); @@ -294,7 +294,7 @@ describe("DecisioningEngine:createDecisionProvider", () => { ], activity: { id: - "39ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d183" + "48ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d168" }, correlationID: "02c77ea8-7c0e-4d33-8090-4a5bfd3d7503" }, @@ -402,7 +402,7 @@ describe("DecisioningEngine:createDecisionProvider", () => { ], activity: { id: - "39ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d183" + "48ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d168" }, correlationID: "02c77ea8-7c0e-4d33-8090-4a5bfd3d7503" }, diff --git a/test/unit/specs/components/DecisioningEngine/createEvaluateRulesetsCommand.spec.js b/test/unit/specs/components/DecisioningEngine/createEvaluateRulesetsCommand.spec.js index f2fa070e1..7c5bd3889 100644 --- a/test/unit/specs/components/DecisioningEngine/createEvaluateRulesetsCommand.spec.js +++ b/test/unit/specs/components/DecisioningEngine/createEvaluateRulesetsCommand.spec.js @@ -35,6 +35,11 @@ describe("DecisioningEngine:evaluateRulesetsCommand", () => { decisionProvider.addPayload({ id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", + scopeDetails: { + activity: { + id: "abc#xyz" + } + }, items: [ { id: "79129ecf-6430-4fbd-955a-b4f1dfdaa6fe", @@ -120,6 +125,11 @@ describe("DecisioningEngine:evaluateRulesetsCommand", () => { propositions: [ { id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", + scopeDetails: { + activity: { + id: "abc#xyz" + } + }, items: [ { schema: "https://ns.adobe.com/personalization/dom-action", @@ -160,6 +170,11 @@ describe("DecisioningEngine:evaluateRulesetsCommand", () => { propositions: [ { id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", + scopeDetails: { + activity: { + id: "abc#xyz" + } + }, items: [ { schema: "https://ns.adobe.com/personalization/dom-action", diff --git a/test/unit/specs/components/DecisioningEngine/createEventRegistry.spec.js b/test/unit/specs/components/DecisioningEngine/createEventRegistry.spec.js index 1f268031c..e7f1ecd32 100644 --- a/test/unit/specs/components/DecisioningEngine/createEventRegistry.spec.js +++ b/test/unit/specs/components/DecisioningEngine/createEventRegistry.spec.js @@ -32,10 +32,36 @@ describe("DecisioningEngine:createEventRegistry", () => { const getContent = () => ({ xdm: { - eventType: "display", + eventType: "decisioning.propositionDisplay", _experience: { decisioning: { - propositions: [{ id: "abc" }, { id: "def" }, { id: "ghi" }] + propositions: [ + { + id: "111", + scope: "mobileapp://com.adobe.aguaAppIos", + scopeDetails: { + decisionProvider: "AJO", + correlationID: "ccaa539e-ca14-4d42-ac9a-0a17e69a63e4", + activity: { + id: "111#aaa" + } + } + }, + { + id: "222", + scope: "mobileapp://com.adobe.aguaAppIos", + scopeDetails: { + decisionProvider: "AJO", + correlationID: "ccaa539e-ca14-4d42-ac9a-0a17e69a63e4", + activity: { + id: "222#bbb" + } + } + } + ], + propositionEventType: { + display: 1 + } } } } @@ -46,23 +72,22 @@ describe("DecisioningEngine:createEventRegistry", () => { }; eventRegistry.addExperienceEdgeEvent(event); - expect(eventRegistry.toJSON()).toEqual({ display: { - abc: { - event: jasmine.objectContaining({ id: "abc", type: "display" }), + "111#aaa": { + event: jasmine.objectContaining({ + "iam.id": "111#aaa", + "iam.eventType": "display" + }), firstTimestamp: jasmine.any(Number), timestamp: jasmine.any(Number), count: 1 }, - def: { - event: jasmine.objectContaining({ id: "def", type: "display" }), - firstTimestamp: jasmine.any(Number), - timestamp: jasmine.any(Number), - count: 1 - }, - ghi: { - event: jasmine.objectContaining({ id: "ghi", type: "display" }), + "222#bbb": { + event: jasmine.objectContaining({ + "iam.id": "222#bbb", + "iam.eventType": "display" + }), firstTimestamp: jasmine.any(Number), timestamp: jasmine.any(Number), count: 1 @@ -111,10 +136,25 @@ describe("DecisioningEngine:createEventRegistry", () => { const getContent = () => ({ xdm: { - eventType: "display", + eventType: "decisioning.propositionDisplay", _experience: { decisioning: { - propositions: [{ id: "abc" }] + propositions: [ + { + id: "111", + scope: "mobileapp://com.adobe.aguaAppIos", + scopeDetails: { + decisionProvider: "AJO", + correlationID: "ccaa539e-ca14-4d42-ac9a-0a17e69a63e4", + activity: { + id: "111#aaa" + } + } + } + ], + propositionEventType: { + display: 1 + } } } } @@ -125,29 +165,35 @@ describe("DecisioningEngine:createEventRegistry", () => { }; let lastEventTime = 0; eventRegistry.addExperienceEdgeEvent(event); - - expect(eventRegistry.getEvent("display", "abc")).toEqual({ - event: jasmine.objectContaining({ id: "abc", type: "display" }), + expect(eventRegistry.getEvent("display", "111#aaa")).toEqual({ + event: jasmine.objectContaining({ + "iam.id": "111#aaa", + "iam.eventType": "display" + }), firstTimestamp: jasmine.any(Number), timestamp: jasmine.any(Number), count: 1 }); - expect(eventRegistry.getEvent("display", "abc").timestamp).toBeGreaterThan( - lastEventTime - ); - lastEventTime = eventRegistry.getEvent("display", "abc").timestamp; + expect( + eventRegistry.getEvent("display", "111#aaa").timestamp + ).toBeGreaterThan(lastEventTime); + + lastEventTime = eventRegistry.getEvent("display", "111#aaa").timestamp; setTimeout(() => { eventRegistry.addExperienceEdgeEvent(event); // again - expect(eventRegistry.getEvent("display", "abc")).toEqual({ - event: jasmine.objectContaining({ id: "abc", type: "display" }), + expect(eventRegistry.getEvent("display", "111#aaa")).toEqual({ + event: jasmine.objectContaining({ + "iam.id": "111#aaa", + "iam.eventType": "display" + }), firstTimestamp: jasmine.any(Number), timestamp: jasmine.any(Number), count: 2 }); expect( - eventRegistry.getEvent("display", "abc").timestamp + eventRegistry.getEvent("display", "111#aaa").timestamp ).toBeGreaterThan(lastEventTime); done(); }, 50); @@ -164,8 +210,8 @@ describe("DecisioningEngine:createEventRegistry", () => { for (let i = 0; i < 2000; i += 1) { events["decisioning.propositionDisplay"][i] = { event: { - id: i, - type: "decisioning.propositionDisplay" + "iam.id": i, + "iam.eventType": "decisioning.propositionDisplay" }, firstTimestamp: "2023-05-23T08:00:00Z", timestamp: mockedTimestamp, @@ -174,8 +220,8 @@ describe("DecisioningEngine:createEventRegistry", () => { events["decisioning.propositionInteract"][i] = { event: { - id: i, - type: "decisioning.propositionInteract" + "iam.id": i, + "iam.eventType": "decisioning.propositionInteract" }, firstTimestamp: "2023-05-23T08:00:00Z", timestamp: mockedTimestamp, @@ -194,8 +240,8 @@ describe("DecisioningEngine:createEventRegistry", () => { expect(displayEvents.length).not.toBeGreaterThan(1000); if (i > 1000) { - expect(interactEvents[0].event.id).toEqual(i - 999); - expect(displayEvents[0].event.id).toEqual(i - 999); + expect(interactEvents[0].event["iam.id"]).toEqual(i - 999); + expect(displayEvents[0].event["iam.id"]).toEqual(i - 999); } if (i > 0) { @@ -220,8 +266,8 @@ describe("DecisioningEngine:createEventRegistry", () => { for (let i = 0; i < 20; i += 1) { events["decisioning.propositionDisplay"][i] = { event: { - id: i, - type: "decisioning.propositionDisplay" + "iam.id": i, + "iam.eventType": "decisioning.propositionDisplay" }, firstTimestamp: 1, timestamp: 1, @@ -245,8 +291,8 @@ describe("DecisioningEngine:createEventRegistry", () => { events["decisioning.propositionDisplay"] = { 1: { event: { - id: 1, - type: "decisioning.propositionInteract" + "iam.id": 1, + "iam.eventType": "decisioning.propositionInteract" }, firstTimestamp: "2023-05-20T10:00:00Z", timestamp: mockedTimestamp, @@ -254,8 +300,8 @@ describe("DecisioningEngine:createEventRegistry", () => { }, 2: { event: { - id: 2, - type: "decisioning.propositionInteract" + "iam.id": 2, + "iam.eventType": "decisioning.propositionInteract" }, firstTimestamp: "2023-05-24T15:00:00Z", timestamp: mockedTimestamp, @@ -265,8 +311,8 @@ describe("DecisioningEngine:createEventRegistry", () => { events["decisioning.propositionInteract"] = { 3: { event: { - id: 3, - type: "decisioning.propositionInteract" + "iam.id": 3, + "iam.eventType": "decisioning.propositionInteract" }, firstTimestamp: "2023-05-23T08:00:00Z", timestamp: mockedTimestamp, @@ -274,8 +320,8 @@ describe("DecisioningEngine:createEventRegistry", () => { }, 4: { event: { - id: 4, - type: "decisioning.propositionInteract" + "iam.id": 4, + "iam.eventType": "decisioning.propositionInteract" }, firstTimestamp: "2023-05-23T08:00:00Z", timestamp: mockedTimestamp, @@ -288,8 +334,8 @@ describe("DecisioningEngine:createEventRegistry", () => { "decisioning.propositionDisplay": { 2: { event: { - id: 2, - type: "decisioning.propositionInteract" + "iam.id": 2, + "iam.eventType": "decisioning.propositionInteract" }, firstTimestamp: "2023-05-24T15:00:00Z", timestamp: mockedTimestamp, @@ -299,8 +345,8 @@ describe("DecisioningEngine:createEventRegistry", () => { "decisioning.propositionInteract": { 3: { event: { - id: 3, - type: "decisioning.propositionInteract" + "iam.id": 3, + "iam.eventType": "decisioning.propositionInteract" }, firstTimestamp: "2023-05-23T08:00:00Z", timestamp: mockedTimestamp, @@ -308,8 +354,8 @@ describe("DecisioningEngine:createEventRegistry", () => { }, 4: { event: { - id: 4, - type: "decisioning.propositionInteract" + "iam.id": 4, + "iam.eventType": "decisioning.propositionInteract" }, firstTimestamp: "2023-05-23T08:00:00Z", timestamp: mockedTimestamp, diff --git a/test/unit/specs/components/DecisioningEngine/createOnResponseHandler.spec.js b/test/unit/specs/components/DecisioningEngine/createOnResponseHandler.spec.js index 5a177c1ef..8a8177164 100644 --- a/test/unit/specs/components/DecisioningEngine/createOnResponseHandler.spec.js +++ b/test/unit/specs/components/DecisioningEngine/createOnResponseHandler.spec.js @@ -77,6 +77,11 @@ describe("DecisioningEngine:createOnResponseHandler", () => { getPayloadsByType: () => [ { id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", + scopeDetails: { + activity: { + id: "abc#xyz" + } + }, items: [ { id: "79129ecf-6430-4fbd-955a-b4f1dfdaa6fe", @@ -175,6 +180,11 @@ describe("DecisioningEngine:createOnResponseHandler", () => { propositions: [ { id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", + scopeDetails: { + activity: { + id: "abc#xyz" + } + }, items: [ { schema: "https://ns.adobe.com/personalization/dom-action", @@ -253,6 +263,11 @@ describe("DecisioningEngine:createOnResponseHandler", () => { getPayloadsByType: () => [ { id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", + scopeDetails: { + activity: { + id: "abc#xyz" + } + }, items: [ { id: "79129ecf-6430-4fbd-955a-b4f1dfdaa6fe", @@ -340,6 +355,11 @@ describe("DecisioningEngine:createOnResponseHandler", () => { propositions: [ { id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", + scopeDetails: { + activity: { + id: "abc#xyz" + } + }, items: [ { schema: "https://ns.adobe.com/personalization/dom-action", diff --git a/test/unit/specs/components/DecisioningEngine/decisioningContext.timestamp.spec.js b/test/unit/specs/components/DecisioningEngine/decisioningContext.timestamp.spec.js index 3e75c6b2e..91c3c4c65 100644 --- a/test/unit/specs/components/DecisioningEngine/decisioningContext.timestamp.spec.js +++ b/test/unit/specs/components/DecisioningEngine/decisioningContext.timestamp.spec.js @@ -133,9 +133,9 @@ describe("DecisioningEngine:globalContext:timeContext", () => { it("satisfies rule based on matched currentDay", () => { setupResponseHandler(applyResponse, mockWindow({}), { definition: { - key: "currentDay", + key: "~state.com.adobe.module.lifecycle/lifecyclecontextdata.dayofweek", matcher: "eq", - values: [mockedTimestamp.getDay()] + values: [mockedTimestamp.getDay() + 1] }, type: "matcher" }); @@ -150,9 +150,9 @@ describe("DecisioningEngine:globalContext:timeContext", () => { it("does not satisfy rule due to unmatched currentDay", () => { setupResponseHandler(applyResponse, mockWindow({}), { definition: { - key: "currentDay", + key: "~state.com.adobe.module.lifecycle/lifecyclecontextdata.dayofweek", matcher: "eq", - values: [mockedTimestamp.getDay() + 1] + values: [mockedTimestamp.getDay()] }, type: "matcher" }); @@ -167,7 +167,7 @@ describe("DecisioningEngine:globalContext:timeContext", () => { it("satisfies rule based on matched currentHour", () => { setupResponseHandler(applyResponse, mockWindow({}), { definition: { - key: "currentHour", + key: "~state.com.adobe.module.lifecycle/lifecyclecontextdata.hourofday", matcher: "eq", values: [mockedTimestamp.getHours()] }, @@ -184,7 +184,7 @@ describe("DecisioningEngine:globalContext:timeContext", () => { it("does not satisfy rule due to unmatched currentHour", () => { setupResponseHandler(applyResponse, mockWindow({}), { definition: { - key: "currentHour", + key: "~state.com.adobe.module.lifecycle/lifecyclecontextdata.hourofday", matcher: "eq", values: [mockedTimestamp.getHours() + 1] }, diff --git a/test/unit/specs/components/DecisioningEngine/utils.spec.js b/test/unit/specs/components/DecisioningEngine/utils.spec.js index 7da1d1dd0..1d2d0478a 100644 --- a/test/unit/specs/components/DecisioningEngine/utils.spec.js +++ b/test/unit/specs/components/DecisioningEngine/utils.spec.js @@ -12,6 +12,7 @@ governing permissions and limitations under the License. import { createRestoreStorage, createSaveStorage, + getActivityId, getExpirationDate } from "../../../../../src/components/DecisioningEngine/utils"; @@ -78,4 +79,116 @@ describe("DecisioningEngine:utils", () => { expect(result).toEqual(expectedDate); jasmine.clock().uninstall(); }); + it("should return the activityId", () => { + const proposition = { + id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", + scope: "web://mywebsite.com", + scopeDetails: { + decisionProvider: "AJO", + characteristics: { + eventToken: "abc" + }, + strategies: [ + { + strategyID: "3VQe3oIqiYq2RAsYzmDTSf", + treatmentID: "yu7rkogezumca7i0i44v" + } + ], + activity: { + id: + "39ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d183" + }, + correlationID: "02c77ea8-7c0e-4d33-8090-4a5bfd3d7503" + }, + items: [ + { + id: "79129ecf-6430-4fbd-955a-b4f1dfdaa6fe", + schema: "https://ns.adobe.com/personalization/ruleset-item", + data: { + version: 1, + rules: [ + { + condition: { + definition: { + conditions: [ + { + definition: { + conditions: [ + { + definition: { + key: "color", + matcher: "eq", + values: ["orange", "blue"] + }, + type: "matcher" + }, + { + definition: { + key: "action", + matcher: "eq", + values: ["lipstick"] + }, + type: "matcher" + } + ], + logic: "and" + }, + type: "group" + } + ], + logic: "and" + }, + type: "group" + }, + consequences: [ + { + type: "schema", + detail: { + schema: "https://ns.adobe.com/personalization/dom-action", + data: { + selector: + "HTML > BODY > DIV.offer:eq(0) > IMG:nth-of-type(1)", + type: "setAttribute", + content: { + src: "img/demo-marketing-offer1-exp-A.png" + }, + prehidingSelector: + "HTML > BODY > DIV:nth-of-type(2) > IMG:nth-of-type(1)" + }, + id: "79129ecf-6430-4fbd-955a-b4f1dfdaa6fe" + }, + id: "79129ecf-6430-4fbd-955a-b4f1dfdaa6fe" + } + ] + } + ] + } + } + ] + }; + expect(getActivityId(proposition)).toEqual( + "39ae8d4b-b55e-43dc-a143-77f50195b487#b47fde8b-57c1-4bbe-ae22-64d5b782d183" + ); + }); + + it("should return the activityId as undefined", () => { + const proposition = { + id: "2e4c7b28-b3e7-4d5b-ae6a-9ab0b44af87e", + scope: "web://mywebsite.com", + scopeDetails: { + decisionProvider: "AJO", + characteristics: { + eventToken: "abc" + }, + strategies: [ + { + strategyID: "3VQe3oIqiYq2RAsYzmDTSf", + treatmentID: "yu7rkogezumca7i0i44v" + } + ], + correlationID: "02c77ea8-7c0e-4d33-8090-4a5bfd3d7503" + } + }; + expect(getActivityId(proposition)).toEqual(undefined); + }); }); diff --git a/test/unit/specs/components/Personalization/createCollect.spec.js b/test/unit/specs/components/Personalization/createCollect.spec.js index 6c65207af..fc4fb4e1e 100644 --- a/test/unit/specs/components/Personalization/createCollect.spec.js +++ b/test/unit/specs/components/Personalization/createCollect.spec.js @@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ import createCollect from "../../../../../src/components/Personalization/createCollect"; -import { PropositionEventType } from "../../../../../src/components/Personalization/constants/propositionEventType"; +import { PropositionEventType } from "../../../../../src/constants/propositionEventType"; describe("Personalization::createCollect", () => { let eventManager; diff --git a/test/unit/specs/components/Personalization/createViewChangeHandler.spec.js b/test/unit/specs/components/Personalization/createViewChangeHandler.spec.js index 5cf1c7aa8..feed84e82 100644 --- a/test/unit/specs/components/Personalization/createViewChangeHandler.spec.js +++ b/test/unit/specs/components/Personalization/createViewChangeHandler.spec.js @@ -11,7 +11,7 @@ governing permissions and limitations under the License. */ import createViewChangeHandler from "../../../../../src/components/Personalization/createViewChangeHandler"; -import { PropositionEventType } from "../../../../../src/components/Personalization/constants/propositionEventType"; +import { PropositionEventType } from "../../../../../src/constants/propositionEventType"; import { CART_VIEW_DECISIONS } from "./responsesMock/eventResponses"; import injectCreateProposition from "../../../../../src/components/Personalization/handlers/injectCreateProposition"; diff --git a/test/unit/specs/components/Personalization/event.spec.js b/test/unit/specs/components/Personalization/event.spec.js index dbe0e55b5..91f8a1b1a 100644 --- a/test/unit/specs/components/Personalization/event.spec.js +++ b/test/unit/specs/components/Personalization/event.spec.js @@ -14,7 +14,7 @@ import { mergeDecisionsMeta, mergeQuery } from "../../../../../src/components/Personalization/event"; -import { PropositionEventType } from "../../../../../src/components/Personalization/constants/propositionEventType"; +import { PropositionEventType } from "../../../../../src/constants/propositionEventType"; describe("Personalization::event", () => { let event;