chore(e2e): make parallelism mode more stable (#3294)

* chore: make parallelism mode more stable

* refactor: optimize e2e tests

* test: make test more stable

* chore: change concurrency to 4 from 2

* refactor: inline variable

* test: fix error

* test: avoid error

* test: avoid error

* test: avoid error

* chore(e2e): remove --stop-on-error on CI runs

* Revert "refactor: inline variable"

This reverts commit 454bb04613.

* test: make more stable

* chore: adjust timeout

* chore: update config

* test: make test more stable

* chore: update yarn.lock

* Revert "chore: update yarn.lock"

This reverts commit 1bb7a661d1.

* test(workflow): increase local timeout

* test: optimize

* test: more stable

* test: fix errors

* test: more stable

* chore: increase retries to 2 in CI
This commit is contained in:
Zeke Zhang 2024-01-06 06:37:23 +08:00 committed by GitHub
parent 16b34be05c
commit 2ab9f8625e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 286 additions and 324 deletions

View File

@ -3,6 +3,7 @@ const { run, isPortReachable } = require('../util');
const { execSync } = require('node:child_process');
const axios = require('axios');
const { pTest } = require('./p-test');
const os = require('os');
/**
* 检查服务是否启动成功
@ -205,7 +206,7 @@ module.exports = (cli) => {
e2e
.command('p-test')
.option('--stop-on-error')
.option('--concurrency [concurrency]', '', 3)
.option('--concurrency [concurrency]', '', os.cpus().length)
.action(async (opts) => {
await pTest(opts);
});

View File

@ -35,7 +35,7 @@ async function runApp(dir, index = 0) {
await client.query(`DROP DATABASE IF EXISTS "${database}"`);
await client.query(`CREATE DATABASE "${database}";`);
await client.end();
return execa('yarn', ['nocobase', 'e2e', 'test', dir, '-x', '--skip-reporter'], {
return execa('yarn', ['nocobase', 'e2e', 'test', dir, '--skip-reporter'], {
shell: true,
stdio: 'inherit',
env: {
@ -59,11 +59,11 @@ exports.pTest = async (options) => {
root: process.cwd(),
});
const commands = splitArrayIntoParts(files, options.concurrency || 3).map((v, i) => {
const commands = splitArrayIntoParts(_.shuffle(files), options.concurrency || 4).map((v, i) => {
return () => runApp(v.join(' '), i);
});
await pAll(commands, { concurrency: 3, stopOnError: false, ...options });
await pAll(commands, { concurrency: 4, stopOnError: false, ...options });
};
function splitArrayIntoParts(array, parts) {

View File

@ -1,29 +1,30 @@
import { expect, oneFormBlockBasedOnUsers, test } from '@nocobase/test/e2e';
test('fields', async ({ page, mockPage }) => {
// 在 CI 中多进程跑的时候,可能需要等待更长的时间
test.slow();
await mockPage(oneFormBlockBasedOnUsers).goto();
await page.getByLabel('schema-initializer-Grid-FormItemInitializers-users').click();
await page.getByLabel('schema-initializer-Grid-FormItemInitializers-users').hover();
await page.getByRole('menuitem', { name: 'Nickname' }).click();
await page.getByRole('menuitem', { name: 'Username' }).click();
await page.getByRole('menuitem', { name: 'Email' }).click();
await page.mouse.move(300, 0);
const sourceElement = page.getByLabel('block-item-CollectionField-users-form-users.nickname');
await sourceElement.hover();
const source = sourceElement.getByLabel('designer-drag');
await source.hover();
const targetElement = page.getByLabel('block-item-CollectionField-users-form-users.username');
await source.dragTo(targetElement);
await page.getByLabel('block-item-CollectionField-users-form-users.nickname').hover();
await page
.getByLabel('block-item-CollectionField-users-form-users.nickname')
.getByLabel('designer-drag')
.dragTo(page.getByLabel('block-item-CollectionField-users-form-users.username'));
await page.reload();
const targetElement2 = page.getByLabel('block-item-CollectionField-users-form-users.email');
await source.hover();
await source.dragTo(targetElement2);
await page.getByLabel('block-item-CollectionField-users-form-users.nickname').hover();
await page
.getByLabel('block-item-CollectionField-users-form-users.nickname')
.getByLabel('designer-drag')
.dragTo(page.getByLabel('block-item-CollectionField-users-form-users.email'));
await page.reload();
await sourceElement.hover();
const nickname = await source.boundingBox();
const username = await targetElement.boundingBox();
const email = await targetElement2.boundingBox();
const nickname = await page.getByLabel('block-item-CollectionField-users-form-users.nickname').boundingBox();
const username = await page.getByLabel('block-item-CollectionField-users-form-users.username').boundingBox();
const email = await page.getByLabel('block-item-CollectionField-users-form-users.email').boundingBox();
const max = Math.max(username.y, nickname.y, email.y);
//拖拽调整排序符合预期
expect(nickname.y).toBe(max);

View File

@ -589,6 +589,13 @@ test.describe('creation form block schema settings', () => {
await page.getByLabel('Set default value').getByRole('textbox').fill('test default value');
await page.getByRole('button', { name: 'OK', exact: true }).click();
// 确保下拉选项被隐藏
await page.getByRole('button', { name: 'Nickname', exact: true }).hover();
await page
.getByRole('button', { name: 'designer-schema-settings-TableV2.Column-TableV2.Column.Designer-users' })
.hover();
await page.mouse.move(300, 0);
// 当新增一行时,应该显示默认值
await page.getByRole('button', { name: 'plus' }).click();
await expect(
@ -802,8 +809,7 @@ test.describe('creation form block schema settings', () => {
await page.getByLabel('block-item-CardItem-users-form').hover();
//保存模板后当前区块为引用区块
const titleTag = await page.getByLabel('block-item-CardItem-users-form').locator('.title-tag').nth(1).innerText();
expect(titleTag).toContain('Reference template');
await expect(page.getByLabel('block-item-CardItem-users-form')).toHaveText(/Reference template/);
// using block template
await mockPage({
@ -1105,14 +1111,16 @@ test.describe('creation form block schema settings', () => {
await page.getByRole('menuitem', { name: 'Users' }).hover();
await page.getByRole('menuitem', { name: 'Duplicate template' }).hover();
await page.getByRole('menuitem', { name: 'Users_Form (Fields only)' }).click();
await page.mouse.move(300, 0);
await expect(page.getByLabel('block-item-CardItem-users-form')).toBeVisible();
//在新建操作中使用引用模板
await page.getByLabel('action-Action-Add new-create-users-table').click();
await page.getByLabel('schema-initializer-Grid-CreateFormBlockInitializers-users').click();
await page.getByRole('menuitem', { name: 'form Form' }).hover();
await page.getByLabel('schema-initializer-Grid-CreateFormBlockInitializers-users').hover();
await page.getByRole('menuitem', { name: 'form Form' }).first().hover();
await page.getByRole('menuitem', { name: 'Reference template' }).hover();
await page.getByRole('menuitem', { name: 'Users_Form (Fields only)' }).click();
await page.mouse.move(300, 0);
await page.getByLabel('schema-initializer-Grid-CreateFormBlockInitializers-users').hover();
await expect(page.locator('.ant-drawer').getByLabel('block-item-CardItem-users-form')).toBeVisible();
await page.locator('.ant-drawer-mask').click();
@ -1120,13 +1128,13 @@ test.describe('creation form block schema settings', () => {
//在编辑操作中使用引用模板
await page.getByLabel('action-Action.Link-Edit-update-users-table-0').click();
await page.getByLabel('schema-initializer-Grid-RecordBlockInitializers-users').click();
await page.getByRole('menuitem', { name: 'form Form' }).hover();
await page.getByRole('menuitem', { name: 'form Form' }).first().hover();
await page.getByRole('menuitem', { name: 'Reference template' }).hover();
await page.getByRole('menuitem', { name: 'Users_Form (Fields only)' }).click();
await page.getByLabel('schema-initializer-Grid-RecordBlockInitializers-users').hover();
await page.mouse.move(300, 0);
//修改引用模板
await page.locator('.ant-drawer').getByLabel('schema-initializer-Grid-FormItemInitializers-users').click();
await page.locator('.ant-drawer').getByLabel('schema-initializer-Grid-FormItemInitializers-users').hover();
await page.getByRole('menuitem', { name: 'Phone' }).click();
await page.locator('.ant-drawer-mask').click();
//复制模板不同步,引用模板同步

View File

@ -3,19 +3,18 @@ import { expect, test, twoTabsPage } from '@nocobase/test/e2e';
test('tabs', async ({ page, mockPage }) => {
await mockPage(twoTabsPage).goto();
const sourceElement = page.locator('span:has-text("tab 2")');
await sourceElement.hover();
const source = page.getByRole('button', { name: 'drag' });
await source.hover();
const targetElement = page.locator('span:has-text("tab 1")');
const sourceBoundingBox = await sourceElement.boundingBox();
const targetBoundingBox = await targetElement.boundingBox();
let tab1Box = await page.getByText('tab 1').boundingBox();
let tab2Box = await page.getByText('tab 2').boundingBox();
//拖拽标签调整排序 拖拽前 1-2
expect(targetBoundingBox.x).toBeLessThan(sourceBoundingBox.x);
await source.dragTo(targetElement);
await sourceElement.dragTo(targetElement);
const tab2 = await page.locator('span:has-text("tab 2")').boundingBox();
const tab1 = await page.locator('span:has-text("tab 1")').boundingBox();
expect(tab1Box.x).toBeLessThan(tab2Box.x);
await page.getByText('tab 1').hover();
await page.getByRole('button', { name: 'designer-drag-handler-Page-tab' }).dragTo(page.getByText('tab 2'));
await expect(page.getByText('tab 1')).toBeVisible();
tab1Box = await page.getByText('tab 1').boundingBox();
tab2Box = await page.getByText('tab 2').boundingBox();
//拖拽后 2-1
expect(tab2.x).toBeLessThan(tab1.x);
expect(tab2Box.x).toBeLessThan(tab1Box.x);
});

View File

@ -101,6 +101,7 @@ test.describe('configure columns', () => {
await expect(page.getByRole('menuitem', { name: 'One to one (belongs to)' }).getByRole('switch')).toBeChecked();
await expect(page.getByRole('menuitem', { name: 'One to one (has one)' }).getByRole('switch')).toBeChecked();
await expect(page.getByRole('menuitem', { name: 'Many to one' }).getByRole('switch')).toBeChecked();
await page.mouse.move(300, 0);
await expect(page.getByRole('button', { name: 'ID', exact: true })).toBeVisible();
await expect(page.getByRole('button', { name: 'One to one (belongs to)', exact: true })).toBeVisible();
await expect(page.getByRole('button', { name: 'One to one (has one)', exact: true })).toBeVisible();
@ -124,26 +125,19 @@ test.describe('configure columns', () => {
// display association fields -------------------------------------------------------------
await configureColumnButton.hover();
await page.getByText('Display collection fields', { exact: true }).hover();
await page.mouse.wheel(0, 300);
await page.getByRole('menuitem', { name: 'One to one (belongs to)' }).nth(1).hover();
await page.getByRole('menuitem', { name: 'Nickname' }).click();
await expect(page.getByRole('menuitem', { name: 'Nickname' }).getByRole('switch')).toBeChecked();
await page.mouse.move(300, 0);
await expect(page.getByRole('button', { name: 'Nickname', exact: true })).toBeVisible();
// 开关应该是开启状态
await configureColumnButton.hover();
await page.getByRole('menuitem', { name: 'One to one (belongs to)' }).nth(1).hover();
await expect(page.getByRole('menuitem', { name: 'Nickname' }).getByRole('switch')).toBeChecked();
// 点击开关,删除创建的字段
await page.getByRole('menuitem', { name: 'Nickname' }).click();
await expect(page.getByRole('button', { name: 'Nickname', exact: true })).not.toBeVisible();
// 开关应该是关闭状态
await configureColumnButton.hover();
await page.getByRole('menuitem', { name: 'One to one (belongs to)' }).nth(1).hover();
await page.getByRole('menuitem', { name: 'Nickname' }).click();
await expect(page.getByRole('menuitem', { name: 'Nickname' }).getByRole('switch')).not.toBeChecked();
await page.mouse.move(300, 0);
await expect(page.getByRole('button', { name: 'Nickname', exact: true })).not.toBeVisible();
});
test.pgOnly('display inherit fields', async ({ page, mockPage }) => {});

View File

@ -41,7 +41,7 @@ test.describe('table block schema settings', () => {
await expect(page.getByRole('menuitem', { name: 'Fix block' }).getByRole('switch')).toBeChecked();
// 等待页面重新渲染
await page.waitForTimeout(100);
await page.waitForTimeout(1000);
const fixedTableSize = await page.getByLabel('block-item-CardItem-general-table').boundingBox();
expect(fixedTableSize.height).toBeGreaterThan(570);
expect(fixedTableSize.height).toBeLessThan(575);
@ -116,8 +116,8 @@ test.describe('table block schema settings', () => {
.getByRole('img', { name: 'menu' })
.dragTo(page.getByLabel('table-index-1').getByRole('img', { name: 'menu' }));
// 等待表格刷新
await page.waitForTimeout(3000);
await page.reload();
await page.waitForLoadState('networkidle');
email1 = await page.getByText(records[0].email).boundingBox();
email2 = await page.getByText(records[1].email).boundingBox();

View File

@ -15,7 +15,7 @@ export const defineConfig = (config?: PlaywrightTestConfig) => {
testMatch: /(.*\/e2e\/|.*\/__e2e__\/).+\.test\.[tj]sx*$/,
// Run all tests in parallel.
fullyParallel: true,
fullyParallel: false,
// Fail the build on CI if you accidentally left test.only in the source code.
forbidOnly: !!process.env.CI,
@ -27,7 +27,7 @@ export const defineConfig = (config?: PlaywrightTestConfig) => {
// workers: process.env.CI ? 1 : undefined,
workers: 1,
maxFailures: 1,
maxFailures: 0,
// Reporter to use
reporter: process.env.PLAYWRIGHT_SKIP_REPORTER

View File

@ -32,7 +32,7 @@ test.describe('view', () => {
await expect(page.getByRole('button', { name: 'phone' })).not.toBeVisible();
await page.getByLabel('action-Action.Link-Association block-customize:popup-general-table').click();
//关系区块不可见
await expect(await page.getByLabel('block-item-CardItem-users-form')).not.toBeVisible();
await expect(page.getByLabel('block-item-CardItem-users-form')).not.toBeVisible();
});
//关系字段有权限,关系目标表个别字段有权限
test('association field accept, target collection accept with fields', async ({
@ -70,9 +70,9 @@ test.describe('view', () => {
await expect(page.getByRole('button', { name: 'phone' })).not.toBeVisible();
await page.getByLabel('action-Action.Link-Association block-customize:popup-general-table').click();
//关系区块可见,个别字段可见
await expect(await page.getByLabel('block-item-CardItem-users-form')).toBeVisible();
await expect(await page.getByLabel('block-item-CollectionField-users-form-users.nickname')).not.toBeVisible();
await expect(await page.getByLabel('block-item-CollectionField-users-form-users.email')).toBeVisible();
await expect(page.getByLabel('block-item-CardItem-users-form')).toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-users-form-users.nickname')).not.toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-users-form-users.email')).toBeVisible();
});
});
@ -107,10 +107,8 @@ test.describe('update', () => {
await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible();
await page.getByLabel('action-Action.Link-Association field-customize:popup-general-table').click();
//关系字段组件可见,子表单/子表格中字段不可见
await expect(
await page.getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo'),
).toBeVisible();
await expect(await page.getByLabel('block-item-CollectionField-users-form-users.email-Email')).not.toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo')).toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-users-form-users.email-Email')).not.toBeVisible();
});
//关系字段有权限,关系目标表个别字段有权限
test('association field accept, target collection accept with fields', async ({
@ -148,11 +146,9 @@ test.describe('update', () => {
await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible();
await page.getByLabel('action-Action.Link-Association field-customize:popup-general-table').click();
//关系字段组件可见,子表单/子表格中个别字段可见
await expect(
await page.getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo'),
).toBeVisible();
await expect(await page.getByLabel('block-item-CollectionField-users-form-users.email')).toBeVisible();
await expect(await page.getByLabel('block-item-CollectionField-users-form-users.phone')).not.toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo')).toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-users-form-users.email')).toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-users-form-users.phone')).not.toBeVisible();
});
});
@ -188,12 +184,10 @@ test.describe('create', () => {
await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible();
await page.getByLabel('action-Action-Add new-create').click();
//关系字段组件可见,子表单/子表格中字段不可见
await expect(
await page.getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo'),
).toBeVisible();
await expect(await page.getByLabel('block-item-CollectionField-users-form-users.email')).not.toBeVisible();
await expect(await page.getByLabel('block-item-CollectionField-users-form-users.phone')).not.toBeVisible();
await expect(await page.getByLabel('block-item-CollectionField-users-form-users.username')).not.toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo')).toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-users-form-users.email')).not.toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-users-form-users.phone')).not.toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-users-form-users.username')).not.toBeVisible();
});
//关系字段有权限,关系目标表个别字段有权限
test('association field accept, target collection accept with fields', async ({
@ -232,11 +226,9 @@ test.describe('create', () => {
await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible();
await page.getByLabel('action-Action-Add new-create').click();
//关系字段组件可见,子表单/子表格中个别字段可见
await expect(
await page.getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo'),
).toBeVisible();
await expect(await page.getByLabel('block-item-CollectionField-users-form-users.email')).toBeVisible();
await expect(await page.getByLabel('block-item-CollectionField-users-form-users.phone')).not.toBeVisible();
await expect(await page.getByLabel('block-item-CollectionField-users-form-users.username')).not.toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo')).toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-users-form-users.email')).toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-users-form-users.phone')).not.toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-users-form-users.username')).not.toBeVisible();
});
});

View File

@ -100,7 +100,7 @@ test.describe('create', () => {
}, roleData);
await page.reload();
await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible();
await expect(await page.getByLabel('action-Action-Add new-create-general-table')).not.toBeVisible();
await expect(page.getByLabel('action-Action-Add new-create-general-table')).not.toBeVisible();
await updateRole({
name: roleData.name,
strategy: {
@ -108,7 +108,7 @@ test.describe('create', () => {
},
});
await page.reload();
await expect(await page.getByLabel('action-Action-Add new-create-general-table')).toBeVisible();
await expect(page.getByLabel('action-Action-Add new-create-general-table')).toBeVisible();
});
test('individual collection permission', async ({ page, mockPage, mockRole, updateRole }) => {
await mockPage(oneTableBlock).goto();
@ -136,7 +136,7 @@ test.describe('create', () => {
await page.reload();
await mockPage(oneTableBlock).goto();
await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible();
await expect(await page.getByLabel('action-Action-Add new-create-general-table')).not.toBeVisible();
await expect(page.getByLabel('action-Action-Add new-create-general-table')).not.toBeVisible();
await updateRole({
name: roleData.name,
resources: [
@ -153,7 +153,7 @@ test.describe('create', () => {
],
});
await page.reload();
await expect(await page.getByLabel('action-Action-Add new-create-general-table')).toBeVisible();
await expect(page.getByLabel('action-Action-Add new-create-general-table')).toBeVisible();
});
test('individual collection permission width fields', async ({ page, mockPage, mockRole }) => {
await mockPage(oneTableBlock).goto();
@ -184,8 +184,8 @@ test.describe('create', () => {
}, roleData);
await page.reload();
await mockPage(oneTableBlock).goto();
await expect(await page.getByLabel('action-Action-Add new-create-general-table')).toBeVisible();
await await page.getByLabel('action-Action-Add new-create-general-table').click();
await expect(page.getByLabel('action-Action-Add new-create-general-table')).toBeVisible();
await page.getByLabel('action-Action-Add new-create-general-table').click();
await expect(page.getByLabel('block-item-CollectionField-general-form-general.singleLineText')).toBeVisible();
});
});
@ -206,7 +206,7 @@ test.describe('update', () => {
window.localStorage.setItem('NOCOBASE_ROLE', roleData.name);
}, roleData);
await page.reload();
await expect(await page.getByLabel('action-Action.Link-Edit')).not.toBeVisible();
await expect(page.getByLabel('action-Action.Link-Edit')).not.toBeVisible();
await updateRole({
name: roleData.name,
strategy: {
@ -214,7 +214,7 @@ test.describe('update', () => {
},
});
await page.reload();
await expect(await page.getByLabel('action-Action.Link-Edit')).toBeVisible();
await expect(page.getByLabel('action-Action.Link-Edit')).toBeVisible();
});
test('individual collection permission', async ({ page, mockPage, mockRole, mockRecord, updateRole }) => {
await mockPage(oneTableBlock).goto();
@ -239,7 +239,7 @@ test.describe('update', () => {
await page.reload();
await mockPage(oneTableBlock).goto();
await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible();
await expect(await page.getByLabel('action-Action.Link-Edit')).not.toBeVisible();
await expect(page.getByLabel('action-Action.Link-Edit')).not.toBeVisible();
await updateRole({
name: roleData.name,
resources: [
@ -256,7 +256,7 @@ test.describe('update', () => {
],
});
await page.reload();
await expect(await page.getByLabel('action-Action.Link-Edit')).toBeVisible();
await expect(page.getByLabel('action-Action.Link-Edit')).toBeVisible();
});
test('individual collection permission with fields', async ({ page, mockPage, mockRole, mockRecord }) => {
await mockPage(oneTableBlock).goto();
@ -277,7 +277,7 @@ test.describe('update', () => {
}, roleData);
await page.reload();
await mockPage(oneTableBlock).goto();
await expect(await page.getByLabel('action-Action.Link-Edit')).toBeVisible();
await expect(page.getByLabel('action-Action.Link-Edit')).toBeVisible();
await page.getByLabel('action-Action.Link-Edit').click();
await expect(page.getByLabel('block-item-CollectionField-general-form-general.singleLineText')).toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-general-form-general.phone')).toBeVisible();
@ -301,7 +301,7 @@ test.describe('destroy', () => {
window.localStorage.setItem('NOCOBASE_ROLE', roleData.name);
}, roleData);
await page.reload();
await expect(await page.getByLabel('action-Action-Delete-destroy-general-table')).not.toBeVisible();
await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).not.toBeVisible();
await updateRole({
name: roleData.name,
strategy: {
@ -309,7 +309,7 @@ test.describe('destroy', () => {
},
});
await page.reload();
await expect(await page.getByLabel('action-Action-Delete-destroy-general-table')).toBeVisible();
await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).toBeVisible();
});
test('individual collection permission', async ({ page, mockPage, mockRole, updateRole }) => {
await mockPage().goto();
@ -333,7 +333,7 @@ test.describe('destroy', () => {
await page.reload();
await mockPage(oneTableBlock).goto();
await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible();
await expect(await page.getByLabel('action-Action-Delete-destroy-general-table')).not.toBeVisible();
await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).not.toBeVisible();
await updateRole({
name: roleData.name,
resources: [
@ -350,7 +350,7 @@ test.describe('destroy', () => {
],
});
await page.reload();
await expect(await page.getByLabel('action-Action-Delete-destroy-general-table')).toBeVisible();
await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).toBeVisible();
});
});
@ -369,7 +369,7 @@ test.describe('export', () => {
window.localStorage.setItem('NOCOBASE_ROLE', roleData.name);
}, roleData);
await page.reload();
await expect(await page.getByLabel('action-Action-Export')).not.toBeVisible();
await expect(page.getByLabel('action-Action-Export')).not.toBeVisible();
await updateRole({
name: roleData.name,
strategy: {
@ -377,7 +377,7 @@ test.describe('export', () => {
},
});
await page.reload();
await expect(await page.getByLabel('action-Action-Export')).toBeVisible();
await expect(page.getByLabel('action-Action-Export')).toBeVisible();
});
test('individual collection permission', async ({ page, mockPage, mockRole }) => {
await mockPage().goto();
@ -403,7 +403,7 @@ test.describe('export', () => {
}, roleData);
await page.reload();
await mockPage(oneTableBlock).goto();
await expect(await page.getByLabel('action-Action-Export')).toBeVisible();
await expect(page.getByLabel('action-Action-Export')).toBeVisible();
});
});
@ -422,7 +422,7 @@ test.describe('import', () => {
window.localStorage.setItem('NOCOBASE_ROLE', roleData.name);
}, roleData);
await page.reload();
await expect(await page.getByLabel('action-Action-Import')).not.toBeVisible();
await expect(page.getByLabel('action-Action-Import')).not.toBeVisible();
await updateRole({
name: roleData.name,
strategy: {
@ -430,7 +430,7 @@ test.describe('import', () => {
},
});
await page.reload();
await expect(await page.getByLabel('action-Action-Import')).toBeVisible();
await expect(page.getByLabel('action-Action-Import')).toBeVisible();
});
test('individual collection permission', async ({ page, mockPage, mockRole }) => {
await mockPage().goto();
@ -456,6 +456,6 @@ test.describe('import', () => {
}, roleData);
await page.reload();
await mockPage(oneTableBlock).goto();
await expect(await page.getByLabel('action-Action-Import')).toBeVisible();
await expect(page.getByLabel('action-Action-Import')).toBeVisible();
});
});

View File

@ -11,16 +11,16 @@ test('allows to configure interface', async ({ page, mockPage, mockRole, updateR
window.localStorage.setItem('NOCOBASE_ROLE', roleData.name);
}, roleData);
await page.reload();
await expect(await page.getByTestId('ui-editor-button')).toBeVisible();
await expect(await page.getByTestId('schema-initializer-Menu-header')).toBeVisible();
await expect(page.getByTestId('ui-editor-button')).toBeVisible();
await expect(page.getByTestId('schema-initializer-Menu-header')).toBeVisible();
//更新权限,无ui配置权限
await updateRole({
name: roleData.name,
snippets: ['!ui.*'],
});
await page.reload();
await expect(await page.getByTestId('ui-editor-button')).not.toBeVisible();
await expect(await page.getByTestId('schema-initializer-Menu-header')).not.toBeVisible();
await expect(page.getByTestId('ui-editor-button')).not.toBeVisible();
await expect(page.getByTestId('schema-initializer-Menu-header')).not.toBeVisible();
});
test('allows to install ,install,disabled plugins ', async ({ page, mockPage, mockRole, updateRole }) => {
@ -33,22 +33,20 @@ test('allows to install ,install,disabled plugins ', async ({ page, mockPage, mo
window.localStorage.setItem('NOCOBASE_ROLE', roleData.name);
}, roleData);
await page.reload();
await expect(await page.getByTestId('plugin-manager-button')).toBeVisible();
await expect(page.getByTestId('plugin-manager-button')).toBeVisible();
await page.getByTestId('plugin-manager-button').click();
await expect(await page.url()).toContain('/pm/list/local');
await expect(
await page.locator('.ant-page-header-heading').getByTitle('Plugin manager', { exact: true }),
).toBeVisible();
expect(page.url()).toContain('/pm/list/local');
await expect(page.locator('.ant-page-header-heading').getByTitle('Plugin manager', { exact: true })).toBeVisible();
//无插件管理权限时访问直接路由访问时404
await updateRole({
name: roleData.name,
snippets: ['!pm'],
});
await page.reload();
await expect(await page.getByTestId('plugin-manager-button')).not.toBeVisible();
await expect(page.getByTestId('plugin-manager-button')).not.toBeVisible();
await page.goto('/pm/list/local');
await expect(await page.getByText('Sorry, the page you visited')).toBeVisible();
await expect(await page.getByRole('button', { name: 'Back Home' })).toBeVisible();
await expect(page.getByText('Sorry, the page you visited')).toBeVisible();
await expect(page.getByRole('button', { name: 'Back Home' })).toBeVisible();
});
test('allows to confgiure plugins ', async ({ page, mockPage, mockRole, updateRole }) => {
@ -87,16 +85,16 @@ test('allows to clear cache,reboot application ', async ({ page, mockPage, mockR
}, roleData);
await page.reload();
await page.getByTestId('user-center-button').hover();
await expect(await page.getByRole('menuitem', { name: 'Clear cache' })).toBeVisible();
await expect(await page.getByRole('menuitem', { name: 'Restart application' })).toBeVisible();
await expect(page.getByRole('menuitem', { name: 'Clear cache' })).toBeVisible();
await expect(page.getByRole('menuitem', { name: 'Restart application' })).toBeVisible();
await updateRole({
name: roleData.name,
snippets: ['!app'],
});
await page.reload();
await page.getByTestId('user-center-button').hover();
await expect(await page.getByRole('menuitem', { name: 'Clear cache' })).not.toBeVisible();
await expect(await page.getByRole('menuitem', { name: 'Restart application' })).not.toBeVisible();
await expect(page.getByRole('menuitem', { name: 'Clear cache' })).not.toBeVisible();
await expect(page.getByRole('menuitem', { name: 'Restart application' })).not.toBeVisible();
});
test('new menu items allow to be asscessed by default ', async ({ page, mockPage, mockRole, updateRole }) => {
@ -130,22 +128,22 @@ test('plugin settings permissions', async ({ page, mockPage, mockRole, updateRol
}, roleData);
await page.reload();
await page.getByTestId('plugin-settings-button').hover();
await expect(await page.getByLabel('acl')).toBeVisible();
await expect(await page.getByLabel('auth')).not.toBeVisible();
await expect(await page.getByLabel('collection-manager')).not.toBeVisible();
await expect(page.getByLabel('acl')).toBeVisible();
await expect(page.getByLabel('auth')).not.toBeVisible();
await expect(page.getByLabel('collection-manager')).not.toBeVisible();
await page.getByLabel('acl').click();
await expect(await page.getByRole('menuitem', { name: 'login Authentication' })).not.toBeVisible();
await expect(await page.getByRole('menuitem', { name: 'database Collection manager' })).not.toBeVisible();
await expect(page.getByRole('menuitem', { name: 'login Authentication' })).not.toBeVisible();
await expect(page.getByRole('menuitem', { name: 'database Collection manager' })).not.toBeVisible();
await updateRole({
name: roleData.name,
snippets: ['pm', 'pm.*', 'pm.auth.authenticators', 'pm.collection-manager', 'pm.collection-manager.collections'],
});
await page.reload();
await page.getByTestId('plugin-settings-button').hover();
await expect(await page.getByLabel('acl')).toBeVisible();
await expect(await page.getByLabel('auth')).toBeVisible();
await expect(await page.getByLabel('collection-manager')).toBeVisible();
await expect(page.getByLabel('acl')).toBeVisible();
await expect(page.getByLabel('auth')).toBeVisible();
await expect(page.getByLabel('collection-manager')).toBeVisible();
await page.getByLabel('acl').click();
await expect(await page.getByRole('menuitem', { name: 'login Authentication' })).toBeVisible();
await expect(await page.getByRole('menuitem', { name: 'database Collection manager' })).toBeVisible();
await expect(page.getByRole('menuitem', { name: 'login Authentication' })).toBeVisible();
await expect(page.getByRole('menuitem', { name: 'database Collection manager' })).toBeVisible();
});

View File

@ -9,7 +9,7 @@ test.describe('bulk edit action setting', () => {
await page.getByLabel('Bulk edit').hover();
await page.getByLabel('designer-schema-settings-Action-Action.Designer-general').hover();
//默认是选中的数据
await expect(await page.getByTitle('Data will be updated').getByText('Selected')).toBeVisible();
await expect(page.getByTitle('Data will be updated').getByText('Selected')).toBeVisible();
await page.getByRole('menuitem', { name: 'Data will be updated' }).click();
//切换为全部数据
await page.getByRole('option', { name: 'All' }).click();

View File

@ -12,7 +12,7 @@ test.describe('data will be updated && Assign field values && after successful s
await page.getByLabel('action-Action-Bulk update-customize:bulkUpdate-general-table').hover();
await page.getByLabel('designer-schema-settings-Action-Action.Designer-general').hover();
//默认是选中的数据
await expect(await page.getByTitle('Data will be updated').getByText('Selected')).toBeVisible();
await expect(page.getByTitle('Data will be updated').getByText('Selected')).toBeVisible();
await page.getByRole('menuitem', { name: 'Data will be updated' }).click();
//切换为全部数据
await page.getByRole('option', { name: 'All' }).click();
@ -30,7 +30,7 @@ test.describe('data will be updated && Assign field values && after successful s
await page.getByLabel('Redirect to').check();
await page.locator('input[type="text"]').click();
await page.locator('input[type="text"]').fill('/admin/pm/list/local/');
await page.getByRole('button', { name: 'OK' }).click();
await page.getByRole('button', { name: 'OK', exact: true }).click();
await page.getByLabel('action-Action-Bulk update-customize:bulkUpdate-general-table').click();
const [request] = await Promise.all([
page.waitForRequest((request) => request.url().includes('api/general:update')),

View File

@ -26,6 +26,8 @@ test.describe('form item & edit form', () => {
page,
showMenu: async () => {
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
// 等待弹窗内容渲染完成
await page.waitForTimeout(1000);
await page.getByLabel('schema-initializer-Grid-FormItemInitializers-general').hover();
},
supportedOptions: ['markdown', 'richtext', 'attachment'],
@ -43,6 +45,8 @@ test.describe('form item & view form', () => {
page,
showMenu: async () => {
await page.getByLabel('action-Action.Link-View record-view-general-table-0').click();
// 等待弹窗内容渲染完成
await page.waitForTimeout(1000);
await page.getByLabel('schema-initializer-Grid-ReadPrettyFormItemInitializers-general').hover();
},
supportedOptions: ['markdown', 'richtext', 'attachment'],

View File

@ -67,6 +67,8 @@ test.describe('form item & edit form', () => {
page,
showMenu: async () => {
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
// 等待弹窗内容渲染完成
await page.waitForTimeout(1000);
await page
.getByLabel(`block-item-CollectionField-general-form-general.attachment-attachment`, { exact: true })
.hover();
@ -86,29 +88,25 @@ test.describe('form item & edit form', () => {
await testPattern({
page,
gotoPage: async () => {
record = await (async (mockPage, mockRecord) => {
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
const record = await mockRecord('general');
await nocoPage.goto();
return record;
})(mockPage, mockRecord);
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
record = await mockRecord('general');
await nocoPage.goto();
},
openDialog: async () => {
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
// 等待弹窗内容渲染完成
await page.waitForTimeout(1000);
},
showMenu: async () => {
await page
.getByLabel(`block-item-CollectionField-general-form-general.attachment-attachment`, { exact: true })
.hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.attachment`, {
exact: true,
})
.hover();
},
openDialog: () =>
(async (page: Page) => {
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
})(page),
showMenu: () =>
(async (page: Page, fieldName: string) => {
await page
.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true })
.hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, {
exact: true,
})
.hover();
})(page, 'attachment'),
expectEditable: async () => {
await expect(
page
@ -172,14 +170,13 @@ test.describe('form item & view form', () => {
});
test('size', async ({ page, mockPage, mockRecord }) => {
const record = await (async (mockPage, mockRecord) => {
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
const record = await mockRecord('general');
await nocoPage.goto();
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
const record = await mockRecord('general');
await nocoPage.goto();
return record;
})(mockPage, mockRecord);
await page.getByLabel('action-Action.Link-View record-view-general-table-0').click();
// 这里是为了等弹窗中的内容渲染稳定后,再去 hover防止错位导致测试报错
await page.waitForTimeout(1000);
// 默认尺寸
// 这里的尺寸不稳定,所以用 try catch 来处理

View File

@ -65,25 +65,21 @@ test.describe('form item & create form', () => {
await testPattern({
page,
gotoPage: async () => {
records = await (async (mockPage, mockRecords) => {
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
const recordsOfUser = await mockRecords('users', 3);
await nocoPage.goto();
return recordsOfUser;
})(mockPage, mockRecords);
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
records = await mockRecords('users', 3);
await nocoPage.goto();
},
openDialog: async () => {
await page.getByRole('button', { name: 'Add new' }).click();
},
showMenu: async () => {
await page
.getByLabel(`block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo`)
.hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.oneToOneBelongsTo`)
.hover();
},
openDialog: () =>
(async (page: Page) => {
await page.getByRole('button', { name: 'Add new' }).click();
})(page),
showMenu: () =>
(async (page: Page, fieldName: string) => {
await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`)
.hover();
})(page, 'oneToOneBelongsTo'),
expectEditable: async () => {
await page
.getByLabel('block-item-CollectionField-general-form-general.oneToOneBelongsTo-oneToOneBelongsTo')
@ -98,7 +94,7 @@ test.describe('form item & create form', () => {
.getByTestId(/select-object/),
).toHaveClass(/ant-select-disabled/);
// 在这里等待一下,防止因闪烁导致下面的断言失败
await page.waitForTimeout(100);
// await page.waitForTimeout(100);
},
expectEasyReading: async () => {
await expect(

View File

@ -278,12 +278,12 @@ test.describe('form item & create form', () => {
).toBeVisible();
// 选择 Sub-form(Popover)
await (async (page: Page, fieldName: string) => {
await page.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`).hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`)
.hover();
})(page, 'manyToMany');
await page.getByLabel(`block-item-CollectionField-general-form-general.manyToMany-manyToMany`).hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.manyToMany`)
.hover();
// 加上这个延迟会使测试更稳定
await page.waitForTimeout(100);
await page.getByRole('menuitem', { name: 'Field component' }).click();
await page.getByRole('option', { name: 'Sub-form(Popover)', exact: true }).click();
await page

View File

@ -1,5 +1,4 @@
import {
Page,
expect,
expectSettingsMenu,
oneTableBlockWithAddNewAndViewAndEditAndMediaFields,
@ -138,7 +137,10 @@ test.describe('form item & edit form', () => {
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
await mockRecord('general');
await nocoPage.goto();
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
// 等待弹窗内容渲染完成
await page.waitForTimeout(1000);
await page.getByLabel(`block-item-CollectionField-general-form-general.markdown-markdown`, { exact: true }).hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.markdown`, {
@ -167,29 +169,25 @@ test.describe('form item & edit form', () => {
await testPattern({
page,
gotoPage: async () => {
record = await (async (mockPage, mockRecord) => {
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
const record = await mockRecord('general');
await nocoPage.goto();
return record;
})(mockPage, mockRecord);
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
record = await mockRecord('general');
await nocoPage.goto();
},
openDialog: async () => {
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
// 等待弹窗内容渲染完成
await page.waitForTimeout(1000);
},
showMenu: async () => {
await page
.getByLabel(`block-item-CollectionField-general-form-general.markdown-markdown`, { exact: true })
.hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.markdown`, {
exact: true,
})
.hover();
},
openDialog: () =>
(async (page: Page) => {
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
})(page),
showMenu: () =>
(async (page: Page, fieldName: string) => {
await page
.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true })
.hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, {
exact: true,
})
.hover();
})(page, 'markdown'),
expectEditable: async () => {
await expect(
page.getByLabel('block-item-CollectionField-general-form-general.markdown-markdown').getByRole('textbox'),
@ -214,29 +212,26 @@ test.describe('form item & edit form', () => {
test('Set validation rules', async ({ page, mockPage, mockRecord }) => {
await testSetValidationRules({
page,
gotoPage: () =>
(async (mockPage, mockRecord) => {
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
const record = await mockRecord('general');
await nocoPage.goto();
return record;
})(mockPage, mockRecord),
openDialog: () =>
(async (page: Page) => {
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
})(page),
showMenu: () =>
(async (page: Page, fieldName: string) => {
await page
.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true })
.hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, {
exact: true,
})
.hover();
})(page, 'markdown'),
gotoPage: async () => {
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
await mockRecord('general');
await nocoPage.goto();
},
openDialog: async () => {
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
// 等待弹窗内容渲染完成
await page.waitForTimeout(1000);
},
showMenu: async () => {
await page
.getByLabel(`block-item-CollectionField-general-form-general.markdown-markdown`, { exact: true })
.hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.markdown`, {
exact: true,
})
.hover();
},
});
});
});

View File

@ -317,7 +317,7 @@ test.describe('form item & edit form', () => {
.getByTestId('select-object-multiple'),
).toHaveClass(/ant-select-disabled/);
// 在这里等待一下,防止因闪烁导致下面的断言失败
await page.waitForTimeout(100);
// await page.waitForTimeout(100);
},
expectEasyReading: async () => {
await expect(page.getByLabel('block-item-CollectionField-general-form-general.oneToMany-oneToMany')).toHaveText(

View File

@ -1,5 +1,4 @@
import {
Page,
expect,
expectSettingsMenu,
oneTableBlockWithAddNewAndViewAndEditAndMediaFields,
@ -137,6 +136,7 @@ test.describe('form item & edit form', () => {
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
await mockRecord('general');
await nocoPage.goto();
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
await page.getByLabel(`block-item-CollectionField-general-form-general.richText-richText`, { exact: true }).hover();
await page
@ -166,29 +166,23 @@ test.describe('form item & edit form', () => {
await testPattern({
page,
gotoPage: async () => {
record = await (async (mockPage, mockRecord) => {
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
const record = await mockRecord('general');
await nocoPage.goto();
return record;
})(mockPage, mockRecord);
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
record = await mockRecord('general');
await nocoPage.goto();
},
openDialog: async () => {
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
},
showMenu: async () => {
await page
.getByLabel(`block-item-CollectionField-general-form-general.richText-richText`, { exact: true })
.hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.richText`, {
exact: true,
})
.hover();
},
openDialog: () =>
(async (page: Page) => {
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
})(page),
showMenu: () =>
(async (page: Page, fieldName: string) => {
await page
.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true })
.hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, {
exact: true,
})
.hover();
})(page, 'richText'),
expectEditable: async () => {
await expect(
page.getByLabel('block-item-CollectionField-general-form-general.richText-richText').locator('.ql-editor'),
@ -213,29 +207,24 @@ test.describe('form item & edit form', () => {
test('Set validation rules', async ({ page, mockPage, mockRecord }) => {
await testSetValidationRules({
page,
gotoPage: () =>
(async (mockPage, mockRecord) => {
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
const record = await mockRecord('general');
await nocoPage.goto();
return record;
})(mockPage, mockRecord),
openDialog: () =>
(async (page: Page) => {
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
})(page),
showMenu: () =>
(async (page: Page, fieldName: string) => {
await page
.getByLabel(`block-item-CollectionField-general-form-general.${fieldName}-${fieldName}`, { exact: true })
.hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`, {
exact: true,
})
.hover();
})(page, 'markdown'),
gotoPage: async () => {
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndMediaFields).waitForInit();
await mockRecord('general');
await nocoPage.goto();
},
openDialog: async () => {
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
},
showMenu: async () => {
await page
.getByLabel(`block-item-CollectionField-general-form-general.markdown-markdown`, { exact: true })
.hover();
await page
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.markdown`, {
exact: true,
})
.hover();
},
});
});
});

View File

@ -61,7 +61,7 @@ test.describe('form item & create form', () => {
expectConstantValue: async () => {
await expect(
page.getByLabel('block-item-CollectionField-general-form-general.time-time').getByPlaceholder('Select time'),
).toHaveValue(new RegExp(nowTime.format('HH:mm:ss')));
).toHaveValue(new RegExp(nowTime.format('HH:')));
},
});
});
@ -90,7 +90,7 @@ test.describe('form item & create form', () => {
.getByLabel('block-item-CollectionField-general-form-general.time-time')
.getByPlaceholder('Select time')
.click();
await page.getByText('Now').click();
await page.getByText('Now', { exact: true }).click();
},
expectReadonly: async () => {
await expect(

View File

@ -154,6 +154,7 @@ export async function testPattern({
// 更改为 Easy-reading
await showMenu();
await page.waitForTimeout(100);
await expect(page.getByText('PatternReadonly')).toBeVisible();
await page.getByRole('menuitem', { name: 'Pattern' }).click();
await page.getByRole('option', { name: 'Easy-reading' }).click();

View File

@ -17,7 +17,7 @@ test('drag and adjust start time, end time, and progress', async ({ page, mockPa
await page.getByRole('menuitem', { name: 'Time scale' }).hover();
await page.mouse.move(300, 0);
await page.getByRole('button', { name: 'Actions' }).click();
await expect(await page.locator('.calendarBottomText').first().textContent()).toContain('W');
await expect(page.locator('.calendarBottomText').first()).toHaveText(/W/);
await page.locator('.bar ').hover();
const draggableElement = await page.getByLabel('task-bar').getByRole('button').first();
await draggableElement.hover();

View File

@ -45,9 +45,9 @@ test.describe('configure params in gantt block', () => {
await page.getByRole('option', { name: 'Single line text2' }).locator('div').click();
await page.getByRole('button', { name: 'Actions' }).click();
await page.mouse.move(300, 0);
const barLabel = await page.getByLabel('block-item-gantt').locator('.barLabel');
const barLabel = page.getByLabel('block-item-gantt').locator('.barLabel');
await barLabel.hover();
expect(await barLabel.textContent()).toBe(mockData['singleLineText2']);
await expect(barLabel).toHaveText(mockData['singleLineText2']);
});
test('set start date field ', async ({ page, mockPage, mockRecord }) => {
await mockPage(oneEmptyGantt).goto();
@ -58,9 +58,10 @@ test.describe('configure params in gantt block', () => {
await page.getByRole('option', { name: 'Start date time2' }).locator('div').click();
await page.mouse.move(300, 0);
await page.getByRole('button', { name: 'Actions' }).click();
await page.locator('.bar').hover();
const tooltip2 = await page.getByLabel('nb-gantt-tooltip');
await expect(await tooltip2.innerText()).toContain(getYmd(new Date(mockData['startDatetime2'])));
await page.locator('.bar').hover({ position: { x: 20, y: 10 } });
await expect(page.getByLabel('nb-gantt-tooltip')).toHaveText(
new RegExp(String(getYmd(new Date(mockData['startDatetime2'])))),
);
});
test('set end date field ', async ({ page, mockPage, mockRecord }) => {
await mockPage(oneEmptyGantt).goto();
@ -72,9 +73,10 @@ test.describe('configure params in gantt block', () => {
await page.getByRole('option', { name: 'End date time2' }).locator('div').click();
await page.mouse.move(300, 0);
await page.getByRole('button', { name: 'Actions' }).click();
await page.locator('.bar').hover();
const tooltip2 = await page.getByLabel('nb-gantt-tooltip');
await expect(await tooltip2.innerText()).toContain(getYmd(new Date(mockData['endDatetime2'])));
await page.locator('.bar').hover({ position: { x: 20, y: 10 } });
await expect(page.getByLabel('nb-gantt-tooltip')).toHaveText(
new RegExp(String(getYmd(new Date(mockData['endDatetime2'])))),
);
});
test('set time scale ', async ({ page, mockPage, mockRecord }) => {
await mockPage(oneEmptyGantt).goto();
@ -87,7 +89,7 @@ test.describe('configure params in gantt block', () => {
await page.getByRole('menuitem', { name: 'Time scale' }).hover();
await page.mouse.move(300, 0);
await page.getByRole('button', { name: 'Actions' }).click();
await page.locator('.bar').hover();
await expect(await page.locator('.calendarBottomText').first().textContent()).toContain('W');
await page.locator('.bar').hover({ position: { x: 20, y: 10 } });
await expect(page.locator('.calendarBottomText').first()).toHaveText(/W/);
});
});

View File

@ -29,19 +29,17 @@ test.describe('configure fields', () => {
await page.getByLabel('designer-schema-initializer-Kanban.Card-Kanban.Card.Designer-general').hover();
await page.getByRole('menuitem', { name: 'ID', exact: true }).click();
await page.getByRole('menuitem', { name: 'Single line text' }).click();
expect(await page.getByLabel('block-item-CollectionField-general-kanban-general.singleLineText').innerText()).toBe(
'singleLineText',
await expect(page.getByLabel('block-item-CollectionField-general-kanban-general.singleLineText')).toHaveText(
/singleLineText/,
);
expect(await page.getByLabel('block-item-CollectionField-general-kanban-general.id').innerText()).toBe('1');
await expect(page.getByLabel('block-item-CollectionField-general-kanban-general.id')).toHaveText(/1/);
//移除字段
await page.getByLabel('block-item-Kanban.Card-general-kanban').hover();
await page.getByLabel('designer-schema-initializer-Kanban.Card-Kanban.Card.Designer-general').hover();
await page.getByRole('menuitem', { name: 'ID', exact: true }).click();
await page.getByRole('menuitem', { name: 'Single line text' }).click();
await expect(
await page.getByLabel('block-item-CollectionField-general-kanban-general.singleLineText'),
).not.toBeVisible();
await expect(await page.getByLabel('block-item-CollectionField-general-kanban-general.id')).not.toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-general-kanban-general.singleLineText')).not.toBeVisible();
await expect(page.getByLabel('block-item-CollectionField-general-kanban-general.id')).not.toBeVisible();
});
test('configure association field', async ({ page, mockPage, mockRecord }) => {
const nocoPage = await mockPage(oneEmptyKanbanBlock).waitForInit();
@ -59,8 +57,8 @@ test.describe('configure fields', () => {
// 解析查询参数
const queryParams = new URLSearchParams(new URL(requestUrl).search);
const appends = queryParams.get('appends[]');
await expect(appends).toContain('manyToOne');
await expect(await page.getByLabel('block-item-CollectionField-general-kanban-general.manyToOne')).toBeVisible();
expect(appends).toContain('manyToOne');
await expect(page.getByLabel('block-item-CollectionField-general-kanban-general.manyToOne')).toBeVisible();
//修改标题字段
await page.getByLabel('schema-initializer-ActionBar-KanbanActionInitializers-general').click();
await page.getByLabel('block-item-CollectionField-general-kanban-general.manyToOne').hover();
@ -70,9 +68,7 @@ test.describe('configure fields', () => {
await page.getByText('Title field').click();
await page.getByRole('option', { name: 'Username' }).click();
//显示新的标题字段符合预期
expect(await page.getByLabel('block-item-CollectionField-general-kanban-general.manyToOne').innerText()).toBe(
'nocobase',
);
await expect(page.getByLabel('block-item-CollectionField-general-kanban-general.manyToOne')).toHaveText(/nocobase/);
});
});
@ -112,6 +108,6 @@ test.describe('configure actions', () => {
await page.getByRole('menuitem', { name: 'ID', exact: true }).click();
await page.getByRole('menuitem', { name: 'Created at' }).getByRole('switch').click();
await page.getByRole('menuitem', { name: 'Single Select' }).getByRole('switch').click();
await expect(await page.getByLabel('block-item-Kanban.Card-general-kanban')).toBeVisible();
await expect(page.getByLabel('block-item-Kanban.Card-general-kanban')).toBeVisible();
});
});

View File

@ -12,6 +12,8 @@ test.describe('configure setting', () => {
await page.getByLabel('block-item-CardItem-general-kanban').hover();
await page.getByLabel('designer-schema-settings-CardItem-Kanban.Designer-general').hover();
await page.getByRole('menuitem', { name: 'Fix block' }).click();
// 等待重渲染完成
await page.waitForTimeout(1000);
const kanbanBoard = page.getByLabel('block-item-CardItem-general-kanban');
const kanbanBoardHeight = await kanbanBoard.evaluate((element) => {
const computedStyle = window.getComputedStyle(element);
@ -21,8 +23,6 @@ test.describe('configure setting', () => {
return window.innerHeight;
});
const expectedHeight = windowHeight - 147;
await page.waitForTimeout(1000);
// 断言高度为预期值
expect(kanbanBoardHeight).toBe(expectedHeight);
});
test('set the data scope', async ({ page, mockPage, mockRecords }) => {

View File

@ -1,7 +1,5 @@
import { faker } from '@faker-js/faker';
import {
CreateWorkFlow,
EditWorkFlow,
ScheduleTriggerNode,
WorkflowListRecords,
apiCreateWorkflow,
@ -114,6 +112,7 @@ test.describe('Configuration Page Path Jump Workflow Management Page', () => {
mockCollections,
mockRecords,
}) => {
test.setTimeout(120000);
//数据表后缀标识
const triggerNodeAppendText = faker.string.alphanumeric(5);
//创建触发器节点数据表
@ -176,6 +175,7 @@ test.describe('Configuration Page Path Jump Workflow Management Page', () => {
mockCollections,
mockRecords,
}) => {
test.setTimeout(120000);
//数据表后缀标识
const triggerNodeAppendText = faker.string.alphanumeric(5);
@ -233,6 +233,7 @@ test.describe('Configuration Page Path Jump Workflow Management Page', () => {
mockCollections,
mockRecords,
}) => {
test.setTimeout(120000);
//数据表后缀标识
const triggerNodeAppendText = faker.string.alphanumeric(5);
@ -294,6 +295,7 @@ test.describe('Configuration page execution history', () => {});
test.describe('Configuration page copy to new version', () => {
test('Copy the Schedule event of the Configuration Trigger node', async ({ page, mockCollections, mockRecords }) => {
test.setTimeout(120000);
//数据表后缀标识
const triggerNodeAppendText = faker.string.alphanumeric(5);

View File

@ -1,18 +1,6 @@
import { faker } from '@faker-js/faker';
import {
CreateWorkFlow,
EditWorkFlow,
ScheduleTriggerNode,
WorkflowListRecords,
apiCreateWorkflow,
apiDeleteWorkflow,
apiGetWorkflow,
apiUpdateWorkflowTrigger,
appendJsonCollectionName,
generalWithNoRelationalFields,
} from '@nocobase/plugin-workflow-test/e2e';
import { CreateWorkFlow, EditWorkFlow, apiCreateWorkflow, apiDeleteWorkflow } from '@nocobase/plugin-workflow-test/e2e';
import { expect, test } from '@nocobase/test/e2e';
import { dayjs } from '@nocobase/utils';
test.describe('Filter', () => {
test('filter workflow name', async ({ page }) => {
@ -161,6 +149,7 @@ test.describe('Duplicate', () => {
await page.getByLabel(`action-Action-Submit-workflows-${workFlowName}`).click();
// 3、预期结果列表中出现筛选的工作流
await page.reload();
await expect(page.getByText(`${workFlowName} copy`)).toBeAttached();
// 4、后置处理删除工作流

View File

@ -3,7 +3,6 @@ import {
ClculationNode,
CollectionTriggerNode,
ConditionBranchNode,
ConditionYesNode,
QueryRecordNode,
apiCreateWorkflow,
apiCreateWorkflowNode,

View File

@ -3,7 +3,6 @@ import {
ClculationNode,
CollectionTriggerNode,
ConditionBranchNode,
ConditionYesNode,
QueryRecordNode,
apiCreateWorkflow,
apiCreateWorkflowNode,
@ -418,7 +417,7 @@ test('Collection event Add Data Trigger, determines that the trigger node single
const conditionNode = new ConditionBranchNode(page, conditionNodeName);
const conditionNodeId = await conditionNode.node.locator('.workflow-node-id').innerText();
await conditionNode.nodeConfigure.click();
await conditionNode.formulaRadio.click();
await conditionNode.formulaRadio.check();
await page.getByLabel('variable-button').click();
await page.getByRole('menuitemcheckbox', { name: 'Trigger variables' }).click();
await page.getByRole('menuitemcheckbox', { name: 'Trigger data' }).click();