mirror of
https://github.com/strapi/strapi.git
synced 2026-05-03 16:22:30 +00:00
test(e2e): add update components tests and update playwright (#22033)
This commit is contained in:
@@ -195,7 +195,7 @@ jobs:
|
||||
uses: ./.github/actions/yarn-nm-install
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: npx playwright@1.42.1 install --with-deps
|
||||
run: npx playwright install --with-deps
|
||||
|
||||
- name: Monorepo build
|
||||
uses: ./.github/actions/run-build
|
||||
@@ -209,7 +209,7 @@ jobs:
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: ce-${{ matrix.project }}--playwright-trace
|
||||
name: ce-${{ matrix.project }}--playwright-trace-${{ github.run_id }}-${{ github.job }}
|
||||
path: test-apps/e2e/test-results/**/trace.zip
|
||||
retention-days: 1
|
||||
|
||||
@@ -239,7 +239,7 @@ jobs:
|
||||
uses: ./.github/actions/yarn-nm-install
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: npx playwright@1.42.1 install --with-deps
|
||||
run: npx playwright install --with-deps
|
||||
|
||||
- name: Monorepo build
|
||||
uses: ./.github/actions/run-build
|
||||
@@ -254,7 +254,7 @@ jobs:
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: ee-${{ matrix.project }}--playwright-trace
|
||||
name: ee-${{ matrix.project }}--playwright-trace-${{ github.run_id }}-${{ github.job }}
|
||||
path: test-apps/e2e/test-results/**/trace.zip
|
||||
retention-days: 1
|
||||
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@
|
||||
"@commitlint/cli": "19.2.0",
|
||||
"@commitlint/config-conventional": "19.1.0",
|
||||
"@commitlint/prompt-cli": "19.2.0",
|
||||
"@playwright/test": "1.42.1",
|
||||
"@playwright/test": "1.48.2",
|
||||
"@strapi/admin-test-utils": "workspace:*",
|
||||
"@strapi/eslint-config": "0.2.0",
|
||||
"@swc/cli": "0.3.10",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { test, expect, type Page } from '@playwright/test';
|
||||
import { describeOnCondition } from '../../utils/shared';
|
||||
import { clickAndWait, describeOnCondition } from '../../utils/shared';
|
||||
import { resetDatabaseAndImportDataFromPath } from '../../utils/dts-import';
|
||||
import { login } from '../../utils/login';
|
||||
import { findAndClose } from '../../utils/shared';
|
||||
@@ -56,9 +56,9 @@ describeOnCondition(edition === 'EE')('Release page', () => {
|
||||
await addEntryToRelease({ page, releaseName });
|
||||
|
||||
// Publish the release
|
||||
await page.getByRole('link', { name: 'Releases' }).click();
|
||||
await page.getByRole('link', { name: `${releaseName}` }).click();
|
||||
await page.getByRole('button', { name: 'Publish' }).click();
|
||||
await clickAndWait(page, page.getByRole('link', { name: 'Releases' }));
|
||||
await clickAndWait(page, page.getByRole('link', { name: `${releaseName}` }));
|
||||
await clickAndWait(page, page.getByRole('button', { name: 'Publish', exact: true }));
|
||||
await expect(page.getByRole('heading', { name: releaseName })).toBeVisible();
|
||||
|
||||
// Check the already released release
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { resetFiles } from '../../../utils/file-reset';
|
||||
import { sharedSetup } from '../../../utils/setup';
|
||||
import {
|
||||
createComponent,
|
||||
createSingleType,
|
||||
createCollectionType,
|
||||
addAttributeToComponent,
|
||||
removeAttributeFromComponent,
|
||||
deleteComponent,
|
||||
type AddAttribute,
|
||||
} from '../../../utils/content-types';
|
||||
import { navToHeader } from '../../../utils/shared';
|
||||
|
||||
test.describe('Update a new component', () => {
|
||||
// very long timeout for these tests because they restart the server multiple times
|
||||
test.describe.configure({ timeout: 300000 });
|
||||
|
||||
const originalAttributes = [{ type: 'text', name: 'testtext' }] satisfies AddAttribute[];
|
||||
|
||||
const addedAttribute = {
|
||||
type: 'text',
|
||||
name: 'addedtext',
|
||||
};
|
||||
|
||||
const componentAttributeName = 'mycomponentname';
|
||||
|
||||
const singleType = {
|
||||
attributes: [
|
||||
{
|
||||
component: {
|
||||
useExisting: 'SomeComponent',
|
||||
options: {
|
||||
name: componentAttributeName,
|
||||
},
|
||||
},
|
||||
type: 'component',
|
||||
name: componentAttributeName,
|
||||
},
|
||||
],
|
||||
name: 'Singletypepage',
|
||||
};
|
||||
|
||||
const collectionType = {
|
||||
attributes: [
|
||||
{
|
||||
component: {
|
||||
useExisting: 'SomeComponent',
|
||||
options: {
|
||||
name: componentAttributeName,
|
||||
},
|
||||
},
|
||||
type: 'component',
|
||||
name: componentAttributeName,
|
||||
},
|
||||
],
|
||||
name: 'Mycollectiontype',
|
||||
};
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await sharedSetup('update-component', page, {
|
||||
resetFiles: true,
|
||||
importData: 'with-admin.tar',
|
||||
login: true,
|
||||
skipTour: true,
|
||||
afterSetup: async () => {
|
||||
const options = {
|
||||
name: 'SomeComponent',
|
||||
categoryCreate: 'BlogPosts',
|
||||
icon: 'paint',
|
||||
attributes: originalAttributes,
|
||||
};
|
||||
|
||||
await createComponent(page, options);
|
||||
|
||||
// https://github.com/strapi/strapi/issues/21943
|
||||
// Until that's fixed we have to manually navigate away
|
||||
await navToHeader(page, ['Content Manager', 'Homepage'], 'Homepage');
|
||||
await navToHeader(page, ['Content-Type Builder'], 'Article');
|
||||
|
||||
await createCollectionType(page, collectionType);
|
||||
|
||||
await createSingleType(page, singleType);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await resetFiles();
|
||||
});
|
||||
|
||||
test('Add attribute to component', async ({ page }) => {
|
||||
await addAttributeToComponent(page, 'SomeComponent', addedAttribute);
|
||||
|
||||
// confirm that it exists in the content type this component was in
|
||||
await navToHeader(page, ['Content-Type Builder', collectionType.name], collectionType.name);
|
||||
await expect(page.getByText(addedAttribute.name, { exact: true })).toBeVisible();
|
||||
|
||||
// confirm that it exists in the single type this component was in
|
||||
await navToHeader(page, ['Content-Type Builder', singleType.name], singleType.name);
|
||||
await expect(page.getByText(addedAttribute.name, { exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
test('Remove attribute from component', async ({ page }) => {
|
||||
const removedAttribute = originalAttributes[0];
|
||||
// confirm that it initially exists in the content type this component was in
|
||||
await navToHeader(page, ['Content-Type Builder', collectionType.name], collectionType.name);
|
||||
await expect(page.getByText(removedAttribute.name, { exact: true })).toBeVisible();
|
||||
|
||||
// confirm that it initially exists in the single type this component was in
|
||||
await navToHeader(page, ['Content-Type Builder', singleType.name], singleType.name);
|
||||
await expect(page.getByText(removedAttribute.name, { exact: true })).toBeVisible();
|
||||
|
||||
await removeAttributeFromComponent(page, 'SomeComponent', removedAttribute.name);
|
||||
|
||||
// confirm that it no longer exists in the content type this component was in
|
||||
await navToHeader(page, ['Content-Type Builder', collectionType.name], collectionType.name);
|
||||
await expect(page.getByText(removedAttribute.name, { exact: true })).not.toBeVisible();
|
||||
|
||||
// confirm that it no longer exists in the single type this component was in
|
||||
await navToHeader(page, ['Content-Type Builder', singleType.name], singleType.name);
|
||||
await expect(page.getByText(removedAttribute.name, { exact: true })).not.toBeVisible();
|
||||
});
|
||||
|
||||
test('delete component', async ({ page }) => {
|
||||
// confirm it exists in collection type
|
||||
await navToHeader(page, ['Content-Type Builder', collectionType.name], collectionType.name);
|
||||
await expect(page.getByText(componentAttributeName, { exact: true })).toBeVisible();
|
||||
|
||||
// confirm it exists in single type
|
||||
await navToHeader(page, ['Content-Type Builder', singleType.name], singleType.name);
|
||||
await expect(page.getByText(componentAttributeName, { exact: true })).toBeVisible();
|
||||
|
||||
// confirm it exists in navigation
|
||||
await expect(page.getByRole('link', { name: 'SomeComponent' })).toBeVisible();
|
||||
|
||||
// delete it
|
||||
await deleteComponent(page, 'SomeComponent');
|
||||
|
||||
// TODO: fix issue that components aren't removed from side navigation or content types until refresh
|
||||
await page.reload({ waitUntil: 'networkidle' });
|
||||
|
||||
// confirm that it no longer exists in the content type this component was in
|
||||
await navToHeader(page, ['Content-Type Builder', collectionType.name], collectionType.name);
|
||||
await expect(page.getByText(componentAttributeName, { exact: true })).not.toBeVisible();
|
||||
|
||||
// confirm that it no longer exists in the single type this component was in
|
||||
await navToHeader(page, ['Content-Type Builder', singleType.name], singleType.name);
|
||||
await expect(page.getByText(componentAttributeName, { exact: true })).not.toBeVisible();
|
||||
|
||||
// confirm that is not longer exists in the navigation
|
||||
await expect(page.getByRole('link', { name: 'SomeComponent' })).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -373,3 +373,46 @@ export const createSingleType = async (page: Page, options: CreateContentTypeOpt
|
||||
export const createCollectionType = async (page: Page, options: CreateContentTypeOptions) => {
|
||||
await createContentType(page, options, 'collection');
|
||||
};
|
||||
|
||||
export const addAttributeToComponent = async (
|
||||
page: Page,
|
||||
componentName: string,
|
||||
attribute: AddAttribute
|
||||
) => {
|
||||
await clickAndWait(page, page.getByRole('link', { name: 'Content-Type Builder' }));
|
||||
await clickAndWait(page, page.getByRole('link', { name: componentName }));
|
||||
await clickAndWait(
|
||||
page,
|
||||
page.getByRole('button', { name: 'Add another field to this component' })
|
||||
);
|
||||
await addAttributes(page, [attribute]);
|
||||
|
||||
await saveAndVerifyContent(page, {
|
||||
name: componentName,
|
||||
attributes: [attribute],
|
||||
});
|
||||
};
|
||||
|
||||
export const removeAttributeFromComponent = async (
|
||||
page: Page,
|
||||
componentName: string,
|
||||
attributeName: string
|
||||
) => {
|
||||
await clickAndWait(page, page.getByRole('link', { name: 'Content-Type Builder' }));
|
||||
await clickAndWait(page, page.getByRole('link', { name: componentName }));
|
||||
await clickAndWait(page, page.getByRole('button', { name: 'Delete ' + attributeName }));
|
||||
|
||||
await saveAndVerifyContent(page, { name: componentName, attributes: [] });
|
||||
};
|
||||
|
||||
export const deleteComponent = async (page: Page, componentName: string) => {
|
||||
await clickAndWait(page, page.getByRole('link', { name: 'Content-Type Builder' }));
|
||||
await clickAndWait(page, page.getByRole('link', { name: componentName }));
|
||||
await clickAndWait(page, page.getByRole('button', { name: 'Edit', exact: true }));
|
||||
|
||||
// need to accept the browser modal
|
||||
page.on('dialog', (dialog) => dialog.accept());
|
||||
await clickAndWait(page, page.getByRole('button', { name: 'Delete', exact: true }));
|
||||
|
||||
await waitForRestart(page);
|
||||
};
|
||||
|
||||
@@ -4587,14 +4587,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@playwright/test@npm:1.42.1":
|
||||
version: 1.42.1
|
||||
resolution: "@playwright/test@npm:1.42.1"
|
||||
"@playwright/test@npm:1.48.2":
|
||||
version: 1.48.2
|
||||
resolution: "@playwright/test@npm:1.48.2"
|
||||
dependencies:
|
||||
playwright: "npm:1.42.1"
|
||||
playwright: "npm:1.48.2"
|
||||
bin:
|
||||
playwright: cli.js
|
||||
checksum: 10c0/e5d7c1ffedabb934643edb010038edcb70d51d224fb6444844a854d94365a6179d4407a83da176cae37ccd42b62c148843e0b6f9b4c6506048e06558c00d4267
|
||||
checksum: 10c0/68bab3bee8d716111e9a166785e6c3c406b6a184fc46d03b5468fcbb92b6242e5628f6a75f9d286e2491ec0e9e59af67542a1f114b6659d790b5a1f41e4d305b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -24435,27 +24435,27 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"playwright-core@npm:1.42.1":
|
||||
version: 1.42.1
|
||||
resolution: "playwright-core@npm:1.42.1"
|
||||
"playwright-core@npm:1.48.2":
|
||||
version: 1.48.2
|
||||
resolution: "playwright-core@npm:1.48.2"
|
||||
bin:
|
||||
playwright-core: cli.js
|
||||
checksum: 10c0/9bb0be6defa32eb1b01429615f10c2ad17dcf701656c081a250369c1eb3b0dcc2a0ee21188cd653cdd2303ca73ff94df0d270b178fe3897eba274793dab368ce
|
||||
checksum: 10c0/511da53d9df01fec5e5798915c68e7d1574890a504d1aae05430bf538d0080efa8db86e3dafdcd450f084ce7622f6bbede23ca52e798bfc4c3b3ea8da52a51f5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"playwright@npm:1.42.1":
|
||||
version: 1.42.1
|
||||
resolution: "playwright@npm:1.42.1"
|
||||
"playwright@npm:1.48.2":
|
||||
version: 1.48.2
|
||||
resolution: "playwright@npm:1.48.2"
|
||||
dependencies:
|
||||
fsevents: "npm:2.3.2"
|
||||
playwright-core: "npm:1.42.1"
|
||||
playwright-core: "npm:1.48.2"
|
||||
dependenciesMeta:
|
||||
fsevents:
|
||||
optional: true
|
||||
bin:
|
||||
playwright: cli.js
|
||||
checksum: 10c0/91dcbfe92d75ca9eb4bfff69bb1ec28007b5a96f6187f48e52aa0f6acf8c24f6039ed6467c152964cc92f4ab64b85dc665b13c52b2fb9f7b9182ddb9db404e37
|
||||
checksum: 10c0/ecde4ee4767556868b24d7700f3502692a3cb14c8ef127052b51b48833ffcce80942954fb188a9b72505122b48b1b625d1bb486721e1c4f2e980215328ba1ad5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -27392,7 +27392,7 @@ __metadata:
|
||||
"@commitlint/cli": "npm:19.2.0"
|
||||
"@commitlint/config-conventional": "npm:19.1.0"
|
||||
"@commitlint/prompt-cli": "npm:19.2.0"
|
||||
"@playwright/test": "npm:1.42.1"
|
||||
"@playwright/test": "npm:1.48.2"
|
||||
"@strapi/admin-test-utils": "workspace:*"
|
||||
"@strapi/eslint-config": "npm:0.2.0"
|
||||
"@swc/cli": "npm:0.3.10"
|
||||
|
||||
Reference in New Issue
Block a user