-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Combine personalization display notifications together #1025
Conversation
renderAttempted: false | ||
}); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Splitting out a proposition into one with the items that were rendered and one with the items that were not rendered may not be necessary anymore. It depends if experience edge will ever return a proposition where this is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand the use case described here, could you please elaborate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the return value to sendEvent we return "propositions" and "decisions". decisions includes all propositions that were not rendered. propositions includes all the propositions with a "renderAttempted" flag added. If we ever render only some of the items in a proposition, how should we return the proposition in "propositions" and "decisions"? Currently and with this refactor we split the proposition into two (one with the items that were rendered and one with the other items), and then return them in "propositions" and "decisions" appropriately. This logic may not be necessary if we never run into this situation.
@@ -49,6 +49,6 @@ test("Test C205528: A redirect offer should redirect the page to the URL in the | |||
} catch (e) { | |||
// an exception will be thrown because a redirect will be executed within the Alloy Client Function | |||
} finally { | |||
await t.expect(redirectLogger.requests.length).eql(1); | |||
await t.expect(redirectLogger.count(() => true)).eql(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had intermittent test failures with this test case related to timing issues. Using .count(...) triggers test cafe to retry this assertion until it succeeds or times out.
@@ -230,30 +229,41 @@ const simulateViewChangeForNonExistingView = async alloy => { | |||
} | |||
}); | |||
|
|||
const noViewViewChangeRequest = networkLogger.edgeEndpointLogs.requests[4]; | |||
const noViewViewChangeRequest = networkLogger.edgeEndpointLogs.requests[3]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With combined display notifications, this test now runs with 2 fewer network requests.
.expect( | ||
networkLogger.edgeEndpointLogs.count( | ||
({ response: { statusCode } }) => | ||
statusCode === 200 || statusCode === 207 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was also getting intermittent failures here. Sometimes Konductor is returning a 200 and sometimes a 207. Maybe this happens when an upstream call fails?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, if one of the Upstreams returns an error, Konductor returns Multi Status code and the errors along with the handles.
@@ -48,6 +48,7 @@ if (argv.reporters && argv.reporters.split(",").includes("coverage")) { | |||
|
|||
module.exports = { | |||
output: { | |||
sourcemap: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes debugging tests a lot easier. I'm not sure why we didn't have it included before.
const preprocess = createPreprocess([remapHeadOffers, remapCustomCodeOffers]); | ||
|
||
const noOpHandler = () => undefined; | ||
const domActionHandler = createDomActionHandler({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of action handlers like you added for DOM actions and HTML actions, etc. But it feels like a leaky abstraction since each one has the same modules object passed in (the dom actions modules).
I'd expect a different modules object for each. For instance...
initDomActionsModules might include actions like customCode, setText, setAttribute, setImageSource, setStyle, move, resize, rearrange, remove, insertAfter, insertBefore
And something like initHTMLActionsModules might include setHtml, replaceHtml, prependHtml, appendHtml (guessing on some of these).
And for in app messages something like initMessagingActionsModules to handle this.
The idea here is to separate each set of actions to a specific schema.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good suggestion. I filed a ticket https://jira.corp.adobe.com/browse/PDCL-11018. Let's discuss this next month.
items = [] | ||
} = proposition.getHandle(); | ||
|
||
items.forEach((item, index) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems to be a lot of duplication in HTMLContentHandler , DomActionHandler, and others. Is that by design?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Talking about the order of rendering: Redirect and DOM Action schema items should always be first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent job @jonsnyder! I really like the new structure of the personalization component.
However there are a few things I have discovered:
- there is an issue in how we handle HTML offers in target global mbox ( I tested against
main
and it works fine, however it fails in this PR) - I see flickering, I guess
showContainers()
gets called prematurely in some places - I was looking at the
handlerChain
and it seems that every handler iterates thruproposition.items
, is this by design? In the previous version we were grouping the propositions.
if (viewStorage === undefined) { | ||
viewStorage = {}; | ||
const getViewPropositions = (currentViewStorage, viewName) => { | ||
const viewPropositions = currentViewStorage[viewName]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that viewCacheManager
is not responsible only for SPA cache anymore, so it should be renamed or split out.
const render = createRender({ | ||
handleChain: htmlContentHandler, | ||
collect, | ||
executeRedirect: url => window.location.replace(url), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe extract this in a function and pass it here.
Also, I noticed there are a few places where window.location
is used and a helper createGetPageLocation
returns the window.location
. I would extract it in utils and reuse.
proposition.includeInDisplayNotification(); | ||
proposition.addRenderer(index, () => undefined); | ||
} | ||
const { type, selector } = data || {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a use-case of a form-based composed HTML offer for global mbox we receive a proposition item that looks like this:
{
"type": "setHtml",
"format": "application/vnd.adobe.target.dom-action",
"content": "\"Hello world\"",
"selector": "head",
"prehidingSelector": "head"
}
When this is rendered, we get a blank HTML head
tag which results in a broken page since all the styles and scripts are removed.
As far as I can tell previously we had a logic that transformed for head
selector the setHtml
action type into appendHtml
, to avoid messing up the HTML head
.
const errorMessage = `Failed to execute action ${details}. ${message} ${ | ||
stack ? `\n ${stack}` : "" | ||
}`; | ||
logger.error(errorMessage); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We didn't log an error before, it was a warning.
renderAttempted: false | ||
}); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand the use case described here, could you please elaborate?
Awesome work @jonsnyder !!! |
Closed in favor of #1036 |
Description
Changes to functionality:
Additionally, this PR includes extensive refactoring of the personalization component. The key changes are:
As much as possible, I followed the current functionality; however, there may be opportunities to simplify the logic if our test cases don't represent real use cases.
Related Issue
https://jira.corp.adobe.com/browse/PDCL-9860
Motivation and Context
This is a prerequisite for building top and bottom of page features. This depends on changes to Target upstream to accept unified display notifications.
Screenshots (if appropriate):
Types of changes
Checklist: