miaoda-game-devkit 0.2.16 → 0.2.17

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/README.md CHANGED
@@ -10,6 +10,17 @@
10
10
  - React 的 `playthroughTest` 与项目级 reporter 自动验证生产入口、真实 DOM 输入、
11
11
  有界推进和结果断言;聚焦运行只提示未检查,完整运行缺少有效流程时失败;
12
12
 
13
+ `playthroughTest` 的主流程回调从参数接收已配置好的 `user`,不要再调用
14
+ `userEvent.setup()`。这避免生成测试自行处理输入实例,但不会隐式接管全局 timer。
15
+ 时间、帧或自定义 scheduler 流程必须显式传入确定性 `step`;精确物理时间、暂停恢复
16
+ 或调度清理测试可使用 `ManualGameClock`。
17
+
18
+ Vitest 的 fake timers(包括 `vi.advanceTimersToNextFrame()`)适合在 devkit 自身的
19
+ 专门 scheduler 合约中使用,但不在所有 production playthrough 中全局启用;React
20
+ Testing Library 的 `asyncWrapper` 和 user-event 内部 timer 会因此互相影响。使用自定义
21
+ scheduler、Worker 或未通过浏览器 timer 接入的引擎时,应传显式 `step` 并通过
22
+ `diagnostics` 暴露权威状态。
23
+
13
24
  - React Vitest 在项目声明 Phaser 3 时使用其 browser bundle,并提供仅供模块能力探测的
14
25
  最小 Canvas 2D 边界,使 Phaser 3 代码不会阻断普通 JSDOM 测试;Storage 使用 JSDOM
15
26
  按 origin 提供的原生实现,Node 25+ worker 会关闭冲突的 Node Web Storage,
@@ -1,5 +1,6 @@
1
1
  import { G as GameClock, a as GameFrameCallback } from '../game-clock-suUidZdT.mjs';
2
2
  import { RenderResult } from '@testing-library/react';
3
+ import { UserEvent } from '@testing-library/user-event';
3
4
  import { ReactNode } from 'react';
4
5
 
5
6
  /** 测试用确定性时钟;应用测试推进它,不直接伪造游戏状态。 */
@@ -26,6 +27,11 @@ interface StepUntilOptions {
26
27
  maxSteps?: number;
27
28
  /** 每轮推进一单位游戏自有时间或工作;即时回合制结果可以省略。 */
28
29
  step?: (step: number) => void | Promise<void>;
30
+ /**
31
+ * Optional read-only state used to make bounded failures actionable.
32
+ * The value is sampled only when the bound is exhausted.
33
+ */
34
+ diagnostics?: () => unknown;
29
35
  }
30
36
 
31
37
  /** 单条 React 主流程测试留下的可序列化运行期证据。 */
