Skip to content

Commit

Permalink
added delayed modal
Browse files Browse the repository at this point in the history
  • Loading branch information
mirafedas committed Mar 19, 2024
1 parent e909bc6 commit 8c1704e
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 7 deletions.
41 changes: 36 additions & 5 deletions libs/blocks/modal/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,45 @@ export async function getModal(details, custom) {
return dialog;
}

export function getHashParams(hashStr) {
if (!hashStr) return {};
return hashStr.split(':').reduce((params, part) => {
if (part.startsWith('#')) {
params.hash = part;
} else {
const [key, val] = part.split('=');
if (key === 'delay' && parseInt(val, 10) > 0) {
params.delay = parseInt(val, 10) * 1000;
}
}
return params;
}, {});
}

export function delayedModal(el) {
const { hash, delay } = getHashParams(el?.dataset.modalHash);
if (!delay || !hash) return false;
el.classList.add('hide-block');
const modalOpenEvent = new Event(`${hash}:modalOpen`);
const pagesModalWasShownOn = window.sessionStorage.getItem(`shown:${hash}`);
el.dataset.modalHash = hash;
el.href = hash;
if (!pagesModalWasShownOn?.includes(window.location.pathname)) {
setTimeout(() => {
window.location.replace(hash);
sendAnalytics(modalOpenEvent);
window.sessionStorage.setItem(`shown:${hash}`, `${pagesModalWasShownOn || ''} ${window.location.pathname}`);
}, delay);
}
return true;
}

// Deep link-based
export default function init(el) {
const { modalHash } = el.dataset;
if (window.location.hash === modalHash && !document.querySelector(`div.dialog-modal${modalHash}`)) {
const details = findDetails(window.location.hash, el);
if (details) return getModal(details);
}
return null;
if (window.location.hash !== modalHash || document.querySelector(`div.dialog-modal${modalHash}`) || delayedModal(el)) return null;
const details = findDetails(window.location.hash, el);
return details ? getModal(details) : null;
}

// Click-based modal
Expand Down
56 changes: 55 additions & 1 deletion test/blocks/modals/modals.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import { readFile, sendKeys } from '@web/test-runner-commands';
import { expect } from '@esm-bundle/chai';
import sinon from 'sinon';
import { delay, waitForElement, waitForRemoval } from '../../helpers/waitfor.js';
import init, { getModal } from '../../../libs/blocks/modal/modal.js';

document.body.innerHTML = await readFile({ path: './mocks/body.html' });
const {
default: init,
getModal,
getHashParams,
delayedModal,
} = await import('../../../libs/blocks/modal/modal.js');

describe('Modals', () => {
beforeEach(() => {
// eslint-disable-next-line no-underscore-dangle
window._satellite = { track: sinon.spy() };
});

afterEach(() => {
sinon.restore();
});

it('Doesnt load modals on page load with no hash', async () => {
window.location.hash = '';
const modal = document.querySelector('.dialog-modal');
Expand Down Expand Up @@ -169,4 +184,43 @@ describe('Modals', () => {
// Test passing, means there was no error thrown
await hashChangeTriggered;
});

it('validates and returns proper hash parameters', () => {
expect(getHashParams()).to.deep.equal({});
expect(getHashParams('#delayed-modal:delay=0')).to.deep.equal({ hash: '#delayed-modal' });
expect(getHashParams('#delayed-modal:delay=1')).to.deep.equal({
delay: 1000,
hash: '#delayed-modal',
});
});

it('shows the modal with a delay, and remembers it was shown on this page', async () => {
window.sessionStorage.removeItem('shown:#delayed-modal');
const el = document.createElement('a');
el.setAttribute('data-modal-hash', '#delayed-modal:delay=1');
expect(delayedModal(el)).to.be.true;
await delay(1000);
expect(el.classList.contains('hide-block')).to.be.true;
const modal = waitForElement('#delayed-modal');
expect(modal).to.be.not.null;
expect(window.sessionStorage.getItem('shown:#delayed-modal').includes(window.location.pathname)).to.be.true;
// eslint-disable-next-line no-underscore-dangle
expect(window._satellite.track.called).to.be.true;
window.sessionStorage.removeItem('shown:#delayed-modal');
el.remove();
});

it('does not show the modal if it was shown on this page', async () => {
const el = document.createElement('a');
el.setAttribute('data-modal-hash', '#dm:delay=1');
window.sessionStorage.setItem('shown:#dm', window.location.pathname);
expect(delayedModal(el)).to.be.true;
await delay(1000);
// eslint-disable-next-line no-underscore-dangle
expect(window._satellite.track.called).to.be.false;
const modal = document.querySelector('#dm');
expect(modal).to.not.exist;
window.sessionStorage.removeItem('shown:#dm');
el.remove();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@
"firefox": "",
"android": "",
"ios": ""
},
{
"action": "insertContentAfter",
"selector": "main > div",
"page filter (optional)": "",
"param-newoffer=123": "",
"chrome": "/fragments/insertafter#delayed-modal:delay=1",
"firefox": "",
"android": "",
"ios": ""
}
],
":type": "sheet"
Expand Down
5 changes: 4 additions & 1 deletion test/features/personalization/personalization.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,11 @@ describe('Functional Test', () => {

const fragment = document.querySelector('a[href="/fragments/insertafter"]');
expect(fragment).to.not.be.null;

expect(fragment.parentElement.previousElementSibling.className).to.equal('marquee');

const delayedModalFragment = document.querySelector('a[href="/fragments/insertafter#delayed-modal:delay=1"]');
expect(delayedModalFragment).to.not.be.null;
delayedModalFragment.remove();
});

it('insertContentBefore should add fragment before target element', async () => {
Expand Down

0 comments on commit 8c1704e

Please sign in to comment.