Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions preview/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@

return {
previewMode: metadata?.previewMode ?? null,
slot: metadata?.slotName ?? null,
Comment thread
winiciuskyutoku marked this conversation as resolved.
Resolved
audience: metadata?.audienceName ?? null,
experience: metadata?.experienceName ?? null,
experiment: metadata?.experimentName ?? null,
Expand All @@ -73,6 +74,10 @@
params.append('previewMode', previewInfo.previewMode);
}

if (previewInfo.slot !== null) {
params.append('slot', previewInfo.slot);
}

if (previewInfo.audience !== null) {
params.append('audience', previewInfo.audience);
}
Expand Down
14 changes: 14 additions & 0 deletions preview/src/widget.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@
<p id="preview-audience">Unknown</p>
</div>
</li>
<li>
<svg class="icon" aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="2" width="18" height="16" rx="1.5" stroke="currentColor" stroke-width="1.5"/>
<path d="M1 6.25H19" stroke="currentColor" stroke-width="1.5"/>
<circle cx="12.5" cy="4.1" r="0.9" fill="currentColor"/>
<circle cx="15.75" cy="4.1" r="0.9" fill="currentColor"/>
<path d="M8 8.5C8.3 10.3 9.2 11.2 11 11.5C9.2 11.8 8.3 12.7 8 14.5C7.7 12.7 6.8 11.8 5 11.5C6.8 11.2 7.7 10.3 8 8.5Z" fill="currentColor" stroke="currentColor" stroke-width="0.75" stroke-linejoin="round"/>
<path d="M13.5 12.5C13.65 13.4 14.1 13.85 15 14C14.1 14.15 13.65 14.6 13.5 15.5C13.35 14.6 12.9 14.15 12 14C12.9 13.85 13.35 13.4 13.5 12.5Z" fill="currentColor" stroke="currentColor" stroke-width="0.5" stroke-linejoin="round"/>
</svg>
<div class="description">
<div class="title">Slot</div>
<p id="preview-slot">Unknown</p>
</div>
</li>
<li>
<svg class="icon" aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.77214 1.09983C3.26456 0.614982 3.92974 0.344849 4.62069 0.344849H11.7931C12.0104 0.344849 12.2189 0.430289 12.3737 0.582724L17.7531 5.87928C17.911 6.03483 18 6.24727 18 6.46899V17.0621C18 17.754 17.7207 18.4149 17.2279 18.9002C16.7354 19.3851 16.0703 19.6552 15.3793 19.6552H4.62069C3.92974 19.6552 3.26456 19.3851 2.77214 18.9002C2.27928 18.4149 2 17.754 2 17.0621V2.93795C2 2.24604 2.27928 1.58511 2.77214 1.09983ZM4.62069 2.00002C4.36051 2.00002 4.11353 2.10191 3.93341 2.27925C3.75373 2.45617 3.65517 2.69337 3.65517 2.93795V17.0621C3.65517 17.3067 3.75373 17.5439 3.93341 17.7208C4.11353 17.8981 4.36051 18 4.62069 18H15.3793C15.6395 18 15.8865 17.8981 16.0666 17.7208C16.2463 17.5439 16.3448 17.3067 16.3448 17.0621V6.81555L11.4541 2.00002H4.62069Z" fill="currentColor"/>
Expand Down
40 changes: 36 additions & 4 deletions preview/src/widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,13 @@ window.addEventListener('DOMContentLoaded', () => {
.ready
.then(onLoad);

const slotContentLabels = {
slotDefaultContent: 'Default content',
fallbackContent: 'Fallback content',
};

function renderExperience(previewMode, experience) {
if(previewMode === 'slotDefaultContent') {
if (slotContentLabels[previewMode] !== undefined) {
document.getElementById('preview-experience')
.closest('li')
.remove();
Expand All @@ -103,8 +108,10 @@ window.addEventListener('DOMContentLoaded', () => {
}

function renderAudience(previewMode, audience) {
if(previewMode === 'slotDefaultContent') {
document.getElementById('preview-audience').textContent = 'None';
if (slotContentLabels[previewMode] !== undefined) {
document.getElementById('preview-audience')
.closest('li')
.remove();

return;
}
Expand All @@ -113,7 +120,17 @@ window.addEventListener('DOMContentLoaded', () => {
}

function renderExperiment(previewMode, variant, experiment) {
if (previewMode === 'slotDefaultContent' || experiment === null) {
if (slotContentLabels[previewMode] !== undefined) {
document.getElementById('preview-experiment')
.closest('li')
.remove();

document.getElementById('preview-content').textContent = slotContentLabels[previewMode];

return;
}

if (experiment === null) {
document.getElementById('preview-content')
.closest('li')
.remove();
Expand All @@ -132,6 +149,18 @@ window.addEventListener('DOMContentLoaded', () => {
}
}

function renderSlot(slot) {
if (slot === null) {
document.getElementById('preview-slot')
.closest('li')
.remove();

return;
}

document.getElementById('preview-slot').textContent = slot;
}

function renderLocale(locale) {
if (locale === null) {
document.getElementById('preview-locale')
Expand All @@ -157,6 +186,7 @@ window.addEventListener('DOMContentLoaded', () => {
const params = new URLSearchParams(window.location.search);

const previewMode = params.get('previewMode');
const slot = params.get('slot');
const experience = params.get('experience');
const audience = params.get('audience');
const experiment = params.get('experiment');
Expand All @@ -169,5 +199,7 @@ window.addEventListener('DOMContentLoaded', () => {

renderExperiment(previewMode, variant, experiment);

renderSlot(slot);

renderLocale(locale);
});
133 changes: 118 additions & 15 deletions preview/test/widget.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ test.describe('Preview widget', () => {

test('should expand clicking on the widget', async ({page}) => {
await open(page, {
previewMode: 'publishedContent',
experience: 'Experience',
experiment: 'Experiment',
audience: 'Audience',
Expand All @@ -47,16 +48,18 @@ test.describe('Preview widget', () => {
await expect(disclosure).toHaveAttribute('aria-expanded', 'true');
await expect(page.locator('#minimize-button')).toHaveAttribute('aria-expanded', 'true');

await expect(page.locator('#preview-experience')).toBeAttached();
await expect(page.locator('#preview-experience')).toHaveText('Experience');

await expect(page.locator('#preview-experiment')).toBeAttached();
await expect(page.locator('#preview-experiment')).toHaveText('Experiment');

await expect(page.locator('#preview-audience')).toBeAttached();
await expect(page.locator('#preview-audience')).toHaveText('Audience');

await expect(page.locator('#preview-content')).toBeAttached();
await expect(page.locator('#preview-content')).toHaveText('Variant');

await expect(page.locator('#preview-locale')).toBeAttached();

await expect(page.locator('#preview-slot')).not.toBeAttached();

await expect(page).toHaveScreenshot('widget-expanded.png');
});

Expand All @@ -78,9 +81,83 @@ test.describe('Preview widget', () => {
await expect(page).toHaveScreenshot('widget-truncated.png');
});

test('should not indicate any specific audience when previewing the default content', async ({page}) => {
test('should display the slot when previewing the default content', async ({page}) => {
Comment thread
winiciuskyutoku marked this conversation as resolved.
Resolved
await open(page, {
previewMode: 'slotDefaultContent',
slot: 'Home banner',
locale: 'en-us',
});

const disclosure = page.locator('#disclosure');

await disclosure.click();

await expect(disclosure).toHaveAttribute('aria-expanded', 'true');

await expect(page.locator('#preview-content')).toHaveText('Default content');

await expect(page.locator('#preview-slot')).toHaveText('Home banner');

await expect(page.locator('.options .title')).toHaveText(['Slot', 'Content', 'Locale']);

await expect(page.locator('#preview-audience')).not.toBeAttached();

await expect(page.locator('#preview-experience')).not.toBeAttached();

await expect(page.locator('#preview-experiment')).not.toBeAttached();

await expect(page).toHaveScreenshot('widget-slot-default-content.png');
});

test('should not display the slot if not specified when previewing the default content', async ({page}) => {
await open(page, {
previewMode: 'slotDefaultContent',
locale: 'en-us',
});

const disclosure = page.locator('#disclosure');

await disclosure.click();

await expect(disclosure).toHaveAttribute('aria-expanded', 'true');

await expect(page.locator('#preview-content')).toHaveText('Default content');

await expect(page.locator('#preview-slot')).not.toBeAttached();
});

test('should display the slot when previewing the fallback content', async ({page}) => {
await open(page, {
previewMode: 'fallbackContent',
slot: 'Home banner',
locale: 'en-us',
});

const disclosure = page.locator('#disclosure');

await disclosure.click();

await expect(disclosure).toHaveAttribute('aria-expanded', 'true');

await expect(page.locator('#preview-content')).toHaveText('Fallback content');

await expect(page.locator('#preview-slot')).toHaveText('Home banner');

await expect(page.locator('.options .title')).toHaveText(['Slot', 'Content', 'Locale']);

await expect(page.locator('#preview-audience')).not.toBeAttached();

await expect(page.locator('#preview-experience')).not.toBeAttached();

await expect(page.locator('#preview-experiment')).not.toBeAttached();

await expect(page).toHaveScreenshot('widget-slot-fallback-content.png');
});

test('should hide the experience when previewing the fallback content', async ({page}) => {
await open(page, {
previewMode: 'fallbackContent',
slot: 'Home banner',
experience: 'Experience',
experiment: 'Experiment',
audience: 'Audience',
Expand All @@ -94,15 +171,43 @@ test.describe('Preview widget', () => {

await expect(disclosure).toHaveAttribute('aria-expanded', 'true');

await expect(page.locator('#preview-audience')).toHaveText('None');

await expect(page.locator('#preview-experience')).not.toBeAttached();

await expect(page.locator('#preview-experiment')).not.toBeAttached();

await expect(page.locator('#preview-content')).not.toBeAttached();
await expect(page.locator('#preview-audience')).not.toBeAttached();

await expect(page).toHaveScreenshot('widget-slot-default-content.png');
await expect(page.locator('#preview-content')).toHaveText('Fallback content');

await expect(page.locator('.options .title')).toHaveText(['Slot', 'Content', 'Locale']);
});

test('should display the slot along with the experience when previewing the slot timeline', async ({page}) => {
await open(page, {
previewMode: 'slotTimeline',
slot: 'Home banner',
experience: 'Experience',
experiment: 'Experiment',
audience: 'Audience',
variant: 'Variant',
locale: 'en-us',
});

const disclosure = page.locator('#disclosure');

await disclosure.click();

await expect(disclosure).toHaveAttribute('aria-expanded', 'true');

await expect(page.locator('#preview-slot')).toHaveText('Home banner');

await expect(page.locator('#preview-experience')).toHaveText('Experience');

await expect(page.locator('#preview-audience')).toHaveText('Audience');

await expect(page.locator('#preview-experiment')).toHaveText('Experiment');

await expect(page.locator('#preview-content')).toHaveText('Variant');
});

test('should display the experiment default content if no variant is specified', async ({page}) => {
Expand Down Expand Up @@ -249,14 +354,12 @@ test.describe('Preview widget', () => {

await expect(page.locator('#disclosure')).toHaveAttribute('aria-expanded', 'true');

await expect.poll(() => events.length).toBeGreaterThan(0);

events.splice(0, events.length);

await page.locator('#leave-button').click();

await expect.poll(() => events.length).toBe(1);
const getLeaveEvents = (): WidgetEvent[] => events.filter(event => event.type === 'croct:preview:leave');

await expect.poll(() => getLeaveEvents().length).toBe(1);

expect(events[0].type).toEqual('croct:preview:leave');
expect(getLeaveEvents()).toEqual([{type: 'croct:preview:leave'}]);
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/plugins/preview/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type Configuration = {
export class PreviewPlugin implements Plugin {
private static readonly PREVIEW_PARAMS = {
previewMode: 'previewMode',
slotName: 'slot',
experienceName: 'experience',
experimentName: 'experiment',
audienceName: 'audience',
Expand Down
33 changes: 33 additions & 0 deletions test/plugins/preview/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ describe('A Preview plugin', () => {
const src = new URL(widget.getAttribute('src')!);

expect(src.searchParams.has('previewMode')).toBe(false);
expect(src.searchParams.has('slot')).toBe(false);
expect(src.searchParams.has('experience')).toBe(false);
expect(src.searchParams.has('experiment')).toBe(false);
expect(src.searchParams.has('audience')).toBe(false);
Expand Down Expand Up @@ -274,6 +275,38 @@ describe('A Preview plugin', () => {
expect(src.searchParams.get('audience')).toBe(metadata.audienceName);
expect(src.searchParams.get('variant')).toBe(metadata.variantName);
expect(src.searchParams.get('locale')).toBe(metadata.locale);
expect(src.searchParams.has('slot')).toBe(false);
});

it('should insert the widget with the slot information', () => {
const plugin = new PreviewPlugin(configuration);

const metadata = {
previewMode: 'slotDefaultContent',
slotId: '2e7ec10a-e27e-4269-9c16-3fc05271c817',
slotName: 'Home banner',
locale: 'en-us',
};

configuration.tokenStore.setToken(Token.of(tokenData.headers, {
...tokenData.payload,
metadata: metadata,
}));

plugin.enable();

const widget = document.body.querySelector('iframe') as HTMLIFrameElement;

const src = new URL(widget.getAttribute('src')!);

expect(src.searchParams.get('previewMode')).toBe(metadata.previewMode);
expect(src.searchParams.get('slot')).toBe(metadata.slotName);
expect(src.searchParams.get('locale')).toBe(metadata.locale);
expect(src.searchParams.has('slotId')).toBe(false);
expect(src.searchParams.has('experience')).toBe(false);
expect(src.searchParams.has('experiment')).toBe(false);
expect(src.searchParams.has('audience')).toBe(false);
expect(src.searchParams.has('variant')).toBe(false);
});

it('should insert the widget when the document is ready', () => {
Expand Down
Loading