@@ -53,9 +59,12 @@ interface ReactPlaythroughMetadata {
53
59
  interface ReactPlaythroughArguments {
54
60
  /** Testing Library 对生产游戏入口的渲染结果。 */
55
61
  view: RenderResult;
62
+ /** 已由 playthroughTest 创建的真实 DOM 用户输入驱动。 */
63
+ user: UserEvent;
56
64
  /**
57
65
  * 在硬性步数上限内等待权威结果。
58
66
  * 返回后必须再断言该结果,进入中间 active/running 状态不算完成。
67
+ * 即时结果不需要 step;时间、帧或自定义 scheduler 流程必须传入确定性 step。
59
68
  */
60
69
  stepUntil(condition: () => boolean, options?: StepUntilOptions): Promise<number>;
61
70
  }
@@ -1,5 +1,6 @@
1
1
  import { G as GameClock, a as GameFrameCallback } from '../game-clock-suUidZdT.js';
2
2
  import { RenderResult } from '@testing-library/react';
3
+ import { UserEvent } from '@testing-library/user-event';
3
4
  import { ReactNode } from 'react';
4
5
 
5
6
  /** 测试用确定性时钟;应用测试推进它,不直接伪造游戏状态。 */
@@ -26,6 +27,11 @@ interface StepUntilOptions {
26
27
  maxSteps?: number;
27
28
  /** 每轮推进一单位游戏自有时间或工作;即时回合制结果可以省略。 */
28
29
  step?: (step: number) => void | Promise<void>;
30
+ /**
31
+ * Optional read-only state used to make bounded failures actionable.
32
+ * The value is sampled only when the bound is exhausted.
33
+ */
34
+ diagnostics?: () => unknown;
29
35
  }
30
36
 
31
37
  /** 单条 React 主流程测试留下的可序列化运行期证据。 */
@@ -53,9 +59,12 @@ interface ReactPlaythroughMetadata {
53
59
  interface ReactPlaythroughArguments {
54
60
  /** Testing Library 对生产游戏入口的渲染结果。 */
55
61
  view: RenderResult;
62
+ /** 已由 playthroughTest 创建的真实 DOM 用户输入驱动。 */
63
+ user: UserEvent;
56
64
  /**
57
65
  * 在硬性步数上限内等待权威结果。
58
66
  * 返回后必须再断言该结果,进入中间 active/running 状态不算完成。
67
+ * 即时结果不需要 step;时间、帧或自定义 scheduler 流程必须传入确定性 step。
59
68
  */
60
69
  stepUntil(condition: () => boolean, options?: StepUntilOptions): Promise<number>;
61
70
  }
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/react/testing.ts
@@ -83,10 +93,21 @@ var ManualGameClock = class {
83
93
 
84
94
  // src/react/react-playthrough.ts
85
95
  var import_react2 = require("@testing-library/react");
96
+ var import_user_event = __toESM(require("@testing-library/user-event"));
86
97
  var import_vitest = require("vitest");
87
98
 
88
99
  // src/react/react-playthrough-core.ts
89
100
  var import_react = require("@testing-library/react");
101
+ function formatDiagnostics(read) {
102
+ if (!read) return void 0;
103
+ try {
104
+ const value = read();
105
+ if (typeof value === "string") return value;
106
+ return JSON.stringify(value);
107
+ } catch (error) {
108
+ return `diagnostics() threw: ${String(error)}`;
109
+ }
110
+ }
90
111
  function normalizePlaythroughWaiverReason(waiverReason) {
91
112
  if (waiverReason === void 0) return void 0;
92
113
  const reason = waiverReason.trim();
@@ -112,8 +133,11 @@ async function runBoundedUntil(condition, options = {}) {
112
133
  });
113
134
  }
114
135
  }
136
+ const diagnostics = formatDiagnostics(options.diagnostics);
137
+ const guidance = options.step ? "The step callback ran, but the authoritative outcome did not change." : "No step callback was provided, so time-driven gameplay was not advanced. Inject a ManualGameClock for this test and pass step: () => clock.stepFrame().";
138
+ const suffix = diagnostics ? ` Last diagnostics: ${diagnostics}` : "";
115
139
  throw new Error(
116
- `Playthrough outcome was not reached within ${maxSteps} steps.`
140
+ `Playthrough outcome was not reached within ${maxSteps} steps. ${guidance}${suffix}`
117
141
  );
118
142
  }
119
143
 
@@ -161,8 +185,10 @@ function definePlaythrough(element, run, waiverReason) {
161
185
  "playthroughTest must render the production game entry."
162
186
  );
163
187
  }
