Skip to content

Commit

Permalink
fix the case when one element is added before the scriptlet and the r…
Browse files Browse the repository at this point in the history
…est after
  • Loading branch information
jellizaveta committed Jul 23, 2024
1 parent 62fe248 commit 99eb37d
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 8 deletions.
27 changes: 19 additions & 8 deletions src/scriptlets/trusted-click-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,14 +347,12 @@ export function trustedClickElement(
};

/**
* Query all selectors from queue on each mutation
* Each selector is swapped to null in selectorsSequence on founding corresponding element
*
* We start looking for elements before possible delay is over, to avoid cases
* when delay is getting off after the last mutation took place.
* Processes a sequence of selectors, handling elements found in DOM (and shadow DOM),
* and updates the sequence.
*
* @returns {string[]} The updated selectors sequence, with fulfilled selectors set to null.
*/
const findElements = (mutations: MutationRecord[], observer: MutationObserver) => {
const fulfillAndHandleSelectors = () => {
const fulfilledSelectors: string[] = [];
selectorsSequence.forEach((selector, i) => {
if (!selector) {
Expand All @@ -376,6 +374,19 @@ export function trustedClickElement(
: selector;
});

return selectorsSequence;
};

/**
* Query all selectors from queue on each mutation
*
* We start looking for elements before possible delay is over, to avoid cases
* when delay is getting off after the last mutation took place.
*
*/
const findElements = (mutations: MutationRecord[], observer: MutationObserver) => {
selectorsSequence = fulfillAndHandleSelectors();

// Disconnect observer after finding all elements
const allSelectorsFulfilled = selectorsSequence.every((selector) => selector === null);
if (allSelectorsFulfilled) {
Expand Down Expand Up @@ -406,7 +417,7 @@ export function trustedClickElement(
* If elements are not found, the observer is initialized.
*/
const checkInitialElements = () => {
const foundElements = selectorsSequence.some((selector) => {
const foundElements = selectorsSequence.every((selector) => {
if (!selector) {
return false;
}
Expand All @@ -415,7 +426,7 @@ export function trustedClickElement(
});
if (foundElements) {
// Click previously collected elements and set canClick to true
findElements([], new MutationObserver(() => {}));
fulfillAndHandleSelectors();
canClick = true;
} else {
// Initialize MutationObserver if elements were not found initially
Expand Down
36 changes: 36 additions & 0 deletions tests/scriptlets/trusted-click-element.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,42 @@ test('Element added to DOM is clicked', (assert) => {
}, 150);
});

test('Multiple elements clicked - one element loaded before scriptlet, rest added later', (assert) => {
const CLICK_ORDER = [1, 2, 3];
// Assert elements for being clicked, hit func execution & click order
const ASSERTIONS = CLICK_ORDER.length + 2;
assert.expect(ASSERTIONS);
const done = assert.async();

const selectorsString = createSelectorsString(CLICK_ORDER);

const panel = createPanel();

const clickables = [];
const clickable1 = createClickable(1);
panel.appendChild(clickable1);
clickables.push(clickable1);

runScriptlet(name, [selectorsString]);

const clickable2 = createClickable(2);
panel.appendChild(clickable2);
clickables.push(clickable2);

const clickable3 = createClickable(3);
panel.appendChild(clickable3);
clickables.push(clickable3);

setTimeout(() => {
clickables.forEach((clickable) => {
assert.ok(clickable.getAttribute('clicked'), 'Element should be clicked');
});
assert.strictEqual(CLICK_ORDER.join(), window.clickOrder.join(), 'Elements were clicked in a given order');
assert.strictEqual(window.hit, 'FIRED', 'hit func executed');
done();
}, 400);
});

test('Single element clicked, delay is set', (assert) => {
const ELEM_COUNT = 1;
const DELAY = 300;
Expand Down

0 comments on commit 99eb37d

Please sign in to comment.