@@ -33,8 +33,10 @@ const NavigationItemEditor = forwardRef
updateItem?.({label: e.target.value})}
onKeyDown={() => clearError?.('label')}
/>
@@ -47,8 +49,10 @@ const NavigationItemEditor = forwardRef updateItem?.({url: value})}
onKeyDown={() => clearError?.('url')}
/>
diff --git a/ghost/admin-x-settings/test/e2e/email/defaultRecipients.test.ts b/ghost/admin-x-settings/test/e2e/email/defaultRecipients.test.ts
index 04cd2c76d1..eea67ae8d7 100644
--- a/ghost/admin-x-settings/test/e2e/email/defaultRecipients.test.ts
+++ b/ghost/admin-x-settings/test/e2e/email/defaultRecipients.test.ts
@@ -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'}
diff --git a/ghost/admin-x-settings/test/e2e/email/mailgun.test.ts b/ghost/admin-x-settings/test/e2e/email/mailgun.test.ts
index 925ab1232d..b74b43cb8f 100644
--- a/ghost/admin-x-settings/test/e2e/email/mailgun.test.ts
+++ b/ghost/admin-x-settings/test/e2e/email/mailgun.test.ts
@@ -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'}
diff --git a/ghost/admin-x-settings/test/e2e/general/facebook.test.ts b/ghost/admin-x-settings/test/e2e/general/facebook.test.ts
index eb5b166236..9a32433dff 100644
--- a/ghost/admin-x-settings/test/e2e/general/facebook.test.ts
+++ b/ghost/admin-x-settings/test/e2e/general/facebook.test.ts
@@ -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'},
diff --git a/ghost/admin-x-settings/test/e2e/general/lockSite.test.ts b/ghost/admin-x-settings/test/e2e/general/lockSite.test.ts
index 24ed5303f0..96019611e0 100644
--- a/ghost/admin-x-settings/test/e2e/general/lockSite.test.ts
+++ b/ghost/admin-x-settings/test/e2e/general/lockSite.test.ts
@@ -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}
]
diff --git a/ghost/admin-x-settings/test/e2e/general/metadata.test.ts b/ghost/admin-x-settings/test/e2e/general/metadata.test.ts
index cc517b8702..159593f19a 100644
--- a/ghost/admin-x-settings/test/e2e/general/metadata.test.ts
+++ b/ghost/admin-x-settings/test/e2e/general/metadata.test.ts
@@ -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'}
diff --git a/ghost/admin-x-settings/test/e2e/general/publicationLanguage.test.ts b/ghost/admin-x-settings/test/e2e/general/publicationLanguage.test.ts
index 7cefc79ad7..0791ea8ea1 100644
--- a/ghost/admin-x-settings/test/e2e/general/publicationLanguage.test.ts
+++ b/ghost/admin-x-settings/test/e2e/general/publicationLanguage.test.ts
@@ -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'}
]
diff --git a/ghost/admin-x-settings/test/e2e/general/socialAccounts.test.ts b/ghost/admin-x-settings/test/e2e/general/socialAccounts.test.ts
index e6b70c2057..35443b2d90 100644
--- a/ghost/admin-x-settings/test/e2e/general/socialAccounts.test.ts
+++ b/ghost/admin-x-settings/test/e2e/general/socialAccounts.test.ts
@@ -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'}
diff --git a/ghost/admin-x-settings/test/e2e/general/timeZone.test.ts b/ghost/admin-x-settings/test/e2e/general/timeZone.test.ts
index 3e29a31873..a9bc88a51b 100644
--- a/ghost/admin-x-settings/test/e2e/general/timeZone.test.ts
+++ b/ghost/admin-x-settings/test/e2e/general/timeZone.test.ts
@@ -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'}
]
diff --git a/ghost/admin-x-settings/test/e2e/general/titleAndDescription.test.ts b/ghost/admin-x-settings/test/e2e/general/titleAndDescription.test.ts
index a0a334afc2..56802177d0 100644
--- a/ghost/admin-x-settings/test/e2e/general/titleAndDescription.test.ts
+++ b/ghost/admin-x-settings/test/e2e/general/titleAndDescription.test.ts
@@ -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'}
diff --git a/ghost/admin-x-settings/test/e2e/general/twitter.test.ts b/ghost/admin-x-settings/test/e2e/general/twitter.test.ts
index 389de30222..5f45eaf9b0 100644
--- a/ghost/admin-x-settings/test/e2e/general/twitter.test.ts
+++ b/ghost/admin-x-settings/test/e2e/general/twitter.test.ts
@@ -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'},
diff --git a/ghost/admin-x-settings/test/e2e/membership/access.test.ts b/ghost/admin-x-settings/test/e2e/membership/access.test.ts
index 11a42a4286..0c6916d5f5 100644
--- a/ghost/admin-x-settings/test/e2e/membership/access.test.ts
+++ b/ghost/admin-x-settings/test/e2e/membership/access.test.ts
@@ -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'},
diff --git a/ghost/admin-x-settings/test/e2e/membership/analytics.test.ts b/ghost/admin-x-settings/test/e2e/membership/analytics.test.ts
index f3775dc039..bbb0d1a1ac 100644
--- a/ghost/admin-x-settings/test/e2e/membership/analytics.test.ts
+++ b/ghost/admin-x-settings/test/e2e/membership/analytics.test.ts
@@ -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},
diff --git a/ghost/admin-x-settings/test/e2e/site/design.test.ts b/ghost/admin-x-settings/test/e2e/site/design.test.ts
index f19d14c4fd..91897109d3 100644
--- a/ghost/admin-x-settings/test/e2e/site/design.test.ts
+++ b/ghost/admin-x-settings/test/e2e/site/design.test.ts
@@ -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: 'homepage preview
'
}
@@ -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'}
]
});
});
diff --git a/ghost/admin-x-settings/test/e2e/site/navigation.test.ts b/ghost/admin-x-settings/test/e2e/site/navigation.test.ts
new file mode 100644
index 0000000000..12e2052b1b
--- /dev/null
+++ b/ghost/admin-x-settings/test/e2e/site/navigation.test.ts
@@ -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/');
+ });
+});
diff --git a/ghost/admin-x-settings/test/utils/e2e.ts b/ghost/admin-x-settings/test/utils/e2e.ts
index 135432836e..02f4b9157b 100644
--- a/ghost/admin-x-settings/test/utils/e2e.ts
+++ b/ghost/admin-x-settings/test/utils/e2e.ts
@@ -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 ?? 'test
'
- });
});
- return lastApiRequest;
+ await mockApiResponse({
+ page,
+ path: responseFixtures.site.site.url,
+ respondTo: {
+ POST: {
+ condition: request => !!request.headers()['x-ghost-preview'],
+ body: responses?.previewHtml?.homepage ?? 'test
',
+ 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,