@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.
@@ -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
- // wrap provider(s) here if needed
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
- return (0, import_utils.expectNoTsError)(container.querySelector('[aria-label^="designer-schema-settings-"]')).toBeInTheDocument();
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
- return container.querySelector('[aria-label^="designer-schema-settings-"]');
64
+ if (!querySettingsButton(container)) {
65
+ revealSchemaToolbar(container);
66
+ }
67
+ return querySettingsButton(container);
44
68
  });
45
- import_react.fireEvent.mouseEnter(button);
46
- import_react.fireEvent.mouseOver(button);
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
- await this._client.query(`CREATE DATABASE IF NOT EXISTS ${name}`);
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
- await this._client.query(`CREATE DATABASE IF NOT EXISTS ${name}`);
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: `storage/tests/gateway-cluster-${(0, import_utils.uid)()}.sock`,
73
- PM2_HOME: import_node_path.default.resolve(process.cwd(), `storage/tests/.pm2-${(0, import_utils.uid)()}`)
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 = import_path.default.join(import_node_process.default.cwd(), "storage", "cache");
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.1.0-beta.9",
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.1.0-beta.9",
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": "c3a2875e4cbbb43b1f2361e6f9f5f84a7d3f3c3c"
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 = path.resolve(process.cwd(), 'storage', 'perf', 'importDataTest');
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
@@ -1,4 +1,4 @@
1
- import { initEnv } from '@nocobase/cli';
1
+ import { initEnv } from '@nocobase/cli-v1';
2
2
 
3
3
  process.env.APP_ENV_PATH = process.env.APP_ENV_PATH || '.env.test';
4
4
 
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
- `packages/**/src/${isServer ? 'client' : 'server'}/**/*`,
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: [`${filterFileOrDir}/src/${isServer ? 'server' : 'client'}/${suffix}`],
224
+ include: isServer
225
+ ? [`${filterFileOrDir}/src/server/${suffix}`]
226
+ : PLUGIN_CLIENT_PACKAGES.map((dir) => `${filterFileOrDir}/src/${dir}/${suffix}`),
220
227
  };
221
228
  };
222
229