Skip to content

Commit

Permalink
MWPW-144108: Project PEP unit tests (#2136)
Browse files Browse the repository at this point in the history
* unit tests for pep

* fixes for gnav unit tests

* optimizing pep unit tests
  • Loading branch information
robert-bogos authored and overmyheadandbody committed Apr 29, 2024
1 parent eb39336 commit b247bb3
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 2 deletions.
2 changes: 1 addition & 1 deletion libs/features/webapp-prompt/webapp-prompt.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class AppPrompt {

const metadata = getMetadata(content.querySelector('.section-metadata'));
metadata['loader-duration'] = parseInt(metadata['loader-duration'] || CONFIG.delay, 10);
metadata['loader-color'] = metadata['loader-color'] || CONFIG.defaultColor;
metadata['loader-color'] = metadata['loader-color'] || CONFIG.loaderColor;
this.options = metadata;
};

Expand Down
5 changes: 4 additions & 1 deletion test/blocks/global-navigation/global-navigation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('global navigation', () => {
before(() => {
document.head.innerHTML = `<link rel="icon" href="/libs/img/favicons/favicon.ico" size="any">
<script src="https://auth.services.adobe.com/imslib/imslib.min.js" type="javascript/blocked" data-loaded="true"></script>
<script src="https://stage.adobeccstatic.com/unav/1.0/UniversalNav.js" type="javascript/blocked" data-loaded="true"></script>
<script src="https://stage.adobeccstatic.com/unav/1.1/UniversalNav.js" type="javascript/blocked" data-loaded="true"></script>
`;
});

Expand Down Expand Up @@ -71,12 +71,15 @@ describe('global navigation', () => {
});

it("should log when there's issues within onReady", async () => {
const ogIms = window.adobeIMS;
const gnav = await createFullGlobalNavigation({});
sinon.stub(gnav, 'decorateProfile').callsFake(() => {
throw new Error('error');
});
window.adobeIMS = { isSignedInUser: () => true };
await gnav.imsReady();
expect(window.lana.log.getCalls().find((c) => c.args[0].includes('issues within onReady'))).to.exist;
window.adobeIMS = ogIms;
});

it('should log when IMS signIn method is not available', async () => {
Expand Down
Binary file added test/features/webapp-prompt/mocks/media-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions test/features/webapp-prompt/mocks/pep-prompt-content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export default ({ color, loaderDuration, redirectUrl, productName }) => `<div>
<p>
<picture>
<source type="image/webp" srcset="http://localhost:2000/test/features/webapp-prompt/mocks/media-icon.png" media="(min-width: 600px)">
<source type="image/webp" srcset="http://localhost:2000/test/features/webapp-prompt/mocks/media-icon.png">
<source type="image/png" srcset="http://localhost:2000/test/features/webapp-prompt/mocks/media-icon.png" media="(min-width: 600px)">
<img loading="lazy" alt="" src="http://localhost:2000/test/features/webapp-prompt/mocks/media-icon.png">
</picture>
</p>
<h2 id="taking-you-to-creative-cloud">Taking you to Creative Cloud</h2>
<h3 id="cancel-to-stay-on-web-page">Cancel to stay on web page</h3>
<p><em><a href="https://www.adobe.com/">Stay on this page</a></em></p>
<div class="section-metadata">
${color && `<div>
<div>loader-color</div>
<div>${color}</div>
</div>`}
${loaderDuration && `<div>
<div>loader-duration</div>
<div>${loaderDuration}</div>
</div>`}
${redirectUrl && `<div>
<div>redirect-url</div>
<div><a href="${redirectUrl}">${redirectUrl}</a></div>
</div>`}
${productName && `<div>
<div>product-name</div>
<div>${productName}</div>
</div>`}
</div>
</div>`;
46 changes: 46 additions & 0 deletions test/features/webapp-prompt/test-utilities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { setViewport } from '@web/test-runner-commands';
import init from '../../../libs/features/webapp-prompt/webapp-prompt.js';
import { viewports, mockRes as importedMockRes } from '../../blocks/global-navigation/test-utilities.js';
import { getConfig, loadStyle, setConfig, updateConfig } from '../../../libs/utils/utils.js';

export const allSelectors = {
fedsUtilities: '.feds-utilities',
pepWrapper: '.appPrompt',
closeIcon: '.appPrompt-close',
promptIcon: '.appPrompt-icon',
avatarImage: '.appPrompt-avatar-image',
title: '.appPrompt-title',
footer: '.appPrompt-footer',
subtitle: '.appPrompt-text',
cta: '.appPrompt-cta--close',
progressWrapper: '.appPrompt-progressWrapper',
progress: '.appPrompt-progress',
appSwitcher: '#unav-app-switcher',
};

export const defaultConfig = {
color: '#b30b00',
loaderDuration: 7500,
redirectUrl: 'https://www.adobe.com/?pep=true',
productName: 'photoshop',
};

export const mockRes = importedMockRes;

export const initPep = async ({ entName = 'firefly-web-usage', isAnchorOpen = false }) => {
setConfig({
imsClientId: 'milo',
codeRoot: '/libs',
locales: { '': { ietf: 'en-US', tk: 'hah7vzn.css' } },
});
updateConfig({ ...getConfig(), entitlements: () => ['firefly-web-usage'] });
await setViewport(viewports.desktop);
await loadStyle('../../../libs/features/webapp-prompt/webapp-prompt.css');

return init({
promptPath: 'https://pep-mocks.test/pep-prompt-content.plain.html',
getAnchorState: async () => ({ id: 'unav-app-switcher', isOpen: isAnchorOpen }),
entName,
parent: document.querySelector('div.feds-utilities'),
});
};
154 changes: 154 additions & 0 deletions test/features/webapp-prompt/webapp-prompt.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { expect } from '@esm-bundle/chai';
import sinon, { stub } from 'sinon';
import pepPromptContent from './mocks/pep-prompt-content.js';

describe('PEP', () => {
let clock;
let allSelectors;
let defaultConfig;
let mockRes;
let initPep;

beforeEach(async () => {
clock = sinon.useFakeTimers({
toFake: ['setTimeout'],
shouldAdvanceTime: true,
});
// We need to import the utilities after mocking setTimeout to ensure
// their setTimeout calls use Sinon's mocked implementation.
// Importing before mocking would lead to a 5s PEP timeout, exceeding the 2s test limit.
const { allSelectors: importedAllSelectors, defaultConfig: importedDefaultConfig, mockRes: importedMockRes } = await import('./test-utilities.js');
allSelectors = importedAllSelectors;
defaultConfig = importedDefaultConfig;
mockRes = importedMockRes;
initPep = (await import('./test-utilities.js')).initPep;
document.body.innerHTML = `<div class="${allSelectors.fedsUtilities.replace('.', '')}" style="position:relative">
<div id="${allSelectors.appSwitcher.replace('#', '')}" tabindex="0">App Switcher</div>
</div>`;
stub(window, 'fetch').callsFake(async (url) => {
if (url.includes('pep-prompt-content.plain.html')) return mockRes({ payload: pepPromptContent({ ...defaultConfig }) });
return null;
});
});

afterEach(() => {
sinon.restore();
clock.restore();
document.body.innerHTML = '';
document.cookie = `${document.cookie};expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
});

describe('PEP rendering tests', () => {
it('should render PEP', async () => {
await initPep({});
await clock.runAllAsync();
expect(document.querySelector(allSelectors.pepWrapper)).to.exist;
});

it('should not render PEP when previously dismissed', async () => {
document.cookie = 'dismissedAppPrompts=["pep-prompt-content.plain.html"]';
await initPep({});
await clock.runAllAsync();
expect(document.querySelector(allSelectors.pepWrapper)).to.not.exist;
});

it('should not render PEP when the entitlement does not match', async () => {
await initPep({ entName: 'not-matching-entitlement' });
await clock.runAllAsync();
expect(document.querySelector(allSelectors.pepWrapper)).to.not.exist;
});

it('should not render PEP when there is no prompt content', async () => {
sinon.restore();
stub(window, 'fetch').callsFake(async (url) => {
if (url.includes('pep-prompt-content.plain.html')) {
return mockRes({
payload: null,
ok: false,
status: 400,
});
}
return null;
});
await initPep({});
await clock.runAllAsync();
expect(document.querySelector(allSelectors.pepWrapper)).to.not.exist;
});

it('should not render PEP when the redirect url or product name are not provided', async () => {
sinon.restore();
stub(window, 'fetch').callsFake(async (url) => {
if (url.includes('pep-prompt-content.plain.html')) return mockRes({ payload: pepPromptContent({ ...defaultConfig, redirectUrl: false, productName: false }) });
return null;
});
await initPep({});
await clock.runAllAsync();
expect(document.querySelector(allSelectors.pepWrapper)).to.not.exist;
});

it('should not render PEP when the anchor element is open', async () => {
await initPep({ isAnchorOpen: true });
await clock.runAllAsync();
expect(document.querySelector(allSelectors.pepWrapper)).to.not.exist;
});
});

describe('PEP configuration tests', () => {
it('should use config values when metadata loader color or duration are not provided', async () => {
sinon.restore();
stub(window, 'fetch').callsFake(async (url) => {
if (url.includes('pep-prompt-content.plain.html')) return mockRes({ payload: pepPromptContent({ ...defaultConfig, color: false, loaderDuration: false }) });
return null;
});
const pep = await initPep({});
await clock.runAllAsync();
const { 'loader-color': pepColor, 'loader-duration': pepDuration } = pep.options;
expect(!!pepColor && !!pepDuration).to.equal(true);
});
});

describe('PEP interaction tests', () => {
it('should close PEP on Escape key', async () => {
await initPep({});
await clock.runAllAsync();
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }));
expect(document.querySelector(allSelectors.pepWrapper)).to.not.exist;
});

it('should close PEP on clicking the close icon', async () => {
await initPep({});
await clock.runAllAsync();
document.querySelector(allSelectors.closeIcon).click();
expect(document.querySelector(allSelectors.pepWrapper)).to.not.exist;
});

it('should close PEP on clicking the CTA', async () => {
await initPep({});
await clock.runAllAsync();
document.querySelector(allSelectors.cta).click();
expect(document.querySelector(allSelectors.pepWrapper)).to.not.exist;
});

it('should close PEP on clicking the anchor element', async () => {
await initPep({});
await clock.runAllAsync();
document.querySelector(allSelectors.appSwitcher).click();
expect(document.querySelector(allSelectors.pepWrapper)).to.not.exist;
});
});

describe('PEP focus tests', () => {
it('should focus on the close icon on initial render', async () => {
await initPep({});
await clock.runAllAsync();
expect(document.activeElement).to.equal(document.querySelector(allSelectors.closeIcon));
});

it('should focus on the anchor element after closing', async () => {
await initPep({});
await clock.runAllAsync();
document.querySelector(allSelectors.closeIcon).click();
expect(document.activeElement).to.equal(document.querySelector(allSelectors.appSwitcher));
});
});
});

0 comments on commit b247bb3

Please sign in to comment.