0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-25 02:31:59 -05:00

Added tests for AdminX navigation settings (#17109)

- Updated test request records to be distinct per API call
- Updated design tests to check preview data
- Added tests for navigation settings

refs https://github.com/TryGhost/Team/issues/3349
This commit is contained in:
Jono M 2023-06-23 20:16:01 +12:00 committed by GitHub
parent 5a1dcbc9a5
commit 2d6e988017
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 275 additions and 85 deletions

View file

@ -44,6 +44,7 @@ const NavigationModal = NiceModal.create(() => {
scrolling={true}
size='lg'
stickyFooter={true}
testId='navigation-modal'
title='Navigation'
onOk={async () => {
if (navigation.validate() && secondaryNavigation.validate()) {

View file

@ -108,10 +108,11 @@ const NavigationEditForm: React.FC<{
</DndContext>
<NavigationItemEditor
action={<Button color='green' icon="add" iconColorClass='text-white' size='sm' onClick={navigation.addItem} />}
action={<Button color='green' data-testid="add-button" icon="add" iconColorClass='text-white' size='sm' onClick={navigation.addItem} />}
baseUrl={baseUrl}
clearError={key => navigation.clearError(navigation.newItem.id, key)}
containerClasses="flex items-start gap-3 p-2"
data-testid="new-navigation-item"
dragHandleClasses="ml-2 invisible"
item={navigation.newItem}
labelPlaceholder="New item label"

View file

@ -21,7 +21,7 @@ export type NavigationItemEditorProps = React.HTMLAttributes<HTMLDivElement> & {
const NavigationItemEditor = forwardRef<HTMLDivElement, NavigationItemEditorProps>(function NavigationItemEditor({baseUrl, item, updateItem, onDelete, clearError, dragHandleProps, labelPlaceholder, unstyled, containerClasses, dragHandleClasses, textFieldClasses, action, ...props}, ref) {
return (
<div ref={ref} className={containerClasses} {...props}>
<div ref={ref} className={containerClasses} data-testid='navigation-item-editor' {...props}>
<button className={dragHandleClasses} type='button' {...dragHandleProps}>
<Icon colorClass='text-grey-500' name='hamburger' size='sm' />
</button>
@ -33,8 +33,10 @@ const NavigationItemEditor = forwardRef<HTMLDivElement, NavigationItemEditorProp
hint={item.errors.label}
hintClassName="px-2"
placeholder={labelPlaceholder}
title='Label'
unstyled={unstyled}
value={item.label}
hideTitle
onChange={e => updateItem?.({label: e.target.value})}
onKeyDown={() => clearError?.('label')}
/>
@ -47,8 +49,10 @@ const NavigationItemEditor = forwardRef<HTMLDivElement, NavigationItemEditorProp
error={!!item.errors.url}
hint={item.errors.url}
hintClassName="px-2"
title='URL'
unstyled={unstyled}
value={item.url}
hideTitle
onChange={value => updateItem?.({url: value})}
onKeyDown={() => clearError?.('url')}
/>

View file

@ -3,7 +3,7 @@ import {mockApi, updatedSettingsResponse} from '../../utils/e2e';
test.describe('Default recipient settings', async () => {
test('Supports editing default recipients', async ({page}) => {
const lastApiRequest = await mockApi({page, responses: {
const lastApiRequests = await mockApi({page, responses: {
settings: {
edit: updatedSettingsResponse([
{key: 'editor_default_email_recipients', value: 'filter'},
@ -22,7 +22,7 @@ test.describe('Default recipient settings', async () => {
await section.getByLabel('Default newsletter recipients').selectOption('All members');
await section.getByRole('button', {name: 'Save'}).click();
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'editor_default_email_recipients', value: 'filter'},
{key: 'editor_default_email_recipients_filter', value: 'status:free,status:-free'}
@ -33,7 +33,7 @@ test.describe('Default recipient settings', async () => {
await section.getByLabel('Default newsletter recipients').selectOption('Usually nobody');
await section.getByRole('button', {name: 'Save'}).click();
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'editor_default_email_recipients', value: 'filter'},
{key: 'editor_default_email_recipients_filter', value: null}
@ -48,7 +48,7 @@ test.describe('Default recipient settings', async () => {
await expect(section.getByText('Paid-members only')).toHaveCount(1);
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'editor_default_email_recipients', value: 'filter'},
{key: 'editor_default_email_recipients_filter', value: 'status:-free'}

View file

@ -3,7 +3,7 @@ import {mockApi, updatedSettingsResponse} from '../../utils/e2e';
test.describe('Mailgun settings', async () => {
test('Supports setting up mailgun', async ({page}) => {
const lastApiRequest = await mockApi({page, responses: {
const lastApiRequests = await mockApi({page, responses: {
settings: {
edit: updatedSettingsResponse([
{key: 'mailgun_domain', value: 'test.com'},
@ -29,7 +29,7 @@ test.describe('Mailgun settings', async () => {
await expect(section.getByText('Mailgun is set up')).toHaveCount(1);
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'mailgun_domain', value: 'test.com'},
{key: 'mailgun_api_key', value: 'test'}

View file

@ -3,7 +3,7 @@ import {mockApi} from '../../utils/e2e';
test.describe('Facebook settings', async () => {
test('Supports editing the facebook card', async ({page}) => {
const lastApiRequest = await mockApi({page, responses: {
const lastApiRequests = await mockApi({page, responses: {
images: {
upload: {images: [{url: 'http://example.com/image.png', ref: null}]}
}
@ -31,7 +31,7 @@ test.describe('Facebook settings', async () => {
await expect(section.getByLabel('Facebook title')).toHaveCount(0);
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'og_image', value: 'http://example.com/image.png'},
{key: 'og_title', value: 'Facetitle'},

View file

@ -3,7 +3,7 @@ import {mockApi, updatedSettingsResponse} from '../../utils/e2e';
test.describe('Site password settings', async () => {
test('Supports locking and unlocking the site', async ({page}) => {
let lastApiRequest = await mockApi({page, responses: {
let lastApiRequests = await mockApi({page, responses: {
settings: {
edit: updatedSettingsResponse([
{key: 'is_private', value: true},
@ -31,7 +31,7 @@ test.describe('Site password settings', async () => {
await expect(section.getByText('Your site is password protected')).toHaveCount(1);
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'is_private', value: true},
{key: 'password', value: 'password'}
@ -40,7 +40,7 @@ test.describe('Site password settings', async () => {
// Remove the site password
lastApiRequest = await mockApi({page, responses: {
lastApiRequests = await mockApi({page, responses: {
settings: {
edit: updatedSettingsResponse([
{key: 'is_private', value: false}
@ -56,7 +56,7 @@ test.describe('Site password settings', async () => {
await expect(section.getByText('Your site is not password protected')).toHaveCount(1);
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'is_private', value: false}
]

View file

@ -3,7 +3,7 @@ import {mockApi, updatedSettingsResponse} from '../../utils/e2e';
test.describe('Metadata settings', async () => {
test('Supports editing metadata', async ({page}) => {
const lastApiRequest = await mockApi({page, responses: {
const lastApiRequests = await mockApi({page, responses: {
settings: {
edit: updatedSettingsResponse([
{key: 'meta_title', value: 'Alternative title'},
@ -31,7 +31,7 @@ test.describe('Metadata settings', async () => {
await expect(section.getByText('Alternative title')).toHaveCount(1);
await expect(section.getByText('Alternative description')).toHaveCount(1);
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'meta_title', value: 'Alternative title'},
{key: 'meta_description', value: 'Alternative description'}

View file

@ -3,7 +3,7 @@ import {mockApi, updatedSettingsResponse} from '../../utils/e2e';
test.describe('Publication language settings', async () => {
test('Supports editing the locale', async ({page}) => {
const lastApiRequest = await mockApi({page, responses: {
const lastApiRequests = await mockApi({page, responses: {
settings: {
edit: updatedSettingsResponse([
{key: 'locale', value: 'jp'}
@ -27,7 +27,7 @@ test.describe('Publication language settings', async () => {
await expect(section.getByText('jp')).toHaveCount(1);
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'locale', value: 'jp'}
]

View file

@ -3,7 +3,7 @@ import {mockApi, updatedSettingsResponse} from '../../utils/e2e';
test.describe('Social account settings', async () => {
test('Supports editing social URLs', async ({page}) => {
const lastApiRequest = await mockApi({page, responses: {
const lastApiRequests = await mockApi({page, responses: {
settings: {
edit: updatedSettingsResponse([
{key: 'facebook', value: 'fb'},
@ -31,7 +31,7 @@ test.describe('Social account settings', async () => {
await expect(section.getByText('https://www.facebook.com/fb')).toHaveCount(1);
await expect(section.getByText('https://twitter.com/tw')).toHaveCount(1);
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'facebook', value: 'fb'},
{key: 'twitter', value: '@tw'}

View file

@ -3,7 +3,7 @@ import {mockApi, updatedSettingsResponse} from '../../utils/e2e';
test.describe('Time zone settings', async () => {
test('Supports editing the time zone', async ({page}) => {
const lastApiRequest = await mockApi({page, responses: {
const lastApiRequests = await mockApi({page, responses: {
settings: {
edit: updatedSettingsResponse([
{key: 'timezone', value: 'Asia/Tokyo'}
@ -27,7 +27,7 @@ test.describe('Time zone settings', async () => {
await expect(section.getByText('Asia/Tokyo')).toHaveCount(1);
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'timezone', value: 'Asia/Tokyo'}
]

View file

@ -3,7 +3,7 @@ import {mockApi, updatedSettingsResponse} from '../../utils/e2e';
test.describe('Title and description settings', async () => {
test('Supports editing the title and description', async ({page}) => {
const lastApiRequest = await mockApi({page, responses: {
const lastApiRequests = await mockApi({page, responses: {
settings: {
edit: updatedSettingsResponse([
{key: 'title', value: 'New Site Title'},
@ -31,7 +31,7 @@ test.describe('Title and description settings', async () => {
await expect(section.getByText('New Site Title')).toHaveCount(1);
await expect(section.getByText('New Site Description')).toHaveCount(1);
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'title', value: 'New Site Title'},
{key: 'description', value: 'New Site Description'}

View file

@ -3,7 +3,7 @@ import {mockApi} from '../../utils/e2e';
test.describe('Twitter settings', async () => {
test('Supports editing the twitter card', async ({page}) => {
const lastApiRequest = await mockApi({page, responses: {
const lastApiRequests = await mockApi({page, responses: {
images: {
upload: {images: [{url: 'http://example.com/image.png', ref: null}]}
}
@ -31,7 +31,7 @@ test.describe('Twitter settings', async () => {
await expect(section.getByLabel('Twitter title')).toHaveCount(0);
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'twitter_image', value: 'http://example.com/image.png'},
{key: 'twitter_title', value: 'Twititle'},

View file

@ -3,7 +3,7 @@ import {mockApi, updatedSettingsResponse} from '../../utils/e2e';
test.describe('Access settings', async () => {
test('Supports editing access', async ({page}) => {
const lastApiRequest = await mockApi({page, responses: {
const lastApiRequests = await mockApi({page, responses: {
settings: {
edit: updatedSettingsResponse([
{key: 'default_content_visibility', value: 'members'},
@ -35,7 +35,7 @@ test.describe('Access settings', async () => {
await expect(section.getByText('Members only')).toHaveCount(1);
await expect(section.getByText('All members')).toHaveCount(1);
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'default_content_visibility', value: 'members'},
{key: 'members_signup_access', value: 'invite'},

View file

@ -3,7 +3,7 @@ import {mockApi, updatedSettingsResponse} from '../../utils/e2e';
test.describe('Analytics settings', async () => {
test('Supports toggling analytics settings', async ({page}) => {
const lastApiRequest = await mockApi({page, responses: {
const lastApiRequests = await mockApi({page, responses: {
settings: {
edit: updatedSettingsResponse([
{key: 'members_track_sources', value: false},
@ -30,7 +30,7 @@ test.describe('Analytics settings', async () => {
await section.getByRole('button', {name: 'Save'}).click();
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'members_track_sources', value: false},
{key: 'email_track_opens', value: false},

View file

@ -1,9 +1,9 @@
import {expect, test} from '@playwright/test';
import {mockApi} from '../../utils/e2e';
test.describe('Theme settings', async () => {
test.describe('Design settings', async () => {
test('Editing brand settings', async ({page}) => {
const lastApiRequest = await mockApi({page, responses: {
const lastApiRequests = await mockApi({page, responses: {
previewHtml: {
homepage: '<html><head><style></style></head><body><div>homepage preview</div></body></html>'
}
@ -24,7 +24,9 @@ test.describe('Theme settings', async () => {
await expect(modal).not.toBeVisible();
expect(lastApiRequest.body).toEqual({
expect(lastApiRequests.previewHtml.homepage.headers?.['x-ghost-preview']).toMatch(/&d=new\+description&/);
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'description', value: 'new description'}
]
@ -32,7 +34,24 @@ test.describe('Theme settings', async () => {
});
test('Editing custom theme settings', async ({page}) => {
const lastApiRequest = await mockApi({page});
const lastApiRequests = await mockApi({page, responses: {
custom_theme_settings: {
browse: {
custom_theme_settings: [{
type: 'select',
options: [
'Logo on cover',
'Logo in the middle',
'Stacked'
],
default: 'Logo on cover',
id: '648047658d265b0c8b33c591',
value: 'Stacked',
key: 'navigation_layout'
}]
}
}
}});
await page.goto('/');
@ -49,13 +68,13 @@ test.describe('Theme settings', async () => {
await expect(modal).not.toBeVisible();
expect(lastApiRequest.body).toMatchObject({
const expectedSettings = {navigation_layout: 'Logo in the middle'};
const expectedEncoded = new URLSearchParams([['custom', JSON.stringify(expectedSettings)]]).toString();
expect(lastApiRequests.previewHtml.homepage.headers?.['x-ghost-preview']).toMatch(new RegExp(`&${expectedEncoded.replace(/\+/g, '\\+')}`));
expect(lastApiRequests.custom_theme_settings.edit.body).toMatchObject({
custom_theme_settings: [
{key: 'navigation_color'},
{key: 'navigation_background_image'},
{key: 'navigation_layout', value: 'Logo in the middle'},
{key: 'show_publication_cover'},
{key: 'email_signup_text'}
{key: 'navigation_layout', value: 'Logo in the middle'}
]
});
});

View file

@ -0,0 +1,123 @@
import {expect, test} from '@playwright/test';
import {mockApi} from '../../utils/e2e';
test.describe('Navigation settings', async () => {
test('Editing primary and secondary navigation', async ({page}) => {
const lastApiRequests = await mockApi({page});
await page.goto('/');
const section = page.getByTestId('navigation');
await section.getByRole('button', {name: 'Customize'}).click();
const modal = page.getByTestId('navigation-modal');
const primaryNavigationTab = modal.getByRole('tabpanel').first();
const primaryItem = primaryNavigationTab.getByTestId('navigation-item-editor').first();
await primaryItem.getByLabel('Label').fill('existing item label');
await primaryItem.getByLabel('URL').fill('/existing');
await primaryNavigationTab.getByTestId('new-navigation-item').getByLabel('Label').fill('new item label');
await primaryNavigationTab.getByTestId('new-navigation-item').getByLabel('URL').fill('/new');
await primaryNavigationTab.getByTestId('new-navigation-item').getByLabel('URL').blur();
await modal.getByRole('tab').last().click();
const secondaryNavigationTab = modal.getByRole('tabpanel').last();
const secondaryItem = secondaryNavigationTab.getByTestId('navigation-item-editor').first();
await secondaryItem.getByLabel('Label').fill('existing item 2');
await secondaryItem.getByLabel('URL').fill('/existing2');
await secondaryNavigationTab.getByTestId('new-navigation-item').getByLabel('Label').fill('new item 2');
await secondaryNavigationTab.getByTestId('new-navigation-item').getByLabel('URL').press('Backspace');
await secondaryNavigationTab.getByTestId('new-navigation-item').getByLabel('URL').fill('https://google.com');
await secondaryNavigationTab.getByTestId('new-navigation-item').getByLabel('URL').blur();
await modal.getByRole('button', {name: 'OK'}).click();
await expect(modal).not.toBeVisible();
expect(lastApiRequests.settings.edit.body).toEqual({
settings: [
{key: 'navigation', value: '[{"url":"/existing/","label":"existing item label"},{"url":"/about/","label":"About"},{"url":"/new/","label":"new item label"}]'},
{key: 'secondary_navigation', value: '[{"url":"/existing2/","label":"existing item 2"},{"url":"https://google.com","label":"new item 2"}]'}
]
});
});
test('Existing item validations', async ({page}) => {
await mockApi({page});
await page.goto('/');
const section = page.getByTestId('navigation');
await section.getByRole('button', {name: 'Customize'}).click();
const modal = page.getByTestId('navigation-modal');
const primaryNavigationTab = modal.getByRole('tabpanel').first();
const primaryItem = primaryNavigationTab.getByTestId('navigation-item-editor').first();
await primaryItem.getByLabel('Label').fill('');
await primaryItem.getByLabel('URL').press('Backspace');
await primaryItem.getByLabel('URL').fill('google.com');
await modal.getByRole('button', {name: 'OK'}).click();
await expect(primaryItem.getByText('You must specify a label')).toHaveCount(1);
await expect(primaryItem.getByText('You must specify a valid URL or relative path')).toHaveCount(1);
await primaryItem.getByLabel('Label').press('A');
await expect(primaryItem.getByText('You must specify a label')).toHaveCount(0);
// The error should hide whenever the user types even if the URL is still not valid
await primaryItem.getByLabel('URL').press('A');
await expect(primaryItem.getByText('You must specify a valid URL or relative path')).toHaveCount(0);
});
test('Adding a new item', async ({page}) => {
await mockApi({page});
await page.goto('/');
const section = page.getByTestId('navigation');
await section.getByRole('button', {name: 'Customize'}).click();
const modal = page.getByTestId('navigation-modal');
const primaryNavigationTab = modal.getByRole('tabpanel').first();
await expect(primaryNavigationTab.getByTestId('navigation-item-editor')).toHaveCount(2);
const newItem = primaryNavigationTab.getByTestId('new-navigation-item');
await newItem.getByLabel('Label').fill('');
await newItem.getByLabel('URL').press('Backspace');
await newItem.getByLabel('URL').fill('google.com');
await newItem.getByTestId('add-button').click();
await expect(newItem.getByText('You must specify a label')).toHaveCount(1);
await expect(newItem.getByText('You must specify a valid URL or relative path')).toHaveCount(1);
await newItem.getByLabel('Label').press('A');
await expect(newItem.getByText('You must specify a label')).toHaveCount(0);
// The error should hide whenever the user types even if the URL is still not valid
await newItem.getByLabel('URL').press('A');
await expect(newItem.getByText('You must specify a valid URL or relative path')).toHaveCount(0);
await newItem.getByLabel('Label').fill('Label');
await newItem.getByLabel('URL').fill('https://google.com');
await newItem.getByTestId('add-button').click();
await expect(primaryNavigationTab.getByTestId('navigation-item-editor')).toHaveCount(3);
await expect(primaryNavigationTab.getByTestId('navigation-item-editor').last().getByLabel('Label')).toHaveValue('Label');
await expect(primaryNavigationTab.getByTestId('navigation-item-editor').last().getByLabel('URL')).toHaveValue('https://google.com/');
await expect(newItem.getByLabel('Label')).toHaveValue('');
await expect(newItem.getByLabel('URL')).toHaveValue('http://test.com/');
});
});

View file

@ -1,11 +1,6 @@
import {Page} from '@playwright/test';
import {Page, Request} from '@playwright/test';
import {readFileSync} from 'fs';
type LastApiRequest = {
url: null | string
body: null | any
};
const responseFixtures = {
settings: JSON.parse(readFileSync(`${__dirname}/responses/settings.json`).toString()),
site: JSON.parse(readFileSync(`${__dirname}/responses/site.json`).toString()),
@ -27,85 +22,132 @@ interface Responses {
browse?: any
edit?: any
}
previewHtml: {
previewHtml?: {
homepage?: string
}
}
interface RequestRecord {
url?: string
body?: any
headers?: {[key: string]: string}
}
type LastRequests = {
settings: {
browse: RequestRecord
edit: RequestRecord
}
site: {
browse: RequestRecord
}
images: {
upload: RequestRecord
}
custom_theme_settings: {
browse: RequestRecord
edit: RequestRecord
}
previewHtml: {
homepage: RequestRecord
}
};
export async function mockApi({page,responses}: {page: Page, responses?: Responses}) {
const lastApiRequest: LastApiRequest = {
url: null,
body: null
const lastApiRequests: LastRequests = {
settings: {browse: {}, edit: {}},
site: {browse: {}},
images: {upload: {}},
custom_theme_settings: {browse: {}, edit: {}},
previewHtml: {homepage: {}}
};
await mockApiResponse({
page,
path: /\/ghost\/api\/admin\/settings\//,
responses: {
GET: {body: responses?.settings?.browse ?? responseFixtures.settings},
PUT: {body: responses?.settings?.edit ?? responseFixtures.settings}
},
lastApiRequest
respondTo: {
GET: {
body: responses?.settings?.browse ?? responseFixtures.settings,
updateLastRequest: lastApiRequests.settings.browse
},
PUT: {
body: responses?.settings?.edit ?? responseFixtures.settings,
updateLastRequest: lastApiRequests.settings.edit
}
}
});
await mockApiResponse({
page,
path: /\/ghost\/api\/admin\/site\//,
responses: {
GET: {body: responses?.site?.browse ?? responseFixtures.site}
},
lastApiRequest
respondTo: {
GET: {
body: responses?.site?.browse ?? responseFixtures.site,
updateLastRequest: lastApiRequests.site.browse
}
}
});
await mockApiResponse({
page,
path: /\/ghost\/api\/admin\/images\/upload\/$/,
responses: {
POST: {body: responses?.images?.upload ?? {images: [{url: 'http://example.com/image.png', ref: null}]}}
},
lastApiRequest
respondTo: {
POST: {
body: responses?.images?.upload ?? {images: [{url: 'http://example.com/image.png', ref: null}]},
updateLastRequest: lastApiRequests.images.upload
}
}
});
await mockApiResponse({
page,
path: /\/ghost\/api\/admin\/custom_theme_settings\/$/,
responses: {
GET: {body: responses?.custom_theme_settings?.browse ?? responseFixtures.custom_theme_settings},
PUT: {body: responses?.custom_theme_settings?.edit ?? responseFixtures.custom_theme_settings}
},
lastApiRequest
});
await page.route(responseFixtures.site.site.url, async (route) => {
if (!route.request().headers()['x-ghost-preview']) {
return route.continue();
respondTo: {
GET: {
body: responses?.custom_theme_settings?.browse ?? responseFixtures.custom_theme_settings,
updateLastRequest: lastApiRequests.custom_theme_settings.browse
},
PUT: {
body: responses?.custom_theme_settings?.edit ?? responseFixtures.custom_theme_settings,
updateLastRequest: lastApiRequests.custom_theme_settings.edit
}
}
await route.fulfill({
status: 200,
body: responses?.previewHtml?.homepage ?? '<html><head><style></style></head><body><div>test</div></body></html>'
});
});
return lastApiRequest;
await mockApiResponse({
page,
path: responseFixtures.site.site.url,
respondTo: {
POST: {
condition: request => !!request.headers()['x-ghost-preview'],
body: responses?.previewHtml?.homepage ?? '<html><head><style></style></head><body><div>test</div></body></html>',
updateLastRequest: lastApiRequests.previewHtml.homepage
}
}
});
return lastApiRequests;
}
interface MockResponse {
interface ResponseOptions {
condition?: (request: Request) => boolean
body: any
status?: number
updateLastRequest: RequestRecord
}
async function mockApiResponse({page, path, lastApiRequest, responses}: { page: Page; path: string | RegExp; lastApiRequest: LastApiRequest, responses: { [method: string]: MockResponse } }) {
async function mockApiResponse({page, path, respondTo}: { page: Page; path: string | RegExp; respondTo: { [method: string]: ResponseOptions } }) {
await page.route(path, async (route) => {
const response = responses[route.request().method()];
const response = respondTo[route.request().method()];
if (!response) {
if (!response || (response.condition && !response.condition(route.request()))) {
return route.continue();
}
const requestBody = JSON.parse(route.request().postData() || 'null');
lastApiRequest.body = requestBody;
lastApiRequest.url = route.request().url();
response.updateLastRequest.body = requestBody;
response.updateLastRequest.url = route.request().url();
response.updateLastRequest.headers = route.request().headers();
await route.fulfill({
status: response.status || 200,