mirror of
https://github.com/strapi/strapi.git
synced 2025-12-27 15:13:21 +00:00
test(e2e): text fields advanced settings (#22635)
This commit is contained in:
parent
a4bb06d54b
commit
7f7cfa5b39
@ -81,7 +81,7 @@ const createConfig = ({ port, testDir, appDir }) => ({
|
||||
/* Default time each action such as `click()` can take */
|
||||
actionTimeout: getEnvNum(process.env.PLAYWRIGHT_ACTION_TIMEOUT, 10 * 1000),
|
||||
// Only record trace when retrying a test to optimize test performance
|
||||
trace: 'on-first-retry',
|
||||
trace: process.env.CI ? 'on-first-retry' : 'retain-on-failure',
|
||||
video: getEnvBool(process.env.PLAYWRIGHT_VIDEO, false)
|
||||
? {
|
||||
mode: 'on-first-retry', // Only save videos when retrying a test
|
||||
|
||||
@ -24,7 +24,9 @@ test.describe('Adding content', () => {
|
||||
name: 'testrepeatablecomp2',
|
||||
icon: 'moon',
|
||||
categorySelect: 'product',
|
||||
attributes: [{ type: 'text', name: 'testrepeatablecomp2text' }],
|
||||
attributes: [
|
||||
{ type: 'text', name: 'testrepeatablecomp2text', advanced: { required: true } },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -37,7 +39,9 @@ test.describe('Adding content', () => {
|
||||
name: 'testsinglecomp2',
|
||||
icon: 'moon',
|
||||
categorySelect: 'product',
|
||||
attributes: [{ type: 'text', name: 'testsinglecomp2text' }],
|
||||
attributes: [
|
||||
{ type: 'text', name: 'testsinglecomp2text', advanced: { required: true } },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -55,7 +59,13 @@ test.describe('Adding content', () => {
|
||||
name: 'testnewcomponentrepeatable',
|
||||
icon: 'moon',
|
||||
categorySelect: 'product',
|
||||
attributes: [{ type: 'text', name: 'testnewcomponentexistingcategorytext' }],
|
||||
attributes: [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'testnewcomponentexistingcategorytext',
|
||||
advanced: { required: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -151,4 +161,35 @@ test.describe('Adding content', () => {
|
||||
const before = await isElementBefore(source, target);
|
||||
expect(before).toBe(true);
|
||||
});
|
||||
|
||||
// TODO: can this become a loop to test every field? might work best to have a create where every first attempt to enter an attribute is made without a name
|
||||
test('when I publish an empty required text field inside a dz I see an error', async ({
|
||||
page,
|
||||
}) => {
|
||||
const fields = [
|
||||
{
|
||||
name: 'testdz',
|
||||
type: 'dz',
|
||||
value: [
|
||||
{
|
||||
category: 'product',
|
||||
name: 'newcomponentexistingcategory',
|
||||
fields: [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'testnewcomponentexistingcategorytext',
|
||||
value: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
] satisfies FieldValue[];
|
||||
|
||||
await createContent(page, 'Article', fields, { save: false, publish: true, verify: false });
|
||||
|
||||
// TODO: check that aria-invalid=true for this input
|
||||
|
||||
expect(page.getByText('This value is required')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
@ -194,12 +194,12 @@ export const createContent = async (
|
||||
|
||||
if (options.save) {
|
||||
await clickAndWait(page, page.getByRole('button', { name: 'Save' }));
|
||||
await findAndClose(page, 'Saved Document');
|
||||
await findAndClose(page, 'Saved Document', { required: options.verify });
|
||||
}
|
||||
|
||||
if (options.publish) {
|
||||
await clickAndWait(page, page.getByRole('button', { name: 'Publish' }));
|
||||
await findAndClose(page, 'Published Document');
|
||||
await findAndClose(page, 'Published Document', { required: options.verify });
|
||||
}
|
||||
|
||||
if (options.verify) {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { kebabCase } from 'lodash/fp';
|
||||
import { isBoolean, kebabCase } from 'lodash/fp';
|
||||
import { waitForRestart } from './restart';
|
||||
import pluralize from 'pluralize';
|
||||
import { expect, type Page } from '@playwright/test';
|
||||
import { clickAndWait, findByRowColumn, navToHeader } from './shared';
|
||||
import { expect, Locator, type Page } from '@playwright/test';
|
||||
import { clickAndWait, ensureCheckbox, findByRowColumn, navToHeader } from './shared';
|
||||
|
||||
export interface AddAttribute {
|
||||
type: string;
|
||||
@ -364,7 +364,15 @@ export const fillAttribute = async (page: Page, attribute: AddAttribute, options
|
||||
await page.locator('textarea[name="enum"]').fill(attribute.enumeration?.values.join('\n'));
|
||||
}
|
||||
|
||||
// TODO: add support for advanced options
|
||||
if (attribute.advanced) {
|
||||
const adv = attribute.advanced;
|
||||
await page.getByText('Advanced Settings').click();
|
||||
|
||||
if (isBoolean(adv.required)) {
|
||||
const checkbox = page.getByRole('checkbox', { name: 'Required field' });
|
||||
await ensureCheckbox(checkbox, adv.required);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const addAttributes = async (
|
||||
|
||||
@ -84,15 +84,22 @@ export const clickAndWait = async (page: Page, locator: Locator) => {
|
||||
/**
|
||||
* Look for an element containing text, and then click a sibling close button
|
||||
*/
|
||||
export const findAndClose = async (
|
||||
page: Page,
|
||||
text: string,
|
||||
role: string = 'status',
|
||||
closeLabel: string = 'Close'
|
||||
) => {
|
||||
|
||||
interface FindAndCloseOptions {
|
||||
role?: string;
|
||||
closeLabel?: string;
|
||||
required?: boolean;
|
||||
}
|
||||
|
||||
export const findAndClose = async (page: Page, text: string, options: FindAndCloseOptions = {}) => {
|
||||
const { role = 'status', closeLabel = 'Close', required = true } = options;
|
||||
|
||||
// Verify the popup text is visible.
|
||||
const elements = page.locator(`:has-text("${text}")[role="${role}"]`);
|
||||
await expect(elements.first()).toBeVisible(); // expect at least one element
|
||||
|
||||
if (required) {
|
||||
await expect(elements.first()).toBeVisible(); // expect at least one element
|
||||
}
|
||||
|
||||
// Find all 'Close' buttons that are siblings of the elements containing the specified text.
|
||||
const closeBtns = page.locator(
|
||||
@ -384,3 +391,18 @@ export const isElementBefore = async (firstLocator, secondLocator) => {
|
||||
return !!(first.compareDocumentPosition(second) & Node.DOCUMENT_POSITION_FOLLOWING);
|
||||
}, secondHandle);
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensures that the specified checkbox is in the desired checked state.
|
||||
* If the checkbox's current state does not match the desired state, it clicks the checkbox to toggle it.
|
||||
*
|
||||
* @param {Locator} locator - Playwright locator for the checkbox element.
|
||||
* @param {boolean} checked - Desired checked state of the checkbox (true for checked, false for unchecked).
|
||||
* @returns {Promise<void>} - Resolves when the checkbox state is correctly set.
|
||||
*/
|
||||
export const ensureCheckbox = async (locator: Locator, checked: boolean) => {
|
||||
const isChecked = await locator.isChecked();
|
||||
if (isChecked !== checked) {
|
||||
await locator.click();
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user