@kkeve/suite 0.0.13 → 0.0.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.
Files changed (117) hide show
  1. package/dist/bin/keve.js +2 -1
  2. package/dist/commands/clean.js +2 -2
  3. package/dist/commands/config.js +7 -7
  4. package/dist/commands/init.js +2 -2
  5. package/dist/commands/report.js +7 -7
  6. package/dist/commands/run.js +16 -12
  7. package/dist/commands/test.js +7 -7
  8. package/dist/config.js +7 -7
  9. package/dist/core/action-log-writer.js +4 -1
  10. package/dist/core/decorator/keve-decorators.d.ts +128 -0
  11. package/dist/core/decorator/keve-decorators.js +254 -0
  12. package/dist/core/decorator/keve-host.d.ts +40 -0
  13. package/dist/core/decorator/keve-host.js +33 -0
  14. package/dist/core/{keve-registry.d.ts → decorator/keve-registry.d.ts} +19 -0
  15. package/dist/core/{keve-registry.js → decorator/keve-registry.js} +13 -1
  16. package/dist/core/generateReport/report.d.ts +1 -1
  17. package/dist/core/generateReport/report.js +2 -2
  18. package/dist/core/generateReport/reportData.d.ts +3 -0
  19. package/dist/core/generateReport/reportData.js +55 -18
  20. package/dist/core/judge/confidence.d.ts +119 -0
  21. package/dist/core/judge/confidence.js +295 -0
  22. package/dist/core/judge/goal-heuristics.d.ts +32 -0
  23. package/dist/core/judge/goal-heuristics.js +128 -0
  24. package/dist/core/judge/pngCodec.d.ts +23 -0
  25. package/dist/core/judge/pngCodec.js +215 -0
  26. package/dist/core/judge/screenshotDiff.d.ts +112 -0
  27. package/dist/core/judge/screenshotDiff.js +420 -0
  28. package/dist/core/page-object/definePage.d.ts +95 -0
  29. package/dist/core/page-object/definePage.js +62 -0
  30. package/dist/core/page-object/elementResolver.d.ts +32 -0
  31. package/dist/core/page-object/elementResolver.js +236 -0
  32. package/dist/core/page-object/engine-types.d.ts +140 -0
  33. package/dist/core/page-object/engine-types.js +34 -0
  34. package/dist/core/sso-cookie.d.ts +18 -0
  35. package/dist/core/sso-cookie.js +10 -0
  36. package/dist/dsl/index.d.ts +15 -0
  37. package/dist/dsl/index.js +29 -0
  38. package/dist/dsl/locatorSource.d.ts +25 -0
  39. package/dist/dsl/locatorSource.js +323 -0
  40. package/dist/dsl/ops.d.ts +46 -0
  41. package/dist/dsl/ops.js +95 -0
  42. package/dist/dsl/toDecorator.d.ts +98 -0
  43. package/dist/dsl/toDecorator.js +747 -0
  44. package/dist/engine-cypress/adapter.d.ts +108 -0
  45. package/dist/engine-cypress/adapter.js +514 -0
  46. package/dist/engine-cypress/agent-page.d.ts +159 -0
  47. package/dist/engine-cypress/agent-page.js +566 -0
  48. package/dist/engine-cypress/agentDom.d.ts +22 -0
  49. package/dist/engine-cypress/agentDom.js +590 -0
  50. package/dist/engine-cypress/bridge.d.ts +39 -0
  51. package/dist/engine-cypress/bridge.js +598 -0
  52. package/dist/engine-cypress/cdp.d.ts +78 -0
  53. package/dist/engine-cypress/cdp.js +339 -0
  54. package/dist/engine-cypress/host.d.ts +22 -0
  55. package/dist/engine-cypress/host.js +480 -0
  56. package/dist/engine-cypress/index.d.ts +26 -0
  57. package/dist/engine-cypress/index.js +58 -0
  58. package/dist/engine-cypress/keveGoal.d.ts +43 -0
  59. package/dist/engine-cypress/keveGoal.js +265 -0
  60. package/dist/engine-cypress/pageOps.d.ts +41 -0
  61. package/dist/engine-cypress/pageOps.js +439 -0
  62. package/dist/engine-cypress/reporter.d.ts +20 -0
  63. package/dist/engine-cypress/reporter.js +128 -0
  64. package/dist/engine-cypress/setup.d.ts +21 -0
  65. package/dist/engine-cypress/setup.js +27 -0
  66. package/dist/engine-cypress/shotBuffer.d.ts +40 -0
  67. package/dist/engine-cypress/shotBuffer.js +41 -0
  68. package/dist/engine-cypress/state.d.ts +56 -0
  69. package/dist/engine-cypress/state.js +81 -0
  70. package/dist/engine-playwright/engineAdapter.d.ts +78 -0
  71. package/dist/engine-playwright/engineAdapter.js +371 -0
  72. package/dist/engine-playwright/global-setup.d.ts +28 -0
  73. package/dist/engine-playwright/global-setup.js +142 -0
  74. package/dist/{core → engine-playwright}/keve-report.d.ts +0 -1
  75. package/dist/engine-playwright/keve-report.js +137 -0
  76. package/dist/{core → engine-playwright}/keve-test.d.ts +10 -8
  77. package/dist/{core → engine-playwright}/keve-test.js +257 -207
  78. package/dist/{core → engine-playwright}/pw-config.js +8 -7
  79. package/dist/index.d.ts +13 -8
  80. package/dist/index.js +43 -28
  81. package/dist/page-agent/agent.d.ts +98 -7
  82. package/dist/page-agent/agent.js +338 -84
  83. package/dist/page-agent/diagnostics.d.ts +184 -0
  84. package/dist/page-agent/diagnostics.js +377 -0
  85. package/dist/page-agent/hooks.d.ts +3 -2
  86. package/dist/page-agent/hooks.js +4 -3
  87. package/dist/page-agent/page-like.d.ts +116 -0
  88. package/dist/page-agent/page-like.js +14 -0
  89. package/dist/page-agent/playwright-page.d.ts +20 -0
  90. package/dist/page-agent/playwright-page.js +98 -0
  91. package/dist/page-agent/system-prompt.d.ts +7 -0
  92. package/dist/page-agent/system-prompt.js +10 -0
  93. package/dist/page-agent/system_prompt.md +1 -1
  94. package/dist/page-agent/tools.d.ts +1 -1
  95. package/dist/page-agent/tools.js +441 -9
  96. package/doc/skills/keve-e2e-gen/references/script-generation-guide.md +11 -0
  97. package/package.json +24 -11
  98. package/scripts/gen-system-prompt.mjs +36 -0
  99. package/scripts/run-dsl-task.mjs +619 -0
  100. package/scripts/runtime/cypress-preprocessor.mjs +44 -0
  101. package/scripts/runtime/cypress.config.mjs +35 -0
  102. package/scripts/runtime/playwright.config.mjs +41 -0
  103. package/scripts/verify-shot-diff.mjs +243 -0
  104. package/dist/commands/auth-update.d.ts +0 -16
  105. package/dist/commands/auth-update.js +0 -88
  106. package/dist/core/auth.d.ts +0 -17
  107. package/dist/core/auth.js +0 -224
  108. package/dist/core/cdp-resolver.d.ts +0 -5
  109. package/dist/core/cdp-resolver.js +0 -93
  110. package/dist/core/global-setup.d.ts +0 -6
  111. package/dist/core/global-setup.js +0 -113
  112. package/dist/core/keve-decorators.d.ts +0 -51
  113. package/dist/core/keve-decorators.js +0 -95
  114. package/dist/core/keve-report.js +0 -376
  115. /package/dist/core/{keve-aspect.d.ts → decorator/keve-aspect.d.ts} +0 -0
  116. /package/dist/core/{keve-aspect.js → decorator/keve-aspect.js} +0 -0
  117. /package/dist/{core → engine-playwright}/pw-config.d.ts +0 -0