188
+ const user = import_user_event.default.setup();
164
189
  await run({
165
190
  view,
191
+ user,
166
192
  async stepUntil(condition, options = {}) {
167
193
  const steps = await runBoundedUntil(condition, options);
168
194
  if (evidence.domInputEvents === 0) {
@@ -55,10 +55,21 @@ var ManualGameClock = class {
55
55
 
56
56
  // src/react/react-playthrough.ts
57
57
  import { render } from "@testing-library/react";
58
+ import userEvent from "@testing-library/user-event";
58
59
  import { expect, test } from "vitest";
59
60
 
60
61
  // src/react/react-playthrough-core.ts
61
62
  import { act } from "@testing-library/react";
63
+ function formatDiagnostics(read) {
64
+ if (!read) return void 0;
65
+ try {
66
+ const value = read();
67
+ if (typeof value === "string") return value;
68
+ return JSON.stringify(value);
69
+ } catch (error) {
70
+ return `diagnostics() threw: ${String(error)}`;
71
+ }
72
+ }
62
73
  function normalizePlaythroughWaiverReason(waiverReason) {
63
74
  if (waiverReason === void 0) return void 0;
64
75
  const reason = waiverReason.trim();
@@ -84,8 +95,11 @@ async function runBoundedUntil(condition, options = {}) {
84
95
  });
85
96
  }
86
97
  }
98
+ const diagnostics = formatDiagnostics(options.diagnostics);
99
+ const guidance = options.step ? "The step callback ran, but the authoritative outcome did not change." : "No step callback was provided, so time-driven gameplay was not advanced. Inject a ManualGameClock for this test and pass step: () => clock.stepFrame().";
100
+ const suffix = diagnostics ? ` Last diagnostics: ${diagnostics}` : "";
87
101
  throw new Error(
88
- `Playthrough outcome was not reached within ${maxSteps} steps.`
102
+ `Playthrough outcome was not reached within ${maxSteps} steps. ${guidance}${suffix}`
89
103
  );
90
104
  }
91
105
 
@@ -133,8 +147,10 @@ function definePlaythrough(element, run, waiverReason) {
133
147
  "playthroughTest must render the production game entry."
134
148
  );
135
149
  }
150
+ const user = userEvent.setup();
136
151
  await run({
137
152
  view,
153
+ user,
138
154
  async stepUntil(condition, options = {}) {
139
155
  const steps = await runBoundedUntil(condition, options);
140
156
  if (evidence.domInputEvents === 0) {
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/react-vitest-config.ts
@@ -33,10 +43,21 @@ var import_node_path = require("path");
33
43
 
34
44
  // src/react/react-playthrough.ts
35
45
  var import_react2 = require("@testing-library/react");
46
+ var import_user_event = __toESM(require("@testing-library/user-event"));
36
47
  var import_vitest = require("vitest");
37
48
 
38
49
  // src/react/react-playthrough-core.ts
39
50
  var import_react = require("@testing-library/react");
51
+ function formatDiagnostics(read) {
52
+ if (!read) return void 0;
53
+ try {
54
+ const value = read();
55
+ if (typeof value === "string") return value;
56
+ return JSON.stringify(value);
57
+ } catch (error) {
58
+ return `diagnostics() threw: ${String(error)}`;
59
+ }
60
+ }
40
61
  function normalizePlaythroughWaiverReason(waiverReason) {
41
62
  if (waiverReason === void 0) return void 0;
42
63
  const reason = waiverReason.trim();
@@ -62,8 +83,11 @@ async function runBoundedUntil(condition, options = {}) {
62
83
  });
63
84
  }
64
85
  }
86
+ const diagnostics = formatDiagnostics(options.diagnostics);
87
+ const guidance = options.step ? "The step callback ran, but the authoritative outcome did not change." : "No step callback was provided, so time-driven gameplay was not advanced. Inject a ManualGameClock for this test and pass step: () => clock.stepFrame().";
88
+ const suffix = diagnostics ? ` Last diagnostics: ${diagnostics}` : "";
65
89
  throw new Error(
66
- `Playthrough outcome was not reached within ${maxSteps} steps.`
90
+ `Playthrough outcome was not reached within ${maxSteps} steps. ${guidance}${suffix}`
67
91
  );
68
92
  }
69
93
 
@@ -111,8 +135,10 @@ function definePlaythrough(element, run, waiverReason) {
111
135
  "playthroughTest must render the production game entry."
112
136
  );
113
137
  }
138
+ const user = import_user_event.default.setup();
114
139
  await run({
115
140
  view,
141
+ user,
116
142
  async stepUntil(condition, options = {}) {
117
143
  const steps = await runBoundedUntil(condition, options);
118
144
  if (evidence.domInputEvents === 0) {
@@ -273,11 +299,12 @@ function assessReactPlaythroughReport(input) {
273
299
  if (!audit.passed) {
274
300
  const cause = productionModule.errors[0] ?? input.unhandledErrors?.[0] ?? audit.issues[0] ?? "\u751F\u4EA7\u53EF\u73A9\u6D41\u7A0B\u6CA1\u6709\u7559\u4E0B\u5B8C\u6574\u8BC1\u636E\u3002";
275
301
  const timedOut = /outcome was not reached within \d+ steps/i.test(cause);
302
+ const missingStep = /No step callback was provided/i.test(cause);
276
303
  return {
277
304
  ...base,
278
305
  status: "FAILED",
279
306
  cause,
280
- next: timedOut ? "\u771F\u5B9E\u8F93\u5165\u5DF2\u6267\u884C\uFF0C\u4F46\u73A9\u6CD5\u6CA1\u6709\u5728\u4E0A\u9650\u5185\u4EA7\u751F\u7ED3\u679C\uFF1B\u68C0\u67E5\u70B9\u51FB\u6216\u6309\u952E\u662F\u5426\u771F\u7684\u8C03\u7528\u6E38\u620F\u7684\u751F\u4EA7\u63A7\u5236\u65B9\u6CD5\uFF0C\u4EE5\u53CA\u6E38\u620F\u771F\u5B9E\u72B6\u6001\u662F\u5426\u5230\u8FBE\u5E76\u663E\u793A\u7ED3\u679C\u3002" : "\u4ECE\u751F\u4EA7\u5165\u53E3\u6267\u884C\u771F\u5B9E DOM \u8F93\u5165\uFF0C\u7528 stepUntil \u6709\u754C\u63A8\u8FDB\u5230\u73A9\u5BB6\u53EF\u89C1\u7ED3\u679C\u6216\u6E38\u620F\u771F\u5B9E\u72B6\u6001\u7684\u53EA\u8BFB snapshot\uFF0C\u5E76\u5728\u5176\u540E\u65AD\u8A00\uFF1B\u4E0D\u8981\u76F4\u8FBE\u5185\u90E8\u5173\u5361\u6216\u4FEE\u6539\u73A9\u6CD5\u72B6\u6001\u3002",
307
+ next: missingStep ? "\u8BE5\u6D41\u7A0B\u662F\u65F6\u95F4\u6216\u5E27\u9A71\u52A8\u7684\uFF0C\u4F46 stepUntil \u6CA1\u6709\u63A8\u8FDB\u6E38\u620F\u65F6\u95F4\uFF1B\u4E3A\u751F\u4EA7\u6E38\u620F\u6CE8\u5165 devkit \u7684 GameClock\uFF0C\u5E76\u4F20\u5165 step: () => clock.stepFrame()\u3002\u4E0D\u8981\u7528\u771F\u5B9E setTimeout\u3002" : timedOut ? "\u771F\u5B9E\u8F93\u5165\u5DF2\u6267\u884C\uFF0C\u4F46\u73A9\u6CD5\u6CA1\u6709\u5728\u4E0A\u9650\u5185\u4EA7\u751F\u7ED3\u679C\uFF1B\u68C0\u67E5\u751F\u4EA7\u63A7\u5236\u662F\u5426\u6536\u5230\u8F93\u5165\uFF0C\u518D\u67E5\u770B\u8D85\u65F6\u9519\u8BEF\u4E2D\u7684 Last diagnostics \u5224\u65AD\u662F\u6E38\u620F\u5FAA\u73AF\u3001\u89C4\u5219\u72B6\u6001\u8FD8\u662F UI \u540C\u6B65\u672A\u63A8\u8FDB\u3002" : "\u4ECE\u751F\u4EA7\u5165\u53E3\u6267\u884C\u771F\u5B9E DOM \u8F93\u5165\uFF0C\u7528 stepUntil \u6709\u754C\u63A8\u8FDB\u5230\u73A9\u5BB6\u53EF\u89C1\u7ED3\u679C\u6216\u6E38\u620F\u771F\u5B9E\u72B6\u6001\u7684\u53EA\u8BFB snapshot\uFF0C\u5E76\u5728\u5176\u540E\u65AD\u8A00\uFF1B\u4E0D\u8981\u76F4\u8FBE\u5185\u90E8\u5173\u5361\u6216\u4FEE\u6539\u73A9\u6CD5\u72B6\u6001\u3002",
281
308
  failsRun: true
282
309
  };
283
310
  }
@@ -9,10 +9,21 @@ import { relative, resolve } from "path";
9
9
 
10
10
  // src/react/react-playthrough.ts
11
11
  import { render } from "@testing-library/react";
12
+ import userEvent from "@testing-library/user-event";
12
13
  import { expect, test } from "vitest";
13
14
 
14
15
  // src/react/react-playthrough-core.ts
15
16
  import { act } from "@testing-library/react";
17
+ function formatDiagnostics(read) {
18
+ if (!read) return void 0;
19
+ try {
20
+ const value = read();
21
+ if (typeof value === "string") return value;
22
+ return JSON.stringify(value);
23
+ } catch (error) {
24
+ return `diagnostics() threw: ${String(error)}`;
25
+ }
26
+ }
16
27
  function normalizePlaythroughWaiverReason(waiverReason) {
17
28
  if (waiverReason === void 0) return void 0;
18
29
  const reason = waiverReason.trim();
@@ -38,8 +49,11 @@ async function runBoundedUntil(condition, options = {}) {
38
49
  });
39
50
  }
40
51
  }
52
+ const diagnostics = formatDiagnostics(options.diagnostics);
53
+ const guidance = options.step ? "The step callback ran, but the authoritative outcome did not change." : "No step callback was provided, so time-driven gameplay was not advanced. Inject a ManualGameClock for this test and pass step: () => clock.stepFrame().";
54
+ const suffix = diagnostics ? ` Last diagnostics: ${diagnostics}` : "";
41
55
  throw new Error(
42
- `Playthrough outcome was not reached within ${maxSteps} steps.`
56
+ `Playthrough outcome was not reached within ${maxSteps} steps. ${guidance}${suffix}`
43
57
  );
44
58
  }
45
59
 
@@ -87,8 +101,10 @@ function definePlaythrough(element, run, waiverReason) {
87
101
  "playthroughTest must render the production game entry."
88
102
  );
89
103
  }
104
+ const user = userEvent.setup();
90
105
  await run({
91
106
  view,
107
+ user,
92
108
  async stepUntil(condition, options = {}) {
93
109
  const steps = await runBoundedUntil(condition, options);
94
110
  if (evidence.domInputEvents === 0) {
@@ -249,11 +265,12 @@ function assessReactPlaythroughReport(input) {
249
265
  if (!audit.passed) {
250
266
  const cause = productionModule.errors[0] ?? input.unhandledErrors?.[0] ?? audit.issues[0] ?? "\u751F\u4EA7\u53EF\u73A9\u6D41\u7A0B\u6CA1\u6709\u7559\u4E0B\u5B8C\u6574\u8BC1\u636E\u3002";
251
267
  const timedOut = /outcome was not reached within \d+ steps/i.test(cause);
268
+ const missingStep = /No step callback was provided/i.test(cause);
252
269
  return {
253
270
  ...base,
254
271
  status: "FAILED",
255
272
  cause,
256
- next: timedOut ? "\u771F\u5B9E\u8F93\u5165\u5DF2\u6267\u884C\uFF0C\u4F46\u73A9\u6CD5\u6CA1\u6709\u5728\u4E0A\u9650\u5185\u4EA7\u751F\u7ED3\u679C\uFF1B\u68C0\u67E5\u70B9\u51FB\u6216\u6309\u952E\u662F\u5426\u771F\u7684\u8C03\u7528\u6E38\u620F\u7684\u751F\u4EA7\u63A7\u5236\u65B9\u6CD5\uFF0C\u4EE5\u53CA\u6E38\u620F\u771F\u5B9E\u72B6\u6001\u662F\u5426\u5230\u8FBE\u5E76\u663E\u793A\u7ED3\u679C\u3002" : "\u4ECE\u751F\u4EA7\u5165\u53E3\u6267\u884C\u771F\u5B9E DOM \u8F93\u5165\uFF0C\u7528 stepUntil \u6709\u754C\u63A8\u8FDB\u5230\u73A9\u5BB6\u53EF\u89C1\u7ED3\u679C\u6216\u6E38\u620F\u771F\u5B9E\u72B6\u6001\u7684\u53EA\u8BFB snapshot\uFF0C\u5E76\u5728\u5176\u540E\u65AD\u8A00\uFF1B\u4E0D\u8981\u76F4\u8FBE\u5185\u90E8\u5173\u5361\u6216\u4FEE\u6539\u73A9\u6CD5\u72B6\u6001\u3002",
273
+ next: missingStep ? "\u8BE5\u6D41\u7A0B\u662F\u65F6\u95F4\u6216\u5E27\u9A71\u52A8\u7684\uFF0C\u4F46 stepUntil \u6CA1\u6709\u63A8\u8FDB\u6E38\u620F\u65F6\u95F4\uFF1B\u4E3A\u751F\u4EA7\u6E38\u620F\u6CE8\u5165 devkit \u7684 GameClock\uFF0C\u5E76\u4F20\u5165 step: () => clock.stepFrame()\u3002\u4E0D\u8981\u7528\u771F\u5B9E setTimeout\u3002" : timedOut ? "\u771F\u5B9E\u8F93\u5165\u5DF2\u6267\u884C\uFF0C\u4F46\u73A9\u6CD5\u6CA1\u6709\u5728\u4E0A\u9650\u5185\u4EA7\u751F\u7ED3\u679C\uFF1B\u68C0\u67E5\u751F\u4EA7\u63A7\u5236\u662F\u5426\u6536\u5230\u8F93\u5165\uFF0C\u518D\u67E5\u770B\u8D85\u65F6\u9519\u8BEF\u4E2D\u7684 Last diagnostics \u5224\u65AD\u662F\u6E38\u620F\u5FAA\u73AF\u3001\u89C4\u5219\u72B6\u6001\u8FD8\u662F UI \u540C\u6B65\u672A\u63A8\u8FDB\u3002" : "\u4ECE\u751F\u4EA7\u5165\u53E3\u6267\u884C\u771F\u5B9E DOM \u8F93\u5165\uFF0C\u7528 stepUntil \u6709\u754C\u63A8\u8FDB\u5230\u73A9\u5BB6\u53EF\u89C1\u7ED3\u679C\u6216\u6E38\u620F\u771F\u5B9E\u72B6\u6001\u7684\u53EA\u8BFB snapshot\uFF0C\u5E76\u5728\u5176\u540E\u65AD\u8A00\uFF1B\u4E0D\u8981\u76F4\u8FBE\u5185\u90E8\u5173\u5361\u6216\u4FEE\u6539\u73A9\u6CD5\u72B6\u6001\u3002",
257
274
  failsRun: true
258
275
  };
259
276
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miaoda-game-devkit",
3
- "version": "0.2.16",
3
+ "version": "0.2.17",
4
4
  "description": "Shared React and Phaser game lint plus deterministic testing tools for Miaoda games",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",
@@ -126,6 +126,7 @@
126
126
  "peerDependencies": {
127
127
  "@testing-library/jest-dom": ">=6 <8",
128
128
  "@testing-library/react": ">=16 <17",
129
+ "@testing-library/user-event": ">=14 <15",
129
130
  "phaser": ">=4.0.0 <5",
130
131
  "phaser4-rex-plugins": ">=4.0.0 <5",
131
132
  "react": ">=19 <20",
@@ -139,6 +140,9 @@
139
140
  "@testing-library/react": {
140
141
  "optional": true
141
142
  },
143
+ "@testing-library/user-event": {
144
+ "optional": true
145
+ },
142
146
  "phaser": {
143
147
  "optional": true
144
148
  },