miaoda-game-devkit 0.2.7 → 0.2.8
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.
|
@@ -308,7 +308,11 @@ function auditGameplayRun(options2, tests) {
|
|
|
308
308
|
}
|
|
309
309
|
issues.push(...getDefinitionIssues(expected, metadata));
|
|
310
310
|
if (test.state !== "passed") {
|
|
311
|
-
|
|
311
|
+
if (test.error) {
|
|
312
|
+
issues.push(`\u73A9\u6CD5\u6D4B\u8BD5 "${expected.id}" \u6D4B\u8BD5\u5931\u8D25\uFF1A${test.error}`);
|
|
313
|
+
} else {
|
|
314
|
+
issues.push(`\u73A9\u6CD5\u6D4B\u8BD5 "${expected.id}" \u7684\u6D4B\u8BD5\u72B6\u6001\u4E3A ${test.state}\u3002`);
|
|
315
|
+
}
|
|
312
316
|
continue;
|
|
313
317
|
}
|
|
314
318
|
if (!metadata.verified || !metadata.evidence) {
|
|
@@ -383,7 +387,8 @@ function formatGameplayIssues(issues) {
|
|
|
383
387
|
destroy: "\u6E05\u7406\uFF1A\u5728 afterEach \u4E2D\u8C03\u7528 host.destroy()\uFF0C\u5E76\u4FDD\u6301\u9500\u6BC1\u5E42\u7B49\u3002",
|
|
384
388
|
registry: "Scene \u6CE8\u518C\uFF1A\u786E\u8BA4\u6E38\u620F\u6E90\u7801\u6CE8\u518C\u4E86\u8BE5 Scene\uFF1B\u6D4B\u8BD5\u9700\u8981\u5207\u6362\u5230\u5B83\u65F6\uFF0C\u5728\u521B\u5EFA host \u65F6\u901A\u8FC7 additionalScenes \u63D0\u4F9B Scene \u7C7B\u3002",
|
|
385
389
|
missing: "\u6253\u5F00\u4E0A\u8FF0\u6587\u4EF6\uFF0C\u7528 gameplayTest \u6DFB\u52A0\u8FD9\u4E9B\u73A9\u6CD5\u6D4B\u8BD5\uFF1Bid \u5FC5\u987B\u4E0E vitest.config.ts \u4E2D\u7684\u914D\u7F6E\u5B8C\u5168\u4E00\u81F4\uFF0C\u521B\u5EFA host \u540E\u8C03\u7528 contract.attachHost(host)\u3002",
|
|
386
|
-
test: "\u5148\u4FEE\u590D\u5BF9\u5E94\u6D4B\u8BD5\u4E0A\u65B9\u663E\u793A\u7684\u7B2C\u4E00\u6761\u539F\u59CB\u9519\u8BEF\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C pnpm test\u3002"
|
|
390
|
+
test: "\u5148\u4FEE\u590D\u5BF9\u5E94\u6D4B\u8BD5\u4E0A\u65B9\u663E\u793A\u7684\u7B2C\u4E00\u6761\u539F\u59CB\u9519\u8BEF\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C pnpm test\u3002",
|
|
391
|
+
unhandled: "\u5F02\u6B65\u9519\u8BEF\uFF1A\u5148\u4FEE\u590D\u4E0A\u65B9\u663E\u793A\u7684\u7B2C\u4E00\u6761\u9519\u8BEF\uFF1B\u8F93\u5165\u3001\u5E27\u63A8\u8FDB\u548C\u751F\u547D\u5468\u671F\u64CD\u4F5C\u90FD\u8981\u5728\u6B63\u786E\u7684 host \u751F\u547D\u5468\u671F\u5185\u5E76\u4F7F\u7528 await\u3002"
|
|
387
392
|
};
|
|
388
393
|
const getCategory = (issue) => {
|
|
389
394
|
if (issue.includes("\u672A\u8BB0\u5F55\u771F\u5B9E DOM \u8F93\u5165")) return { category: "input", key: "input" };
|
|
@@ -408,6 +413,14 @@ function formatGameplayIssues(issues) {
|
|
|
408
413
|
return { category: "registry", key: `registry:${scene}` };
|
|
409
414
|
}
|
|
410
415
|
if (issue.includes("\u7F3A\u5C11 gameplay contract")) return { category: "missing", key: "missing" };
|
|
416
|
+
if (issue.includes("\u6D4B\u8BD5\u5931\u8D25\uFF1A")) {
|
|
417
|
+
const message = issue.split("\u6D4B\u8BD5\u5931\u8D25\uFF1A")[1] ?? issue;
|
|
418
|
+
return { category: "test", key: `test:${message}` };
|
|
419
|
+
}
|
|
420
|
+
if (issue.includes("\u6D4B\u8BD5\u8FD0\u884C\u671F\u95F4\u53D1\u751F\u5F02\u6B65\u9519\u8BEF\uFF1A")) {
|
|
421
|
+
const message = issue.split("\u6D4B\u8BD5\u8FD0\u884C\u671F\u95F4\u53D1\u751F\u5F02\u6B65\u9519\u8BEF\uFF1A")[1] ?? issue;
|
|
422
|
+
return { category: "unhandled", key: `test:${message}` };
|
|
423
|
+
}
|
|
411
424
|
if (issue.includes("\u7684\u6D4B\u8BD5\u72B6\u6001\u4E3A")) return { category: "test", key: "test" };
|
|
412
425
|
return { category: "other", key: `other:${issue}` };
|
|
413
426
|
};
|
|
@@ -431,7 +444,7 @@ function formatGameplayIssues(issues) {
|
|
|
431
444
|
continue;
|
|
432
445
|
}
|
|
433
446
|
const readable = compact.replaceAll(/(?:gameplay )?contract "([^"]+)"/g, '\u73A9\u6CD5\u6D4B\u8BD5 "$1"').replaceAll("evidence requirements", "\u8981\u6C42\u9A8C\u8BC1\u7684\u6E38\u620F\u884C\u4E3A").replaceAll("metadata", "\u6D4B\u8BD5\u914D\u7F6E").replaceAll("host registry", "\u6D4B\u8BD5\u8BB0\u5F55\u7684 Scene \u5217\u8868");
|
|
434
|
-
const id = compact.match(/contract "([^"]+)"/)?.[1];
|
|
447
|
+
const id = compact.match(/(?:contract|玩法测试) "([^"]+)"/)?.[1];
|
|
435
448
|
const { category, key } = getCategory(compact);
|
|
436
449
|
const group = groups.get(key);
|
|
437
450
|
if (group) {
|
|
@@ -817,4 +830,15 @@ describe("gameplay audit", () => {
|
|
|
817
830
|
expect(result.repairs).toHaveLength(1);
|
|
818
831
|
expect(result.repairs[0]).toContain("vitest.config.ts");
|
|
819
832
|
});
|
|
833
|
+
it("\u4FDD\u7559\u5E76\u5408\u5E76 Vitest \u8FD0\u884C\u65F6\u5F02\u5E38\u6D88\u606F", () => {
|
|
834
|
+
const result = formatGameplayIssues([
|
|
835
|
+
'\u73A9\u6CD5\u6D4B\u8BD5 "Map.transition" \u6D4B\u8BD5\u5931\u8D25\uFF1APhaser HEADLESS mouse input target cannot dispatch DOM events',
|
|
836
|
+
'\u73A9\u6CD5\u6D4B\u8BD5 "Editor.transition" \u6D4B\u8BD5\u5931\u8D25\uFF1APhaser HEADLESS mouse input target cannot dispatch DOM events',
|
|
837
|
+
"\u6D4B\u8BD5\u8FD0\u884C\u671F\u95F4\u53D1\u751F\u5F02\u6B65\u9519\u8BEF\uFF1APhaser HEADLESS mouse input target cannot dispatch DOM events"
|
|
838
|
+
]);
|
|
839
|
+
expect(result.issues).toEqual([
|
|
840
|
+
'\u73A9\u6CD5\u6D4B\u8BD5 "Map.transition" \u6D4B\u8BD5\u5931\u8D25\uFF1APhaser HEADLESS mouse input target cannot dispatch DOM events\uFF08\u540C\u7C7B\u95EE\u9898\u8FD8\u51FA\u73B0\u5728\uFF1AEditor.transition\uFF09'
|
|
841
|
+
]);
|
|
842
|
+
expect(result.repairs[0]).toContain("\u7B2C\u4E00\u6761\u539F\u59CB\u9519\u8BEF");
|
|
843
|
+
});
|
|
820
844
|
});
|
|
@@ -313,7 +313,11 @@ function auditGameplayRun(options, tests) {
|
|
|
313
313
|
}
|
|
314
314
|
issues.push(...getDefinitionIssues(expected, metadata));
|
|
315
315
|
if (test.state !== "passed") {
|
|
316
|
-
|
|
316
|
+
if (test.error) {
|
|
317
|
+
issues.push(`\u73A9\u6CD5\u6D4B\u8BD5 "${expected.id}" \u6D4B\u8BD5\u5931\u8D25\uFF1A${test.error}`);
|
|
318
|
+
} else {
|
|
319
|
+
issues.push(`\u73A9\u6CD5\u6D4B\u8BD5 "${expected.id}" \u7684\u6D4B\u8BD5\u72B6\u6001\u4E3A ${test.state}\u3002`);
|
|
320
|
+
}
|
|
317
321
|
continue;
|
|
318
322
|
}
|
|
319
323
|
if (!metadata.verified || !metadata.evidence) {
|
|
@@ -370,11 +374,13 @@ function isGameplayContractMetadata(value) {
|
|
|
370
374
|
}
|
|
371
375
|
function toAuditTest(test) {
|
|
372
376
|
const metadata = test.meta().gameplayContract;
|
|
377
|
+
const firstError = test.result().errors?.[0];
|
|
373
378
|
return {
|
|
374
379
|
file: normalizePath(test.module.relativeModuleId),
|
|
375
380
|
name: test.fullName,
|
|
376
381
|
state: test.result().state,
|
|
377
|
-
metadata: isGameplayContractMetadata(metadata) ? metadata : void 0
|
|
382
|
+
metadata: isGameplayContractMetadata(metadata) ? metadata : void 0,
|
|
383
|
+
error: firstError?.message?.replaceAll(/\s+/g, " ").trim().slice(0, 360) || void 0
|
|
378
384
|
};
|
|
379
385
|
}
|
|
380
386
|
function formatGameplayIssues(issues) {
|
|
@@ -405,7 +411,8 @@ function formatGameplayIssues(issues) {
|
|
|
405
411
|
destroy: "\u6E05\u7406\uFF1A\u5728 afterEach \u4E2D\u8C03\u7528 host.destroy()\uFF0C\u5E76\u4FDD\u6301\u9500\u6BC1\u5E42\u7B49\u3002",
|
|
406
412
|
registry: "Scene \u6CE8\u518C\uFF1A\u786E\u8BA4\u6E38\u620F\u6E90\u7801\u6CE8\u518C\u4E86\u8BE5 Scene\uFF1B\u6D4B\u8BD5\u9700\u8981\u5207\u6362\u5230\u5B83\u65F6\uFF0C\u5728\u521B\u5EFA host \u65F6\u901A\u8FC7 additionalScenes \u63D0\u4F9B Scene \u7C7B\u3002",
|
|
407
413
|
missing: "\u6253\u5F00\u4E0A\u8FF0\u6587\u4EF6\uFF0C\u7528 gameplayTest \u6DFB\u52A0\u8FD9\u4E9B\u73A9\u6CD5\u6D4B\u8BD5\uFF1Bid \u5FC5\u987B\u4E0E vitest.config.ts \u4E2D\u7684\u914D\u7F6E\u5B8C\u5168\u4E00\u81F4\uFF0C\u521B\u5EFA host \u540E\u8C03\u7528 contract.attachHost(host)\u3002",
|
|
408
|
-
test: "\u5148\u4FEE\u590D\u5BF9\u5E94\u6D4B\u8BD5\u4E0A\u65B9\u663E\u793A\u7684\u7B2C\u4E00\u6761\u539F\u59CB\u9519\u8BEF\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C pnpm test\u3002"
|
|
414
|
+
test: "\u5148\u4FEE\u590D\u5BF9\u5E94\u6D4B\u8BD5\u4E0A\u65B9\u663E\u793A\u7684\u7B2C\u4E00\u6761\u539F\u59CB\u9519\u8BEF\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C pnpm test\u3002",
|
|
415
|
+
unhandled: "\u5F02\u6B65\u9519\u8BEF\uFF1A\u5148\u4FEE\u590D\u4E0A\u65B9\u663E\u793A\u7684\u7B2C\u4E00\u6761\u9519\u8BEF\uFF1B\u8F93\u5165\u3001\u5E27\u63A8\u8FDB\u548C\u751F\u547D\u5468\u671F\u64CD\u4F5C\u90FD\u8981\u5728\u6B63\u786E\u7684 host \u751F\u547D\u5468\u671F\u5185\u5E76\u4F7F\u7528 await\u3002"
|
|
409
416
|
};
|
|
410
417
|
const getCategory = (issue) => {
|
|
411
418
|
if (issue.includes("\u672A\u8BB0\u5F55\u771F\u5B9E DOM \u8F93\u5165")) return { category: "input", key: "input" };
|
|
@@ -430,6 +437,14 @@ function formatGameplayIssues(issues) {
|
|
|
430
437
|
return { category: "registry", key: `registry:${scene}` };
|
|
431
438
|
}
|
|
432
439
|
if (issue.includes("\u7F3A\u5C11 gameplay contract")) return { category: "missing", key: "missing" };
|
|
440
|
+
if (issue.includes("\u6D4B\u8BD5\u5931\u8D25\uFF1A")) {
|
|
441
|
+
const message = issue.split("\u6D4B\u8BD5\u5931\u8D25\uFF1A")[1] ?? issue;
|
|
442
|
+
return { category: "test", key: `test:${message}` };
|
|
443
|
+
}
|
|
444
|
+
if (issue.includes("\u6D4B\u8BD5\u8FD0\u884C\u671F\u95F4\u53D1\u751F\u5F02\u6B65\u9519\u8BEF\uFF1A")) {
|
|
445
|
+
const message = issue.split("\u6D4B\u8BD5\u8FD0\u884C\u671F\u95F4\u53D1\u751F\u5F02\u6B65\u9519\u8BEF\uFF1A")[1] ?? issue;
|
|
446
|
+
return { category: "unhandled", key: `test:${message}` };
|
|
447
|
+
}
|
|
433
448
|
if (issue.includes("\u7684\u6D4B\u8BD5\u72B6\u6001\u4E3A")) return { category: "test", key: "test" };
|
|
434
449
|
return { category: "other", key: `other:${issue}` };
|
|
435
450
|
};
|
|
@@ -453,7 +468,7 @@ function formatGameplayIssues(issues) {
|
|
|
453
468
|
continue;
|
|
454
469
|
}
|
|
455
470
|
const readable = compact.replaceAll(/(?:gameplay )?contract "([^"]+)"/g, '\u73A9\u6CD5\u6D4B\u8BD5 "$1"').replaceAll("evidence requirements", "\u8981\u6C42\u9A8C\u8BC1\u7684\u6E38\u620F\u884C\u4E3A").replaceAll("metadata", "\u6D4B\u8BD5\u914D\u7F6E").replaceAll("host registry", "\u6D4B\u8BD5\u8BB0\u5F55\u7684 Scene \u5217\u8868");
|
|
456
|
-
const id = compact.match(/contract "([^"]+)"/)?.[1];
|
|
471
|
+
const id = compact.match(/(?:contract|玩法测试) "([^"]+)"/)?.[1];
|
|
457
472
|
const { category, key } = getCategory(compact);
|
|
458
473
|
const group = groups.get(key);
|
|
459
474
|
if (group) {
|
|
@@ -530,7 +545,7 @@ var GameplayAuditReporter = class {
|
|
|
530
545
|
for (const issue of result.issues) this.reportPreflightIssue(issue);
|
|
531
546
|
}
|
|
532
547
|
/** 在测试运行结束后汇总全部 contract、Ledger 和 Scene registry,并决定命令退出码。 */
|
|
533
|
-
onTestRunEnd(testModules,
|
|
548
|
+
onTestRunEnd(testModules, unhandledErrors = [], reason = "passed") {
|
|
534
549
|
const collectionFailed = reason === "failed" && testModules.some(
|
|
535
550
|
(testModule) => testModule.state() === "failed" && [...testModule.children.allTests()].length === 0
|
|
536
551
|
);
|
|
@@ -545,9 +560,11 @@ var GameplayAuditReporter = class {
|
|
|
545
560
|
(testModule) => [...testModule.children.allTests()].map(toAuditTest)
|
|
546
561
|
);
|
|
547
562
|
const result = auditGameplayRun(this.options, tests);
|
|
563
|
+
const runtimeIssues = unhandledErrors.map((error) => error.message?.replaceAll(/\s+/g, " ").trim()).filter(Boolean).map((message) => `\u6D4B\u8BD5\u8FD0\u884C\u671F\u95F4\u53D1\u751F\u5F02\u6B65\u9519\u8BEF\uFF1A${message}`);
|
|
548
564
|
const combinedIssues = [
|
|
549
565
|
...this.preflightIssues,
|
|
550
|
-
...result.issues
|
|
566
|
+
...result.issues,
|
|
567
|
+
...runtimeIssues
|
|
551
568
|
];
|
|
552
569
|
if (combinedIssues.length > 0) {
|
|
553
570
|
printIssues("FINAL", [...new Set(combinedIssues)]);
|
package/dist/vitest-config.js
CHANGED
|
@@ -333,7 +333,11 @@ function auditGameplayRun(options, tests) {
|
|
|
333
333
|
}
|
|
334
334
|
issues.push(...getDefinitionIssues(expected, metadata));
|
|
335
335
|
if (test.state !== "passed") {
|
|
336
|
-
|
|
336
|
+
if (test.error) {
|
|
337
|
+
issues.push(`\u73A9\u6CD5\u6D4B\u8BD5 "${expected.id}" \u6D4B\u8BD5\u5931\u8D25\uFF1A${test.error}`);
|
|
338
|
+
} else {
|
|
339
|
+
issues.push(`\u73A9\u6CD5\u6D4B\u8BD5 "${expected.id}" \u7684\u6D4B\u8BD5\u72B6\u6001\u4E3A ${test.state}\u3002`);
|
|
340
|
+
}
|
|
337
341
|
continue;
|
|
338
342
|
}
|
|
339
343
|
if (!metadata.verified || !metadata.evidence) {
|
|
@@ -390,11 +394,13 @@ function isGameplayContractMetadata(value) {
|
|
|
390
394
|
}
|
|
391
395
|
function toAuditTest(test) {
|
|
392
396
|
const metadata = test.meta().gameplayContract;
|
|
397
|
+
const firstError = test.result().errors?.[0];
|
|
393
398
|
return {
|
|
394
399
|
file: normalizePath(test.module.relativeModuleId),
|
|
395
400
|
name: test.fullName,
|
|
396
401
|
state: test.result().state,
|
|
397
|
-
metadata: isGameplayContractMetadata(metadata) ? metadata : void 0
|
|
402
|
+
metadata: isGameplayContractMetadata(metadata) ? metadata : void 0,
|
|
403
|
+
error: firstError?.message?.replaceAll(/\s+/g, " ").trim().slice(0, 360) || void 0
|
|
398
404
|
};
|
|
399
405
|
}
|
|
400
406
|
function formatGameplayIssues(issues) {
|
|
@@ -425,7 +431,8 @@ function formatGameplayIssues(issues) {
|
|
|
425
431
|
destroy: "\u6E05\u7406\uFF1A\u5728 afterEach \u4E2D\u8C03\u7528 host.destroy()\uFF0C\u5E76\u4FDD\u6301\u9500\u6BC1\u5E42\u7B49\u3002",
|
|
426
432
|
registry: "Scene \u6CE8\u518C\uFF1A\u786E\u8BA4\u6E38\u620F\u6E90\u7801\u6CE8\u518C\u4E86\u8BE5 Scene\uFF1B\u6D4B\u8BD5\u9700\u8981\u5207\u6362\u5230\u5B83\u65F6\uFF0C\u5728\u521B\u5EFA host \u65F6\u901A\u8FC7 additionalScenes \u63D0\u4F9B Scene \u7C7B\u3002",
|
|
427
433
|
missing: "\u6253\u5F00\u4E0A\u8FF0\u6587\u4EF6\uFF0C\u7528 gameplayTest \u6DFB\u52A0\u8FD9\u4E9B\u73A9\u6CD5\u6D4B\u8BD5\uFF1Bid \u5FC5\u987B\u4E0E vitest.config.ts \u4E2D\u7684\u914D\u7F6E\u5B8C\u5168\u4E00\u81F4\uFF0C\u521B\u5EFA host \u540E\u8C03\u7528 contract.attachHost(host)\u3002",
|
|
428
|
-
test: "\u5148\u4FEE\u590D\u5BF9\u5E94\u6D4B\u8BD5\u4E0A\u65B9\u663E\u793A\u7684\u7B2C\u4E00\u6761\u539F\u59CB\u9519\u8BEF\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C pnpm test\u3002"
|
|
434
|
+
test: "\u5148\u4FEE\u590D\u5BF9\u5E94\u6D4B\u8BD5\u4E0A\u65B9\u663E\u793A\u7684\u7B2C\u4E00\u6761\u539F\u59CB\u9519\u8BEF\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C pnpm test\u3002",
|
|
435
|
+
unhandled: "\u5F02\u6B65\u9519\u8BEF\uFF1A\u5148\u4FEE\u590D\u4E0A\u65B9\u663E\u793A\u7684\u7B2C\u4E00\u6761\u9519\u8BEF\uFF1B\u8F93\u5165\u3001\u5E27\u63A8\u8FDB\u548C\u751F\u547D\u5468\u671F\u64CD\u4F5C\u90FD\u8981\u5728\u6B63\u786E\u7684 host \u751F\u547D\u5468\u671F\u5185\u5E76\u4F7F\u7528 await\u3002"
|
|
429
436
|
};
|
|
430
437
|
const getCategory = (issue) => {
|
|
431
438
|
if (issue.includes("\u672A\u8BB0\u5F55\u771F\u5B9E DOM \u8F93\u5165")) return { category: "input", key: "input" };
|
|
@@ -450,6 +457,14 @@ function formatGameplayIssues(issues) {
|
|
|
450
457
|
return { category: "registry", key: `registry:${scene}` };
|
|
451
458
|
}
|
|
452
459
|
if (issue.includes("\u7F3A\u5C11 gameplay contract")) return { category: "missing", key: "missing" };
|
|
460
|
+
if (issue.includes("\u6D4B\u8BD5\u5931\u8D25\uFF1A")) {
|
|
461
|
+
const message = issue.split("\u6D4B\u8BD5\u5931\u8D25\uFF1A")[1] ?? issue;
|
|
462
|
+
return { category: "test", key: `test:${message}` };
|
|
463
|
+
}
|
|
464
|
+
if (issue.includes("\u6D4B\u8BD5\u8FD0\u884C\u671F\u95F4\u53D1\u751F\u5F02\u6B65\u9519\u8BEF\uFF1A")) {
|
|
465
|
+
const message = issue.split("\u6D4B\u8BD5\u8FD0\u884C\u671F\u95F4\u53D1\u751F\u5F02\u6B65\u9519\u8BEF\uFF1A")[1] ?? issue;
|
|
466
|
+
return { category: "unhandled", key: `test:${message}` };
|
|
467
|
+
}
|
|
453
468
|
if (issue.includes("\u7684\u6D4B\u8BD5\u72B6\u6001\u4E3A")) return { category: "test", key: "test" };
|
|
454
469
|
return { category: "other", key: `other:${issue}` };
|
|
455
470
|
};
|
|
@@ -473,7 +488,7 @@ function formatGameplayIssues(issues) {
|
|
|
473
488
|
continue;
|
|
474
489
|
}
|
|
475
490
|
const readable = compact.replaceAll(/(?:gameplay )?contract "([^"]+)"/g, '\u73A9\u6CD5\u6D4B\u8BD5 "$1"').replaceAll("evidence requirements", "\u8981\u6C42\u9A8C\u8BC1\u7684\u6E38\u620F\u884C\u4E3A").replaceAll("metadata", "\u6D4B\u8BD5\u914D\u7F6E").replaceAll("host registry", "\u6D4B\u8BD5\u8BB0\u5F55\u7684 Scene \u5217\u8868");
|
|
476
|
-
const id = compact.match(/contract "([^"]+)"/)?.[1];
|
|
491
|
+
const id = compact.match(/(?:contract|玩法测试) "([^"]+)"/)?.[1];
|
|
477
492
|
const { category, key } = getCategory(compact);
|
|
478
493
|
const group = groups.get(key);
|
|
479
494
|
if (group) {
|
|
@@ -550,7 +565,7 @@ var GameplayAuditReporter = class {
|
|
|
550
565
|
for (const issue of result.issues) this.reportPreflightIssue(issue);
|
|
551
566
|
}
|
|
552
567
|
/** 在测试运行结束后汇总全部 contract、Ledger 和 Scene registry,并决定命令退出码。 */
|
|
553
|
-
onTestRunEnd(testModules,
|
|
568
|
+
onTestRunEnd(testModules, unhandledErrors = [], reason = "passed") {
|
|
554
569
|
const collectionFailed = reason === "failed" && testModules.some(
|
|
555
570
|
(testModule) => testModule.state() === "failed" && [...testModule.children.allTests()].length === 0
|
|
556
571
|
);
|
|
@@ -565,9 +580,11 @@ var GameplayAuditReporter = class {
|
|
|
565
580
|
(testModule) => [...testModule.children.allTests()].map(toAuditTest)
|
|
566
581
|
);
|
|
567
582
|
const result = auditGameplayRun(this.options, tests);
|
|
583
|
+
const runtimeIssues = unhandledErrors.map((error) => error.message?.replaceAll(/\s+/g, " ").trim()).filter(Boolean).map((message) => `\u6D4B\u8BD5\u8FD0\u884C\u671F\u95F4\u53D1\u751F\u5F02\u6B65\u9519\u8BEF\uFF1A${message}`);
|
|
568
584
|
const combinedIssues = [
|
|
569
585
|
...this.preflightIssues,
|
|
570
|
-
...result.issues
|
|
586
|
+
...result.issues,
|
|
587
|
+
...runtimeIssues
|
|
571
588
|
];
|
|
572
589
|
if (combinedIssues.length > 0) {
|
|
573
590
|
printIssues("FINAL", [...new Set(combinedIssues)]);
|
package/dist/vitest-config.mjs
CHANGED
|
@@ -309,7 +309,11 @@ function auditGameplayRun(options, tests) {
|
|
|
309
309
|
}
|
|
310
310
|
issues.push(...getDefinitionIssues(expected, metadata));
|
|
311
311
|
if (test.state !== "passed") {
|
|
312
|
-
|
|
312
|
+
if (test.error) {
|
|
313
|
+
issues.push(`\u73A9\u6CD5\u6D4B\u8BD5 "${expected.id}" \u6D4B\u8BD5\u5931\u8D25\uFF1A${test.error}`);
|
|
314
|
+
} else {
|
|
315
|
+
issues.push(`\u73A9\u6CD5\u6D4B\u8BD5 "${expected.id}" \u7684\u6D4B\u8BD5\u72B6\u6001\u4E3A ${test.state}\u3002`);
|
|
316
|
+
}
|
|
313
317
|
continue;
|
|
314
318
|
}
|
|
315
319
|
if (!metadata.verified || !metadata.evidence) {
|
|
@@ -366,11 +370,13 @@ function isGameplayContractMetadata(value) {
|
|
|
366
370
|
}
|
|
367
371
|
function toAuditTest(test) {
|
|
368
372
|
const metadata = test.meta().gameplayContract;
|
|
373
|
+
const firstError = test.result().errors?.[0];
|
|
369
374
|
return {
|
|
370
375
|
file: normalizePath(test.module.relativeModuleId),
|
|
371
376
|
name: test.fullName,
|
|
372
377
|
state: test.result().state,
|
|
373
|
-
metadata: isGameplayContractMetadata(metadata) ? metadata : void 0
|
|
378
|
+
metadata: isGameplayContractMetadata(metadata) ? metadata : void 0,
|
|
379
|
+
error: firstError?.message?.replaceAll(/\s+/g, " ").trim().slice(0, 360) || void 0
|
|
374
380
|
};
|
|
375
381
|
}
|
|
376
382
|
function formatGameplayIssues(issues) {
|
|
@@ -401,7 +407,8 @@ function formatGameplayIssues(issues) {
|
|
|
401
407
|
destroy: "\u6E05\u7406\uFF1A\u5728 afterEach \u4E2D\u8C03\u7528 host.destroy()\uFF0C\u5E76\u4FDD\u6301\u9500\u6BC1\u5E42\u7B49\u3002",
|
|
402
408
|
registry: "Scene \u6CE8\u518C\uFF1A\u786E\u8BA4\u6E38\u620F\u6E90\u7801\u6CE8\u518C\u4E86\u8BE5 Scene\uFF1B\u6D4B\u8BD5\u9700\u8981\u5207\u6362\u5230\u5B83\u65F6\uFF0C\u5728\u521B\u5EFA host \u65F6\u901A\u8FC7 additionalScenes \u63D0\u4F9B Scene \u7C7B\u3002",
|
|
403
409
|
missing: "\u6253\u5F00\u4E0A\u8FF0\u6587\u4EF6\uFF0C\u7528 gameplayTest \u6DFB\u52A0\u8FD9\u4E9B\u73A9\u6CD5\u6D4B\u8BD5\uFF1Bid \u5FC5\u987B\u4E0E vitest.config.ts \u4E2D\u7684\u914D\u7F6E\u5B8C\u5168\u4E00\u81F4\uFF0C\u521B\u5EFA host \u540E\u8C03\u7528 contract.attachHost(host)\u3002",
|
|
404
|
-
test: "\u5148\u4FEE\u590D\u5BF9\u5E94\u6D4B\u8BD5\u4E0A\u65B9\u663E\u793A\u7684\u7B2C\u4E00\u6761\u539F\u59CB\u9519\u8BEF\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C pnpm test\u3002"
|
|
410
|
+
test: "\u5148\u4FEE\u590D\u5BF9\u5E94\u6D4B\u8BD5\u4E0A\u65B9\u663E\u793A\u7684\u7B2C\u4E00\u6761\u539F\u59CB\u9519\u8BEF\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C pnpm test\u3002",
|
|
411
|
+
unhandled: "\u5F02\u6B65\u9519\u8BEF\uFF1A\u5148\u4FEE\u590D\u4E0A\u65B9\u663E\u793A\u7684\u7B2C\u4E00\u6761\u9519\u8BEF\uFF1B\u8F93\u5165\u3001\u5E27\u63A8\u8FDB\u548C\u751F\u547D\u5468\u671F\u64CD\u4F5C\u90FD\u8981\u5728\u6B63\u786E\u7684 host \u751F\u547D\u5468\u671F\u5185\u5E76\u4F7F\u7528 await\u3002"
|
|
405
412
|
};
|
|
406
413
|
const getCategory = (issue) => {
|
|
407
414
|
if (issue.includes("\u672A\u8BB0\u5F55\u771F\u5B9E DOM \u8F93\u5165")) return { category: "input", key: "input" };
|
|
@@ -426,6 +433,14 @@ function formatGameplayIssues(issues) {
|
|
|
426
433
|
return { category: "registry", key: `registry:${scene}` };
|
|
427
434
|
}
|
|
428
435
|
if (issue.includes("\u7F3A\u5C11 gameplay contract")) return { category: "missing", key: "missing" };
|
|
436
|
+
if (issue.includes("\u6D4B\u8BD5\u5931\u8D25\uFF1A")) {
|
|
437
|
+
const message = issue.split("\u6D4B\u8BD5\u5931\u8D25\uFF1A")[1] ?? issue;
|
|
438
|
+
return { category: "test", key: `test:${message}` };
|
|
439
|
+
}
|
|
440
|
+
if (issue.includes("\u6D4B\u8BD5\u8FD0\u884C\u671F\u95F4\u53D1\u751F\u5F02\u6B65\u9519\u8BEF\uFF1A")) {
|
|
441
|
+
const message = issue.split("\u6D4B\u8BD5\u8FD0\u884C\u671F\u95F4\u53D1\u751F\u5F02\u6B65\u9519\u8BEF\uFF1A")[1] ?? issue;
|
|
442
|
+
return { category: "unhandled", key: `test:${message}` };
|
|
443
|
+
}
|
|
429
444
|
if (issue.includes("\u7684\u6D4B\u8BD5\u72B6\u6001\u4E3A")) return { category: "test", key: "test" };
|
|
430
445
|
return { category: "other", key: `other:${issue}` };
|
|
431
446
|
};
|
|
@@ -449,7 +464,7 @@ function formatGameplayIssues(issues) {
|
|
|
449
464
|
continue;
|
|
450
465
|
}
|
|
451
466
|
const readable = compact.replaceAll(/(?:gameplay )?contract "([^"]+)"/g, '\u73A9\u6CD5\u6D4B\u8BD5 "$1"').replaceAll("evidence requirements", "\u8981\u6C42\u9A8C\u8BC1\u7684\u6E38\u620F\u884C\u4E3A").replaceAll("metadata", "\u6D4B\u8BD5\u914D\u7F6E").replaceAll("host registry", "\u6D4B\u8BD5\u8BB0\u5F55\u7684 Scene \u5217\u8868");
|
|
452
|
-
const id = compact.match(/contract "([^"]+)"/)?.[1];
|
|
467
|
+
const id = compact.match(/(?:contract|玩法测试) "([^"]+)"/)?.[1];
|
|
453
468
|
const { category, key } = getCategory(compact);
|
|
454
469
|
const group = groups.get(key);
|
|
455
470
|
if (group) {
|
|
@@ -526,7 +541,7 @@ var GameplayAuditReporter = class {
|
|
|
526
541
|
for (const issue of result.issues) this.reportPreflightIssue(issue);
|
|
527
542
|
}
|
|
528
543
|
/** 在测试运行结束后汇总全部 contract、Ledger 和 Scene registry,并决定命令退出码。 */
|
|
529
|
-
onTestRunEnd(testModules,
|
|
544
|
+
onTestRunEnd(testModules, unhandledErrors = [], reason = "passed") {
|
|
530
545
|
const collectionFailed = reason === "failed" && testModules.some(
|
|
531
546
|
(testModule) => testModule.state() === "failed" && [...testModule.children.allTests()].length === 0
|
|
532
547
|
);
|
|
@@ -541,9 +556,11 @@ var GameplayAuditReporter = class {
|
|
|
541
556
|
(testModule) => [...testModule.children.allTests()].map(toAuditTest)
|
|
542
557
|
);
|
|
543
558
|
const result = auditGameplayRun(this.options, tests);
|
|
559
|
+
const runtimeIssues = unhandledErrors.map((error) => error.message?.replaceAll(/\s+/g, " ").trim()).filter(Boolean).map((message) => `\u6D4B\u8BD5\u8FD0\u884C\u671F\u95F4\u53D1\u751F\u5F02\u6B65\u9519\u8BEF\uFF1A${message}`);
|
|
544
560
|
const combinedIssues = [
|
|
545
561
|
...this.preflightIssues,
|
|
546
|
-
...result.issues
|
|
562
|
+
...result.issues,
|
|
563
|
+
...runtimeIssues
|
|
547
564
|
];
|
|
548
565
|
if (combinedIssues.length > 0) {
|
|
549
566
|
printIssues("FINAL", [...new Set(combinedIssues)]);
|