@nocobase/test 0.20.0-alpha.9 → 0.21.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ import React, { FC } from 'react';
2
+ import { GetAppComponentOptions, GetAppOptions } from '../web';
3
+ export { renderHook } from '@testing-library/react-hooks';
4
+ declare function customRender(ui: React.ReactElement, options?: {}): import("@testing-library/react").RenderResult<typeof import("@testing-library/dom/types/queries"), HTMLElement, HTMLElement>;
5
+ export * from '@testing-library/react';
6
+ export { default as userEvent } from '@testing-library/user-event';
7
+ export { customRender as render };
8
+ export declare const sleep: (timeout?: number) => Promise<unknown>;
9
+ export declare const WaitApp: () => Promise<void>;
10
+ interface RenderHookOptions extends Omit<GetAppOptions, 'value' | 'onChange'> {
11
+ hook: () => any;
12
+ props?: any;
13
+ Wrapper?: FC<{
14
+ children: React.ReactNode;
15
+ }>;
16
+ }
17
+ export declare const renderHookWithApp: (options: RenderHookOptions) => Promise<import("@testing-library/react-hooks").RenderHookResult<any, any, import("@testing-library/react-hooks").Renderer<any>>>;
18
+ export declare const renderApp: (options: GetAppComponentOptions) => Promise<import("@testing-library/react").RenderResult<typeof import("@testing-library/dom/types/queries"), HTMLElement, HTMLElement>>;
19
+ export declare const renderReadPrettyApp: (options: GetAppComponentOptions) => Promise<import("@testing-library/react").RenderResult<typeof import("@testing-library/dom/types/queries"), HTMLElement, HTMLElement>>;
@@ -0,0 +1,545 @@
1
+ import { expect } from "vitest";
2
+ import React, { Fragment } from "react";
3
+ import { render, waitFor, screen } from "@testing-library/react";
4
+ export * from "@testing-library/react";
5
+ import { renderHook } from "@testing-library/react-hooks";
6
+ import { renderHook as renderHook2 } from "@testing-library/react-hooks";
7
+ import MockAdapter from "axios-mock-adapter";
8
+ import { Application, LocalDataSource, SchemaComponent, DataBlockProvider } from "@nocobase/client";
9
+ import { default as default2 } from "@testing-library/user-event";
10
+ const dataSourceMainCollections = [
11
+ {
12
+ key: "h7b9i8khc3q",
13
+ name: "users",
14
+ inherit: false,
15
+ hidden: false,
16
+ description: null,
17
+ category: [],
18
+ namespace: "users.users",
19
+ duplicator: {
20
+ dumpable: "optional",
21
+ "with": "rolesUsers"
22
+ },
23
+ sortable: "sort",
24
+ model: "UserModel",
25
+ createdBy: true,
26
+ updatedBy: true,
27
+ logging: true,
28
+ from: "db2cm",
29
+ title: '{{t("Users")}}',
30
+ rawTitle: '{{t("Users")}}',
31
+ fields: [
32
+ {
33
+ uiSchema: {
34
+ type: "number",
35
+ title: '{{t("ID")}}',
36
+ "x-component": "InputNumber",
37
+ "x-read-pretty": true,
38
+ rawTitle: '{{t("ID")}}'
39
+ },
40
+ key: "ffp1f2sula0",
41
+ name: "id",
42
+ type: "bigInt",
43
+ "interface": "id",
44
+ description: null,
45
+ collectionName: "users",
46
+ parentKey: null,
47
+ reverseKey: null,
48
+ autoIncrement: true,
49
+ primaryKey: true,
50
+ allowNull: false
51
+ },
52
+ {
53
+ uiSchema: {
54
+ type: "string",
55
+ title: '{{t("Nickname")}}',
56
+ "x-component": "Input",
57
+ rawTitle: '{{t("Nickname")}}'
58
+ },
59
+ key: "vrv7yjue90g",
60
+ name: "nickname",
61
+ type: "string",
62
+ "interface": "input",
63
+ description: null,
64
+ collectionName: "users",
65
+ parentKey: null,
66
+ reverseKey: null
67
+ },
68
+ {
69
+ uiSchema: {
70
+ type: "string",
71
+ title: '{{t("Username")}}',
72
+ "x-component": "Input",
73
+ "x-validator": {
74
+ username: true
75
+ },
76
+ required: true,
77
+ rawTitle: '{{t("Username")}}'
78
+ },
79
+ key: "2ccs6evyrub",
80
+ name: "username",
81
+ type: "string",
82
+ "interface": "input",
83
+ description: null,
84
+ collectionName: "users",
85
+ parentKey: null,
86
+ reverseKey: null,
87
+ unique: true
88
+ },
89
+ {
90
+ uiSchema: {
91
+ type: "string",
92
+ title: '{{t("Email")}}',
93
+ "x-component": "Input",
94
+ "x-validator": "email",
95
+ required: true,
96
+ rawTitle: '{{t("Email")}}'
97
+ },
98
+ key: "rrskwjl5wt1",
99
+ name: "email",
100
+ type: "string",
101
+ "interface": "email",
102
+ description: null,
103
+ collectionName: "users",
104
+ parentKey: null,
105
+ reverseKey: null,
106
+ unique: true
107
+ },
108
+ {
109
+ key: "t09bauwm0wb",
110
+ name: "roles",
111
+ type: "belongsToMany",
112
+ "interface": "m2m",
113
+ description: null,
114
+ collectionName: "users",
115
+ parentKey: null,
116
+ reverseKey: null,
117
+ target: "roles",
118
+ foreignKey: "userId",
119
+ otherKey: "roleName",
120
+ onDelete: "CASCADE",
121
+ sourceKey: "id",
122
+ targetKey: "name",
123
+ through: "rolesUsers",
124
+ uiSchema: {
125
+ type: "array",
126
+ title: '{{t("Roles")}}',
127
+ "x-component": "AssociationField",
128
+ "x-component-props": {
129
+ multiple: true,
130
+ fieldNames: {
131
+ label: "title",
132
+ value: "name"
133
+ }
134
+ }
135
+ }
136
+ },
137
+ {
138
+ key: "1pz0art9mt7",
139
+ name: "f_n2fu6hvprct",
140
+ type: "string",
141
+ "interface": "select",
142
+ description: null,
143
+ collectionName: "t_vwpds9fs4xs",
144
+ parentKey: null,
145
+ reverseKey: null,
146
+ uiSchema: {
147
+ "enum": [
148
+ {
149
+ value: "test1",
150
+ label: "test1"
151
+ },
152
+ {
153
+ value: "test2",
154
+ label: "test2"
155
+ }
156
+ ],
157
+ type: "string",
158
+ "x-component": "Select",
159
+ title: "test"
160
+ }
161
+ }
162
+ ]
163
+ },
164
+ {
165
+ key: "pqnenvqrzxr",
166
+ name: "roles",
167
+ inherit: false,
168
+ hidden: false,
169
+ description: null,
170
+ category: [],
171
+ namespace: "acl.acl",
172
+ duplicator: {
173
+ dumpable: "required",
174
+ "with": "uiSchemas"
175
+ },
176
+ autoGenId: false,
177
+ model: "RoleModel",
178
+ filterTargetKey: "name",
179
+ sortable: true,
180
+ from: "db2cm",
181
+ title: '{{t("Roles")}}',
182
+ rawTitle: '{{t("Roles")}}',
183
+ fields: [
184
+ {
185
+ uiSchema: {
186
+ type: "string",
187
+ title: '{{t("Role UID")}}',
188
+ "x-component": "Input",
189
+ rawTitle: '{{t("Role UID")}}'
190
+ },
191
+ key: "jbz9m80bxmp",
192
+ name: "name",
193
+ type: "uid",
194
+ "interface": "input",
195
+ description: null,
196
+ collectionName: "roles",
197
+ parentKey: null,
198
+ reverseKey: null,
199
+ prefix: "r_",
200
+ primaryKey: true
201
+ },
202
+ {
203
+ uiSchema: {
204
+ type: "string",
205
+ title: '{{t("Role name")}}',
206
+ "x-component": "Input",
207
+ rawTitle: '{{t("Role name")}}'
208
+ },
209
+ key: "faywtz4sf3u",
210
+ name: "title",
211
+ type: "string",
212
+ "interface": "input",
213
+ description: null,
214
+ collectionName: "roles",
215
+ parentKey: null,
216
+ reverseKey: null,
217
+ unique: true,
218
+ translation: true
219
+ },
220
+ {
221
+ key: "1enkovm9sye",
222
+ name: "description",
223
+ type: "string",
224
+ "interface": null,
225
+ description: null,
226
+ collectionName: "roles",
227
+ parentKey: null,
228
+ reverseKey: null
229
+ }
230
+ ]
231
+ }
232
+ ];
233
+ const key = "data-source2";
234
+ const displayName = "Data Source 2";
235
+ const status = "loaded";
236
+ const type = "postgres";
237
+ const isDBInstance = true;
238
+ const collections = [
239
+ {
240
+ name: "test",
241
+ title: "test",
242
+ tableName: "test",
243
+ timestamps: false,
244
+ autoGenId: false,
245
+ filterTargetKey: "id",
246
+ fields: [
247
+ {
248
+ name: "id",
249
+ type: "integer",
250
+ allowNull: false,
251
+ primaryKey: false,
252
+ unique: false,
253
+ autoIncrement: true,
254
+ possibleTypes: [
255
+ "integer",
256
+ "sort"
257
+ ],
258
+ rawType: "INTEGER",
259
+ "interface": "integer",
260
+ uiSchema: {
261
+ type: "number",
262
+ "x-component": "InputNumber",
263
+ "x-component-props": {
264
+ stringMode: true,
265
+ step: "1"
266
+ },
267
+ "x-validator": "integer",
268
+ title: "id"
269
+ }
270
+ },
271
+ {
272
+ name: "title",
273
+ type: "string",
274
+ allowNull: false,
275
+ primaryKey: false,
276
+ unique: false,
277
+ possibleTypes: [
278
+ "string",
279
+ "uuid",
280
+ "nanoid"
281
+ ],
282
+ rawType: "CHARACTER VARYING(255)",
283
+ "interface": "input",
284
+ uiSchema: {
285
+ "x-component": "Input",
286
+ "x-component-props": {
287
+ style: {
288
+ width: "100%"
289
+ }
290
+ },
291
+ title: "title"
292
+ }
293
+ },
294
+ {
295
+ name: "content",
296
+ type: "text",
297
+ allowNull: true,
298
+ primaryKey: false,
299
+ unique: false,
300
+ rawType: "TEXT",
301
+ "interface": "textarea",
302
+ uiSchema: {
303
+ type: "string",
304
+ "x-component": "Input.TextArea",
305
+ title: "content"
306
+ }
307
+ }
308
+ ],
309
+ introspected: true
310
+ },
311
+ {
312
+ name: "test2",
313
+ title: "test2",
314
+ tableName: "test2",
315
+ timestamps: false,
316
+ autoGenId: false,
317
+ filterTargetKey: "id",
318
+ fields: [
319
+ {
320
+ name: "id",
321
+ type: "integer",
322
+ allowNull: false,
323
+ primaryKey: true,
324
+ unique: false,
325
+ autoIncrement: true,
326
+ possibleTypes: [
327
+ "integer",
328
+ "sort"
329
+ ],
330
+ rawType: "INTEGER",
331
+ "interface": "integer",
332
+ uiSchema: {
333
+ type: "number",
334
+ "x-component": "InputNumber",
335
+ "x-component-props": {
336
+ stringMode: true,
337
+ step: "1"
338
+ },
339
+ "x-validator": "integer",
340
+ title: "id"
341
+ }
342
+ },
343
+ {
344
+ name: "title",
345
+ type: "string",
346
+ allowNull: true,
347
+ primaryKey: false,
348
+ unique: false,
349
+ possibleTypes: [
350
+ "string",
351
+ "uuid",
352
+ "nanoid"
353
+ ],
354
+ rawType: "CHARACTER VARYING(255)",
355
+ "interface": "input",
356
+ uiSchema: {
357
+ "x-component": "Input",
358
+ "x-component-props": {
359
+ style: {
360
+ width: "100%"
361
+ }
362
+ },
363
+ title: "title"
364
+ }
365
+ },
366
+ {
367
+ name: "content",
368
+ type: "text",
369
+ allowNull: true,
370
+ primaryKey: false,
371
+ unique: false,
372
+ rawType: "TEXT",
373
+ "interface": "textarea",
374
+ uiSchema: {
375
+ type: "string",
376
+ "x-component": "Input.TextArea",
377
+ title: "content"
378
+ }
379
+ }
380
+ ],
381
+ introspected: true
382
+ }
383
+ ];
384
+ const dataSource2 = {
385
+ key,
386
+ displayName,
387
+ status,
388
+ type,
389
+ isDBInstance,
390
+ collections
391
+ };
392
+ const data = [
393
+ {
394
+ f_o3y6p9gf1gx: null,
395
+ createdAt: "2023-03-30T07:53:10.941Z",
396
+ updatedAt: "2024-04-12T03:27:45.748Z",
397
+ appLang: "zh-CN",
398
+ createdById: null,
399
+ email: "admin@nocobase.com",
400
+ f_2ytvt3phlp2: null,
401
+ f_3jl554hv7lt: null,
402
+ f_51qityssoq1: null,
403
+ f_dybwctlb233: null,
404
+ f_hbegrnglpv2: null,
405
+ f_ndkyrfvh9il: null,
406
+ f_o33xmbd62fj: null,
407
+ f_t52vqdtfv4h: null,
408
+ f_vak0o8efq4v: [],
409
+ id: 1,
410
+ nickname: "Super Admin",
411
+ phone: null,
412
+ systemSettings: {
413
+ theme: "compact",
414
+ themeId: 1
415
+ },
416
+ updatedById: 1,
417
+ username: "nocobase"
418
+ }
419
+ ];
420
+ const usersListData = {
421
+ data
422
+ };
423
+ const mockApi = (axiosInstance, apis = {}) => {
424
+ const mock = new MockAdapter(axiosInstance);
425
+ Object.keys(apis).forEach((key2) => {
426
+ mock.onAny(key2).reply(200, apis[key2]);
427
+ });
428
+ return (apis2 = {}) => {
429
+ Object.keys(apis2).forEach((key2) => {
430
+ mock.onAny(key2).reply(200, apis2[key2]);
431
+ });
432
+ };
433
+ };
434
+ const mockAppApi = (app, apis = {}) => {
435
+ const mock = mockApi(app.apiClient.axios, apis);
436
+ return mock;
437
+ };
438
+ const getApp = (options) => {
439
+ const { appOptions, enableUserListDataBlock, providers, apis, enableMultipleDataSource } = options;
440
+ const app = appOptions instanceof Application ? appOptions : new Application(appOptions);
441
+ if (providers) {
442
+ app.addProviders(providers);
443
+ }
444
+ app.getCollectionManager().addCollections(dataSourceMainCollections);
445
+ if (enableUserListDataBlock && !apis["users:list"]) {
446
+ apis["users:list"] = usersListData;
447
+ }
448
+ if (enableMultipleDataSource) {
449
+ app.dataSourceManager.addDataSource(LocalDataSource, dataSource2);
450
+ }
451
+ mockAppApi(app, apis);
452
+ const App = app.getRootComponent();
453
+ return {
454
+ App,
455
+ app
456
+ };
457
+ };
458
+ const getAppComponent = (options) => {
459
+ const {
460
+ Component,
461
+ enableUserListDataBlock,
462
+ enableMultipleDataSource,
463
+ value,
464
+ props,
465
+ appOptions,
466
+ apis,
467
+ onChange,
468
+ schema: optionsSchema = {}
469
+ } = options;
470
+ const schema = {
471
+ type: "object",
472
+ name: "test",
473
+ default: value,
474
+ "x-component": Component,
475
+ "x-component-props": {
476
+ onChange,
477
+ ...props
478
+ },
479
+ ...optionsSchema
480
+ };
481
+ if (!schema.name) {
482
+ schema.name = "test";
483
+ }
484
+ if (!schema.type) {
485
+ schema.type = "void";
486
+ }
487
+ const TestDemo = () => {
488
+ if (!enableUserListDataBlock) {
489
+ return /* @__PURE__ */ React.createElement(SchemaComponent, { schema });
490
+ }
491
+ return /* @__PURE__ */ React.createElement(DataBlockProvider, { collection: "users", action: "list" }, /* @__PURE__ */ React.createElement(SchemaComponent, { schema }));
492
+ };
493
+ const { App } = getApp({
494
+ appOptions,
495
+ apis,
496
+ providers: [TestDemo],
497
+ enableMultipleDataSource,
498
+ enableUserListDataBlock
499
+ });
500
+ return App;
501
+ };
502
+ function customRender(ui, options = {}) {
503
+ return render(ui, {
504
+ // wrap provider(s) here if needed
505
+ wrapper: ({ children }) => children,
506
+ ...options
507
+ });
508
+ }
509
+ const sleep = async (timeout = 0) => {
510
+ return new Promise((resolve) => {
511
+ setTimeout(resolve, timeout);
512
+ });
513
+ };
514
+ const WaitApp = async () => {
515
+ await waitFor(() => {
516
+ expect(screen.queryByText("Loading...")).not.toBeInTheDocument();
517
+ });
518
+ };
519
+ const renderHookWithApp = async (options) => {
520
+ const { hook: useHook, props, Wrapper = Fragment, ...otherOptions } = options;
521
+ const { App } = getApp(otherOptions);
522
+ const WrapperValue = ({ children }) => /* @__PURE__ */ React.createElement(App, null, /* @__PURE__ */ React.createElement(Wrapper, null, children));
523
+ const res = renderHook(() => useHook(), { wrapper: WrapperValue, initialProps: props });
524
+ await WaitApp();
525
+ return res;
526
+ };
527
+ const renderApp = async (options) => {
528
+ const App = getAppComponent(options);
529
+ const res = render(/* @__PURE__ */ React.createElement(App, null));
530
+ await WaitApp();
531
+ return res;
532
+ };
533
+ const renderReadPrettyApp = (options) => {
534
+ return renderApp({ ...options, schema: { ...options.schema || {}, "x-read-pretty": true } });
535
+ };
536
+ export {
537
+ WaitApp,
538
+ customRender as render,
539
+ renderApp,
540
+ renderHook2 as renderHook,
541
+ renderHookWithApp,
542
+ renderReadPrettyApp,
543
+ sleep,
544
+ default2 as userEvent
545
+ };
@@ -0,0 +1,2 @@
1
+ import { type PlaywrightTestConfig } from '@playwright/test';
2
+ export declare const defineConfig: (config?: PlaywrightTestConfig) => PlaywrightTestConfig<{}, {}>;