mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-12-02 04:07:50 +08:00
feat: run e2e with pro plugins (#3890)
* feat: run e2e with pro plugins * fix: name * chore: fix typo * fix: make e2e pass * chore: only run pro e2e * Revert "chore: only run pro e2e" This reverts commit 9beff480c125ecbf221a61d69e09ca6e98119816. * chore: increase timeout * feat: support to set maxDepth * chore: set default maxDepth to 1 * chore: fix e2e to make pass * chore: add test for BlockSchemaToolbar * chore: split files to avoid slowing down testing * chore: make e2e more stable * chore: make e2e more stable * refactor: e2e --------- Co-authored-by: Zeke Zhang <958414905@qq.com>
This commit is contained in:
parent
2a4c356bc2
commit
31d68f91e8
18
.github/workflows/nocobase-test-e2e.yml
vendored
18
.github/workflows/nocobase-test-e2e.yml
vendored
@ -42,7 +42,19 @@ jobs:
|
|||||||
--health-timeout 5s
|
--health-timeout 5s
|
||||||
--health-retries 5
|
--health-retries 5
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
|
- name: Checkout pro-plugins
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
repository: nocobase/pro-plugins
|
||||||
|
ref: main
|
||||||
|
path: packages/pro-plugins
|
||||||
|
ssh-key: ${{ secrets.SUBMODULE_SSH_KEY }}
|
||||||
|
- name: Set variables
|
||||||
|
run: |
|
||||||
|
APPEND_PRESET_LOCAL_PLUGINS=$(find ./packages/pro-plugins/@nocobase -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sed 's/^plugin-//' | tr '\n' ',' | sed 's/,$//')
|
||||||
|
echo "var2=$APPEND_PRESET_LOCAL_PLUGINS" >> $GITHUB_OUTPUT
|
||||||
|
id: vars
|
||||||
- name: Use Node.js ${{ matrix.node_version }}
|
- name: Use Node.js ${{ matrix.node_version }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
@ -51,7 +63,6 @@ jobs:
|
|||||||
- name: Get yarn cache directory path
|
- name: Get yarn cache directory path
|
||||||
id: yarn-cache-dir-path
|
id: yarn-cache-dir-path
|
||||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
||||||
with:
|
with:
|
||||||
@ -78,4 +89,5 @@ jobs:
|
|||||||
DB_USER: nocobase
|
DB_USER: nocobase
|
||||||
DB_PASSWORD: password
|
DB_PASSWORD: password
|
||||||
DB_DATABASE: nocobase
|
DB_DATABASE: nocobase
|
||||||
timeout-minutes: 180
|
APPEND_PRESET_LOCAL_PLUGINS: ${{ steps.vars.outputs.var2 }}
|
||||||
|
timeout-minutes: 240
|
||||||
|
@ -85,6 +85,7 @@ async function appReady() {
|
|||||||
async function runApp(options = {}) {
|
async function runApp(options = {}) {
|
||||||
console.log('installing...');
|
console.log('installing...');
|
||||||
await run('nocobase', ['install', '-f']);
|
await run('nocobase', ['install', '-f']);
|
||||||
|
await run('nocobase', ['pm', 'enable-all']);
|
||||||
if (await isPortReachable(process.env.APP_PORT)) {
|
if (await isPortReachable(process.env.APP_PORT)) {
|
||||||
console.log('app started');
|
console.log('app started');
|
||||||
return;
|
return;
|
||||||
@ -232,6 +233,7 @@ module.exports = (cli) => {
|
|||||||
|
|
||||||
e2e.command('reinstall-app').action(async (options) => {
|
e2e.command('reinstall-app').action(async (options) => {
|
||||||
await run('nocobase', ['install', '-f'], options);
|
await run('nocobase', ['install', '-f'], options);
|
||||||
|
await run('nocobase', ['pm2', 'enable-all']);
|
||||||
});
|
});
|
||||||
|
|
||||||
e2e.command('install-deps').action(async () => {
|
e2e.command('install-deps').action(async () => {
|
||||||
|
@ -9,7 +9,7 @@ import { useSchemaTemplate } from '../../schema-templates';
|
|||||||
export const BlockSchemaToolbar = (props) => {
|
export const BlockSchemaToolbar = (props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const cm = useCollectionManager();
|
const cm = useCollectionManager();
|
||||||
let { name: currentCollectionName, title: currentCollectionTitle } = useCollection();
|
let { name: currentCollectionName, title: currentCollectionTitle } = useCollection() || {};
|
||||||
const template = useSchemaTemplate();
|
const template = useSchemaTemplate();
|
||||||
const { association } = useDataBlockProps() || {};
|
const { association } = useDataBlockProps() || {};
|
||||||
const compile = useCompile();
|
const compile = useCompile();
|
||||||
@ -40,13 +40,13 @@ export const BlockSchemaToolbar = (props) => {
|
|||||||
return <SchemaToolbar title={toolbarTitle} {...props} />;
|
return <SchemaToolbar title={toolbarTitle} {...props} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
function getCollectionTitle(arg0: {
|
export function getCollectionTitle(arg: {
|
||||||
collectionTitle: string;
|
collectionTitle: string;
|
||||||
collectionName: string;
|
collectionName: string;
|
||||||
associationField: any;
|
associationField: any;
|
||||||
compile: any;
|
compile: any;
|
||||||
}) {
|
}) {
|
||||||
const { collectionTitle, collectionName, associationField, compile } = arg0;
|
const { collectionTitle, collectionName, associationField, compile } = arg;
|
||||||
|
|
||||||
if (associationField) {
|
if (associationField) {
|
||||||
return `${compile(collectionTitle || collectionName)} > ${compile(
|
return `${compile(collectionTitle || collectionName)} > ${compile(
|
||||||
@ -54,5 +54,5 @@ function getCollectionTitle(arg0: {
|
|||||||
)}`;
|
)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return collectionTitle || collectionName;
|
return compile(collectionTitle || collectionName);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
import { getCollectionTitle } from '../BlockSchemaToolbar';
|
||||||
|
|
||||||
|
describe('getCollectionTitle', () => {
|
||||||
|
it('should return collectionTitle if associationField is falsy', () => {
|
||||||
|
const arg = {
|
||||||
|
collectionTitle: 'Collection Title',
|
||||||
|
collectionName: 'Collection Name',
|
||||||
|
associationField: null,
|
||||||
|
compile: vi.fn((value) => value),
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = getCollectionTitle(arg);
|
||||||
|
|
||||||
|
expect(result).toBe('Collection Title');
|
||||||
|
expect(arg.compile).toHaveBeenCalledWith('Collection Title');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return compiled collectionTitle and associationField title if associationField is truthy', () => {
|
||||||
|
const arg = {
|
||||||
|
collectionTitle: 'Collection Title',
|
||||||
|
collectionName: 'Collection Name',
|
||||||
|
associationField: {
|
||||||
|
uiSchema: {
|
||||||
|
title: 'Association Field Title',
|
||||||
|
},
|
||||||
|
name: 'Association Field Name',
|
||||||
|
},
|
||||||
|
compile: vi.fn((value) => `Compiled: ${value}`),
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = getCollectionTitle(arg);
|
||||||
|
|
||||||
|
expect(result).toBe('Compiled: Collection Title > Compiled: Association Field Title');
|
||||||
|
expect(arg.compile).toHaveBeenCalledTimes(2);
|
||||||
|
expect(arg.compile).toHaveBeenCalledWith('Collection Title');
|
||||||
|
expect(arg.compile).toHaveBeenCalledWith('Association Field Title');
|
||||||
|
});
|
||||||
|
});
|
@ -24,7 +24,7 @@ test.describe('where single data details block can be added', () => {
|
|||||||
clearBlockTemplates,
|
clearBlockTemplates,
|
||||||
}) => {
|
}) => {
|
||||||
const nocoPage = await mockPage(T3848).waitForInit();
|
const nocoPage = await mockPage(T3848).waitForInit();
|
||||||
await mockRecord('example');
|
await mockRecord('example', 2);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
// 1.打开弹窗
|
// 1.打开弹窗
|
||||||
|
@ -11,7 +11,7 @@ import { T2200, T2614, T2615, T2845, T2993 } from './templatesOfBug';
|
|||||||
test.describe('display association fields', () => {
|
test.describe('display association fields', () => {
|
||||||
test('form: should display correctly', async ({ page, mockPage, mockRecord }) => {
|
test('form: should display correctly', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(oneFormWithMultiLevelAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneFormWithMultiLevelAssociationFields).waitForInit();
|
||||||
await mockRecord('general');
|
await mockRecord('general', 2);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
// 为关系字段选中一个值
|
// 为关系字段选中一个值
|
||||||
@ -30,7 +30,7 @@ test.describe('display association fields', () => {
|
|||||||
|
|
||||||
test('subform: should display correctly', async ({ page, mockPage, mockRecord }) => {
|
test('subform: should display correctly', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(oneSubformWithMultiLevelAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneSubformWithMultiLevelAssociationFields).waitForInit();
|
||||||
await mockRecord('general');
|
await mockRecord('general', 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
// 为子表单中的关系字段选中一个值
|
// 为子表单中的关系字段选中一个值
|
||||||
@ -52,7 +52,7 @@ test.describe('display association fields', () => {
|
|||||||
// https://nocobase.height.app/T-2615
|
// https://nocobase.height.app/T-2615
|
||||||
test('should load association data', async ({ page, mockPage, mockRecord }) => {
|
test('should load association data', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(T2615).waitForInit();
|
const nocoPage = await mockPage(T2615).waitForInit();
|
||||||
await mockRecord('T2615');
|
await mockRecord('T2615', 2);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
// 1. 新增表单中应该显示关系字段的数据
|
// 1. 新增表单中应该显示关系字段的数据
|
||||||
@ -91,7 +91,7 @@ test.describe('display association fields', () => {
|
|||||||
test('should load association data of subform', async ({ page, mockPage, mockRecord }) => {
|
test('should load association data of subform', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(T2845).waitForInit();
|
const nocoPage = await mockPage(T2845).waitForInit();
|
||||||
// 和 T2615 使用一样的数据表结构
|
// 和 T2615 使用一样的数据表结构
|
||||||
const record = await mockRecord('T2615');
|
const record = await mockRecord('T2615', 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
// 1. 新增表单中应该显示关系字段的数据
|
// 1. 新增表单中应该显示关系字段的数据
|
||||||
@ -139,7 +139,7 @@ test.describe('display association fields', () => {
|
|||||||
// https://nocobase.height.app/T-2614
|
// https://nocobase.height.app/T-2614
|
||||||
test('should load association data in subform', async ({ page, mockPage, mockRecord }) => {
|
test('should load association data in subform', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(T2614).waitForInit();
|
const nocoPage = await mockPage(T2614).waitForInit();
|
||||||
await mockRecord('T2614');
|
await mockRecord('T2614', 2);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
// 查看详情
|
// 查看详情
|
||||||
@ -167,7 +167,7 @@ test.describe('display association fields', () => {
|
|||||||
// https://nocobase.height.app/T-2993
|
// https://nocobase.height.app/T-2993
|
||||||
test('should load association data of sub details', async ({ page, mockPage, mockRecord }) => {
|
test('should load association data of sub details', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(T2993).waitForInit();
|
const nocoPage = await mockPage(T2993).waitForInit();
|
||||||
const record = await mockRecord('T2993');
|
const record = await mockRecord('T2993', 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
await page.getByLabel('action-Action-Add new-create-').click();
|
await page.getByLabel('action-Action-Add new-create-').click();
|
||||||
@ -186,7 +186,7 @@ test.describe('display association fields', () => {
|
|||||||
test.describe('association fields', () => {
|
test.describe('association fields', () => {
|
||||||
test('subform: load association fields', async ({ page, mockPage, mockRecord }) => {
|
test('subform: load association fields', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(oneTableSubformWithMultiLevelAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableSubformWithMultiLevelAssociationFields).waitForInit();
|
||||||
const record = await mockRecord('general');
|
const record = await mockRecord('general', 4);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
// 查看详情
|
// 查看详情
|
||||||
@ -229,7 +229,7 @@ test.describe('association fields', () => {
|
|||||||
|
|
||||||
test('subtable: load association fields', async ({ page, mockPage, mockRecord }) => {
|
test('subtable: load association fields', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(oneTableSubtableWithMultiLevelAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableSubtableWithMultiLevelAssociationFields).waitForInit();
|
||||||
const record = await mockRecord('general');
|
const record = await mockRecord('general', 2);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
// 查看详情
|
// 查看详情
|
||||||
|
@ -3,7 +3,7 @@ import { expect, formBlockDefaultValueTemplate, test } from '@nocobase/test/e2e'
|
|||||||
test.describe('variables with default value', () => {
|
test.describe('variables with default value', () => {
|
||||||
test('current form', async ({ page, mockPage, mockRecord }) => {
|
test('current form', async ({ page, mockPage, mockRecord }) => {
|
||||||
const nocoPage = await mockPage(formBlockDefaultValueTemplate).waitForInit();
|
const nocoPage = await mockPage(formBlockDefaultValueTemplate).waitForInit();
|
||||||
await mockRecord('general');
|
await mockRecord('general', 2);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
await page.getByRole('button', { name: 'Add new' }).click();
|
await page.getByRole('button', { name: 'Add new' }).click();
|
||||||
|
@ -2,6 +2,7 @@ import {
|
|||||||
Page,
|
Page,
|
||||||
expect,
|
expect,
|
||||||
expectSettingsMenu,
|
expectSettingsMenu,
|
||||||
|
mockUserRecordsWithoutDepartments,
|
||||||
oneEmptyTableBlockWithActions,
|
oneEmptyTableBlockWithActions,
|
||||||
oneEmptyTableWithTreeCollection,
|
oneEmptyTableWithTreeCollection,
|
||||||
oneTableBlockWithActionsAndFormBlocks,
|
oneTableBlockWithActionsAndFormBlocks,
|
||||||
@ -232,7 +233,7 @@ test.describe('table block schema settings', () => {
|
|||||||
test.describe('connect data blocks', () => {
|
test.describe('connect data blocks', () => {
|
||||||
test('connecting two blocks of the same collection', async ({ page, mockPage, mockRecords }) => {
|
test('connecting two blocks of the same collection', async ({ page, mockPage, mockRecords }) => {
|
||||||
const nocoPage = await mockPage(twoTableWithSameCollection).waitForInit();
|
const nocoPage = await mockPage(twoTableWithSameCollection).waitForInit();
|
||||||
const records = await mockRecords('users', 3);
|
const records = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
// 将左边的 Table 连接到右边的 Table
|
// 将左边的 Table 连接到右边的 Table
|
||||||
@ -257,7 +258,7 @@ test.describe('table block schema settings', () => {
|
|||||||
|
|
||||||
test('connecting two blocks connected by a relationship field', async ({ page, mockPage, mockRecords }) => {
|
test('connecting two blocks connected by a relationship field', async ({ page, mockPage, mockRecords }) => {
|
||||||
const nocoPage = await mockPage(twoTableWithAssociationFields).waitForInit();
|
const nocoPage = await mockPage(twoTableWithAssociationFields).waitForInit();
|
||||||
await mockRecords('users', 3);
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
// 将左边的 Table 连接到右边的 Table
|
// 将左边的 Table 连接到右边的 Table
|
||||||
|
@ -46,6 +46,17 @@ export default (app: Application) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pm.command('enable-all')
|
||||||
|
.ipc()
|
||||||
|
.preload()
|
||||||
|
.action(async () => {
|
||||||
|
try {
|
||||||
|
await app.pm.enable('*');
|
||||||
|
} catch (error) {
|
||||||
|
throw new PluginCommandError(`Failed to enable plugin`, { cause: error });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
pm.command('enable')
|
pm.command('enable')
|
||||||
.ipc()
|
.ipc()
|
||||||
.preload()
|
.preload()
|
||||||
|
@ -75,7 +75,7 @@ export class Locale {
|
|||||||
|
|
||||||
getResources(lang: string) {
|
getResources(lang: string) {
|
||||||
const resources = {};
|
const resources = {};
|
||||||
const names = this.app.pm.getAliases();
|
const names = this.app.pm.getPlugins().keys();
|
||||||
for (const name of names) {
|
for (const name of names) {
|
||||||
try {
|
try {
|
||||||
const p = this.app.pm.get(name);
|
const p = this.app.pm.get(name);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import Topo from '@hapi/topo';
|
||||||
import { CleanOptions, Collection, SyncOptions } from '@nocobase/database';
|
import { CleanOptions, Collection, SyncOptions } from '@nocobase/database';
|
||||||
import { importModule, isURL } from '@nocobase/utils';
|
import { importModule, isURL } from '@nocobase/utils';
|
||||||
import { fsExists } from '@nocobase/utils/plugin-symlink';
|
import { fsExists } from '@nocobase/utils/plugin-symlink';
|
||||||
@ -328,6 +329,9 @@ export class PluginManager {
|
|||||||
if (options.name) {
|
if (options.name) {
|
||||||
this.pluginAliases.set(options.name, instance);
|
this.pluginAliases.set(options.name, instance);
|
||||||
}
|
}
|
||||||
|
if (options.packageName) {
|
||||||
|
this.pluginAliases.set(options.packageName, instance);
|
||||||
|
}
|
||||||
if (insert && options.name) {
|
if (insert && options.name) {
|
||||||
await this.repository.updateOrCreate({
|
await this.repository.updateOrCreate({
|
||||||
values: {
|
values: {
|
||||||
@ -478,8 +482,27 @@ export class PluginManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sort(names: string | string[]) {
|
||||||
|
const pluginNames = _.castArray(names);
|
||||||
|
if (pluginNames.length === 1) {
|
||||||
|
return pluginNames;
|
||||||
|
}
|
||||||
|
const sorter = new Topo.Sorter<string>();
|
||||||
|
for (const pluginName of pluginNames) {
|
||||||
|
const plugin = this.get(pluginName);
|
||||||
|
const peerDependencies = Object.keys(plugin.options?.packageJson?.peerDependencies || {});
|
||||||
|
sorter.add(pluginName, { after: peerDependencies, group: plugin.options?.packageName || pluginName });
|
||||||
|
}
|
||||||
|
return sorter.nodes;
|
||||||
|
}
|
||||||
|
|
||||||
async enable(name: string | string[]) {
|
async enable(name: string | string[]) {
|
||||||
const pluginNames = _.castArray(name);
|
let pluginNames = name;
|
||||||
|
if (name === '*') {
|
||||||
|
const items = await this.repository.find();
|
||||||
|
pluginNames = items.map((item: any) => item.name);
|
||||||
|
}
|
||||||
|
pluginNames = this.sort(pluginNames);
|
||||||
this.app.log.debug(`enabling plugin ${pluginNames.join(',')}`);
|
this.app.log.debug(`enabling plugin ${pluginNames.join(',')}`);
|
||||||
this.app.setMaintainingMessage(`enabling plugin ${pluginNames.join(',')}`);
|
this.app.setMaintainingMessage(`enabling plugin ${pluginNames.join(',')}`);
|
||||||
const toBeUpdated = [];
|
const toBeUpdated = [];
|
||||||
@ -492,9 +515,17 @@ export class PluginManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
await this.app.emitAsync('beforeEnablePlugin', pluginName);
|
await this.app.emitAsync('beforeEnablePlugin', pluginName);
|
||||||
await plugin.beforeEnable();
|
try {
|
||||||
plugin.enabled = true;
|
await plugin.beforeEnable();
|
||||||
toBeUpdated.push(pluginName);
|
plugin.enabled = true;
|
||||||
|
toBeUpdated.push(pluginName);
|
||||||
|
} catch (error) {
|
||||||
|
if (name === '*') {
|
||||||
|
this.app.log.error(error.message);
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (toBeUpdated.length === 0) {
|
if (toBeUpdated.length === 0) {
|
||||||
return;
|
return;
|
||||||
@ -509,10 +540,10 @@ export class PluginManager {
|
|||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await this.app.reload();
|
await this.app.reload();
|
||||||
this.app.log.debug(`syncing database in enable plugin ${pluginNames.join(',')}...`);
|
this.app.log.debug(`syncing database in enable plugin ${toBeUpdated.join(',')}...`);
|
||||||
this.app.setMaintainingMessage(`syncing database in enable plugin ${pluginNames.join(',')}...`);
|
this.app.setMaintainingMessage(`syncing database in enable plugin ${toBeUpdated.join(',')}...`);
|
||||||
await this.app.db.sync();
|
await this.app.db.sync();
|
||||||
for (const pluginName of pluginNames) {
|
for (const pluginName of toBeUpdated) {
|
||||||
const plugin = this.get(pluginName);
|
const plugin = this.get(pluginName);
|
||||||
if (!plugin.installed) {
|
if (!plugin.installed) {
|
||||||
this.app.log.debug(`installing plugin ${pluginName}...`);
|
this.app.log.debug(`installing plugin ${pluginName}...`);
|
||||||
@ -529,7 +560,7 @@ export class PluginManager {
|
|||||||
installed: true,
|
installed: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
for (const pluginName of pluginNames) {
|
for (const pluginName of toBeUpdated) {
|
||||||
const plugin = this.get(pluginName);
|
const plugin = this.get(pluginName);
|
||||||
this.app.log.debug(`emit afterEnablePlugin event...`);
|
this.app.log.debug(`emit afterEnablePlugin event...`);
|
||||||
await plugin.afterEnable();
|
await plugin.afterEnable();
|
||||||
@ -884,7 +915,7 @@ export class PluginManager {
|
|||||||
async list(options: any = {}) {
|
async list(options: any = {}) {
|
||||||
const { locale = 'en-US', isPreset = false } = options;
|
const { locale = 'en-US', isPreset = false } = options;
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
[...this.getAliases()]
|
[...this.getPlugins().keys()]
|
||||||
.map((name) => {
|
.map((name) => {
|
||||||
const plugin = this.get(name);
|
const plugin = this.get(name);
|
||||||
if (!isPreset && plugin.options.isPreset) {
|
if (!isPreset && plugin.options.isPreset) {
|
||||||
|
@ -206,11 +206,21 @@ interface ExtendUtils {
|
|||||||
mockCollection: (collectionSetting: CollectionSetting) => Promise<any>;
|
mockCollection: (collectionSetting: CollectionSetting) => Promise<any>;
|
||||||
/**
|
/**
|
||||||
* 自动生成一条对应 collection 的数据
|
* 自动生成一条对应 collection 的数据
|
||||||
* @param collectionName 数据表名称
|
|
||||||
* @param data 自定义的数据,缺失时会生成随机数据
|
|
||||||
* @returns 返回一条生成的数据
|
* @returns 返回一条生成的数据
|
||||||
*/
|
*/
|
||||||
mockRecord: <T = any>(collectionName: string, data?: any) => Promise<T>;
|
mockRecord: {
|
||||||
|
/**
|
||||||
|
* @param collectionName 数据表名称
|
||||||
|
* @param data 自定义的数据,缺失时会生成随机数据
|
||||||
|
* @param maxDepth - 生成的数据的最大深度,默认为 4,当不想生成太多数据时可以设置一个较低的值
|
||||||
|
*/
|
||||||
|
<T = any>(collectionName: string, data?: any, maxDepth?: number): Promise<T>;
|
||||||
|
/**
|
||||||
|
* @param collectionName 数据表名称
|
||||||
|
* @param maxDepth - 生成的数据的最大深度,默认为 4,当不想生成太多数据时可以设置一个较低的值
|
||||||
|
*/
|
||||||
|
<T = any>(collectionName: string, maxDepth?: number): Promise<T>;
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* 自动生成多条对应 collection 的数据
|
* 自动生成多条对应 collection 的数据
|
||||||
*/
|
*/
|
||||||
@ -218,13 +228,15 @@ interface ExtendUtils {
|
|||||||
/**
|
/**
|
||||||
* @param collectionName - 数据表名称
|
* @param collectionName - 数据表名称
|
||||||
* @param count - 生成的数据条数
|
* @param count - 生成的数据条数
|
||||||
|
* @param maxDepth - 生成的数据的最大深度,默认为 4,当不想生成太多数据时可以设置一个较低的值
|
||||||
*/
|
*/
|
||||||
<T = any>(collectionName: string, count?: number): Promise<T[]>;
|
<T = any>(collectionName: string, count?: number, maxDepth?: number): Promise<T[]>;
|
||||||
/**
|
/**
|
||||||
* @param collectionName - 数据表名称
|
* @param collectionName - 数据表名称
|
||||||
* @param data - 指定生成的数据
|
* @param data - 指定生成的数据
|
||||||
|
* @param maxDepth - 生成的数据的最大深度,默认为 4,当不想生成太多数据时可以设置一个较低的值
|
||||||
*/
|
*/
|
||||||
<T = any>(collectionName: string, data?: any[]): Promise<T[]>;
|
<T = any>(collectionName: string, data?: any[], maxDepth?: number): Promise<T[]>;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* 该方法已弃用,请使用 mockCollections
|
* 该方法已弃用,请使用 mockCollections
|
||||||
@ -408,18 +420,28 @@ const _test = base.extend<ExtendUtils>({
|
|||||||
},
|
},
|
||||||
mockRecords: async ({ page }, use) => {
|
mockRecords: async ({ page }, use) => {
|
||||||
const mockRecords = async (collectionName: string, count: any = 3, data?: any) => {
|
const mockRecords = async (collectionName: string, count: any = 3, data?: any) => {
|
||||||
|
let maxDepth: number;
|
||||||
|
if (_.isNumber(data)) {
|
||||||
|
maxDepth = data;
|
||||||
|
data = undefined;
|
||||||
|
}
|
||||||
if (_.isArray(count)) {
|
if (_.isArray(count)) {
|
||||||
data = count;
|
data = count;
|
||||||
count = data.length;
|
count = data.length;
|
||||||
}
|
}
|
||||||
return createRandomData(collectionName, count, data);
|
return createRandomData(collectionName, count, data, maxDepth);
|
||||||
};
|
};
|
||||||
|
|
||||||
await use(mockRecords);
|
await use(mockRecords);
|
||||||
},
|
},
|
||||||
mockRecord: async ({ page }, use) => {
|
mockRecord: async ({ page }, use) => {
|
||||||
const mockRecord = async (collectionName: string, data?: any) => {
|
const mockRecord = async (collectionName: string, data?: any, maxDepth?: any) => {
|
||||||
const result = await createRandomData(collectionName, 1, data);
|
if (_.isNumber(data)) {
|
||||||
|
maxDepth = data;
|
||||||
|
data = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await createRandomData(collectionName, 1, data, maxDepth);
|
||||||
return result[0];
|
return result[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -861,7 +883,7 @@ const generateFakerData = (collectionSetting: CollectionSetting) => {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
const createRandomData = async (collectionName: string, count = 10, data?: any) => {
|
const createRandomData = async (collectionName: string, count = 10, data?: any, maxDepth?: number) => {
|
||||||
const api = await request.newContext({
|
const api = await request.newContext({
|
||||||
storageState: process.env.PLAYWRIGHT_AUTH_FILE,
|
storageState: process.env.PLAYWRIGHT_AUTH_FILE,
|
||||||
});
|
});
|
||||||
@ -869,10 +891,13 @@ const createRandomData = async (collectionName: string, count = 10, data?: any)
|
|||||||
const state = await api.storageState();
|
const state = await api.storageState();
|
||||||
const headers = getHeaders(state);
|
const headers = getHeaders(state);
|
||||||
|
|
||||||
const result = await api.post(`/api/${collectionName}:mock?count=${count}`, {
|
const result = await api.post(
|
||||||
headers,
|
`/api/${collectionName}:mock?count=${count}&maxDepth=${_.isNumber(maxDepth) ? maxDepth : 1}`,
|
||||||
data,
|
{
|
||||||
});
|
headers,
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
if (!result.ok()) {
|
if (!result.ok()) {
|
||||||
throw new Error(await result.text());
|
throw new Error(await result.text());
|
||||||
@ -993,3 +1018,13 @@ export const createBlockInPage = async (page: Page, name: string) => {
|
|||||||
|
|
||||||
await page.mouse.move(300, 0);
|
await page.mouse.move(300, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const mockUserRecordsWithoutDepartments = (mockRecords: ExtendUtils['mockRecords'], count: number) => {
|
||||||
|
return mockRecords(
|
||||||
|
'users',
|
||||||
|
Array.from({ length: count }).map(() => ({
|
||||||
|
departments: null,
|
||||||
|
mainDepartment: null,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
expectInitializerMenu,
|
expectInitializerMenu,
|
||||||
|
mockUserRecordsWithoutDepartments,
|
||||||
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
||||||
test,
|
test,
|
||||||
} from '@nocobase/test/e2e';
|
} from '@nocobase/test/e2e';
|
||||||
@ -7,7 +8,7 @@ import {
|
|||||||
test.describe('form item & create form', () => {
|
test.describe('form item & create form', () => {
|
||||||
test('configure fields', async ({ page, mockPage, mockRecords }) => {
|
test('configure fields', async ({ page, mockPage, mockRecords }) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
await mockRecords('users', 3);
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
await expectInitializerMenu({
|
await expectInitializerMenu({
|
||||||
@ -24,7 +25,7 @@ test.describe('form item & create form', () => {
|
|||||||
test.describe('form item & edit form', () => {
|
test.describe('form item & edit form', () => {
|
||||||
test('configure fields', async ({ page, mockPage, mockRecords }) => {
|
test('configure fields', async ({ page, mockPage, mockRecords }) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
await mockRecords('users', 3);
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await mockRecords('general', 1);
|
await mockRecords('general', 1);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import {
|
|||||||
Page,
|
Page,
|
||||||
expect,
|
expect,
|
||||||
expectSettingsMenu,
|
expectSettingsMenu,
|
||||||
|
mockUserRecordsWithoutDepartments,
|
||||||
oneFilterFormBlockWithAllAssociationFields,
|
oneFilterFormBlockWithAllAssociationFields,
|
||||||
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
||||||
test,
|
test,
|
||||||
@ -11,7 +12,7 @@ import { createColumnItem, showSettingsMenu, testPattern } from '../../utils';
|
|||||||
test.describe('form item & create form', () => {
|
test.describe('form item & create form', () => {
|
||||||
test('supported options', async ({ page, mockPage, mockRecords }) => {
|
test('supported options', async ({ page, mockPage, mockRecords }) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
await mockRecords('users', 3);
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
await expectSettingsMenu({
|
await expectSettingsMenu({
|
||||||
@ -44,7 +45,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('set default value', async ({ page, mockPage, mockRecord, mockRecords }) => {
|
test('set default value', async ({ page, mockPage, mockRecord, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -67,7 +68,7 @@ test.describe('form item & create form', () => {
|
|||||||
page,
|
page,
|
||||||
gotoPage: async () => {
|
gotoPage: async () => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
records = await mockRecords('users', 3);
|
records = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
},
|
},
|
||||||
openDialog: async () => {
|
openDialog: async () => {
|
||||||
@ -108,7 +109,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
||||||
const records = await (async (mockPage, mockRecords) => {
|
const records = await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -154,7 +155,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('field component', async ({ page, mockPage, mockRecords }) => {
|
test('field component', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -180,7 +181,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -201,7 +202,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('title field', async ({ page, mockPage, mockRecords }) => {
|
test('title field', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -222,7 +223,7 @@ test.describe('form item & create form', () => {
|
|||||||
test.describe('form item & edit form', () => {
|
test.describe('form item & edit form', () => {
|
||||||
test('supported options', async ({ page, mockRecords, mockPage }) => {
|
test('supported options', async ({ page, mockRecords, mockPage }) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
await mockRecords('users', 3);
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await mockRecords('general', 1);
|
await mockRecords('general', 1);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -262,7 +263,7 @@ test.describe('form item & edit form', () => {
|
|||||||
record = (
|
record = (
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -308,7 +309,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
||||||
const { recordsOfUser } = await (async (mockPage, mockRecords) => {
|
const { recordsOfUser } = await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -355,7 +356,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('field component', async ({ page, mockPage, mockRecords }) => {
|
test('field component', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -382,7 +383,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -404,7 +405,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('title field', async ({ page, mockPage, mockRecords }) => {
|
test('title field', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import {
|
|||||||
Page,
|
Page,
|
||||||
expect,
|
expect,
|
||||||
expectSettingsMenu,
|
expectSettingsMenu,
|
||||||
|
mockUserRecordsWithoutDepartments,
|
||||||
oneFilterFormBlockWithAllAssociationFields,
|
oneFilterFormBlockWithAllAssociationFields,
|
||||||
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
||||||
test,
|
test,
|
||||||
@ -11,7 +12,7 @@ import { createColumnItem, showSettingsMenu, testPattern } from '../../utils';
|
|||||||
test.describe('form item & create form', () => {
|
test.describe('form item & create form', () => {
|
||||||
test('supported options', async ({ page, mockPage, mockRecords }) => {
|
test('supported options', async ({ page, mockPage, mockRecords }) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
await mockRecords('users', 3);
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
await expectSettingsMenu({
|
await expectSettingsMenu({
|
||||||
@ -42,7 +43,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('set default value', async ({ page, mockPage, mockRecord, mockRecords }) => {
|
test('set default value', async ({ page, mockPage, mockRecord, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -66,7 +67,7 @@ test.describe('form item & create form', () => {
|
|||||||
gotoPage: async () => {
|
gotoPage: async () => {
|
||||||
records = await (async (mockPage, mockRecords) => {
|
records = await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -112,7 +113,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
||||||
const records = await (async (mockPage, mockRecords) => {
|
const records = await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -158,7 +159,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('field component', async ({ page, mockPage, mockRecords }) => {
|
test('field component', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -184,7 +185,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -205,7 +206,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('title field', async ({ page, mockPage, mockRecords }) => {
|
test('title field', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -226,7 +227,7 @@ test.describe('form item & create form', () => {
|
|||||||
test.describe('form item & edit form', () => {
|
test.describe('form item & edit form', () => {
|
||||||
test('supported options', async ({ page, mockRecords, mockPage }) => {
|
test('supported options', async ({ page, mockRecords, mockPage }) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
await mockRecords('users', 3);
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await mockRecords('general', 1);
|
await mockRecords('general', 1);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -264,7 +265,7 @@ test.describe('form item & edit form', () => {
|
|||||||
record = (
|
record = (
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -310,7 +311,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -356,7 +357,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('field component', async ({ page, mockPage, mockRecords }) => {
|
test('field component', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -383,7 +384,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -405,7 +406,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('title field', async ({ page, mockPage, mockRecords }) => {
|
test('title field', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
@ -1,803 +0,0 @@
|
|||||||
import {
|
|
||||||
Page,
|
|
||||||
expect,
|
|
||||||
expectSettingsMenu,
|
|
||||||
oneFilterFormBlockWithAllAssociationFields,
|
|
||||||
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
|
||||||
test,
|
|
||||||
} from '@nocobase/test/e2e';
|
|
||||||
import { createColumnItem, showSettingsMenu, testDefaultValue, testPattern } from '../../utils';
|
|
||||||
|
|
||||||
test.describe('form item & create form', () => {
|
|
||||||
test('supported options', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
await mockRecords('users', 3);
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
await expectSettingsMenu({
|
|
||||||
page,
|
|
||||||
showMenu: async () => {
|
|
||||||
await page.getByRole('button', { name: 'Add new' }).click();
|
|
||||||
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();
|
|
||||||
},
|
|
||||||
supportedOptions: [
|
|
||||||
'Edit field title',
|
|
||||||
'Display title',
|
|
||||||
'Edit description',
|
|
||||||
'Required',
|
|
||||||
'Set default value',
|
|
||||||
'Set the data scope',
|
|
||||||
'Set default sorting rules',
|
|
||||||
'Field component',
|
|
||||||
'Quick create',
|
|
||||||
'Allow multiple',
|
|
||||||
'Pattern',
|
|
||||||
'Title field',
|
|
||||||
'Delete',
|
|
||||||
],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('set default value', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
let recordsOfUser;
|
|
||||||
await testDefaultValue({
|
|
||||||
page,
|
|
||||||
gotoPage: async () => {
|
|
||||||
recordsOfUser = await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return recordsOfUser;
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
},
|
|
||||||
openDialog: () =>
|
|
||||||
(async (page: Page) => {
|
|
||||||
await page.getByRole('button', { name: 'Add new' }).click();
|
|
||||||
})(page),
|
|
||||||
closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(),
|
|
||||||
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, 'manyToMany'),
|
|
||||||
supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'],
|
|
||||||
inputConstantValue: async () => {
|
|
||||||
await page.getByLabel('block-item-VariableInput-').getByTestId('select-object-multiple').click();
|
|
||||||
await page.getByRole('option', { name: String(recordsOfUser[0].id), exact: true }).click();
|
|
||||||
await page.getByRole('option', { name: String(recordsOfUser[1].id), exact: true }).click();
|
|
||||||
await page.getByRole('option', { name: String(recordsOfUser[2].id), exact: true }).click();
|
|
||||||
},
|
|
||||||
expectConstantValue: async () => {
|
|
||||||
await expect(
|
|
||||||
page.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany'),
|
|
||||||
).toHaveText(`manyToMany:${recordsOfUser.map((record) => record.id).join('')}`);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('pattern', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
let records;
|
|
||||||
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);
|
|
||||||
},
|
|
||||||
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, 'manyToMany'),
|
|
||||||
expectEditable: async () => {
|
|
||||||
await page
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.getByTestId('select-object-multiple')
|
|
||||||
.click();
|
|
||||||
await page.getByRole('option', { name: String(records[0].id), exact: true }).click();
|
|
||||||
await page.getByRole('option', { name: String(records[1].id), exact: true }).click();
|
|
||||||
await page.getByRole('option', { name: String(records[2].id), exact: true }).click();
|
|
||||||
},
|
|
||||||
expectReadonly: async () => {
|
|
||||||
await expect(
|
|
||||||
page
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.getByTestId('select-object-multiple'),
|
|
||||||
).toHaveClass(/ant-select-disabled/);
|
|
||||||
// 在这里等待一下,防止因闪烁导致下面的断言失败
|
|
||||||
await page.waitForTimeout(100);
|
|
||||||
},
|
|
||||||
expectEasyReading: async () => {
|
|
||||||
await expect(
|
|
||||||
page.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany'),
|
|
||||||
).toHaveText(`manyToMany:${records.map((record) => record.id).join(',')}`);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
const records = await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return recordsOfUser;
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByRole('button', { name: 'Add new' }).click();
|
|
||||||
})(page);
|
|
||||||
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.getByRole('menuitem', { name: 'Set the data scope' }).click();
|
|
||||||
await page.getByText('Add condition', { exact: true }).click();
|
|
||||||
await page.getByTestId('select-filter-field').click();
|
|
||||||
await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click();
|
|
||||||
await page.getByRole('spinbutton').click();
|
|
||||||
await page.getByRole('spinbutton').fill(String(records[0].id));
|
|
||||||
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
|
||||||
|
|
||||||
// 再次打开弹窗,设置的值应该还在
|
|
||||||
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.getByRole('menuitem', { name: 'Set the data scope' }).click();
|
|
||||||
await expect(page.getByTestId('select-filter-field')).toHaveText('ID');
|
|
||||||
await expect(page.getByRole('spinbutton')).toHaveValue(String(records[0].id));
|
|
||||||
await page.getByRole('button', { name: 'Cancel', exact: true }).click();
|
|
||||||
|
|
||||||
// 数据应该被过滤了
|
|
||||||
await page
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.getByTestId('select-object-multiple')
|
|
||||||
.click();
|
|
||||||
await expect(page.getByRole('option', { name: String(records[0].id), exact: true })).toBeVisible();
|
|
||||||
await expect(page.getByRole('option')).toHaveCount(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('set default sorting rules', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return recordsOfUser;
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByRole('button', { name: 'Add new' }).click();
|
|
||||||
})(page);
|
|
||||||
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.getByRole('menuitem', { name: 'Set default sorting rules' }).click();
|
|
||||||
|
|
||||||
// 配置
|
|
||||||
await page.getByRole('button', { name: 'Add sort field' }).click();
|
|
||||||
await page.getByTestId('select-single').click();
|
|
||||||
await page.getByRole('option', { name: 'ID', exact: true }).click();
|
|
||||||
await page.getByText('DESC', { exact: true }).click();
|
|
||||||
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
|
||||||
|
|
||||||
// 再次打开弹窗,设置的值应该还在
|
|
||||||
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.getByRole('menuitem', { name: 'Set default sorting rules' }).click();
|
|
||||||
await expect(page.getByRole('dialog').getByTestId('select-single')).toHaveText('ID');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('field component', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return recordsOfUser;
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByRole('button', { name: 'Add new' }).click();
|
|
||||||
})(page);
|
|
||||||
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.getByRole('menuitem', { name: 'Field component' }).click();
|
|
||||||
|
|
||||||
// 断言支持的选项
|
|
||||||
await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible();
|
|
||||||
await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible();
|
|
||||||
await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible();
|
|
||||||
await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible();
|
|
||||||
await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible();
|
|
||||||
|
|
||||||
// 选择 Record picker
|
|
||||||
await page.getByRole('option', { name: 'Record picker', exact: true }).click();
|
|
||||||
await expect(
|
|
||||||
page
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.getByTestId('select-data-picker'),
|
|
||||||
).toBeVisible();
|
|
||||||
|
|
||||||
// 选择 Sub-table
|
|
||||||
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.getByRole('menuitem', { name: 'Field component' }).click();
|
|
||||||
await page.getByRole('option', { name: 'Sub-table', exact: true }).click();
|
|
||||||
await expect(
|
|
||||||
page
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.getByLabel('schema-initializer-AssociationField.SubTable-table:configureColumns-users'),
|
|
||||||
).toBeVisible();
|
|
||||||
|
|
||||||
// 选择 Sub-form
|
|
||||||
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.getByRole('menuitem', { name: 'Field component' }).click();
|
|
||||||
await page.getByRole('option', { name: 'Sub-form', exact: true }).click();
|
|
||||||
await expect(
|
|
||||||
page
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.getByLabel('schema-initializer-Grid-form:configureFields-users'),
|
|
||||||
).toBeVisible();
|
|
||||||
|
|
||||||
// 选择 Sub-form(Popover)
|
|
||||||
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
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.getByRole('img', { name: 'edit' })
|
|
||||||
.click();
|
|
||||||
await expect(page.getByTestId('popover-CollectionField-general')).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return recordsOfUser;
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByRole('button', { name: 'Add new' }).click();
|
|
||||||
})(page);
|
|
||||||
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 expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('allow multiple', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return recordsOfUser;
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByRole('button', { name: 'Add new' }).click();
|
|
||||||
})(page);
|
|
||||||
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 expect(page.getByRole('menuitem', { name: 'Allow multiple' })).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('title field', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return recordsOfUser;
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByRole('button', { name: 'Add new' }).click();
|
|
||||||
})(page);
|
|
||||||
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 expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test.describe('form item & edit form', () => {
|
|
||||||
test('supported options', async ({ page, mockRecords, mockPage }) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
await mockRecords('users', 3);
|
|
||||||
await mockRecords('general', 1);
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
await expectSettingsMenu({
|
|
||||||
page,
|
|
||||||
showMenu: async () => {
|
|
||||||
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
|
|
||||||
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();
|
|
||||||
},
|
|
||||||
supportedOptions: [
|
|
||||||
'Edit field title',
|
|
||||||
'Display title',
|
|
||||||
'Edit description',
|
|
||||||
'Required',
|
|
||||||
'Set the data scope',
|
|
||||||
'Set default sorting rules',
|
|
||||||
'Field component',
|
|
||||||
'Quick create',
|
|
||||||
'Allow multiple',
|
|
||||||
'Pattern',
|
|
||||||
'Title field',
|
|
||||||
'Delete',
|
|
||||||
],
|
|
||||||
unsupportedOptions: ['Set default value'],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('pattern', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
let record;
|
|
||||||
await testPattern({
|
|
||||||
page,
|
|
||||||
gotoPage: async () => {
|
|
||||||
record = (
|
|
||||||
await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
const record = (await mockRecords('general', 1))[0];
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return { record, recordsOfUser };
|
|
||||||
})(mockPage, mockRecords)
|
|
||||||
).record;
|
|
||||||
},
|
|
||||||
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}`).hover();
|
|
||||||
await page
|
|
||||||
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`)
|
|
||||||
.hover();
|
|
||||||
})(page, 'manyToMany'),
|
|
||||||
expectEditable: async () => {
|
|
||||||
await expect(
|
|
||||||
page
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.getByTestId('select-object-multiple'),
|
|
||||||
).toHaveText(`${record.manyToMany.map((item) => item.id).join('')}`);
|
|
||||||
},
|
|
||||||
expectReadonly: async () => {
|
|
||||||
await expect(
|
|
||||||
page
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.getByTestId('select-object-multiple'),
|
|
||||||
).toHaveClass(/ant-select-disabled/);
|
|
||||||
// 在这里等待一下,防止因闪烁导致下面的断言失败
|
|
||||||
await page.waitForTimeout(100);
|
|
||||||
},
|
|
||||||
expectEasyReading: async () => {
|
|
||||||
await expect(
|
|
||||||
page.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany'),
|
|
||||||
).toHaveText(`manyToMany:${record.manyToMany.map((item) => item.id).join(',')}`);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
const { recordsOfUser } = await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
const record = (await mockRecords('general', 1))[0];
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return { record, recordsOfUser };
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
|
|
||||||
})(page);
|
|
||||||
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.getByRole('menuitem', { name: 'Set the data scope' }).click();
|
|
||||||
await page.getByText('Add condition', { exact: true }).click();
|
|
||||||
await page.getByTestId('select-filter-field').click();
|
|
||||||
await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click();
|
|
||||||
await page.getByRole('spinbutton').click();
|
|
||||||
await page.getByRole('spinbutton').fill(String(recordsOfUser[0].id));
|
|
||||||
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
|
||||||
|
|
||||||
// 再次打开弹窗,设置的值应该还在
|
|
||||||
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.getByRole('menuitem', { name: 'Set the data scope' }).click();
|
|
||||||
await expect(page.getByTestId('select-filter-field')).toHaveText('ID');
|
|
||||||
await expect(page.getByRole('spinbutton')).toHaveValue(String(recordsOfUser[0].id));
|
|
||||||
await page.getByRole('button', { name: 'Cancel', exact: true }).click();
|
|
||||||
|
|
||||||
// 数据应该被过滤了
|
|
||||||
await page
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.getByTestId('select-object-multiple')
|
|
||||||
.click();
|
|
||||||
await expect(page.getByRole('option', { name: String(recordsOfUser[0].id), exact: true })).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('set default sorting rules', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
const record = (await mockRecords('general', 1))[0];
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return { record, recordsOfUser };
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
|
|
||||||
})(page);
|
|
||||||
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.getByRole('menuitem', { name: 'Set default sorting rules' }).click();
|
|
||||||
|
|
||||||
// 配置
|
|
||||||
await page.getByRole('button', { name: 'Add sort field' }).click();
|
|
||||||
await page.getByTestId('select-single').click();
|
|
||||||
await page.getByRole('option', { name: 'ID', exact: true }).click();
|
|
||||||
await page.getByText('DESC', { exact: true }).click();
|
|
||||||
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
|
||||||
|
|
||||||
// 再次打开弹窗,设置的值应该还在
|
|
||||||
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.getByRole('menuitem', { name: 'Set default sorting rules' }).click();
|
|
||||||
await expect(page.getByRole('dialog').getByTestId('select-single')).toHaveText('ID');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('field component', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
const record = (await mockRecords('general', 1))[0];
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return { record, recordsOfUser };
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
|
|
||||||
})(page);
|
|
||||||
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.getByRole('menuitem', { name: 'Field component' }).click();
|
|
||||||
|
|
||||||
// 断言支持的选项
|
|
||||||
await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible();
|
|
||||||
await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible();
|
|
||||||
await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible();
|
|
||||||
await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible();
|
|
||||||
await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
const record = (await mockRecords('general', 1))[0];
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return { record, recordsOfUser };
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
|
|
||||||
})(page);
|
|
||||||
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 expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('allow multiple', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
const record = (await mockRecords('general', 1))[0];
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return { record, recordsOfUser };
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
|
|
||||||
})(page);
|
|
||||||
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 expect(page.getByRole('menuitem', { name: 'Allow multiple' })).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('title field', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
|
||||||
const record = (await mockRecords('general', 1))[0];
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return { record, recordsOfUser };
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
|
|
||||||
})(page);
|
|
||||||
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 expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test.describe('form item & view form', () => {
|
|
||||||
test('supported options', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
await mockRecords('general', 1);
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
await expectSettingsMenu({
|
|
||||||
page,
|
|
||||||
showMenu: async () => {
|
|
||||||
await page.getByLabel('action-Action.Link-View record-view-general-table-0').click();
|
|
||||||
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();
|
|
||||||
},
|
|
||||||
supportedOptions: [
|
|
||||||
'Edit field title',
|
|
||||||
'Display title',
|
|
||||||
'Edit tooltip',
|
|
||||||
'Field component',
|
|
||||||
'Enable link',
|
|
||||||
'Title field',
|
|
||||||
'Delete',
|
|
||||||
],
|
|
||||||
unsupportedOptions: ['Set default value'],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('field component', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const record = (await mockRecords('general', 1))[0];
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return record;
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByLabel('action-Action.Link-View record-view-general-table-0').click();
|
|
||||||
})(page);
|
|
||||||
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.getByRole('menuitem', { name: 'Field component' }).click();
|
|
||||||
|
|
||||||
// 断言支持的选项
|
|
||||||
await expect(page.getByRole('option', { name: 'Title', exact: true })).toBeVisible();
|
|
||||||
await expect(page.getByRole('option', { name: 'Tag', exact: true })).toBeVisible();
|
|
||||||
await expect(page.getByRole('option', { name: 'Sub-details', exact: true })).toBeVisible();
|
|
||||||
await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible();
|
|
||||||
|
|
||||||
// 切换到 Sub-details,应该显示 Initializer 按钮
|
|
||||||
await page.getByRole('option', { name: 'Sub-details', exact: true }).click();
|
|
||||||
await page.mouse.move(300, 0);
|
|
||||||
await expect(
|
|
||||||
page
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.getByLabel('schema-initializer-Grid-form:')
|
|
||||||
.first(),
|
|
||||||
).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('title field', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const record = (await mockRecords('general', 1))[0];
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return record;
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByLabel('action-Action.Link-View record-view-general-table-0').click();
|
|
||||||
})(page);
|
|
||||||
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 expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('enable link', async ({ page, mockPage, mockRecords }) => {
|
|
||||||
// test.fail();
|
|
||||||
const record = await (async (mockPage, mockRecords) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
const record = (await mockRecords('general', 1))[0];
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
return record;
|
|
||||||
})(mockPage, mockRecords);
|
|
||||||
await (async (page: Page) => {
|
|
||||||
await page.getByLabel('action-Action.Link-View record-view-general-table-0').click();
|
|
||||||
})(page);
|
|
||||||
|
|
||||||
// 初始状态是一个可点击的链接
|
|
||||||
await expect(
|
|
||||||
page
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.locator('a')
|
|
||||||
.filter({ hasText: record.manyToMany[0].id }),
|
|
||||||
).toBeVisible();
|
|
||||||
|
|
||||||
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 expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked();
|
|
||||||
await page.getByRole('menuitem', { name: 'Enable link' }).click();
|
|
||||||
await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).not.toBeChecked();
|
|
||||||
|
|
||||||
// 应变为非链接状态
|
|
||||||
await expect(
|
|
||||||
page
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.locator('a')
|
|
||||||
.filter({ hasText: record.manyToMany[0].id }),
|
|
||||||
).not.toBeVisible();
|
|
||||||
|
|
||||||
// 再次开启链接状态
|
|
||||||
await page.getByRole('menuitem', { name: 'Enable link' }).click();
|
|
||||||
await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked();
|
|
||||||
await expect(
|
|
||||||
page
|
|
||||||
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
|
||||||
.locator('a')
|
|
||||||
.filter({ hasText: record.manyToMany[0].id }),
|
|
||||||
).toBeVisible();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test.describe('form item & filter form', () => {
|
|
||||||
test('supported options', async ({ page, mockPage }) => {
|
|
||||||
const nocoPage = await mockPage(oneFilterFormBlockWithAllAssociationFields).waitForInit();
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
await expectSettingsMenu({
|
|
||||||
page,
|
|
||||||
showMenu: async () => {
|
|
||||||
await page.getByLabel('block-item-CollectionField-general-filter-form-general.manyToMany-manyToMany').hover();
|
|
||||||
await page.getByRole('button', { name: 'designer-schema-settings-CollectionField' }).hover();
|
|
||||||
},
|
|
||||||
supportedOptions: [
|
|
||||||
'Edit field title',
|
|
||||||
'Edit description',
|
|
||||||
'Set the data scope',
|
|
||||||
'Field component',
|
|
||||||
'Title field',
|
|
||||||
'Delete',
|
|
||||||
],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test.describe('table column & table', () => {
|
|
||||||
test('supported options', async ({ page, mockPage, mockRecord }) => {
|
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
|
||||||
await mockRecord('general');
|
|
||||||
await nocoPage.goto();
|
|
||||||
|
|
||||||
await expectSettingsMenu({
|
|
||||||
page,
|
|
||||||
showMenu: async () => {
|
|
||||||
await createColumnItem(page, 'manyToMany');
|
|
||||||
await showSettingsMenu(page, 'manyToMany');
|
|
||||||
},
|
|
||||||
supportedOptions: [
|
|
||||||
'Custom column title',
|
|
||||||
'Column width',
|
|
||||||
'Enable link',
|
|
||||||
'Title field',
|
|
||||||
'Field component',
|
|
||||||
'Delete',
|
|
||||||
],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -0,0 +1,349 @@
|
|||||||
|
import {
|
||||||
|
Page,
|
||||||
|
expect,
|
||||||
|
expectSettingsMenu,
|
||||||
|
mockUserRecordsWithoutDepartments,
|
||||||
|
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
||||||
|
test,
|
||||||
|
} from '@nocobase/test/e2e';
|
||||||
|
import { testDefaultValue, testPattern } from '../../utils';
|
||||||
|
|
||||||
|
test.describe('form item & create form', () => {
|
||||||
|
test('supported options', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
await expectSettingsMenu({
|
||||||
|
page,
|
||||||
|
showMenu: async () => {
|
||||||
|
await page.getByRole('button', { name: 'Add new' }).click();
|
||||||
|
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();
|
||||||
|
},
|
||||||
|
supportedOptions: [
|
||||||
|
'Edit field title',
|
||||||
|
'Display title',
|
||||||
|
'Edit description',
|
||||||
|
'Required',
|
||||||
|
'Set default value',
|
||||||
|
'Set the data scope',
|
||||||
|
'Set default sorting rules',
|
||||||
|
'Field component',
|
||||||
|
'Quick create',
|
||||||
|
'Allow multiple',
|
||||||
|
'Pattern',
|
||||||
|
'Title field',
|
||||||
|
'Delete',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('set default value', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
let recordsOfUser;
|
||||||
|
await testDefaultValue({
|
||||||
|
page,
|
||||||
|
gotoPage: async () => {
|
||||||
|
recordsOfUser = await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return recordsOfUser;
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
},
|
||||||
|
openDialog: () =>
|
||||||
|
(async (page: Page) => {
|
||||||
|
await page.getByRole('button', { name: 'Add new' }).click();
|
||||||
|
})(page),
|
||||||
|
closeDialog: () => page.getByLabel('drawer-Action.Container-general-Add record-mask').click(),
|
||||||
|
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, 'manyToMany'),
|
||||||
|
supportVariables: ['Constant', 'Current user', 'Date variables', 'Current form'],
|
||||||
|
inputConstantValue: async () => {
|
||||||
|
await page.getByLabel('block-item-VariableInput-').getByTestId('select-object-multiple').click();
|
||||||
|
await page.getByRole('option', { name: String(recordsOfUser[0].id), exact: true }).click();
|
||||||
|
await page.getByRole('option', { name: String(recordsOfUser[1].id), exact: true }).click();
|
||||||
|
await page.getByRole('option', { name: String(recordsOfUser[2].id), exact: true }).click();
|
||||||
|
},
|
||||||
|
expectConstantValue: async () => {
|
||||||
|
await expect(
|
||||||
|
page.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany'),
|
||||||
|
).toHaveText(`manyToMany:${recordsOfUser.map((record) => record.id).join('')}`);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('pattern', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
let records;
|
||||||
|
await testPattern({
|
||||||
|
page,
|
||||||
|
gotoPage: async () => {
|
||||||
|
records = await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return recordsOfUser;
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
},
|
||||||
|
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, 'manyToMany'),
|
||||||
|
expectEditable: async () => {
|
||||||
|
await page
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.getByTestId('select-object-multiple')
|
||||||
|
.click();
|
||||||
|
await page.getByRole('option', { name: String(records[0].id), exact: true }).click();
|
||||||
|
await page.getByRole('option', { name: String(records[1].id), exact: true }).click();
|
||||||
|
await page.getByRole('option', { name: String(records[2].id), exact: true }).click();
|
||||||
|
},
|
||||||
|
expectReadonly: async () => {
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.getByTestId('select-object-multiple'),
|
||||||
|
).toHaveClass(/ant-select-disabled/);
|
||||||
|
// 在这里等待一下,防止因闪烁导致下面的断言失败
|
||||||
|
await page.waitForTimeout(100);
|
||||||
|
},
|
||||||
|
expectEasyReading: async () => {
|
||||||
|
await expect(
|
||||||
|
page.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany'),
|
||||||
|
).toHaveText(`manyToMany:${records.map((record) => record.id).join(',')}`);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
const records = await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return recordsOfUser;
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
await (async (page: Page) => {
|
||||||
|
await page.getByRole('button', { name: 'Add new' }).click();
|
||||||
|
})(page);
|
||||||
|
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.getByRole('menuitem', { name: 'Set the data scope' }).click();
|
||||||
|
await page.getByText('Add condition', { exact: true }).click();
|
||||||
|
await page.getByTestId('select-filter-field').click();
|
||||||
|
await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click();
|
||||||
|
await page.getByRole('spinbutton').click();
|
||||||
|
await page.getByRole('spinbutton').fill(String(records[0].id));
|
||||||
|
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
||||||
|
|
||||||
|
// 再次打开弹窗,设置的值应该还在
|
||||||
|
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.getByRole('menuitem', { name: 'Set the data scope' }).click();
|
||||||
|
await expect(page.getByTestId('select-filter-field')).toHaveText('ID');
|
||||||
|
await expect(page.getByRole('spinbutton')).toHaveValue(String(records[0].id));
|
||||||
|
await page.getByRole('button', { name: 'Cancel', exact: true }).click();
|
||||||
|
|
||||||
|
// 数据应该被过滤了
|
||||||
|
await page
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.getByTestId('select-object-multiple')
|
||||||
|
.click();
|
||||||
|
await expect(page.getByRole('option', { name: String(records[0].id), exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option')).toHaveCount(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('set default sorting rules', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return recordsOfUser;
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
await (async (page: Page) => {
|
||||||
|
await page.getByRole('button', { name: 'Add new' }).click();
|
||||||
|
})(page);
|
||||||
|
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.getByRole('menuitem', { name: 'Set default sorting rules' }).click();
|
||||||
|
|
||||||
|
// 配置
|
||||||
|
await page.getByRole('button', { name: 'Add sort field' }).click();
|
||||||
|
await page.getByTestId('select-single').click();
|
||||||
|
await page.getByRole('option', { name: 'ID', exact: true }).click();
|
||||||
|
await page.getByText('DESC', { exact: true }).click();
|
||||||
|
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
||||||
|
|
||||||
|
// 再次打开弹窗,设置的值应该还在
|
||||||
|
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.getByRole('menuitem', { name: 'Set default sorting rules' }).click();
|
||||||
|
await expect(page.getByRole('dialog').getByTestId('select-single')).toHaveText('ID');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('field component', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
await nocoPage.goto();
|
||||||
|
await page.getByRole('button', { name: 'Add new' }).click();
|
||||||
|
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.getByRole('menuitem', { name: 'Field component' }).click();
|
||||||
|
|
||||||
|
// 断言支持的选项
|
||||||
|
await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible();
|
||||||
|
|
||||||
|
// 选择 Record picker
|
||||||
|
await page.getByRole('option', { name: 'Record picker', exact: true }).click();
|
||||||
|
await page.mouse.move(300, 0);
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.getByTestId('select-data-picker'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
// 选择 Sub-table
|
||||||
|
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.getByRole('menuitem', { name: 'Field component' }).click();
|
||||||
|
await page.getByRole('option', { name: 'Sub-table', exact: true }).click();
|
||||||
|
await page.mouse.move(300, 0);
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.getByLabel('schema-initializer-AssociationField.SubTable-table:configureColumns-users'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
// 选择 Sub-form
|
||||||
|
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.getByRole('menuitem', { name: 'Field component' }).click();
|
||||||
|
await page.getByRole('option', { name: 'Sub-form', exact: true }).click();
|
||||||
|
await page.mouse.move(300, 0);
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.getByLabel('schema-initializer-Grid-form:configureFields-users'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
// 选择 Sub-form(Popover)
|
||||||
|
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
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.getByRole('img', { name: 'edit' })
|
||||||
|
.click();
|
||||||
|
await page.mouse.move(300, 0);
|
||||||
|
await expect(page.getByTestId('popover-CollectionField-general')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return recordsOfUser;
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
await (async (page: Page) => {
|
||||||
|
await page.getByRole('button', { name: 'Add new' }).click();
|
||||||
|
})(page);
|
||||||
|
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 expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('allow multiple', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return recordsOfUser;
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
await (async (page: Page) => {
|
||||||
|
await page.getByRole('button', { name: 'Add new' }).click();
|
||||||
|
})(page);
|
||||||
|
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 expect(page.getByRole('menuitem', { name: 'Allow multiple' })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('title field', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return recordsOfUser;
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
await (async (page: Page) => {
|
||||||
|
await page.getByRole('button', { name: 'Add new' }).click();
|
||||||
|
})(page);
|
||||||
|
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 expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,263 @@
|
|||||||
|
import {
|
||||||
|
Page,
|
||||||
|
expect,
|
||||||
|
expectSettingsMenu,
|
||||||
|
mockUserRecordsWithoutDepartments,
|
||||||
|
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
||||||
|
test,
|
||||||
|
} from '@nocobase/test/e2e';
|
||||||
|
import { testPattern } from '../../utils';
|
||||||
|
|
||||||
|
test.describe('form item & edit form', () => {
|
||||||
|
test('supported options', async ({ page, mockRecords, mockPage }) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
await mockRecords('general', 1);
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
await expectSettingsMenu({
|
||||||
|
page,
|
||||||
|
showMenu: async () => {
|
||||||
|
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
|
||||||
|
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();
|
||||||
|
},
|
||||||
|
supportedOptions: [
|
||||||
|
'Edit field title',
|
||||||
|
'Display title',
|
||||||
|
'Edit description',
|
||||||
|
'Required',
|
||||||
|
'Set the data scope',
|
||||||
|
'Set default sorting rules',
|
||||||
|
'Field component',
|
||||||
|
'Quick create',
|
||||||
|
'Allow multiple',
|
||||||
|
'Pattern',
|
||||||
|
'Title field',
|
||||||
|
'Delete',
|
||||||
|
],
|
||||||
|
unsupportedOptions: ['Set default value'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('pattern', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
let record;
|
||||||
|
await testPattern({
|
||||||
|
page,
|
||||||
|
gotoPage: async () => {
|
||||||
|
record = (
|
||||||
|
await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
const record = (await mockRecords('general', 1))[0];
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return { record, recordsOfUser };
|
||||||
|
})(mockPage, mockRecords)
|
||||||
|
).record;
|
||||||
|
},
|
||||||
|
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}`).hover();
|
||||||
|
await page
|
||||||
|
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.${fieldName}`)
|
||||||
|
.hover();
|
||||||
|
})(page, 'manyToMany'),
|
||||||
|
expectEditable: async () => {
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.getByTestId('select-object-multiple'),
|
||||||
|
).toHaveText(`${record.manyToMany.map((item) => item.id).join('')}`);
|
||||||
|
},
|
||||||
|
expectReadonly: async () => {
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.getByTestId('select-object-multiple'),
|
||||||
|
).toHaveClass(/ant-select-disabled/);
|
||||||
|
// 在这里等待一下,防止因闪烁导致下面的断言失败
|
||||||
|
await page.waitForTimeout(100);
|
||||||
|
},
|
||||||
|
expectEasyReading: async () => {
|
||||||
|
await expect(
|
||||||
|
page.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany'),
|
||||||
|
).toHaveText(`manyToMany:${record.manyToMany.map((item) => item.id).join(',')}`);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
const { recordsOfUser } = await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
const record = (await mockRecords('general', 1))[0];
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return { record, recordsOfUser };
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
await (async (page: Page) => {
|
||||||
|
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
|
||||||
|
})(page);
|
||||||
|
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.getByRole('menuitem', { name: 'Set the data scope' }).click();
|
||||||
|
await page.getByText('Add condition', { exact: true }).click();
|
||||||
|
await page.getByTestId('select-filter-field').click();
|
||||||
|
await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click();
|
||||||
|
await page.getByRole('spinbutton').click();
|
||||||
|
await page.getByRole('spinbutton').fill(String(recordsOfUser[0].id));
|
||||||
|
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
||||||
|
|
||||||
|
// 再次打开弹窗,设置的值应该还在
|
||||||
|
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.getByRole('menuitem', { name: 'Set the data scope' }).click();
|
||||||
|
await expect(page.getByTestId('select-filter-field')).toHaveText('ID');
|
||||||
|
await expect(page.getByRole('spinbutton')).toHaveValue(String(recordsOfUser[0].id));
|
||||||
|
await page.getByRole('button', { name: 'Cancel', exact: true }).click();
|
||||||
|
|
||||||
|
// 数据应该被过滤了
|
||||||
|
await page
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.getByTestId('select-object-multiple')
|
||||||
|
.click();
|
||||||
|
await expect(page.getByRole('option', { name: String(recordsOfUser[0].id), exact: true })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('set default sorting rules', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
const record = (await mockRecords('general', 1))[0];
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return { record, recordsOfUser };
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
await (async (page: Page) => {
|
||||||
|
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
|
||||||
|
})(page);
|
||||||
|
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.getByRole('menuitem', { name: 'Set default sorting rules' }).click();
|
||||||
|
|
||||||
|
// 配置
|
||||||
|
await page.getByRole('button', { name: 'Add sort field' }).click();
|
||||||
|
await page.getByTestId('select-single').click();
|
||||||
|
await page.getByRole('option', { name: 'ID', exact: true }).click();
|
||||||
|
await page.getByText('DESC', { exact: true }).click();
|
||||||
|
await page.getByRole('button', { name: 'OK', exact: true }).click();
|
||||||
|
|
||||||
|
// 再次打开弹窗,设置的值应该还在
|
||||||
|
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.getByRole('menuitem', { name: 'Set default sorting rules' }).click();
|
||||||
|
await expect(page.getByRole('dialog').getByTestId('select-single')).toHaveText('ID');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('field component', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
const record = (await mockRecords('general', 1))[0];
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return { record, recordsOfUser };
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
await (async (page: Page) => {
|
||||||
|
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
|
||||||
|
})(page);
|
||||||
|
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.getByRole('menuitem', { name: 'Field component' }).click();
|
||||||
|
|
||||||
|
// 断言支持的选项
|
||||||
|
await expect(page.getByRole('option', { name: 'Select', exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option', { name: 'Record picker', exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option', { name: 'Sub-form', exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option', { name: 'Sub-form(Popover)', exact: true })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
const record = (await mockRecords('general', 1))[0];
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return { record, recordsOfUser };
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
await (async (page: Page) => {
|
||||||
|
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
|
||||||
|
})(page);
|
||||||
|
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 expect(page.getByRole('menuitem', { name: 'Quick create' })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('allow multiple', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
const record = (await mockRecords('general', 1))[0];
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return { record, recordsOfUser };
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
await (async (page: Page) => {
|
||||||
|
await page.getByLabel('action-Action.Link-Edit record-update-general-table-0').click();
|
||||||
|
})(page);
|
||||||
|
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 expect(page.getByRole('menuitem', { name: 'Allow multiple' })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('title field', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
|
await mockRecords('general', 1);
|
||||||
|
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.manyToMany-manyToMany`).hover();
|
||||||
|
await page
|
||||||
|
.getByLabel(`designer-schema-settings-CollectionField-FormItem.Designer-general-general.manyToMany`)
|
||||||
|
.hover();
|
||||||
|
await expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,144 @@
|
|||||||
|
import {
|
||||||
|
Page,
|
||||||
|
expect,
|
||||||
|
expectSettingsMenu,
|
||||||
|
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
||||||
|
test,
|
||||||
|
} from '@nocobase/test/e2e';
|
||||||
|
|
||||||
|
test.describe('form item & view form', () => {
|
||||||
|
test('supported options', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
await mockRecords('general', 1);
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
await expectSettingsMenu({
|
||||||
|
page,
|
||||||
|
showMenu: async () => {
|
||||||
|
await page.getByLabel('action-Action.Link-View record-view-general-table-0').click();
|
||||||
|
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();
|
||||||
|
},
|
||||||
|
supportedOptions: [
|
||||||
|
'Edit field title',
|
||||||
|
'Display title',
|
||||||
|
'Edit tooltip',
|
||||||
|
'Field component',
|
||||||
|
'Enable link',
|
||||||
|
'Title field',
|
||||||
|
'Delete',
|
||||||
|
],
|
||||||
|
unsupportedOptions: ['Set default value'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('field component', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const record = (await mockRecords('general', 1))[0];
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return record;
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
await (async (page: Page) => {
|
||||||
|
await page.getByLabel('action-Action.Link-View record-view-general-table-0').click();
|
||||||
|
})(page);
|
||||||
|
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.getByRole('menuitem', { name: 'Field component' }).click();
|
||||||
|
|
||||||
|
// 断言支持的选项
|
||||||
|
await expect(page.getByRole('option', { name: 'Title', exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option', { name: 'Tag', exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option', { name: 'Sub-details', exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option', { name: 'Sub-table', exact: true })).toBeVisible();
|
||||||
|
|
||||||
|
// 切换到 Sub-details,应该显示 Initializer 按钮
|
||||||
|
await page.getByRole('option', { name: 'Sub-details', exact: true }).click();
|
||||||
|
await page.mouse.move(300, 0);
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.getByLabel('schema-initializer-Grid-form:')
|
||||||
|
.first(),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('title field', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const record = (await mockRecords('general', 1))[0];
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return record;
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
await (async (page: Page) => {
|
||||||
|
await page.getByLabel('action-Action.Link-View record-view-general-table-0').click();
|
||||||
|
})(page);
|
||||||
|
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 expect(page.getByRole('menuitem', { name: 'Title field' })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('enable link', async ({ page, mockPage, mockRecords }) => {
|
||||||
|
// test.fail();
|
||||||
|
const record = await (async (mockPage, mockRecords) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
const record = (await mockRecords('general', 1))[0];
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
return record;
|
||||||
|
})(mockPage, mockRecords);
|
||||||
|
await (async (page: Page) => {
|
||||||
|
await page.getByLabel('action-Action.Link-View record-view-general-table-0').click();
|
||||||
|
})(page);
|
||||||
|
|
||||||
|
// 初始状态是一个可点击的链接
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.locator('a')
|
||||||
|
.filter({ hasText: record.manyToMany[0].id }),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
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 expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked();
|
||||||
|
await page.getByRole('menuitem', { name: 'Enable link' }).click();
|
||||||
|
await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).not.toBeChecked();
|
||||||
|
|
||||||
|
// 应变为非链接状态
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.locator('a')
|
||||||
|
.filter({ hasText: record.manyToMany[0].id }),
|
||||||
|
).not.toBeVisible();
|
||||||
|
|
||||||
|
// 再次开启链接状态
|
||||||
|
await page.getByRole('menuitem', { name: 'Enable link' }).click();
|
||||||
|
await expect(page.getByRole('menuitem', { name: 'Enable link' }).getByRole('switch')).toBeChecked();
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByLabel('block-item-CollectionField-general-form-general.manyToMany-manyToMany')
|
||||||
|
.locator('a')
|
||||||
|
.filter({ hasText: record.manyToMany[0].id }),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,24 @@
|
|||||||
|
import { expectSettingsMenu, oneFilterFormBlockWithAllAssociationFields, test } from '@nocobase/test/e2e';
|
||||||
|
|
||||||
|
test.describe('form item & filter form', () => {
|
||||||
|
test('supported options', async ({ page, mockPage }) => {
|
||||||
|
const nocoPage = await mockPage(oneFilterFormBlockWithAllAssociationFields).waitForInit();
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
await expectSettingsMenu({
|
||||||
|
page,
|
||||||
|
showMenu: async () => {
|
||||||
|
await page.getByLabel('block-item-CollectionField-general-filter-form-general.manyToMany-manyToMany').hover();
|
||||||
|
await page.getByRole('button', { name: 'designer-schema-settings-CollectionField' }).hover();
|
||||||
|
},
|
||||||
|
supportedOptions: [
|
||||||
|
'Edit field title',
|
||||||
|
'Edit description',
|
||||||
|
'Set the data scope',
|
||||||
|
'Field component',
|
||||||
|
'Title field',
|
||||||
|
'Delete',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,30 @@
|
|||||||
|
import {
|
||||||
|
expectSettingsMenu,
|
||||||
|
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
||||||
|
test,
|
||||||
|
} from '@nocobase/test/e2e';
|
||||||
|
import { createColumnItem, showSettingsMenu } from '../../utils';
|
||||||
|
|
||||||
|
test.describe('table column & table', () => {
|
||||||
|
test('supported options', async ({ page, mockPage, mockRecord }) => {
|
||||||
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
|
await mockRecord('general');
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
await expectSettingsMenu({
|
||||||
|
page,
|
||||||
|
showMenu: async () => {
|
||||||
|
await createColumnItem(page, 'manyToMany');
|
||||||
|
await showSettingsMenu(page, 'manyToMany');
|
||||||
|
},
|
||||||
|
supportedOptions: [
|
||||||
|
'Custom column title',
|
||||||
|
'Column width',
|
||||||
|
'Enable link',
|
||||||
|
'Title field',
|
||||||
|
'Field component',
|
||||||
|
'Delete',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -2,6 +2,7 @@ import {
|
|||||||
Page,
|
Page,
|
||||||
expect,
|
expect,
|
||||||
expectSettingsMenu,
|
expectSettingsMenu,
|
||||||
|
mockUserRecordsWithoutDepartments,
|
||||||
oneFilterFormBlockWithAllAssociationFields,
|
oneFilterFormBlockWithAllAssociationFields,
|
||||||
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
||||||
test,
|
test,
|
||||||
@ -12,7 +13,7 @@ import { T3377 } from './templatesOfBug';
|
|||||||
test.describe('form item & create form', () => {
|
test.describe('form item & create form', () => {
|
||||||
test('supported options', async ({ page, mockPage, mockRecords }) => {
|
test('supported options', async ({ page, mockPage, mockRecords }) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
await mockRecords('users', 3);
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
await expectSettingsMenu({
|
await expectSettingsMenu({
|
||||||
@ -48,7 +49,7 @@ test.describe('form item & create form', () => {
|
|||||||
gotoPage: async () => {
|
gotoPage: async () => {
|
||||||
records = await (async (mockPage, mockRecords) => {
|
records = await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -101,7 +102,7 @@ test.describe('form item & create form', () => {
|
|||||||
gotoPage: async () => {
|
gotoPage: async () => {
|
||||||
records = await (async (mockPage, mockRecords) => {
|
records = await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -145,7 +146,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
||||||
const records = await (async (mockPage, mockRecords) => {
|
const records = await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -191,7 +192,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('field component', async ({ page, mockPage, mockRecords }) => {
|
test('field component', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -217,7 +218,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -238,7 +239,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('title field', async ({ page, mockPage, mockRecords }) => {
|
test('title field', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -259,7 +260,7 @@ test.describe('form item & create form', () => {
|
|||||||
test.describe('form item & edit form', () => {
|
test.describe('form item & edit form', () => {
|
||||||
test('supported options', async ({ page, mockRecords, mockPage }) => {
|
test('supported options', async ({ page, mockRecords, mockPage }) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
await mockRecords('users', 3);
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await mockRecords('general', 1);
|
await mockRecords('general', 1);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -297,7 +298,7 @@ test.describe('form item & edit form', () => {
|
|||||||
record = (
|
record = (
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -343,7 +344,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
||||||
const { recordsOfUser } = await (async (mockPage, mockRecords) => {
|
const { recordsOfUser } = await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -390,7 +391,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('field component', async ({ page, mockPage, mockRecords }) => {
|
test('field component', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -417,7 +418,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -439,7 +440,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('title field', async ({ page, mockPage, mockRecords }) => {
|
test('title field', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import {
|
|||||||
Page,
|
Page,
|
||||||
expect,
|
expect,
|
||||||
expectSettingsMenu,
|
expectSettingsMenu,
|
||||||
|
mockUserRecordsWithoutDepartments,
|
||||||
oneFilterFormBlockWithAllAssociationFields,
|
oneFilterFormBlockWithAllAssociationFields,
|
||||||
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
oneTableBlockWithAddNewAndViewAndEditAndAssociationFields,
|
||||||
test,
|
test,
|
||||||
@ -11,7 +12,7 @@ import { createColumnItem, showSettingsMenu, testPattern } from '../../utils';
|
|||||||
test.describe('form item & create form', () => {
|
test.describe('form item & create form', () => {
|
||||||
test('supported options', async ({ page, mockPage, mockRecords }) => {
|
test('supported options', async ({ page, mockPage, mockRecords }) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
await mockRecords('users', 3);
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
await expectSettingsMenu({
|
await expectSettingsMenu({
|
||||||
@ -43,7 +44,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('set default value', async ({ page, mockPage, mockRecord, mockRecords }) => {
|
test('set default value', async ({ page, mockPage, mockRecord, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -66,7 +67,7 @@ test.describe('form item & create form', () => {
|
|||||||
gotoPage: async () => {
|
gotoPage: async () => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -111,7 +112,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
||||||
const records = await (async (mockPage, mockRecords) => {
|
const records = await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -157,7 +158,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('field component', async ({ page, mockPage, mockRecords }) => {
|
test('field component', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -184,7 +185,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -205,7 +206,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('allow multiple', async ({ page, mockPage, mockRecords }) => {
|
test('allow multiple', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -225,7 +226,7 @@ test.describe('form item & create form', () => {
|
|||||||
test('title field', async ({ page, mockPage, mockRecords }) => {
|
test('title field', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
return recordsOfUser;
|
return recordsOfUser;
|
||||||
@ -246,7 +247,7 @@ test.describe('form item & create form', () => {
|
|||||||
test.describe('form item & edit form', () => {
|
test.describe('form item & edit form', () => {
|
||||||
test('supported options', async ({ page, mockRecords, mockPage }) => {
|
test('supported options', async ({ page, mockRecords, mockPage }) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
await mockRecords('users', 3);
|
await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
await mockRecords('general', 1);
|
await mockRecords('general', 1);
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -285,7 +286,7 @@ test.describe('form item & edit form', () => {
|
|||||||
record = (
|
record = (
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -331,7 +332,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
test('Set the data scope', async ({ page, mockPage, mockRecords }) => {
|
||||||
const { record } = await (async (mockPage, mockRecords) => {
|
const { record } = await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -378,7 +379,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('field component', async ({ page, mockPage, mockRecords }) => {
|
test('field component', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -406,7 +407,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
test('quick create', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -428,7 +429,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('allow multiple', async ({ page, mockPage, mockRecords }) => {
|
test('allow multiple', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
@ -449,7 +450,7 @@ test.describe('form item & edit form', () => {
|
|||||||
test('title field', async ({ page, mockPage, mockRecords }) => {
|
test('title field', async ({ page, mockPage, mockRecords }) => {
|
||||||
await (async (mockPage, mockRecords) => {
|
await (async (mockPage, mockRecords) => {
|
||||||
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
const nocoPage = await mockPage(oneTableBlockWithAddNewAndViewAndEditAndAssociationFields).waitForInit();
|
||||||
const recordsOfUser = await mockRecords('users', 3);
|
const recordsOfUser = await mockUserRecordsWithoutDepartments(mockRecords, 3);
|
||||||
const record = (await mockRecords('general', 1))[0];
|
const record = (await mockRecords('general', 1))[0];
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
@ -87,21 +87,24 @@ test.describe('configure actions', () => {
|
|||||||
test('add new action in kanban', async ({ page, mockPage }) => {
|
test('add new action in kanban', async ({ page, mockPage }) => {
|
||||||
const nocoPage = await mockPage(oneEmptyKanbanBlock).waitForInit();
|
const nocoPage = await mockPage(oneEmptyKanbanBlock).waitForInit();
|
||||||
await nocoPage.goto();
|
await nocoPage.goto();
|
||||||
await page.getByLabel('schema-initializer-ActionBar-kanban:configureActions-general').click();
|
await page.getByLabel('schema-initializer-ActionBar-kanban:configureActions-general').hover();
|
||||||
await page.getByRole('menuitem', { name: 'Add new' }).getByRole('switch').click();
|
await page.getByRole('menuitem', { name: 'Add new' }).getByRole('switch').click();
|
||||||
//按钮正常显示
|
//按钮正常显示
|
||||||
await expect(page.getByLabel('action-Action-Add ')).toBeVisible();
|
await expect(page.getByLabel('action-Action-Add ')).toBeVisible();
|
||||||
//添加数据
|
//添加数据
|
||||||
await page.getByLabel('action-Action-Add new-create-general-kanban').click();
|
await page.getByLabel('action-Action-Add new-create-general-kanban').click();
|
||||||
await page.getByLabel('schema-initializer-Grid-popup:addNew:addBlock-general').click();
|
await page.getByLabel('schema-initializer-Grid-popup:addNew:addBlock-general').hover();
|
||||||
await page.getByRole('menuitem', { name: 'form Form' }).click();
|
await page.getByRole('menuitem', { name: 'form Form' }).click();
|
||||||
await page.mouse.move(300, 0);
|
await page.mouse.move(300, 0);
|
||||||
await page.getByLabel('schema-initializer-Grid-form:configureFields-general').click();
|
await page.getByLabel('schema-initializer-Grid-form:configureFields-general').hover();
|
||||||
await page.getByRole('menuitem', { name: 'Single Select' }).click();
|
await page.getByRole('menuitem', { name: 'Single Select' }).click();
|
||||||
|
await page.mouse.move(300, 0);
|
||||||
await page.getByLabel('block-item-CollectionField-').locator('.ant-select').click();
|
await page.getByLabel('block-item-CollectionField-').locator('.ant-select').click();
|
||||||
await page.getByRole('option', { name: 'option1' }).click();
|
await page.getByRole('option', { name: 'option1' }).click();
|
||||||
|
await page.mouse.move(300, 0);
|
||||||
await page.getByLabel('schema-initializer-ActionBar-createForm:configureActions-general').hover();
|
await page.getByLabel('schema-initializer-ActionBar-createForm:configureActions-general').hover();
|
||||||
await page.getByRole('menuitem', { name: 'Submit' }).click();
|
await page.getByRole('menuitem', { name: 'Submit' }).click();
|
||||||
|
await page.mouse.move(300, 0);
|
||||||
await page.getByLabel('action-Action-Submit-submit-general-form').click();
|
await page.getByLabel('action-Action-Submit-submit-general-form').click();
|
||||||
await page.getByLabel('block-item-Kanban.Card-general-kanban').hover();
|
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.getByLabel('designer-schema-initializer-Kanban.Card-Kanban.Card.Designer-general').hover();
|
||||||
|
@ -2,13 +2,13 @@ import Database, { Collection, Repository } from '@nocobase/database';
|
|||||||
import { CollectionRepository } from '@nocobase/plugin-collection-manager';
|
import { CollectionRepository } from '@nocobase/plugin-collection-manager';
|
||||||
import { InstallOptions, Plugin } from '@nocobase/server';
|
import { InstallOptions, Plugin } from '@nocobase/server';
|
||||||
import { merge, uid } from '@nocobase/utils';
|
import { merge, uid } from '@nocobase/utils';
|
||||||
|
import { promises as fs } from 'fs';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import path from 'path';
|
||||||
|
import { Client } from 'pg';
|
||||||
import collectionTemplates from './collection-templates';
|
import collectionTemplates from './collection-templates';
|
||||||
import * as fieldInterfaces from './field-interfaces';
|
import * as fieldInterfaces from './field-interfaces';
|
||||||
import { mockAttachment } from './field-interfaces';
|
import { mockAttachment } from './field-interfaces';
|
||||||
import { Client } from 'pg';
|
|
||||||
import path from 'path';
|
|
||||||
import { promises as fs } from 'fs';
|
|
||||||
|
|
||||||
export class PluginMockCollectionsServer extends Plugin {
|
export class PluginMockCollectionsServer extends Plugin {
|
||||||
async load() {
|
async load() {
|
||||||
@ -190,7 +190,7 @@ export class PluginMockCollectionsServer extends Plugin {
|
|||||||
this.app.resourcer.registerActions({
|
this.app.resourcer.registerActions({
|
||||||
mock: async (ctx, next) => {
|
mock: async (ctx, next) => {
|
||||||
const { resourceName } = ctx.action;
|
const { resourceName } = ctx.action;
|
||||||
const { values, count = 10 } = ctx.action.params;
|
const { values, count = 10, maxDepth = 4 } = ctx.action.params;
|
||||||
const mockCollectionData = async (collectionName, count = 1, depth = 0, maxDepth = 4) => {
|
const mockCollectionData = async (collectionName, count = 1, depth = 0, maxDepth = 4) => {
|
||||||
const collection = ctx.db.getCollection(collectionName) as Collection;
|
const collection = ctx.db.getCollection(collectionName) as Collection;
|
||||||
const items = await Promise.all(
|
const items = await Promise.all(
|
||||||
@ -224,7 +224,7 @@ export class PluginMockCollectionsServer extends Plugin {
|
|||||||
if (Array.isArray(values)) {
|
if (Array.isArray(values)) {
|
||||||
size = values.length;
|
size = values.length;
|
||||||
}
|
}
|
||||||
const data = await mockCollectionData(resourceName, size);
|
const data = await mockCollectionData(resourceName, size, 0, Number(maxDepth));
|
||||||
// ctx.body = {
|
// ctx.body = {
|
||||||
// values: (Array.isArray(data) ? data : [data]).map((item, index) => {
|
// values: (Array.isArray(data) ? data : [data]).map((item, index) => {
|
||||||
// if (Array.isArray(values)) {
|
// if (Array.isArray(values)) {
|
||||||
|
@ -2,7 +2,6 @@ import Database from '@nocobase/database';
|
|||||||
import PluginMultiAppManager from '@nocobase/plugin-multi-app-manager';
|
import PluginMultiAppManager from '@nocobase/plugin-multi-app-manager';
|
||||||
import { Application, AppSupervisor, Plugin } from '@nocobase/server';
|
import { Application, AppSupervisor, Plugin } from '@nocobase/server';
|
||||||
import lodash from 'lodash';
|
import lodash from 'lodash';
|
||||||
import { resolve } from 'path';
|
|
||||||
|
|
||||||
const subAppFilteredPlugins = ['multi-app-share-collection', 'multi-app-manager'];
|
const subAppFilteredPlugins = ['multi-app-share-collection', 'multi-app-manager'];
|
||||||
const unSyncPlugins = ['localization-management'];
|
const unSyncPlugins = ['localization-management'];
|
||||||
@ -235,13 +234,6 @@ export class MultiAppShareCollectionPlugin extends Plugin {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.importCollections(resolve(__dirname, 'collections'));
|
|
||||||
|
|
||||||
// this.db.addMigrations({
|
|
||||||
// namespace: 'multi-app-share-collection',
|
|
||||||
// directory: resolve(__dirname, './migrations'),
|
|
||||||
// });
|
|
||||||
|
|
||||||
this.app.resourcer.registerActionHandlers({
|
this.app.resourcer.registerActionHandlers({
|
||||||
'applications:shareCollections': async (ctx, next) => {
|
'applications:shareCollections': async (ctx, next) => {
|
||||||
const { filterByTk, values } = ctx.action.params;
|
const { filterByTk, values } = ctx.action.params;
|
||||||
@ -262,9 +254,13 @@ export class MultiAppShareCollectionPlugin extends Plugin {
|
|||||||
schema: appName,
|
schema: appName,
|
||||||
};
|
};
|
||||||
|
|
||||||
const plugins = [...mainApp.pm.getAliases()].filter(
|
const plugins = [...mainApp.pm.getPlugins().values()]
|
||||||
(name) => name !== 'multi-app-manager' && name !== 'multi-app-share-collection',
|
.filter(
|
||||||
);
|
(plugin) =>
|
||||||
|
plugin?.options?.packageName !== '@nocobase/plugin-multi-app-manager' &&
|
||||||
|
plugin?.options?.packageName !== '@nocobase/plugin-multi-app-share-collection',
|
||||||
|
)
|
||||||
|
.map((plugin) => plugin.name);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
database: lodash.merge(databaseOptions, {
|
database: lodash.merge(databaseOptions, {
|
||||||
|
Loading…
Reference in New Issue
Block a user