@nocobase/test 2.1.0-beta.9 → 2.2.0-alpha.1
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.
- package/lib/client/index.js +4 -2
- package/lib/client/renderAppOptions.js +1 -1
- package/lib/client/renderSettings.js +29 -4
- package/lib/scripts/test-db-creator.js +30 -2
- package/lib/server/mock-isolated-cluster.js +2 -13
- package/lib/server/mock-server.js +1 -3
- package/package.json +4 -3
- package/perf/scenarios/import/init.ts +2 -1
- package/setup/server.ts +1 -1
- package/vitest.mjs +9 -2
package/lib/client/index.js
CHANGED
|
@@ -46,7 +46,9 @@ __export(client_exports, {
|
|
|
46
46
|
waitForApp: () => waitForApp
|
|
47
47
|
});
|
|
48
48
|
module.exports = __toCommonJS(client_exports);
|
|
49
|
+
var import_react = __toESM(require("react"));
|
|
49
50
|
var import_react2 = require("@testing-library/react");
|
|
51
|
+
var import_flow_engine = require("@nocobase/flow-engine");
|
|
50
52
|
var import_web = require("../web");
|
|
51
53
|
__reExport(client_exports, require("./utils"), module.exports);
|
|
52
54
|
var import_react_hooks = require("@testing-library/react-hooks");
|
|
@@ -59,9 +61,9 @@ __reExport(client_exports, require("./renderSingleSettings"), module.exports);
|
|
|
59
61
|
__reExport(client_exports, require("./settingsChecker"), module.exports);
|
|
60
62
|
__reExport(client_exports, require("./commonSettingsChecker"), module.exports);
|
|
61
63
|
function customRender(ui, options = {}) {
|
|
64
|
+
const flowEngine = new import_flow_engine.FlowEngine();
|
|
62
65
|
return (0, import_react2.render)(ui, {
|
|
63
|
-
|
|
64
|
-
wrapper: /* @__PURE__ */ __name(({ children }) => children, "wrapper"),
|
|
66
|
+
wrapper: /* @__PURE__ */ __name(({ children }) => /* @__PURE__ */ import_react.default.createElement(import_flow_engine.FlowEngineProvider, { engine: flowEngine }, children), "wrapper"),
|
|
65
67
|
...options
|
|
66
68
|
});
|
|
67
69
|
}
|
|
@@ -42,8 +42,8 @@ __export(renderAppOptions_exports, {
|
|
|
42
42
|
});
|
|
43
43
|
module.exports = __toCommonJS(renderAppOptions_exports);
|
|
44
44
|
var import_react = __toESM(require("react"));
|
|
45
|
-
var import__ = require(".");
|
|
46
45
|
var import_web = require("../web");
|
|
46
|
+
var import__ = require(".");
|
|
47
47
|
var import_utils = require("./utils");
|
|
48
48
|
const renderAppOptions = /* @__PURE__ */ __name(async (options) => {
|
|
49
49
|
const App = (0, import_web.getAppComponent)(options);
|
|
@@ -35,15 +35,40 @@ module.exports = __toCommonJS(renderSettings_exports);
|
|
|
35
35
|
var import_react = require("@testing-library/react");
|
|
36
36
|
var import_renderAppOptions = require("./renderAppOptions");
|
|
37
37
|
var import_utils = require("./utils");
|
|
38
|
+
const querySettingsButton = /* @__PURE__ */ __name((container) => {
|
|
39
|
+
return container.querySelector('[aria-label^="designer-schema-settings-"]');
|
|
40
|
+
}, "querySettingsButton");
|
|
41
|
+
const querySettingsTrigger = /* @__PURE__ */ __name((container) => {
|
|
42
|
+
const button = querySettingsButton(container);
|
|
43
|
+
if (!button) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return button.closest(".ant-dropdown-trigger") || button;
|
|
47
|
+
}, "querySettingsTrigger");
|
|
48
|
+
const revealSchemaToolbar = /* @__PURE__ */ __name((container) => {
|
|
49
|
+
const blockItem = container.querySelector('[aria-label^="block-item-"]');
|
|
50
|
+
if (!blockItem) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
import_react.fireEvent.mouseEnter(blockItem);
|
|
54
|
+
import_react.fireEvent.mouseOver(blockItem);
|
|
55
|
+
}, "revealSchemaToolbar");
|
|
38
56
|
async function showSettingsMenu(container = document) {
|
|
39
57
|
await (0, import_react.waitFor)(() => {
|
|
40
|
-
|
|
58
|
+
if (!querySettingsButton(container)) {
|
|
59
|
+
revealSchemaToolbar(container);
|
|
60
|
+
}
|
|
61
|
+
return (0, import_utils.expectNoTsError)(querySettingsButton(container)).toBeInTheDocument();
|
|
41
62
|
});
|
|
42
63
|
const button = await (0, import_react.waitFor)(() => {
|
|
43
|
-
|
|
64
|
+
if (!querySettingsButton(container)) {
|
|
65
|
+
revealSchemaToolbar(container);
|
|
66
|
+
}
|
|
67
|
+
return querySettingsButton(container);
|
|
44
68
|
});
|
|
45
|
-
|
|
46
|
-
import_react.fireEvent.
|
|
69
|
+
const trigger = querySettingsTrigger(container) || button;
|
|
70
|
+
import_react.fireEvent.mouseEnter(trigger);
|
|
71
|
+
import_react.fireEvent.mouseOver(trigger);
|
|
47
72
|
await (0, import_react.waitFor)(() => {
|
|
48
73
|
return (0, import_utils.expectNoTsError)(import_react.screen.queryByTestId("schema-settings-menu")).toBeInTheDocument();
|
|
49
74
|
});
|
|
@@ -80,6 +80,18 @@ const _BaseClient = class _BaseClient {
|
|
|
80
80
|
};
|
|
81
81
|
__name(_BaseClient, "BaseClient");
|
|
82
82
|
let BaseClient = _BaseClient;
|
|
83
|
+
function escapeMysqlIdentifier(name) {
|
|
84
|
+
return `\`${String(name).replace(/`/g, "``")}\``;
|
|
85
|
+
}
|
|
86
|
+
__name(escapeMysqlIdentifier, "escapeMysqlIdentifier");
|
|
87
|
+
function escapeMysqlString(value) {
|
|
88
|
+
return `'${String(value).replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
89
|
+
}
|
|
90
|
+
__name(escapeMysqlString, "escapeMysqlString");
|
|
91
|
+
function mysqlAppUser() {
|
|
92
|
+
return String(process.env["DB_APP_USER"] || process.env["DB_USER"] || "").trim();
|
|
93
|
+
}
|
|
94
|
+
__name(mysqlAppUser, "mysqlAppUser");
|
|
83
95
|
const _PostgresClient = class _PostgresClient extends BaseClient {
|
|
84
96
|
async _removeDB(name) {
|
|
85
97
|
await this._client.query(`DROP DATABASE IF EXISTS ${name}`);
|
|
@@ -107,7 +119,15 @@ const _MySQLClient = class _MySQLClient extends BaseClient {
|
|
|
107
119
|
await this._client.query(`DROP DATABASE IF EXISTS ${name}`);
|
|
108
120
|
}
|
|
109
121
|
async _createDB(name) {
|
|
110
|
-
|
|
122
|
+
const database = escapeMysqlIdentifier(name);
|
|
123
|
+
const appUser = mysqlAppUser();
|
|
124
|
+
if (!appUser) {
|
|
125
|
+
throw new Error("DB_APP_USER or DB_USER is required for MySQL test database grants.");
|
|
126
|
+
}
|
|
127
|
+
const user = escapeMysqlString(appUser);
|
|
128
|
+
await this._client.query(`CREATE DATABASE IF NOT EXISTS ${database}`);
|
|
129
|
+
await this._client.query(`GRANT ALL PRIVILEGES ON ${database}.* TO ${user}@'%'`);
|
|
130
|
+
await this._client.query("FLUSH PRIVILEGES");
|
|
111
131
|
}
|
|
112
132
|
async _createConnection() {
|
|
113
133
|
return import_promise.default.createConnection({
|
|
@@ -126,7 +146,15 @@ const _MariaDBClient = class _MariaDBClient extends BaseClient {
|
|
|
126
146
|
await this._client.query(`DROP DATABASE IF EXISTS ${name}`);
|
|
127
147
|
}
|
|
128
148
|
async _createDB(name) {
|
|
129
|
-
|
|
149
|
+
const database = escapeMysqlIdentifier(name);
|
|
150
|
+
const appUser = mysqlAppUser();
|
|
151
|
+
if (!appUser) {
|
|
152
|
+
throw new Error("DB_APP_USER or DB_USER is required for MariaDB test database grants.");
|
|
153
|
+
}
|
|
154
|
+
const user = escapeMysqlString(appUser);
|
|
155
|
+
await this._client.query(`CREATE DATABASE IF NOT EXISTS ${database}`);
|
|
156
|
+
await this._client.query(`GRANT ALL PRIVILEGES ON ${database}.* TO ${user}@'%'`);
|
|
157
|
+
await this._client.query("FLUSH PRIVILEGES");
|
|
130
158
|
}
|
|
131
159
|
async _createConnection() {
|
|
132
160
|
return await import_mariadb.default.createConnection({
|
|
@@ -7,11 +7,9 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
var __create = Object.create;
|
|
11
10
|
var __defProp = Object.defineProperty;
|
|
12
11
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
15
13
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
16
14
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
17
15
|
var __export = (target, all) => {
|
|
@@ -26,21 +24,12 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
26
24
|
}
|
|
27
25
|
return to;
|
|
28
26
|
};
|
|
29
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
30
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
31
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
32
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
33
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
34
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
35
|
-
mod
|
|
36
|
-
));
|
|
37
27
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
38
28
|
var mock_isolated_cluster_exports = {};
|
|
39
29
|
__export(mock_isolated_cluster_exports, {
|
|
40
30
|
MockIsolatedCluster: () => MockIsolatedCluster
|
|
41
31
|
});
|
|
42
32
|
module.exports = __toCommonJS(mock_isolated_cluster_exports);
|
|
43
|
-
var import_node_path = __toESM(require("node:path"));
|
|
44
33
|
var import_node_child_process = require("node:child_process");
|
|
45
34
|
var import_portfinder = require("portfinder");
|
|
46
35
|
var import_utils = require("@nocobase/utils");
|
|
@@ -69,8 +58,8 @@ const _MockIsolatedCluster = class _MockIsolatedCluster {
|
|
|
69
58
|
...this.options.env,
|
|
70
59
|
APP_PORT: `${port}`,
|
|
71
60
|
APPEND_PRESET_BUILT_IN_PLUGINS: (this.options.plugins ?? []).join(","),
|
|
72
|
-
SOCKET_PATH: `
|
|
73
|
-
PM2_HOME:
|
|
61
|
+
SOCKET_PATH: (0, import_utils.storagePathJoin)("tests", `gateway-cluster-${(0, import_utils.uid)()}.sock`),
|
|
62
|
+
PM2_HOME: (0, import_utils.storagePathJoin)("tests", `.pm2-${(0, import_utils.uid)()}`)
|
|
74
63
|
}
|
|
75
64
|
});
|
|
76
65
|
await new Promise((resolve, reject) => {
|
|
@@ -53,8 +53,6 @@ var import_qs = __toESM(require("qs"));
|
|
|
53
53
|
var import_supertest = __toESM(require("supertest"));
|
|
54
54
|
var import_memory_pub_sub_adapter = require("./memory-pub-sub-adapter");
|
|
55
55
|
var import_mock_data_source = require("./mock-data-source");
|
|
56
|
-
var import_path = __toESM(require("path"));
|
|
57
|
-
var import_node_process = __toESM(require("node:process"));
|
|
58
56
|
var import_fs = require("fs");
|
|
59
57
|
const _MockServer = class _MockServer extends import_server.Application {
|
|
60
58
|
registerMockDataSource() {
|
|
@@ -264,7 +262,7 @@ async function createMockCluster({
|
|
|
264
262
|
}
|
|
265
263
|
__name(createMockCluster, "createMockCluster");
|
|
266
264
|
async function createMockServer(options = {}) {
|
|
267
|
-
const cachePath =
|
|
265
|
+
const cachePath = (0, import_utils.storagePathJoin)("cache");
|
|
268
266
|
try {
|
|
269
267
|
await import_fs.promises.rm(cachePath, { recursive: true, force: true });
|
|
270
268
|
await import_fs.promises.mkdir(cachePath, { recursive: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/test",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0-alpha.1",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"module": "./src/index.ts",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -51,7 +51,8 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@faker-js/faker": "8.1.0",
|
|
54
|
-
"@nocobase/server": "2.
|
|
54
|
+
"@nocobase/server": "2.2.0-alpha.1",
|
|
55
|
+
"@nocobase/utils": "2.2.0-alpha.1",
|
|
55
56
|
"@playwright/test": "^1.45.3",
|
|
56
57
|
"@testing-library/jest-dom": "^6.4.2",
|
|
57
58
|
"@testing-library/react": "^14.0.0",
|
|
@@ -76,5 +77,5 @@
|
|
|
76
77
|
"vitest-dom": "^0.1.1",
|
|
77
78
|
"ws": "^8.13.0"
|
|
78
79
|
},
|
|
79
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "303663aba6c6eefa27e6a6435b4c0352074ec40f"
|
|
80
81
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createMockServer } from '@nocobase/test';
|
|
2
2
|
import { CollectionRepository } from '@nocobase/plugin-data-source-main';
|
|
3
|
+
import { storagePathJoin } from '@nocobase/utils';
|
|
3
4
|
import fs from 'fs';
|
|
4
5
|
import path from 'path';
|
|
5
6
|
import os from 'os';
|
|
@@ -7,7 +8,7 @@ import ExcelJS from 'exceljs';
|
|
|
7
8
|
import { faker } from '@faker-js/faker';
|
|
8
9
|
import request from 'superagent';
|
|
9
10
|
|
|
10
|
-
const storagePath =
|
|
11
|
+
const storagePath = storagePathJoin('perf', 'importDataTest');
|
|
11
12
|
|
|
12
13
|
export default async function main() {
|
|
13
14
|
const app = await createMockServer({
|
package/setup/server.ts
CHANGED
package/vitest.mjs
CHANGED
|
@@ -10,6 +10,7 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
10
10
|
const __dirname = dirname(__filename);
|
|
11
11
|
|
|
12
12
|
const CORE_CLIENT_PACKAGES = ['sdk', 'client', 'client-v2', 'flow-engine'];
|
|
13
|
+
const PLUGIN_CLIENT_PACKAGES = ['client', 'client-v2'];
|
|
13
14
|
// 按路径填写要跳过服务端测试的插件目录(相对仓库根目录)
|
|
14
15
|
const skipPluginPaths = [
|
|
15
16
|
'packages/plugins/@nocobase/plugin-audit-logs',
|
|
@@ -114,7 +115,7 @@ const defineCommonConfig = () => {
|
|
|
114
115
|
function getExclude(isServer) {
|
|
115
116
|
return [
|
|
116
117
|
`packages/core/${isServer ? '' : '!'}(${CORE_CLIENT_PACKAGES.join('|')})/**/*`,
|
|
117
|
-
|
|
118
|
+
...(isServer ? PLUGIN_CLIENT_PACKAGES : ['server']).map((dir) => `packages/**/src/${dir}/**/*`),
|
|
118
119
|
];
|
|
119
120
|
}
|
|
120
121
|
|
|
@@ -181,6 +182,10 @@ export const getFilterInclude = (isServer, isCoverage) => {
|
|
|
181
182
|
return false;
|
|
182
183
|
});
|
|
183
184
|
|
|
185
|
+
if (argv[0] === 'run' || argv[0] === 'watch') {
|
|
186
|
+
argv = argv.slice(1);
|
|
187
|
+
}
|
|
188
|
+
|
|
184
189
|
let filterFileOrDir = argv[0];
|
|
185
190
|
|
|
186
191
|
if (!filterFileOrDir) return {};
|
|
@@ -216,7 +221,9 @@ export const getFilterInclude = (isServer, isCoverage) => {
|
|
|
216
221
|
|
|
217
222
|
// 插件目录,区分 client 和 server
|
|
218
223
|
return {
|
|
219
|
-
include:
|
|
224
|
+
include: isServer
|
|
225
|
+
? [`${filterFileOrDir}/src/server/${suffix}`]
|
|
226
|
+
: PLUGIN_CLIENT_PACKAGES.map((dir) => `${filterFileOrDir}/src/${dir}/${suffix}`),
|
|
220
227
|
};
|
|
221
228
|
};
|
|
222
229
|
|