mirror of
https://github.com/strapi/strapi.git
synced 2025-11-02 02:44:55 +00:00
test: add smoke test for settings menu (#19585)
Co-authored-by: RufusLeTerrible <MarionLemaire@users.noreply.github.com> Co-authored-by: Ben Irvin <ben@innerdvations.com> Co-authored-by: Ben Irvin <ben.irvin@strapi.io>
This commit is contained in:
parent
ed2f056a39
commit
6e80fa164c
66
tests/e2e/tests/settings/smoke-test.spec.ts
Normal file
66
tests/e2e/tests/settings/smoke-test.spec.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import { test } from '@playwright/test';
|
||||
|
||||
import { login } from '../../utils/login';
|
||||
import { describeOnCondition, navToHeader } from '../../utils/shared';
|
||||
import { resetDatabaseAndImportDataFromPath } from '../../utils/dts-import';
|
||||
|
||||
const edition = process.env.STRAPI_DISABLE_EE === 'true' ? 'CE' : 'EE';
|
||||
|
||||
test.describe('Settings', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await resetDatabaseAndImportDataFromPath('with-admin.tar');
|
||||
await page.goto('/admin');
|
||||
await login({ page });
|
||||
});
|
||||
|
||||
test('every expected feature is displayed', async ({ page }) => {
|
||||
await navToHeader(page, ['Settings'], 'Overview');
|
||||
|
||||
await navToHeader(page, ['Settings', 'API Tokens'], 'API Tokens');
|
||||
|
||||
await navToHeader(page, ['Settings', 'Documentation'], 'Documentation');
|
||||
|
||||
await navToHeader(page, ['Settings', 'Internationalization'], 'Internationalization');
|
||||
|
||||
await navToHeader(page, ['Settings', 'Media Library'], 'Media Library');
|
||||
|
||||
await navToHeader(page, ['Settings', 'Single Sign-On'], 'Single Sign-On');
|
||||
|
||||
await navToHeader(page, ['Settings', 'Transfer Tokens'], 'Transfer Tokens');
|
||||
|
||||
await navToHeader(page, ['Settings', 'Webhooks'], 'Webhooks');
|
||||
|
||||
// admin
|
||||
await navToHeader(page, ['Settings', ['Administration Panel', 'Roles']], 'Roles');
|
||||
|
||||
await navToHeader(page, ['Settings', ['Administration Panel', 'Users']], 'Users');
|
||||
|
||||
// u&p
|
||||
await navToHeader(page, ['Settings', ['Users & Permissions', 'Roles']], 'Roles');
|
||||
|
||||
await navToHeader(page, ['Settings', ['Users & Permissions', 'Providers']], 'Providers');
|
||||
|
||||
await navToHeader(
|
||||
page,
|
||||
['Settings', ['Users & Permissions', 'Email templates']],
|
||||
'Email templates'
|
||||
);
|
||||
|
||||
await navToHeader(
|
||||
page,
|
||||
['Settings', ['Users & Permissions', 'Advanced settings']],
|
||||
'Advanced settings'
|
||||
);
|
||||
|
||||
// EE features should still be displayed because they will show a "purchase" page
|
||||
await navToHeader(page, ['Settings', 'Review Workflows'], 'Review Workflows');
|
||||
await navToHeader(page, ['Settings', ['Administration Panel', 'Audit Logs']], 'Audit Logs');
|
||||
});
|
||||
|
||||
describeOnCondition(edition === 'EE')(() => {
|
||||
test('every EE feature is displayed', async ({ page }) => {
|
||||
await navToHeader(page, ['Settings', 'Review Workflows'], 'Review Workflows');
|
||||
await navToHeader(page, ['Settings', ['Administration Panel', 'Audit Logs']], 'Audit Logs');
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,27 +1,57 @@
|
||||
import { test, Page, expect } from '@playwright/test';
|
||||
import { test, expect, type Page, type Locator } from '@playwright/test';
|
||||
import { waitForRestart } from './restart';
|
||||
import pluralize from 'pluralize';
|
||||
import { kebabCase } from 'lodash/fp';
|
||||
|
||||
type NavItem = string | [string, string] | Locator;
|
||||
|
||||
/**
|
||||
* Execute a test suite only if the condition is true
|
||||
*/
|
||||
export const describeOnCondition = (shouldDescribe: boolean) =>
|
||||
shouldDescribe ? test.describe : test.describe.skip;
|
||||
|
||||
/**
|
||||
* Find an element in the dom after the previous element
|
||||
* Useful for narrowing down which link to click when there are multiple with the same name
|
||||
*/
|
||||
// TODO: instead of siblingText + linkText, accept an array of any number items
|
||||
export const locateFirstAfter = async (page: Page, firstText: string, secondText: string) => {
|
||||
// It first searches for text containing "firstText" then uses xpath `following` to find "secondText" after it.
|
||||
// `translate` is used to make the search case-insensitive
|
||||
const item = page
|
||||
.locator(
|
||||
`xpath=//text()[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), "${firstText.toLowerCase()}")]/following::a[starts-with(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), "${secondText.toLowerCase()}")]`
|
||||
)
|
||||
.first();
|
||||
|
||||
return item;
|
||||
};
|
||||
|
||||
/**
|
||||
* Navigate to a page and confirm the header, awaiting each step
|
||||
*/
|
||||
export const navToHeader = async (page: Page, navItems: string[], headerText: string) => {
|
||||
export const navToHeader = async (page: Page, navItems: NavItem[], headerText: string) => {
|
||||
for (const navItem of navItems) {
|
||||
// This does not use getByRole because sometimes "Settings" is "Settings 1" if there's a badge notification
|
||||
// BUT if we don't match exact it conflicts with "Advanceed Settings"
|
||||
// As a workaround, we implement our own startsWith with page.locator
|
||||
const item = page.locator(`role=link[name^="${navItem}"]`);
|
||||
// This handles some common issues
|
||||
// 1. Uses name^= to only ensure starts with, because for example badge notifications cause "Settings" to really be "Settings 1"
|
||||
// 2. To avoid duplicates, we accept a locator
|
||||
// 3. To avoid duplicates and writing complex locators, we accept an array to pass to locateFirstAfter, which matches item0 then finds the next item1 in the dom
|
||||
let item;
|
||||
if (typeof navItem === 'string') {
|
||||
item = page.locator(`role=link[name^="${navItem}"]`).last();
|
||||
} else if (Array.isArray(navItem)) {
|
||||
item = await locateFirstAfter(page, navItem[0], navItem[1]);
|
||||
} else {
|
||||
// it's a Locator
|
||||
item = navItem;
|
||||
}
|
||||
|
||||
await expect(item).toBeVisible();
|
||||
await item.click();
|
||||
}
|
||||
|
||||
// Verify header is correct
|
||||
const header = page.getByRole('heading', { name: headerText, exact: true });
|
||||
await expect(header).toBeVisible();
|
||||
return header;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user