0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-04-08 02:52:39 -05:00

Moved AdminX test config to framework package (#19096)

refs https://github.com/TryGhost/Product/issues/4180
This commit is contained in:
Jono M 2023-11-22 13:39:32 +00:00 committed by GitHub
parent cc6e881342
commit f19f32b132
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
76 changed files with 231 additions and 184 deletions

View file

@ -1,11 +1,11 @@
import {useEffect, useState} from 'react';
export interface PaginationMeta {
limit: number;
limit: number | 'all';
pages: number;
total: number;
next: number;
prev: number;
next: number | null;
prev: number | null;
}
export interface PaginationData {
@ -42,7 +42,7 @@ export const usePagination = ({limit, meta, page, setPage}: {meta?: PaginationMe
page,
setPage,
pages: prevMeta?.pages ?? null,
limit: prevMeta?.limit ?? limit,
limit: prevMeta?.limit && prevMeta.limit !== 'all' ? prevMeta.limit : limit,
total: prevMeta?.total ?? null,
nextPage: () => setPage(Math.min(page + 1, prevMeta?.pages ? prevMeta.pages : page)),
prevPage: () => setPage(Math.max(1, page - 1))

View file

@ -1,2 +1,2 @@
es
dist
types

View file

@ -7,32 +7,49 @@
"private": true,
"exports": {
".": {
"import": "./es/index.js",
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"types": "./types/index.d.ts"
},
"./errors": {
"import": "./es/errors.js",
"import": "./dist/errors.js",
"require": "./dist/errors.cjs",
"types": "./types/errors.d.ts"
},
"./helpers": {
"import": "./es/helpers.js",
"import": "./dist/helpers.js",
"require": "./dist/helpers.cjs",
"types": "./types/helpers.d.ts"
},
"./hooks": {
"import": "./es/hooks.js",
"import": "./dist/hooks.js",
"require": "./dist/hooks.cjs",
"types": "./types/hooks.d.ts"
},
"./routing": {
"import": "./es/routing.js",
"import": "./dist/routing.js",
"require": "./dist/routing.cjs",
"types": "./types/routing.d.ts"
},
"./api/*": {
"import": "./es/api/*.js",
"import": "./dist/api/*.js",
"require": "./dist/api/*.cjs",
"types": "./types/api/*.d.ts"
},
"./vite": {
"import": "./es/vite.js",
"import": "./dist/vite.js",
"require": "./dist/vite.cjs",
"types": "./types/vite.d.ts"
},
"./playwright": {
"import": "./dist/playwright.js",
"require": "./dist/playwright.cjs",
"types": "./types/playwright.d.ts"
},
"./test/*": {
"import": "./dist/test/*.js",
"require": "./dist/test/*.cjs",
"types": "./types/test/*.d.ts"
}
},
"sideEffects": false,

View file

@ -18,12 +18,12 @@ export type Action = {
id: string;
name: string;
slug: string;
image: string;
image: string|null;
},
resource?: {
id: string;
slug: string;
name: string;
name?: string;
title?: string;
}
@ -32,9 +32,13 @@ export type Action = {
};
export interface ActionsResponseType {
actions: Array<Omit<Action, 'context'> & {context: string}>;
meta: Meta;
}
export interface ActionsList {
actions: Action[];
meta: Meta;
isEnd: boolean;
}
@ -42,7 +46,7 @@ export interface ActionsResponseType {
const dataType = 'ActionsResponseType';
export const useBrowseActions = createInfiniteQuery<ActionsResponseType>({
export const useBrowseActions = createInfiniteQuery<ActionsList>({
dataType,
path: '/actions/',
returnData: (originalData) => {

View file

@ -17,7 +17,7 @@ export type Config = {
}
enableDeveloperExperiments: boolean;
database: string;
blogUrl: string;
blogUrl?: string;
labs: Record<string, boolean>;
stripeDirect: boolean;
mail: string;

View file

@ -10,7 +10,12 @@ export type Setting = {
value: SettingValue;
}
export type SettingsResponseMeta = Meta & { sent_email_verification?: boolean }
export type SettingsResponseMeta = Meta & {
filters?: {
group?: string;
};
sent_email_verification?: boolean;
}
export interface SettingsResponseType {
meta?: SettingsResponseMeta;

View file

@ -11,11 +11,11 @@ export type User = {
name: string;
slug: string;
email: string;
profile_image: string;
profile_image: string|null;
cover_image: string|null;
bio: string|null;
website: string;
location: string;
website: string|null;
location: string|null;
facebook: string|null;
twitter: string|null;
accessibility: string|null;

View file

@ -0,0 +1,62 @@
import {defineConfig, devices, PlaywrightTestConfig} from '@playwright/test';
export const E2E_PORT = 5173;
export default function adminXPlaywrightConfig(overrides: Partial<PlaywrightTestConfig> = {}) {
/**
* See https://playwright.dev/docs/test-configuration.
*/
return defineConfig({
testDir: './test/acceptance',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Hardcode to use all cores in CI */
workers: process.env.CI ? '100%' : (process.env.PLAYWRIGHT_SLOWMO ? 1 : undefined),
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
baseURL: `http://localhost:${E2E_PORT}`,
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
launchOptions: {
slowMo: parseInt(process.env.PLAYWRIGHT_SLOWMO ?? '') || 0,
// force GPU hardware acceleration
// (even in headless mode)
args: ['--use-gl=egl']
}
},
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: {...devices['Desktop Chrome']}
},
...(process.env.ALL_BROWSERS ? [{
name: 'firefox',
use: {...devices['Desktop Firefox']}
},
{
name: 'webkit',
use: {...devices['Desktop Safari']}
}] : [])
],
/* Run local dev server before starting the tests */
webServer: {
command: `yarn dev:start`,
url: `http://localhost:${E2E_PORT}`,
reuseExistingServer: !process.env.CI,
timeout: 10000
},
...overrides
});
}

View file

@ -1,19 +1,35 @@
import {ActionsResponseType} from '../../src/api/actions';
import {ConfigResponseType} from '../../src/api/config';
import {CustomThemeSettingsResponseType} from '../../src/api/customThemeSettings';
import {InvitesResponseType} from '../../src/api/invites';
import {LabelsResponseType} from '../../src/api/labels';
import {Locator, Page, expect} from '@playwright/test';
import {NewslettersResponseType} from '../../src/api/newsletters';
import {OffersResponseType} from '../../src/api/offers';
import {RecommendationResponseType} from '../../src/api/recommendations';
import {RolesResponseType} from '../../src/api/roles';
import {SettingsResponseType} from '../../src/api/settings';
import {SiteResponseType} from '../../src/api/site';
import {ThemesResponseType} from '../../src/api/themes';
import {TiersResponseType} from '../../src/api/tiers';
import {UsersResponseType} from '../../src/api/users';
import {readFileSync} from 'fs';
import actionsFixture from './responses/actions.json';
import configFixture from './responses/config.json';
import customThemeSettingsFixture from './responses/custom_theme_settings.json';
import incomingRecommendationsFixture from './responses/incoming_recommendations.json';
import invitesFixture from './responses/invites.json';
import labelsFixture from './responses/labels.json';
import meFixture from './responses/me.json';
import newslettersFixture from './responses/newsletters.json';
import offersFixture from './responses/offers.json';
import recommendationsFixture from './responses/recommendations.json';
import rolesFixture from './responses/roles.json';
import settingsFixture from './responses/settings.json';
import siteFixture from './responses/site.json';
import themesFixture from './responses/themes.json';
import tiersFixture from './responses/tiers.json';
import usersFixture from './responses/users.json';
import {ActionsResponseType} from '../api/actions';
import {ConfigResponseType} from '../api/config';
import {CustomThemeSettingsResponseType} from '../api/customThemeSettings';
import {InvitesResponseType} from '../api/invites';
import {LabelsResponseType} from '../api/labels';
import {NewslettersResponseType} from '../api/newsletters';
import {OffersResponseType} from '../api/offers';
import {IncomingRecommendationResponseType, RecommendationResponseType} from '../api/recommendations';
import {RolesResponseType} from '../api/roles';
import {SettingsResponseType} from '../api/settings';
import {ThemesResponseType} from '../api/themes';
import {TiersResponseType} from '../api/tiers';
import {UsersResponseType} from '../api/users';
interface MockRequestConfig {
method: string;
@ -28,29 +44,27 @@ interface RequestRecord {
headers?: {[key: string]: string}
}
const siteFixture = JSON.parse(readFileSync(`${__dirname}/responses/site.json`).toString()) as SiteResponseType;
export const responseFixtures = {
settings: JSON.parse(readFileSync(`${__dirname}/responses/settings.json`).toString()) as SettingsResponseType,
recommendations: JSON.parse(readFileSync(`${__dirname}/responses/recommendations.json`).toString()) as RecommendationResponseType,
incomingRecommendations: JSON.parse(readFileSync(`${__dirname}/responses/incoming_recommendations.json`).toString()) as RecommendationResponseType,
config: JSON.parse(readFileSync(`${__dirname}/responses/config.json`).toString()) as ConfigResponseType,
users: JSON.parse(readFileSync(`${__dirname}/responses/users.json`).toString()) as UsersResponseType,
me: JSON.parse(readFileSync(`${__dirname}/responses/me.json`).toString()) as UsersResponseType,
roles: JSON.parse(readFileSync(`${__dirname}/responses/roles.json`).toString()) as RolesResponseType,
settings: settingsFixture as SettingsResponseType,
recommendations: recommendationsFixture as RecommendationResponseType,
incomingRecommendations: incomingRecommendationsFixture as IncomingRecommendationResponseType,
config: configFixture as ConfigResponseType,
users: usersFixture as UsersResponseType,
me: meFixture as UsersResponseType,
roles: rolesFixture as RolesResponseType,
site: siteFixture,
invites: JSON.parse(readFileSync(`${__dirname}/responses/invites.json`).toString()) as InvitesResponseType,
customThemeSettings: JSON.parse(readFileSync(`${__dirname}/responses/custom_theme_settings.json`).toString()) as CustomThemeSettingsResponseType,
tiers: JSON.parse(readFileSync(`${__dirname}/responses/tiers.json`).toString()) as TiersResponseType,
labels: JSON.parse(readFileSync(`${__dirname}/responses/labels.json`).toString()) as LabelsResponseType,
offers: JSON.parse(readFileSync(`${__dirname}/responses/offers.json`).toString()) as OffersResponseType,
themes: JSON.parse(readFileSync(`${__dirname}/responses/themes.json`).toString()) as ThemesResponseType,
newsletters: JSON.parse(readFileSync(`${__dirname}/responses/newsletters.json`).toString()) as NewslettersResponseType,
actions: JSON.parse(readFileSync(`${__dirname}/responses/actions.json`).toString()) as ActionsResponseType,
invites: invitesFixture as InvitesResponseType,
customThemeSettings: customThemeSettingsFixture as CustomThemeSettingsResponseType,
tiers: tiersFixture as TiersResponseType,
labels: labelsFixture as LabelsResponseType,
offers: offersFixture as OffersResponseType,
themes: themesFixture as ThemesResponseType,
newsletters: newslettersFixture as NewslettersResponseType,
actions: actionsFixture as ActionsResponseType,
latestPost: {posts: [{id: '1', url: `${siteFixture.site.url}/test-post/`}]}
};
let defaultLabFlags = {
const defaultLabFlags = {
audienceFeedback: false,
collections: false,
themeErrorsNotification: false,
@ -213,7 +227,7 @@ export function meWithRole(name: string) {
};
export async function mockSitePreview({page, url, response}: {page: Page, url: string, response: string}) {
let lastRequest: {previewHeader?: string} = {};
const lastRequest: {previewHeader?: string} = {};
await page.route(url, async (route) => {
if (route.request().method() !== 'POST') {

View file

@ -8,7 +8,7 @@
"featured_image": "https://recommendation1.com/image.jpg",
"favicon": "https://recommendation1.com/favicon.ico",
"url": "https://recommendation1.com/",
"one_click_subscribe": "true",
"one_click_subscribe": true,
"created_at": "2023-10-28T20:00:00.000Z",
"updated_at": "2023-10-30T20:00:00.000Z",
"count": {
@ -24,7 +24,7 @@
"featured_image": "https://recommendation2.com/image.jpg",
"favicon": "https://recommendation2.com/favicon.ico",
"url": "https://recommendation2.com/",
"one_click_subscribe": "false",
"one_click_subscribe": false,
"created_at": "2023-10-28T20:00:00.000Z",
"updated_at": "2023-10-30T20:00:00.000Z",
"count": {

View file

@ -9,11 +9,11 @@ import {RequestOptions, apiUrl, useFetchApi} from './fetchApi';
export interface Meta {
pagination: {
page: number;
limit: number;
limit: number | 'all';
pages: number;
total: number;
next: number;
prev: number;
next: number | null;
prev: number | null;
}
}

View file

@ -17,9 +17,9 @@ export default (function viteConfig() {
reportCompressedSize: false,
minify: false,
sourcemap: true,
outDir: 'es',
outDir: 'dist',
lib: {
formats: ['es'],
formats: ['es', 'cjs'],
entry: glob.sync(resolve(__dirname, 'src/**/*.{ts,tsx}')).reduce((entries, path) => {
if (path.endsWith('.d.ts')) {
return entries;

View file

@ -0,0 +1,3 @@
import adminXPlaywrightConfig from '@tryghost/admin-x-framework/playwright';
export default adminXPlaywrightConfig();

View file

@ -1,58 +0,0 @@
import {defineConfig, devices} from '@playwright/test';
export const E2E_PORT = 5173;
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './test/acceptance',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Hardcode to use all cores in CI */
workers: process.env.CI ? '100%' : (process.env.PLAYWRIGHT_SLOWMO ? 1 : undefined),
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
baseURL: `http://localhost:${E2E_PORT}`,
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
launchOptions: {
slowMo: parseInt(process.env.PLAYWRIGHT_SLOWMO ?? '') || 0,
// force GPU hardware acceleration
// (even in headless mode)
args: ['--use-gl=egl']
}
},
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: {...devices['Desktop Chrome']}
},
...(process.env.ALL_BROWSERS ? [{
name: 'firefox',
use: {...devices['Desktop Firefox']}
},
{
name: 'webkit',
use: {...devices['Desktop Safari']}
}] : [])
],
/* Run local dev server before starting the tests */
webServer: {
command: `yarn dev:start`,
url: `http://localhost:${E2E_PORT}`,
reuseExistingServer: !process.env.CI,
timeout: 10000
}
});

View file

@ -27,7 +27,7 @@ const HistoryAvatar: React.FC<{action: Action}> = ({action}) => {
<div className='relative shrink-0'>
<Avatar
bgColor={generateAvatarColor(action.actor?.name || action.actor?.slug || '')}
image={action.actor?.image}
image={action.actor?.image ?? undefined}
label={getInitials(action.actor?.name || action.actor?.slug)}
labelColor='white'
size='md'

View file

@ -381,7 +381,7 @@ const UserDetailModalContent: React.FC<{user: User}> = ({user}) => {
id='avatar'
imageClassName='w-full h-full object-cover rounded-full shrink-0'
imageContainerClassName='relative group bg-cover bg-center -ml-2 h-[80px] w-[80px] shrink-0'
imageURL={formState.profile_image}
imageURL={formState.profile_image ?? undefined}
pintura={
{
isEnabled: editor.isEnabled,

View file

@ -42,7 +42,7 @@ const Owner: React.FC<OwnerProps> = ({user}) => {
return (
<div className={clsx('group flex gap-3', hasAdminAccess(currentUser) && 'cursor-pointer')} data-testid='owner-user' onClick={showDetailModal}>
<Avatar bgColor={generateAvatarColor((user.name ? user.name : user.email))} image={user.profile_image} label={getInitials(user.name)} labelColor='white' size='lg' />
<Avatar bgColor={generateAvatarColor((user.name ? user.name : user.email))} image={user.profile_image ?? undefined} label={getInitials(user.name)} labelColor='white' size='lg' />
<div className='flex flex-col'>
<span>{user.name} &mdash; <strong>Owner</strong> {hasAdminAccess(currentUser) && <button className='ml-2 inline-block text-sm font-bold text-green group-hover:visible md:invisible' type='button'>View profile</button>}</span>
<span className='text-xs text-grey-700'>{user.email}</span>
@ -83,7 +83,7 @@ const UsersList: React.FC<UsersListProps> = ({users, groupname}) => {
<ListItem
key={user.id}
action={canEdit && <Button color='green' label='Edit' link={true} onClick={() => showDetailModal(user)}/>}
avatar={(<Avatar bgColor={generateAvatarColor((user.name ? user.name : user.email))} image={user.profile_image} label={getInitials(user.name)} labelColor='white' />)}
avatar={(<Avatar bgColor={generateAvatarColor((user.name ? user.name : user.email))} image={user.profile_image ?? undefined} label={getInitials(user.name)} labelColor='white' />)}
bgOnHover={canEdit}
className='min-h-[64px]'
detail={user.email}

View file

@ -32,7 +32,7 @@ const Recommendations: React.FC<{ keywords: string[] }> = ({keywords}) => {
return;
}
const newPage = limit < 100 ? 1 : (page + 1);
const newPage = typeof limit === 'number' && limit < 100 ? 1 : (page + 1);
return {
...otherParams,
@ -65,7 +65,7 @@ const Recommendations: React.FC<{ keywords: string[] }> = ({keywords}) => {
return;
}
const newPage = limit < 100 ? 1 : (page + 1);
const newPage = typeof limit === 'number' && limit < 100 ? 1 : (page + 1);
return {
...otherParams,

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '../../utils/acceptance';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
// CodeMirror takes some time to load in Playwright meaning the first few characters typed don't always
// show up in the input. Since that lag is not consistent, this workaround ensures we type enough

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures} from '../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('History', async () => {
test('Browsing history', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures, updatedSettingsResponse} from '../../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('AMP integration', async () => {
test('Supports toggling and filling in AMP integration', async ({page}) => {

View file

@ -1,6 +1,6 @@
import {Integration, IntegrationsResponseType} from '../../../../src/api/integrations';
import {Webhook, WebhooksResponseType} from '../../../../src/api/webhooks';
import {chooseOptionInSelect, globalDataRequests, limitRequests, mockApi, responseFixtures} from '../../../utils/acceptance';
import {Integration, IntegrationsResponseType} from '@tryghost/admin-x-framework/api/integrations';
import {Webhook, WebhooksResponseType} from '@tryghost/admin-x-framework/api/webhooks';
import {chooseOptionInSelect, globalDataRequests, limitRequests, mockApi, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
import {expect, test} from '@playwright/test';
test.describe('Custom integrations', async () => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures, updatedSettingsResponse} from '../../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('First Promoter integration', async () => {
test('Supports toggling and filling in First Promoter integration', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '../../../utils/acceptance';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Pintura integration', async () => {
test('Can toggle Pintura', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures, updatedSettingsResponse} from '../../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Slack integration', async () => {
test('Supports updating Slack settings', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '../../../utils/acceptance';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Unsplash integration', async () => {
test('Supports toggling unsplash integration', async ({page}) => {

View file

@ -1,6 +1,6 @@
import {Integration, IntegrationsResponseType} from '../../../../src/api/integrations';
import {Integration, IntegrationsResponseType} from '@tryghost/admin-x-framework/api/integrations';
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures} from '../../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Zapier integration settings', async () => {
test('Showing and regenerating API keys', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi} from '../../utils/acceptance';
import {globalDataRequests, mockApi} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Labs', async () => {
test('Delete all content', async ({page}) => {

View file

@ -1,4 +1,4 @@
import {chooseOptionInSelect, globalDataRequests, mockApi, responseFixtures, updatedSettingsResponse} from '../../utils/acceptance';
import {chooseOptionInSelect, globalDataRequests, mockApi, responseFixtures, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
import {expect, test} from '@playwright/test';
test.describe('Default recipient settings', async () => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '../../utils/acceptance';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Mailgun settings', async () => {
test('Supports setting up mailgun', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {NewslettersResponseType} from '../../../src/api/newsletters';
import {chooseOptionInSelect, globalDataRequests, limitRequests, mockApi, responseFixtures} from '../../utils/acceptance';
import {NewslettersResponseType} from '@tryghost/admin-x-framework/api/newsletters';
import {chooseOptionInSelect, globalDataRequests, limitRequests, mockApi, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
import {expect, test} from '@playwright/test';
test.describe('Newsletter settings', async () => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures} from '../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Facebook settings', async () => {
test('Supports editing the facebook card', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '../../utils/acceptance';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Site password settings', async () => {
test('Supports locking and unlocking the site', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '../../utils/acceptance';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Metadata settings', async () => {
test('Supports editing metadata', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '../../utils/acceptance';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Publication language settings', async () => {
test('Supports editing the locale', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, testUrlValidation, updatedSettingsResponse} from '../../utils/acceptance';
import {globalDataRequests, mockApi, testUrlValidation, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Social account settings', async () => {
test('Supports editing social URLs', async ({page}) => {

View file

@ -1,4 +1,4 @@
import {chooseOptionInSelect, globalDataRequests, mockApi, updatedSettingsResponse} from '../../utils/acceptance';
import {chooseOptionInSelect, globalDataRequests, mockApi, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
import {expect, test} from '@playwright/test';
test.describe('Time zone settings', async () => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '../../utils/acceptance';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Title and description settings', async () => {
test('Supports editing the title and description', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures} from '../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Twitter settings', async () => {
test('Supports editing the twitter card', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, limitRequests, mockApi, responseFixtures} from '../../../utils/acceptance';
import {globalDataRequests, limitRequests, mockApi, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('User actions', async () => {
test('Supports suspending a user', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, limitRequests, mockApi, responseFixtures} from '../../../utils/acceptance';
import {globalDataRequests, limitRequests, mockApi, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('User invitations', async () => {
test('Supports inviting a user', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures} from '../../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('User passwords', async () => {
test('Supports changing password', async ({page}) => {

View file

@ -1,6 +1,6 @@
import {StaffTokenResponseType} from '../../../../src/api/staffToken';
import {StaffTokenResponseType} from '@tryghost/admin-x-framework/api/staffToken';
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures, testUrlValidation} from '../../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures, testUrlValidation} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('User profile', async () => {
test('Supports editing user profiles', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, meWithRole, mockApi, responseFixtures} from '../../../utils/acceptance';
import {globalDataRequests, meWithRole, mockApi, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('User roles', async () => {
test('Shows users under their role', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi} from '../utils/acceptance';
import {globalDataRequests, mockApi} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Layout', async () => {
test('Confirms when leaving if a section is dirty', async ({page}) => {

View file

@ -1,4 +1,4 @@
import {chooseOptionInSelect, globalDataRequests, mockApi, responseFixtures, updatedSettingsResponse} from '../../utils/acceptance';
import {chooseOptionInSelect, globalDataRequests, mockApi, responseFixtures, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
import {expect, test} from '@playwright/test';
test.describe('Access settings', async () => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '../../utils/acceptance';
import {globalDataRequests, mockApi, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Analytics settings', async () => {
test('Supports toggling analytics settings', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures, settingsWithStripe, toggleLabsFlag} from '../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures, settingsWithStripe, toggleLabsFlag} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Offers Modal', () => {
test.beforeEach(async () => {
@ -32,7 +32,7 @@ test.describe('Offers Modal', () => {
const modal = page.getByTestId('offers-modal');
await expect(modal).toContainText('Active offers');
await expect(modal).toContainText('First offer');
await expect(modal).toContainText('Second offer');
await expect(modal).toContainText('Second offer');
});
test('Can view archived offers', async ({page}) => {
@ -49,7 +49,7 @@ test.describe('Offers Modal', () => {
const modal = page.getByTestId('offers-modal');
await modal.getByText('Archived').click();
await expect(modal).toContainText('Archived offers');
await expect(modal).toContainText('Third offer');
await expect(modal).toContainText('Third offer');
});
test('Supports updating an offer', async ({page}) => {
@ -57,11 +57,11 @@ test.describe('Offers Modal', () => {
...globalDataRequests,
browseSettings: {...globalDataRequests.browseSettings, response: settingsWithStripe},
browseOffers: {method: 'GET', path: '/offers/?limit=all', response: responseFixtures.offers},
browseOffersById: {method: 'GET', path: `/offers/${responseFixtures.offers.offers[0].id}/`, response: responseFixtures.offers},
browseOffersById: {method: 'GET', path: `/offers/${responseFixtures.offers.offers![0].id}/`, response: responseFixtures.offers},
browseTiers: {method: 'GET', path: '/tiers/', response: responseFixtures.tiers},
editOffer: {method: 'PUT', path: `/offers/${responseFixtures.offers.offers[0].id}/`, response: {
editOffer: {method: 'PUT', path: `/offers/${responseFixtures.offers.offers![0].id}/`, response: {
offers: [{
id: responseFixtures.offers.offers[0].id,
id: responseFixtures.offers.offers![0].id,
name: 'Updated offer',
body_font_category: 'sans_serif'
}]
@ -73,7 +73,7 @@ test.describe('Offers Modal', () => {
await section.getByRole('button', {name: 'Manage offers'}).click();
const modal = page.getByTestId('offers-modal');
await expect(modal).toContainText('Active offers');
await expect(modal).toContainText('First offer');
await expect(modal).toContainText('First offer');
await modal.getByText('First offer').click();
const offerUpdateModal = page.getByTestId('offer-update-modal');
@ -91,7 +91,7 @@ test.describe('Offers Modal', () => {
expect(lastApiRequests.editOffer?.body).toMatchObject({
offers: [{
id: responseFixtures.offers.offers[0].id,
id: responseFixtures.offers.offers![0].id,
name: 'First offer',
code: 'black-friday-offer'
}]

View file

@ -1,6 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, mockSitePreview} from '../../utils/acceptance';
import {responseFixtures} from '../../utils/acceptance';
import {globalDataRequests, mockApi, mockSitePreview, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Portal Settings', async () => {
test('Loads Portal Preview Modal', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures, toggleLabsFlag} from '../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures, toggleLabsFlag} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Recommendations', async () => {
test.beforeEach(async () => {
@ -174,6 +174,7 @@ test.describe('Recommendations', async () => {
expect(confirmation).toContainText('Your recommendation Recommendation 1 title will no longer be visible to your audience.');
await confirmation.getByRole('button', {name: 'Delete'}).click();
await expect(page.getByTestId('toast-success')).toContainText('deleted the recommendation');
expect(lastApiRequests.deleteRecommendation).toBeTruthy();
});

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures, updatedSettingsResponse} from '../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures, updatedSettingsResponse} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Stripe settings', async () => {
test('Supports the Stripe Connect flow', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures, settingsWithStripe} from '../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures, settingsWithStripe} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Tier settings', async () => {
test('Supports creating a new tier', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, meWithRole, mockApi, responseFixtures} from '../utils/acceptance';
import {globalDataRequests, meWithRole, mockApi, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('User permissions', async () => {
test('Editors can only see users', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi} from '../utils/acceptance';
import {globalDataRequests, mockApi} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Routing', async () => {
test('Reopens the opened modal when refreshing the page', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi} from '../utils/acceptance';
import {globalDataRequests, mockApi} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Search', async () => {
test('Hiding and showing groups based on the search term', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, mockSitePreview, responseFixtures} from '../../utils/acceptance';
import {ElementHandle, expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, mockSitePreview, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Announcement Bar', async () => {
test('Working with the announcement bar preview', async ({page}) => {
@ -26,7 +26,7 @@ test.describe('Announcement Bar', async () => {
await page.waitForSelector('[data-testid="announcement-bar-preview-iframe"]');
const checkTextInIframes = async (iframesHandles, textToSearch) => {
const checkTextInIframes = async (iframesHandles: ElementHandle[], textToSearch: string) => {
let textExists = false;
for (const iframeHandle of iframesHandles) {
const frame = await iframeHandle.contentFrame();

View file

@ -1,4 +1,4 @@
import {chooseOptionInSelect, globalDataRequests, mockApi, mockSitePreview, responseFixtures} from '../../utils/acceptance';
import {chooseOptionInSelect, globalDataRequests, mockApi, mockSitePreview, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
import {expect, test} from '@playwright/test';
test.describe('Design settings', async () => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, mockApi, responseFixtures} from '../../utils/acceptance';
import {globalDataRequests, mockApi, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Navigation settings', async () => {
test('Editing primary and secondary navigation', async ({page}) => {

View file

@ -1,5 +1,5 @@
import {expect, test} from '@playwright/test';
import {globalDataRequests, limitRequests, mockApi, responseFixtures} from '../../utils/acceptance';
import {globalDataRequests, limitRequests, mockApi, responseFixtures} from '@tryghost/admin-x-framework/test/acceptance';
test.describe('Theme settings', async () => {
test('Browsing and installing default themes', async ({page}) => {

View file

@ -1,5 +1,5 @@
import * as assert from 'assert/strict';
import {CustomThemeSetting} from '../../../src/api/customThemeSettings';
import {CustomThemeSetting} from '@tryghost/admin-x-framework/api/customThemeSettings';
import {isCustomThemeSettingVisible} from '../../../src/utils/isCustomThemeSettingsVisible';
describe('isCustomThemeSettingVisible', function () {

View file

@ -19,5 +19,5 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
"include": ["src", "test"]
}