@epoint-testtech/ep-stage-skill 0.0.3-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.
Files changed (151) hide show
  1. package/SKILL.md +27 -0
  2. package/codex-skill/ep-stage/create-project/SKILL.md +59 -0
  3. package/codex-skill/ep-stage/glue-test/SKILL.md +258 -0
  4. package/codex-skill/ep-stage/glue-test/references/crud-pipeline.md +139 -0
  5. package/codex-skill/ep-stage/glue-test/references/gap-review-protocol.md +43 -0
  6. package/codex-skill/ep-stage/glue-test/references/harness-principles.md +46 -0
  7. package/codex-skill/ep-stage/glue-test/scripts/generate-crud-spec.mjs +149 -0
  8. package/codex-skill/ep-stage/glue-testcase/SKILL.md +31 -0
  9. package/codex-skill/ep-stage/glue-testcase/examples/observable-testcase.json +40 -0
  10. package/codex-skill/ep-stage/glue-testcase/references/testcase-schema.md +67 -0
  11. package/codex-skill/ep-stage/recording-to-glue/SKILL.md +27 -0
  12. package/codex-skill/ep-stage/scripts/validate-skill.mjs +73 -0
  13. package/dist/src/capability/coverage-diff.d.ts +34 -0
  14. package/dist/src/capability/coverage-diff.d.ts.map +1 -0
  15. package/dist/src/capability/coverage-diff.js +91 -0
  16. package/dist/src/capability/page-structure.d.ts +31 -0
  17. package/dist/src/capability/page-structure.d.ts.map +1 -0
  18. package/dist/src/capability/page-structure.js +50 -0
  19. package/dist/src/capability/scenario-inference.d.ts +36 -0
  20. package/dist/src/capability/scenario-inference.d.ts.map +1 -0
  21. package/dist/src/capability/scenario-inference.js +114 -0
  22. package/dist/src/cli/generate-crud-contract.d.ts +2 -0
  23. package/dist/src/cli/generate-crud-contract.d.ts.map +1 -0
  24. package/dist/src/cli/generate-crud-contract.js +77 -0
  25. package/dist/src/cli/generate-playwright-tests.d.ts +30 -0
  26. package/dist/src/cli/generate-playwright-tests.d.ts.map +1 -0
  27. package/dist/src/cli/generate-playwright-tests.js +81 -0
  28. package/dist/src/cli/run-gap-pipeline.d.ts +256 -0
  29. package/dist/src/cli/run-gap-pipeline.d.ts.map +1 -0
  30. package/dist/src/cli/run-gap-pipeline.js +1468 -0
  31. package/dist/src/context/stage-context.d.ts +63 -0
  32. package/dist/src/context/stage-context.d.ts.map +1 -0
  33. package/dist/src/context/stage-context.js +297 -0
  34. package/dist/src/contracts/crud-business-module.d.ts +645 -0
  35. package/dist/src/contracts/crud-business-module.d.ts.map +1 -0
  36. package/dist/src/contracts/crud-business-module.js +1 -0
  37. package/dist/src/contracts/gap-inference.d.ts +213 -0
  38. package/dist/src/contracts/gap-inference.d.ts.map +1 -0
  39. package/dist/src/contracts/gap-inference.js +11 -0
  40. package/dist/src/contracts/observable-chain.d.ts +250 -0
  41. package/dist/src/contracts/observable-chain.d.ts.map +1 -0
  42. package/dist/src/contracts/observable-chain.js +1 -0
  43. package/dist/src/extractors/code-list.d.ts +40 -0
  44. package/dist/src/extractors/code-list.d.ts.map +1 -0
  45. package/dist/src/extractors/code-list.js +225 -0
  46. package/dist/src/extractors/html-page.d.ts +67 -0
  47. package/dist/src/extractors/html-page.d.ts.map +1 -0
  48. package/dist/src/extractors/html-page.js +195 -0
  49. package/dist/src/extractors/java-action.d.ts +8 -0
  50. package/dist/src/extractors/java-action.d.ts.map +1 -0
  51. package/dist/src/extractors/java-action.js +53 -0
  52. package/dist/src/extractors/spec-yaml.d.ts +28 -0
  53. package/dist/src/extractors/spec-yaml.d.ts.map +1 -0
  54. package/dist/src/extractors/spec-yaml.js +29 -0
  55. package/dist/src/gap-planner/action-candidates.d.ts +9 -0
  56. package/dist/src/gap-planner/action-candidates.d.ts.map +1 -0
  57. package/dist/src/gap-planner/action-candidates.js +66 -0
  58. package/dist/src/gap-planner/list-gap-workflows.d.ts +17 -0
  59. package/dist/src/gap-planner/list-gap-workflows.d.ts.map +1 -0
  60. package/dist/src/gap-planner/list-gap-workflows.js +47 -0
  61. package/dist/src/gap-planner/plan-agent-workflows.d.ts +26 -0
  62. package/dist/src/gap-planner/plan-agent-workflows.d.ts.map +1 -0
  63. package/dist/src/gap-planner/plan-agent-workflows.js +116 -0
  64. package/dist/src/gap-planner/skeleton-coverage.d.ts +9 -0
  65. package/dist/src/gap-planner/skeleton-coverage.d.ts.map +1 -0
  66. package/dist/src/gap-planner/skeleton-coverage.js +41 -0
  67. package/dist/src/gap-planner/stable-id.d.ts +16 -0
  68. package/dist/src/gap-planner/stable-id.d.ts.map +1 -0
  69. package/dist/src/gap-planner/stable-id.js +19 -0
  70. package/dist/src/generalization/generalization-eval.d.ts +71 -0
  71. package/dist/src/generalization/generalization-eval.d.ts.map +1 -0
  72. package/dist/src/generalization/generalization-eval.js +53 -0
  73. package/dist/src/generators/agent-inferred-workflow-script.d.ts +22 -0
  74. package/dist/src/generators/agent-inferred-workflow-script.d.ts.map +1 -0
  75. package/dist/src/generators/agent-inferred-workflow-script.js +230 -0
  76. package/dist/src/generators/stage-skeleton-script.d.ts +107 -0
  77. package/dist/src/generators/stage-skeleton-script.d.ts.map +1 -0
  78. package/dist/src/generators/stage-skeleton-script.js +607 -0
  79. package/dist/src/index.d.ts +52 -0
  80. package/dist/src/index.d.ts.map +1 -0
  81. package/dist/src/index.js +26 -0
  82. package/dist/src/material/material-inventory.d.ts +92 -0
  83. package/dist/src/material/material-inventory.d.ts.map +1 -0
  84. package/dist/src/material/material-inventory.js +191 -0
  85. package/dist/src/normalizers/crud-contract.d.ts +107 -0
  86. package/dist/src/normalizers/crud-contract.d.ts.map +1 -0
  87. package/dist/src/normalizers/crud-contract.js +1068 -0
  88. package/dist/src/testcase/testcase-generator.d.ts +43 -0
  89. package/dist/src/testcase/testcase-generator.d.ts.map +1 -0
  90. package/dist/src/testcase/testcase-generator.js +152 -0
  91. package/dist/src/testcase/testcase-skeleton.d.ts +91 -0
  92. package/dist/src/testcase/testcase-skeleton.d.ts.map +1 -0
  93. package/dist/src/testcase/testcase-skeleton.js +121 -0
  94. package/dist/src/testcase/testcase-spec-assembly.d.ts +11 -0
  95. package/dist/src/testcase/testcase-spec-assembly.d.ts.map +1 -0
  96. package/dist/src/testcase/testcase-spec-assembly.js +24 -0
  97. package/dist/src/trace/review-summary.d.ts +17 -0
  98. package/dist/src/trace/review-summary.d.ts.map +1 -0
  99. package/dist/src/trace/review-summary.js +34 -0
  100. package/dist/src/trace/trace-writer.d.ts +17 -0
  101. package/dist/src/trace/trace-writer.d.ts.map +1 -0
  102. package/dist/src/trace/trace-writer.js +81 -0
  103. package/dist/test/crud-contract.test.d.ts +2 -0
  104. package/dist/test/crud-contract.test.d.ts.map +1 -0
  105. package/dist/test/crud-contract.test.js +819 -0
  106. package/dist/test/gap-inference.test.d.ts +2 -0
  107. package/dist/test/gap-inference.test.d.ts.map +1 -0
  108. package/dist/test/gap-inference.test.js +597 -0
  109. package/dist/test/generalization.test.d.ts +2 -0
  110. package/dist/test/generalization.test.d.ts.map +1 -0
  111. package/dist/test/generalization.test.js +73 -0
  112. package/dist/test/material-inventory.test.d.ts +2 -0
  113. package/dist/test/material-inventory.test.d.ts.map +1 -0
  114. package/dist/test/material-inventory.test.js +141 -0
  115. package/dist/test/observable-chain.test.d.ts +2 -0
  116. package/dist/test/observable-chain.test.d.ts.map +1 -0
  117. package/dist/test/observable-chain.test.js +123 -0
  118. package/dist/test/observable-pipeline.test.d.ts +2 -0
  119. package/dist/test/observable-pipeline.test.d.ts.map +1 -0
  120. package/dist/test/observable-pipeline.test.js +461 -0
  121. package/dist/test/page-structure.test.d.ts +2 -0
  122. package/dist/test/page-structure.test.d.ts.map +1 -0
  123. package/dist/test/page-structure.test.js +45 -0
  124. package/dist/test/scenario-inference.test.d.ts +2 -0
  125. package/dist/test/scenario-inference.test.d.ts.map +1 -0
  126. package/dist/test/scenario-inference.test.js +73 -0
  127. package/dist/test/stage-context.test.d.ts +2 -0
  128. package/dist/test/stage-context.test.d.ts.map +1 -0
  129. package/dist/test/stage-context.test.js +263 -0
  130. package/dist/test/testcase-generator.test.d.ts +2 -0
  131. package/dist/test/testcase-generator.test.d.ts.map +1 -0
  132. package/dist/test/testcase-generator.test.js +276 -0
  133. package/dist/test/testcase-skeleton.test.d.ts +2 -0
  134. package/dist/test/testcase-skeleton.test.d.ts.map +1 -0
  135. package/dist/test/testcase-skeleton.test.js +185 -0
  136. package/dist/test/testcase-spec-assembly.test.d.ts +2 -0
  137. package/dist/test/testcase-spec-assembly.test.d.ts.map +1 -0
  138. package/dist/test/testcase-spec-assembly.test.js +105 -0
  139. package/dist/vitest.config.d.ts +3 -0
  140. package/dist/vitest.config.d.ts.map +1 -0
  141. package/dist/vitest.config.js +7 -0
  142. package/docs/README.md +134 -0
  143. package/docs/mvp-usage-guide.md +298 -0
  144. package/examples/schemeresource-observable-docs/schemeresource.context.md +20 -0
  145. package/examples/schemeresource.module-hints.json +38 -0
  146. package/examples/schemeresource.observable.code_list.md +37 -0
  147. package/examples/zwplace-observable-docs/zwplace.context.md +16 -0
  148. package/examples/zwplace-placecategory-validation.json +29 -0
  149. package/examples/zwplace.module-hints.json +69 -0
  150. package/examples/zwplace.observable.code_list.md +37 -0
  151. package/package.json +38 -0
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Agent 推理 Custom workflow 测试片段生成器。
3
+ *
4
+ * 渲染 executionSource='agent_inferred' 的 Playwright test 片段,
5
+ * 并提供幂等追加函数,避免重复追加到同一 spec。
6
+ */
7
+ function singleQuoted(value) {
8
+ return `'${value.replaceAll('\\', '\\\\').replaceAll("'", "\\'")}'`;
9
+ }
10
+ function locatorLiteral(value) {
11
+ return JSON.stringify(value);
12
+ }
13
+ function arrayLiteral(values) {
14
+ return `[${values.map(singleQuoted).join(', ')}]`;
15
+ }
16
+ function evidenceSourceByKind(kind) {
17
+ if (kind.startsWith('html_') || kind === 'grid_row_action') {
18
+ return 'upstream_html';
19
+ }
20
+ if (kind.startsWith('java_')) {
21
+ return 'upstream_java_action';
22
+ }
23
+ if (kind === 'test_policy_hint') {
24
+ return 'module_hints';
25
+ }
26
+ return 'agent_reasoning';
27
+ }
28
+ /**
29
+ * 将 EvidenceRef.kind 映射为 GlueEvidenceSource 值。
30
+ * 确保所有映射结果都在 GlueEvidenceSource 值域内。
31
+ */
32
+ function evidenceSources(workflow) {
33
+ const mapped = workflow.evidence.map((item) => evidenceSourceByKind(item.kind));
34
+ if (workflow.resolvedRuntime?.locator || workflow.resolvedRuntime?.pageSnapshotPath) {
35
+ mapped.push('runtime_page');
36
+ }
37
+ return Array.from(new Set([...mapped, 'agent_reasoning']));
38
+ }
39
+ function renderEvidenceRefs(workflow) {
40
+ const rendered = workflow.evidence.map((item) => {
41
+ const properties = [
42
+ `source: ${singleQuoted(evidenceSourceByKind(item.kind))}`,
43
+ `file: ${singleQuoted(item.path)}`,
44
+ item.locator ? `selector: ${singleQuoted(item.locator)}` : undefined,
45
+ item.evidenceText ? `text: ${singleQuoted(item.evidenceText)}` : undefined,
46
+ `note: ${singleQuoted(`上游证据 ${item.kind}${item.evidenceText ? `:${item.evidenceText}` : ''}`)}`,
47
+ ].filter((value) => Boolean(value));
48
+ return ` { ${properties.join(', ')} }`;
49
+ });
50
+ if (workflow.resolvedRuntime?.locator || workflow.resolvedRuntime?.pageSnapshotPath) {
51
+ rendered.push(` { source: 'runtime_page', note: 'gap-executor 在真实页面确认按钮可见并完成定位收敛' }`);
52
+ if (workflow.resolvedRuntime.iframeSrcKeyword) {
53
+ rendered.push(` { source: 'runtime_page', selector: ${singleQuoted(`iframe[src*="${workflow.resolvedRuntime.iframeSrcKeyword}"]`)}, note: 'gap-executor 确认该动作位于业务 iframe 内' }`);
54
+ }
55
+ if (workflow.resolvedRuntime.exploration?.networkResponses?.length) {
56
+ const networkSummary = workflow.resolvedRuntime.exploration.networkResponses.slice(0, 3).join(' | ');
57
+ rendered.push(` { source: 'runtime_page', note: ${singleQuoted(`运行态观察到网络响应:${networkSummary}`)} }`);
58
+ }
59
+ }
60
+ rendered.push(` { source: 'agent_reasoning', note: 'gap-executor 在真实页面确认按钮可见并可点击' }`);
61
+ return `[\n${rendered.join(',\n')}\n ]`;
62
+ }
63
+ function variableName(label) {
64
+ return `repoBtn${label.replace(/[^\p{L}\p{N}]/gu, '')}`;
65
+ }
66
+ function frameVariableName(label) {
67
+ return `repoIFrame${label.replace(/[^\p{L}\p{N}]/gu, '')}`;
68
+ }
69
+ function confirmButtonVariableName(label) {
70
+ return `repoBtn${label.replace(/[^\p{L}\p{N}]/gu, '')}确认`;
71
+ }
72
+ function feedbackVariableName(label) {
73
+ return `repoMsgBox${label.replace(/[^\p{L}\p{N}]/gu, '')}反馈`;
74
+ }
75
+ function actualFeedbackVariableName(label) {
76
+ return `实际${label.replace(/[^\p{L}\p{N}]/gu, '')}反馈文案`;
77
+ }
78
+ function resolvedLocator(workflow) {
79
+ const locator = workflow.resolvedRuntime?.locator ?? workflow.actionCandidates[0]?.locator;
80
+ if (!locator) {
81
+ throw new Error(`workflow ${workflow.workflowId} 缺少 resolved locator,不能生成 Custom test`);
82
+ }
83
+ return locator;
84
+ }
85
+ function assertRenderableWorkflow(workflow) {
86
+ if (workflow.status !== 'planned' && workflow.status !== 'resolved') {
87
+ throw new Error(`workflow ${workflow.workflowId} 状态为 ${workflow.status},不能生成 Custom test`);
88
+ }
89
+ if (workflow.businessIntent.status !== 'resolved') {
90
+ throw new Error(`workflow ${workflow.workflowId} 缺少 resolved businessIntent`);
91
+ }
92
+ if (workflow.elementActions.status !== 'resolved') {
93
+ throw new Error(`workflow ${workflow.workflowId} 缺少 resolved elementActions`);
94
+ }
95
+ if (workflow.assertionExpectation.status !== 'resolved') {
96
+ throw new Error(`workflow ${workflow.workflowId} 缺少 resolved assertionExpectation`);
97
+ }
98
+ }
99
+ function renderGapFindingBlock(workflow, label, assertion) {
100
+ const observed = workflow.resolvedRuntime?.exploration?.observedMessage?.replace(/\s+/g, ' ').trim();
101
+ if (!observed || observed.includes(assertion)) {
102
+ return '';
103
+ }
104
+ const kind = /暂未实现|未实现|未配置|联系管理员/.test(observed)
105
+ ? 'feature_incomplete'
106
+ : 'behavior_mismatch';
107
+ return `
108
+ gapFinding: {
109
+ kind: ${singleQuoted(kind)},
110
+ summary: ${singleQuoted(`运行态推理发现「${label}」未满足业务预期。`)},
111
+ observed: ${singleQuoted(observed)},
112
+ },`;
113
+ }
114
+ function renderRuntimeAwareAssertionBlock(input) {
115
+ const exploration = input.workflow.resolvedRuntime?.exploration;
116
+ if (!exploration) {
117
+ return `
118
+ await expect(${input.repoVariable}).toBeVisible();
119
+ await ${input.repoVariable}.click();
120
+
121
+ await expect(page.getByText(${singleQuoted(input.assertion)})).toBeVisible({ timeout: 30000 });`;
122
+ }
123
+ const confirmVariable = confirmButtonVariableName(input.label);
124
+ const feedbackVariable = feedbackVariableName(input.label);
125
+ const actualVariable = actualFeedbackVariableName(input.label);
126
+ const runtimeObserved = exploration.observedMessage?.replace(/\s+/g, ' ').trim() ?? '';
127
+ const confirmBlock = exploration.confirmDialogPresent
128
+ ? `
129
+
130
+ const ${confirmVariable} = ${input.locatorOwner}
131
+ .locator("xpath=//*[contains(@class,'mini-messagebox')]//a[normalize-space()='确定' or normalize-space()='确认']")
132
+ .first();
133
+ await expect(${confirmVariable}).toBeVisible({ timeout: 15000 });
134
+ await ${confirmVariable}.click();`
135
+ : '';
136
+ return `
137
+ await expect(${input.repoVariable}).toBeVisible();
138
+ await ${input.repoVariable}.click();${confirmBlock}
139
+
140
+ const runtimeObserved反馈文案 = ${singleQuoted(runtimeObserved)};
141
+ const ${feedbackVariable} = ${input.locatorOwner}.locator("xpath=//*[contains(@class,'mini-messagebox') or contains(@class,'mini-tips')]");
142
+ await page.waitForTimeout(1000);
143
+ const 反馈文本列表 = (await ${feedbackVariable}.allInnerTexts())
144
+ .map((text) => text.replace(/\\s+/g, ' ').trim())
145
+ .filter(Boolean);
146
+ const ${actualVariable} =
147
+ 反馈文本列表.find((text) => runtimeObserved反馈文案 && text.includes(runtimeObserved反馈文案)) ??
148
+ 反馈文本列表.find((text) => text.includes(${singleQuoted(input.assertion)})) ??
149
+ runtimeObserved反馈文案 ??
150
+ 反馈文本列表.sort((a, b) => b.length - a.length)[0] ??
151
+ '';
152
+ expect(
153
+ ${actualVariable}.includes(${singleQuoted(input.assertion)}),
154
+ ${singleQuoted(`${input.label}未达成业务预期:期望出现「${input.assertion}」,系统实际反馈「`)} + ${actualVariable} + '」',
155
+ ).toBe(true);`;
156
+ }
157
+ export function renderAgentWorkflowTest(options) {
158
+ const { workflow } = options;
159
+ assertRenderableWorkflow(workflow);
160
+ const title = workflow.resolvedRuntime?.playwrightTestTitle ?? `Custom:${workflow.actionCandidates[0]?.label ?? workflow.workflowId}`;
161
+ const label = workflow.actionCandidates[0]?.label ?? workflow.workflowId;
162
+ const locator = resolvedLocator(workflow);
163
+ const repoVariable = variableName(label);
164
+ const frameVariable = frameVariableName(label);
165
+ const intent = workflow.businessIntent.value;
166
+ const actions = workflow.elementActions.value;
167
+ const assertion = workflow.assertionExpectation.value;
168
+ const iframeSrcKeyword = workflow.resolvedRuntime?.iframeSrcKeyword;
169
+ const locatorOwner = iframeSrcKeyword ? frameVariable : 'page';
170
+ const gapFindingBlock = renderGapFindingBlock(workflow, label, assertion);
171
+ const assertionBlock = renderRuntimeAwareAssertionBlock({
172
+ label,
173
+ locatorOwner,
174
+ repoVariable,
175
+ assertion,
176
+ workflow,
177
+ });
178
+ const iframeSetup = iframeSrcKeyword
179
+ ? `
180
+ const ${frameVariable} = page.locator(${singleQuoted(`iframe[src*="${iframeSrcKeyword}"]`)}).contentFrame();
181
+ `
182
+ : '';
183
+ return `
184
+ test(${singleQuoted(title)}, async ({ page }) => {
185
+ test.slow();
186
+
187
+ await runRecordedWorkflow(
188
+ recorder,
189
+ {
190
+ moduleId: ${singleQuoted(options.moduleId)},
191
+ workflowId: ${singleQuoted(workflow.workflowId)},
192
+ workflowKind: 'custom',
193
+ workflowName: ${singleQuoted(label)},
194
+ executionSource: 'agent_inferred',
195
+ businessIntent: ${singleQuoted(intent)},
196
+ elementActions: ${arrayLiteral(actions)},
197
+ assertionExpectation: ${singleQuoted(assertion)},
198
+ evidenceSources: ${arrayLiteral(evidenceSources(workflow))},
199
+ evidenceRefs: ${renderEvidenceRefs(workflow)},
200
+ reviewReason: ${singleQuoted(workflow.reviewReason ?? '该工作流由 gap-planner 识别为自定义业务动作。')},
201
+ playwrightSuiteTitle: ${singleQuoted(options.suiteTitle)},
202
+ playwrightTestTitle: ${singleQuoted(title)},
203
+ ${gapFindingBlock}
204
+ },
205
+ async () => {
206
+ await openModule(page);
207
+ ${iframeSetup}
208
+ const ${repoVariable} = ${locatorOwner}.locator(${locatorLiteral(locator)});
209
+ ${assertionBlock}
210
+ },
211
+ );
212
+ });
213
+ `;
214
+ }
215
+ export function appendAgentWorkflowTest(options) {
216
+ if (options.source.includes(options.workflowId) || options.source.includes(`test('${options.testTitle}'`)) {
217
+ return options.source;
218
+ }
219
+ const marker = ' // @stage-gap-append';
220
+ const markerIndex = options.source.indexOf(marker);
221
+ if (markerIndex !== -1) {
222
+ return `${options.source.slice(0, markerIndex)}${options.testSource}\n${options.source.slice(markerIndex)}`;
223
+ }
224
+ const closingMarker = '\n});\n';
225
+ const index = options.source.lastIndexOf(closingMarker);
226
+ if (index === -1) {
227
+ throw new Error('目标 spec 文件未找到 gap 追加标记或 test.describe 结束标记');
228
+ }
229
+ return `${options.source.slice(0, index)}${options.testSource}${options.source.slice(index)}`;
230
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * stage-skeleton CRUD 骨架脚本生成器。
3
+ *
4
+ * 核心职责:
5
+ * - 将 crud-business-module/v1 契约映射为胶水模板骨架使用的 CrudFlowSlots
6
+ * - 生成调用 LoginPage、MenuPage、CrudPage 的 Playwright 测试文件
7
+ * - 避免直接拼接 page.fill/page.click,保证测试流程复用骨架层
8
+ */
9
+ import type { CrudBusinessModuleContract } from '../contracts/crud-business-module.js';
10
+ export type StageSkeletonCrudDeletePolicy = 'success_delete' | 'blocked_by_business_rule';
11
+ export type StageSkeletonCrudDataValueStrategy = 'timestamp_prefix' | 'fixed_value';
12
+ export type StageSkeletonCrudListboxSelectionSlot = {
13
+ field: string;
14
+ label: string;
15
+ value: string;
16
+ };
17
+ export type StageSkeletonCrudInputSearchConditionSlot = {
18
+ component: 'input';
19
+ field: string;
20
+ label: string;
21
+ seedValue: string;
22
+ strategy?: StageSkeletonCrudDataValueStrategy;
23
+ fixedValue?: string;
24
+ updatePrefix?: string;
25
+ addLocator: string;
26
+ editLocator: string;
27
+ listLocator: string;
28
+ searchSeedValue?: string;
29
+ };
30
+ export type StageSkeletonCrudListboxSearchConditionSlot = {
31
+ component: 'listbox';
32
+ field: string;
33
+ label: string;
34
+ value: string;
35
+ createSelections?: StageSkeletonCrudListboxSelectionSlot[];
36
+ };
37
+ export type StageSkeletonCrudSearchConditionSlot = StageSkeletonCrudInputSearchConditionSlot | StageSkeletonCrudListboxSearchConditionSlot;
38
+ /**
39
+ * stage-skeleton CRUD 骨架槽位。
40
+ *
41
+ * 该类型与 `packages/stage-create/templates/glue/src/skeletons/crud.skeleton.ts`
42
+ * 中的 CrudFlowSlots 保持结构一致。
43
+ */
44
+ export type StageSkeletonCrudFlowSlots = {
45
+ moduleId: string;
46
+ searchConditions: StageSkeletonCrudSearchConditionSlot[];
47
+ frames: {
48
+ listIframeSrcKeyword: string;
49
+ addIframeSrcKeyword: string;
50
+ editIframeSrcKeyword: string;
51
+ };
52
+ locators: {
53
+ createButton: string;
54
+ addAutofillTrigger?: string;
55
+ addSaveButton: string;
56
+ listSearchSubmit: string;
57
+ listResultValueLocatorTemplate: string;
58
+ listEditActionLocatorTemplate: string;
59
+ editSaveButton: string;
60
+ listRowSelectLocatorTemplate: string;
61
+ listDeleteButton: string;
62
+ deleteConfirmButton?: string;
63
+ };
64
+ assertions: {
65
+ deletePolicy: StageSkeletonCrudDeletePolicy;
66
+ blockedDeleteMessage?: string;
67
+ };
68
+ };
69
+ /**
70
+ * 生成 stage-skeleton 测试脚本的输入参数。
71
+ *
72
+ * @property contract CRUD 业务模块契约
73
+ * @property menuNavigation 菜单路径,传给 MenuPage.navigateToMenu
74
+ * @property testName 生成的测试用例名称
75
+ */
76
+ export type StageSkeletonScriptOptions = {
77
+ contract: CrudBusinessModuleContract;
78
+ menuNavigation: string;
79
+ testName?: string;
80
+ };
81
+ /**
82
+ * 将 CRUD 业务模块契约映射为 stage-skeleton 的 CrudFlowSlots。
83
+ *
84
+ * @param contract CRUD 业务模块契约
85
+ * @returns 可传给 CrudPage 的槽位对象
86
+ * @throws 当关键页面、字段或策略缺失时抛出异常
87
+ */
88
+ export declare function mapContractToStageSkeletonCrudSlots(contract: CrudBusinessModuleContract): StageSkeletonCrudFlowSlots;
89
+ /**
90
+ * 将 CrudFlowSlots 渲染为 TypeScript 对象字面量。
91
+ *
92
+ * @param slots CRUD 骨架槽位
93
+ * @returns TypeScript 对象源码
94
+ */
95
+ export declare function renderStageSkeletonCrudSlots(slots: StageSkeletonCrudFlowSlots): string;
96
+ /**
97
+ * 生成动作级 CRUD + Export Playwright 测试脚本。
98
+ *
99
+ * 每个标准工作流(Create / Read / Update / Delete / Export)独立输出为
100
+ * 一个 test case,使用 GlueWorkflowRecorder 记录执行报告。
101
+ * 末尾保留 `// @stage-gap-append` 标记供 gap Custom test 追加。
102
+ *
103
+ * @param options 生成参数
104
+ * @returns 完整的 `.spec.ts` 源码
105
+ */
106
+ export declare function generateStageSkeletonCrudSpec(options: StageSkeletonScriptOptions): string;
107
+ //# sourceMappingURL=stage-skeleton-script.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stage-skeleton-script.d.ts","sourceRoot":"","sources":["../../../src/generators/stage-skeleton-script.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,0BAA0B,EAAiF,MAAM,sCAAsC,CAAC;AAEtK,MAAM,MAAM,6BAA6B,GAAG,gBAAgB,GAAG,0BAA0B,CAAC;AAC1F,MAAM,MAAM,kCAAkC,GAAG,kBAAkB,GAAG,aAAa,CAAC;AAEpF,MAAM,MAAM,qCAAqC,GAAG;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,yCAAyC,GAAG;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,kCAAkC,CAAC;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,2CAA2C,GAAG;IACxD,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,qCAAqC,EAAE,CAAC;CAC5D,CAAC;AAEF,MAAM,MAAM,oCAAoC,GAC5C,yCAAyC,GACzC,2CAA2C,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,oCAAoC,EAAE,CAAC;IACzD,MAAM,EAAE;QACN,oBAAoB,EAAE,MAAM,CAAC;QAC7B,mBAAmB,EAAE,MAAM,CAAC;QAC5B,oBAAoB,EAAE,MAAM,CAAC;KAC9B,CAAC;IACF,QAAQ,EAAE;QACR,YAAY,EAAE,MAAM,CAAC;QACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,MAAM,CAAC;QACzB,8BAA8B,EAAE,MAAM,CAAC;QACvC,6BAA6B,EAAE,MAAM,CAAC;QACtC,cAAc,EAAE,MAAM,CAAC;QACvB,4BAA4B,EAAE,MAAM,CAAC;QACrC,gBAAgB,EAAE,MAAM,CAAC;QACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC9B,CAAC;IACF,UAAU,EAAE;QACV,YAAY,EAAE,6BAA6B,CAAC;QAC5C,oBAAoB,CAAC,EAAE,MAAM,CAAC;KAC/B,CAAC;CACH,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AA+QF;;;;;;GAMG;AACH,wBAAgB,mCAAmC,CAAC,QAAQ,EAAE,0BAA0B,GAAG,0BAA0B,CA0CpH;AA6DD;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,0BAA0B,GAAG,MAAM,CAwBtF;AAwBD;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,0BAA0B,GAAG,MAAM,CAoMzF"}