@@ -1,93 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.resolveCdpWsUrl = resolveCdpWsUrl;
37
- const fs = __importStar(require("node:fs"));
38
- const os = __importStar(require("node:os"));
39
- const path = __importStar(require("node:path"));
40
- const node_child_process_1 = require("node:child_process");
41
- // TODO: consolidate doc-reading logic into keve-suite/spec
42
- function getChromeUserDataDir() {
43
- const p = os.platform();
44
- const h = os.homedir();
45
- if (p === 'darwin')
46
- return path.join(h, 'Library', 'Application Support', 'Google', 'Chrome');
47
- if (p === 'win32')
48
- return path.join(h, 'AppData', 'Local', 'Google', 'Chrome', 'User Data');
49
- return path.join(h, '.config', 'google-chrome');
50
- }
51
- function getChromeWsUrlFromPort() {
52
- const portFile = path.join(getChromeUserDataDir(), 'DevToolsActivePort');
53
- if (!fs.existsSync(portFile))
54
- return null;
55
- try {
56
- const [portStr, wsPath] = fs.readFileSync(portFile, 'utf8').trim().split('\n').map(l => l.trim()).filter(Boolean);
57
- const port = parseInt(portStr, 10);
58
- if (!port || !wsPath)
59
- return null;
60
- try {
61
- (0, node_child_process_1.execSync)(`lsof -P -i TCP:${port} 2>/dev/null | grep LISTEN`, { encoding: 'utf8' });
62
- }
63
- catch {
64
- return null;
65
- }
66
- return `ws://127.0.0.1:${port}${wsPath}`;
67
- }
68
- catch {
69
- return null;
70
- }
71
- }
72
- async function fetchWsUrlFromHttpEndpoint(endpoint) {
73
- try {
74
- const url = endpoint.replace(/\/$/, '') + '/json/version';
75
- const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
76
- const data = await res.json();
77
- return data.webSocketDebuggerUrl || null;
78
- }
79
- catch (e) {
80
- console.warn(`[cdp-resolver] Failed to fetch from ${endpoint}: ${e.message}`);
81
- return null;
82
- }
83
- }
84
- async function resolveCdpWsUrl(options) {
85
- if (options.wsEndpoint)
86
- return options.wsEndpoint;
87
- if (options.endpoint) {
88
- const wsUrl = await fetchWsUrlFromHttpEndpoint(options.endpoint);
89
- if (wsUrl)
90
- return wsUrl;
91
- }
92
- return getChromeWsUrlFromPort();
93
- }
@@ -1,6 +0,0 @@
1
- declare global {
2
- var __keve_cdp_browser: import('@playwright/test').Browser | undefined;
3
- }
4
- export declare function getCdpBrowser(): Promise<import('@playwright/test').Browser>;
5
- export declare function isCdpMode(): boolean;
6
- export default function (): Promise<void>;
@@ -1,113 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.getCdpBrowser = getCdpBrowser;
37
- exports.isCdpMode = isCdpMode;
38
- exports.default = default_1;
39
- const fs = __importStar(require("node:fs"));
40
- const path = __importStar(require("node:path"));
41
- const auth_1 = require("./auth");
42
- async function getCdpBrowser() {
43
- // 如果已有共享的 browser 对象,直接复用
44
- if (globalThis.__keve_cdp_browser && globalThis.__keve_cdp_browser.isConnected()) {
45
- return globalThis.__keve_cdp_browser;
46
- }
47
- const { chromium } = await Promise.resolve().then(() => __importStar(require('@playwright/test')));
48
- let wsUrl = process.env.KEVE_CDP_WS_ENDPOINT;
49
- // 如果只提供了 HTTP endpoint,自动获取 WebSocket URL
50
- if (!wsUrl && process.env.KEVE_CDP_ENDPOINT) {
51
- const httpUrl = process.env.KEVE_CDP_ENDPOINT.replace(/\/$/, '');
52
- try {
53
- const resp = await fetch(`${httpUrl}/json/version`);
54
- const data = await resp.json();
55
- wsUrl = data.webSocketDebuggerUrl;
56
- console.log(`[keve CDP] Resolved WS endpoint: ${wsUrl}`);
57
- }
58
- catch (e) {
59
- throw new Error(`Failed to resolve CDP WebSocket URL from ${httpUrl}: ${e.message}`);
60
- }
61
- }
62
- if (!wsUrl)
63
- throw new Error('No CDP endpoint configured');
64
- const browser = await chromium.connectOverCDP(wsUrl, { timeout: 15000 });
65
- console.log(`[keve CDP] Connected via ${wsUrl}`);
66
- globalThis.__keve_cdp_browser = browser;
67
- return browser;
68
- }
69
- function isCdpMode() {
70
- return !!process.env.KEVE_CDP_WS_ENDPOINT || !!process.env.KEVE_CDP_ENDPOINT;
71
- }
72
- async function default_1() {
73
- const projectRoot = path.resolve(process.cwd());
74
- const storageStatePath = path.resolve(projectRoot, '.auth/storage-state.json');
75
- const cdpEndpoint = process.env.KEVE_CDP_ENDPOINT || process.env.KEVE_CDP_WS_ENDPOINT;
76
- if (cdpEndpoint) {
77
- console.log(`[keve global-setup] CDP endpoint detected: ${cdpEndpoint}`);
78
- // CDP 模式:在 global-setup 中提前连接一次,缓存 Browser 对象
79
- try {
80
- const browser = await getCdpBrowser();
81
- const contexts = browser.contexts();
82
- const pages = contexts.length > 0 ? contexts[0].pages() : [];
83
- console.log(`[keve global-setup] CDP connected. contexts=${contexts.length}, pages=${pages.length}`);
84
- if (pages.length > 0) {
85
- console.log(`[keve global-setup] Existing tabs: ${pages.map(p => p.url()).join(', ')}`);
86
- }
87
- }
88
- catch (e) {
89
- console.warn(`[keve global-setup] CDP connection failed: ${e.message}`);
90
- }
91
- if (!fs.existsSync(storageStatePath)) {
92
- const authDir = path.dirname(storageStatePath);
93
- if (!fs.existsSync(authDir))
94
- fs.mkdirSync(authDir, { recursive: true });
95
- fs.writeFileSync(storageStatePath, JSON.stringify({ cookies: [], origins: [] }));
96
- }
97
- return;
98
- }
99
- console.log(`[keve global-setup] Acquiring fresh auth state...`);
100
- const success = await (0, auth_1.acquireStorageState)({
101
- logPrefix: '[keve global-setup]',
102
- });
103
- if (!success) {
104
- console.warn(`[keve global-setup] Auth acquisition failed. Tests may fail due to auth issues.`);
105
- if (!fs.existsSync(storageStatePath)) {
106
- const authDir = path.dirname(storageStatePath);
107
- if (!fs.existsSync(authDir))
108
- fs.mkdirSync(authDir, { recursive: true });
109
- fs.writeFileSync(storageStatePath, JSON.stringify({ cookies: [], origins: [] }));
110
- console.log(`[keve global-setup] Created empty storage state → ${storageStatePath}`);
111
- }
112
- }
113
- }
@@ -1,51 +0,0 @@
1
- /**
2
- * keve-decorators — @keveModel + @keveScene 装饰器
3
- *
4
- * 使用 TC39 Stage 3 装饰器 API (Playwright 1.58+ 默认支持)
5
- *
6
- * 执行顺序(TC39 Stage 3 规范):
7
- * 1. Method decorator 函数调用 → 注册 addInitializer
8
- * 2. Class decorator 函数调用 → 注册 addInitializer
9
- * 3. Method addInitializers 执行 → @keveScene 注册场景到 WeakMap
10
- * 4. Class addInitializer 执行 → @keveModel 读取 WeakMap 并调用 test.describe
11
- *
12
- * 两层装饰器 + 函数调用:
13
- * Model (模块) → test.describe → @keveModel
14
- * Scene (场景) → test → @keveScene (fn.toString() 捕获完整脚本)
15
- * Goal (步骤) → 步骤元数据 → keveGoal() 函数调用(在方法体内)
16
- */
17
- import { type KeveGoalMeta } from './keve-registry';
18
- /** Called by keve-test.ts to register the extended test instance */
19
- export declare function setKeveTest(t: any): void;
20
- /** Get the current keve test instance (extended with fixtures) */
21
- export declare function getKeveTest(): any;
22
- export type { KeveGoalMeta, KeveEvalMeta, ErrorCategory } from './keve-registry';
23
- export interface KeveSceneMeta {
24
- id: string;
25
- description: string;
26
- title: string;
27
- code: string;
28
- goals: KeveGoalMeta[];
29
- fn: Function;
30
- }
31
- /**
32
- * @keveModel(name) — Class decorator (模块层)
33
- * Uses context.addInitializer to defer test.describe() registration
34
- * until AFTER all @keveScene addInitializers have run.
35
- */
36
- export declare function keveModel(id: string, description: string): <T extends {
37
- new (...args: any[]): {};
38
- }>(ctor: T, context: ClassDecoratorContext) => T;
39
- /**
40
- * @keveScene(title) — Method decorator (场景层, static methods only)
41
- * Captures fn.toString() as the complete scene script.
42
- * Wraps fn with try-catch-finally to classify errors and decide skipAI.
43
- * Registers scene metadata to both WeakMap and global Map.
44
- *
45
- * The wrapper preserves the original function's destructuring signature by
46
- * extracting the parameter text from fn.toString() and constructing a wrapper
47
- * via new Function(), so Playwright can correctly resolve fixture dependencies.
48
- */
49
- export declare function keveScene(id: string, description: string): (fn: Function, context: ClassMethodDecoratorContext) => Function;
50
- /** 获取 Model 下注册的所有 Scene */
51
- export declare function getModelScenes(ctor: Function): KeveSceneMeta[] | null;
@@ -1,95 +0,0 @@
1
- "use strict";
2
- /**
3
- * keve-decorators — @keveModel + @keveScene 装饰器
4
- *
5
- * 使用 TC39 Stage 3 装饰器 API (Playwright 1.58+ 默认支持)
6
- *
7
- * 执行顺序(TC39 Stage 3 规范):
8
- * 1. Method decorator 函数调用 → 注册 addInitializer
9
- * 2. Class decorator 函数调用 → 注册 addInitializer
10
- * 3. Method addInitializers 执行 → @keveScene 注册场景到 WeakMap
11
- * 4. Class addInitializer 执行 → @keveModel 读取 WeakMap 并调用 test.describe
12
- *
13
- * 两层装饰器 + 函数调用:
14
- * Model (模块) → test.describe → @keveModel
15
- * Scene (场景) → test → @keveScene (fn.toString() 捕获完整脚本)
16
- * Goal (步骤) → 步骤元数据 → keveGoal() 函数调用(在方法体内)
17
- */
18
- Object.defineProperty(exports, "__esModule", { value: true });
19
- exports.setKeveTest = setKeveTest;
20
- exports.getKeveTest = getKeveTest;
21
- exports.keveModel = keveModel;
22
- exports.keveScene = keveScene;
23
- exports.getModelScenes = getModelScenes;
24
- const test_1 = require("@playwright/test");
25
- const keve_registry_1 = require("./keve-registry");
26
- // ─── Configurable test reference ────────────────────────────────────
27
- // keveModel needs to call test.describe / test — but it must use the EXTENDED test
28
- // (with keveGoal/keveAssert fixtures), not the base @playwright/test.
29
- // keve-test.ts calls setKeveTest() after creating the extended test.
30
- let _keveTest = test_1.test;
31
- /** Called by keve-test.ts to register the extended test instance */
32
- function setKeveTest(t) { _keveTest = t; }
33
- /** Get the current keve test instance (extended with fixtures) */
34
- function getKeveTest() { return _keveTest; }
35
- // ─── Internal Registry (WeakMap per Model constructor) ─────────────
36
- /** Model → Scene 列表:每个 @keveModel 类下注册的 @keveScene 列表 */
37
- const modelScenesMap = new WeakMap();
38
- // ─── Error Classification ──────────────────────────────────────────
39
- // Error classification moved to keve-report.ts onTestEnd —
40
- // onTestEnd has access to result.error and result.status, which is more reliable
41
- // than try-catch in the decorator (async rejections, test-level timeouts can bypass decorator catch).
42
- // ─── TC39 Stage 3 Decorators ──────────────────────────────────────
43
- /**
44
- * @keveModel(name) — Class decorator (模块层)
45
- * Uses context.addInitializer to defer test.describe() registration
46
- * until AFTER all @keveScene addInitializers have run.
47
- */
48
- function keveModel(id, description) {
49
- return (ctor, context) => {
50
- context.addInitializer(function () {
51
- const ctor = this;
52
- const scenes = modelScenesMap.get(ctor) || [];
53
- _keveTest.describe(`${id}: ${description}`, () => {
54
- for (const scene of scenes) {
55
- _keveTest(scene.title, scene.fn);
56
- }
57
- });
58
- });
59
- return ctor;
60
- };
61
- }
62
- /**
63
- * @keveScene(title) — Method decorator (场景层, static methods only)
64
- * Captures fn.toString() as the complete scene script.
65
- * Wraps fn with try-catch-finally to classify errors and decide skipAI.
66
- * Registers scene metadata to both WeakMap and global Map.
67
- *
68
- * The wrapper preserves the original function's destructuring signature by
69
- * extracting the parameter text from fn.toString() and constructing a wrapper
70
- * via new Function(), so Playwright can correctly resolve fixture dependencies.
71
- */
72
- function keveScene(id, description) {
73
- return (fn, context) => {
74
- const code = fn.toString(); // Capture original code BEFORE wrapping
75
- const title = `${id}: ${description}`;
76
- // Register the original function directly — Playwright resolves fixture dependencies
77
- // by parsing fn.toString() / AST. Wrapping with new Function() breaks this resolution.
78
- // Error classification is handled in onTestEnd (keve-report.ts), not here.
79
- context.addInitializer(function () {
80
- const ctor = this;
81
- if (!modelScenesMap.has(ctor))
82
- modelScenesMap.set(ctor, []);
83
- const scene = { id, description, title, code, goals: [], fn };
84
- modelScenesMap.get(ctor).push(scene);
85
- // Register to global maps for Reporter access
86
- keve_registry_1.sceneCodeMap.set(title, code); // Stores ORIGINAL code, not wrapped
87
- });
88
- return fn; // Return original function unchanged — preserves fixture parameter signature
89
- };
90
- }
91
- // ─── Utility ───────────────────────────────────────────────────────
92
- /** 获取 Model 下注册的所有 Scene */
93
- function getModelScenes(ctor) {
94
- return modelScenesMap.get(ctor) || null;
95
- }