@provartesting/provardx-cli 1.5.0-beta.6 → 1.5.0-beta.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.
@@ -10,10 +10,10 @@ export interface LicenseValidationResult {
10
10
  /**
11
11
  * Validate the Provar license before starting the MCP server.
12
12
  *
13
- * Requires Provar Automation IDE to be installed with an activated licence.
13
+ * Requires Provar Automation IDE to be installed with an activated license.
14
14
  * We trust the IDE's own licenseStatus field — if it says "Activated" we
15
15
  * accept it. The IDE is responsible for setting licenseStatus to "Expired"
16
- * or "Invalid" when a licence lapses; we do not re-check timing ourselves.
16
+ * or "Invalid" when a license lapses; we do not re-check timing ourselves.
17
17
  *
18
18
  * The result is cached so repeated starts within 2 hours skip the IDE file
19
19
  * read entirely. The 48-hour grace window lets the MCP server keep running
@@ -22,7 +22,7 @@ export interface LicenseValidationResult {
22
22
  *
23
23
  * Validation flow:
24
24
  * 1. MCP cache fresh (< 2h) → serve from cache, skip IDE read
25
- * 2. Scan ~/Provar/.licenses/*.properties for an Activated licence
25
+ * 2. Scan ~/Provar/.licenses/*.properties for an Activated license
26
26
  * 3. Found → write cache, accept (offlineGrace=false)
27
27
  * 4. Not found but MCP cache within 48h grace → serve, offlineGrace=true
28
28
  * 5. Not found, no usable cache → throw LICENSE_NOT_FOUND
@@ -16,10 +16,10 @@ const IDE_CACHE_KEY = '__ide_detection__';
16
16
  /**
17
17
  * Validate the Provar license before starting the MCP server.
18
18
  *
19
- * Requires Provar Automation IDE to be installed with an activated licence.
19
+ * Requires Provar Automation IDE to be installed with an activated license.
20
20
  * We trust the IDE's own licenseStatus field — if it says "Activated" we
21
21
  * accept it. The IDE is responsible for setting licenseStatus to "Expired"
22
- * or "Invalid" when a licence lapses; we do not re-check timing ourselves.
22
+ * or "Invalid" when a license lapses; we do not re-check timing ourselves.
23
23
  *
24
24
  * The result is cached so repeated starts within 2 hours skip the IDE file
25
25
  * read entirely. The 48-hour grace window lets the MCP server keep running
@@ -28,7 +28,7 @@ const IDE_CACHE_KEY = '__ide_detection__';
28
28
  *
29
29
  * Validation flow:
30
30
  * 1. MCP cache fresh (< 2h) → serve from cache, skip IDE read
31
- * 2. Scan ~/Provar/.licenses/*.properties for an Activated licence
31
+ * 2. Scan ~/Provar/.licenses/*.properties for an Activated license
32
32
  * 3. Found → write cache, accept (offlineGrace=false)
33
33
  * 4. Not found but MCP cache within 48h grace → serve, offlineGrace=true
34
34
  * 5. Not found, no usable cache → throw LICENSE_NOT_FOUND
@@ -96,7 +96,7 @@ function validateViaIdeDetection() {
96
96
  checkedAt: Date.now(),
97
97
  };
98
98
  writeCacheEntry(entry);
99
- log('info', 'licenseValidator: IDE licence validated and cached', {
99
+ log('info', 'licenseValidator: IDE license validated and cached', {
100
100
  name: ideState.name,
101
101
  licenseType: ideState.licenseType,
102
102
  });
@@ -0,0 +1,2 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerAllPrompts(server: McpServer): void;
@@ -0,0 +1,18 @@
1
+ /*
2
+ * Copyright (c) 2024 Provar Limited.
3
+ * All rights reserved.
4
+ * Licensed under the BSD 3-Clause license.
5
+ * For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+ import { registerCrtMigrationPrompt, registerSeleniumMigrationPrompt, registerPlaywrightMigrationPrompt, } from './migrationPrompts.js';
8
+ import { registerLoopGeneratePrompt, registerLoopFixPrompt, registerLoopReviewPrompt, registerLoopCoveragePrompt, } from './loopPrompts.js';
9
+ export function registerAllPrompts(server) {
10
+ registerCrtMigrationPrompt(server);
11
+ registerSeleniumMigrationPrompt(server);
12
+ registerPlaywrightMigrationPrompt(server);
13
+ registerLoopGeneratePrompt(server);
14
+ registerLoopFixPrompt(server);
15
+ registerLoopReviewPrompt(server);
16
+ registerLoopCoveragePrompt(server);
17
+ }
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mcp/prompts/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,0BAA0B,EAC1B,+BAA+B,EAC/B,iCAAiC,GAClC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,kBAAkB,CAAC;AAE1B,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACnC,+BAA+B,CAAC,MAAM,CAAC,CAAC;IACxC,iCAAiC,CAAC,MAAM,CAAC,CAAC;IAC1C,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACnC,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,0BAA0B,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerLoopGeneratePrompt(server: McpServer): void;
3
+ export declare function registerLoopFixPrompt(server: McpServer): void;
4
+ export declare function registerLoopReviewPrompt(server: McpServer): void;
5
+ export declare function registerLoopCoveragePrompt(server: McpServer): void;
@@ -0,0 +1,343 @@
1
+ /*
2
+ * Copyright (c) 2024 Provar Limited.
3
+ * All rights reserved.
4
+ * Licensed under the BSD 3-Clause license.
5
+ * For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+ import { z } from 'zod';
8
+ // ── Shared helpers ────────────────────────────────────────────────────────────
9
+ function projectHint(projectPath) {
10
+ return projectPath
11
+ ? `The Provar project root is: ${projectPath}`
12
+ : 'Ask the user for the Provar project root path if it is needed for file operations.';
13
+ }
14
+ // ── Prompt: provar.loop.generate ─────────────────────────────────────────────
15
+ export function registerLoopGeneratePrompt(server) {
16
+ server.prompt('provar.loop.generate', 'Generate a Provar XML test case from a user story or acceptance criteria. Retrieves corpus examples for grounding, generates the test, writes it to the project, then validates it with provar.testcase.validate.', {
17
+ story: z
18
+ .string()
19
+ .describe('The user story or acceptance criteria to test. Paste the full story text, or a numbered list of acceptance criteria. Include the Salesforce object name and the action being tested (e.g. "As a sales rep, I want to close an opportunity so that revenue is recorded").'),
20
+ projectPath: z
21
+ .string()
22
+ .optional()
23
+ .describe('Absolute path to the Provar project root. Used to locate the tests/ directory when writing the output file.'),
24
+ testName: z
25
+ .string()
26
+ .optional()
27
+ .describe('Optional name for the output test case file (without extension). Inferred from the story if omitted.'),
28
+ objectName: z
29
+ .string()
30
+ .optional()
31
+ .describe('Primary Salesforce object under test (e.g. "Opportunity", "Lead"). Helps scope the corpus query if present.'),
32
+ }, ({ story, projectPath, testName, objectName }) => ({
33
+ messages: [
34
+ {
35
+ role: 'user',
36
+ content: {
37
+ type: 'text',
38
+ text: `You are a Provar test automation expert. Generate a Provar XML test case from the user story below.
39
+
40
+ ## Workflow
41
+
42
+ Follow these steps in order:
43
+
44
+ 1. **Extract keywords** — identify the Salesforce object, the action (create/update/close/delete/view), and key
45
+ scenario details from the story. Use these as the query for step 2.
46
+
47
+ 2. **Get corpus examples** — call \`provar.qualityhub.examples.retrieve\` with the keywords you extracted
48
+ (e.g. "close opportunity" or "create lead"). Use the returned XML examples as the sole reference for
49
+ Provar step structure and argument patterns. Do not invent XML structure from prior knowledge.
50
+ If the response has \`"count": 0\` with a \`"warning"\` field (API unavailable or not configured),
51
+ fall back: read the \`provar://docs/step-reference\` MCP resource for step types and attribute
52
+ formats, then continue.
53
+
54
+ 3. **Map acceptance criteria to steps** — for each acceptance criterion, identify the corresponding Provar
55
+ step type: field fills → UiDoAction (set), button clicks → UiDoAction (action), field checks →
56
+ UiAssert, API data setup → ApexCreateObject, API verification → ApexReadObject.
57
+
58
+ 4. **Generate the test case** — produce a valid Provar XML test case that tests the story's acceptance
59
+ criteria. Base the structure entirely on the corpus examples. Follow these rules:
60
+ - All UI steps must be nested inside UiWithScreen blocks
61
+ - The first UiWithScreen must use navigate="Always"
62
+ - UiAssert requires columnAssertions, pageAssertions, resultScope, captureAfter, beforeWait, autoRetry
63
+ - Use ApexConnect for the connection step (first step in the test)
64
+ - Wrap test body in TryCatchFinally if cleanup is needed (ApexDeleteObject in the finally clause)
65
+
66
+ 5. **Write the file** — save the XML to the tests/ directory in the Provar project.
67
+ ${projectHint(projectPath)}
68
+ ${testName ? `Target file name: ${testName}.testcase` : 'Infer the file name from the story (snake_case).'}
69
+
70
+ 6. **Validate** — call \`provar.testcase.validate\` on the saved file. If it reports errors, fix them
71
+ and re-validate until the file passes clean.
72
+
73
+ 7. **Report** — summarise:
74
+ - Which acceptance criteria were covered and how
75
+ - Any criteria that could not be automated (add \`<!-- TODO: manual verification — <criterion> -->\` in the XML)
76
+ - Any validation warnings
77
+
78
+ ## User Story
79
+
80
+ ${story}
81
+
82
+ ${objectName ? `Primary object: ${objectName}` : ''}
83
+
84
+ Begin with step 1: extract keywords, then call provar.qualityhub.examples.retrieve.`,
85
+ },
86
+ },
87
+ ],
88
+ }));
89
+ }
90
+ // ── Prompt: provar.loop.fix ───────────────────────────────────────────────────
91
+ export function registerLoopFixPrompt(server) {
92
+ server.prompt('provar.loop.fix', 'Fix a failing Provar test case using the output from provar.testrun.rca. Reads the current XML, retrieves corpus examples for the failing step type, applies targeted fixes, then re-validates.', {
93
+ testcasePath: z
94
+ .string()
95
+ .describe('Absolute path to the failing .testcase XML file. The file must be readable and within the --allowed-paths configured for this MCP server.'),
96
+ rcaOutput: z
97
+ .string()
98
+ .describe('The RCA report text from provar.testrun.rca, or a raw failure message from a test run. Include the full error text — step name, error type, and message. The more detail, the better the fix.'),
99
+ projectPath: z
100
+ .string()
101
+ .optional()
102
+ .describe('Absolute path to the Provar project root. Used to locate adjacent test files if needed.'),
103
+ }, ({ testcasePath, rcaOutput, projectPath }) => ({
104
+ messages: [
105
+ {
106
+ role: 'user',
107
+ content: {
108
+ type: 'text',
109
+ text: `You are a Provar test automation expert. Fix the failing test case at the path below.
110
+
111
+ ## Failing test case
112
+
113
+ Path: ${testcasePath}
114
+
115
+ ## RCA output
116
+
117
+ \`\`\`
118
+ ${rcaOutput}
119
+ \`\`\`
120
+
121
+ ${projectPath ? `Provar project root: ${projectPath}` : ''}
122
+
123
+ ## Workflow
124
+
125
+ Follow these steps in order:
126
+
127
+ 1. **Read the failing test case** — read the XML file at the path above using your file reading tools.
128
+
129
+ 2. **Parse the failure** — from the RCA output, identify:
130
+ - Which step is failing (step name, testItemId, or title)
131
+ - The failure category (e.g. element not found, assertion mismatch, connection error, XML structure error)
132
+ - The specific error message
133
+
134
+ 3. **Get corpus examples** — call \`provar.qualityhub.examples.retrieve\` with keywords describing the
135
+ failing step's scenario (e.g. "close opportunity UiDoAction" or "assert field value UiAssert").
136
+ Use the returned examples to verify the correct structure for the failing step type.
137
+ If the response has \`"count": 0\` with a \`"warning"\` field, fall back: read the
138
+ \`provar://docs/step-reference\` MCP resource for the correct attribute schema for the failing
139
+ step type, then continue.
140
+
141
+ 4. **Diagnose the root cause** — compare the failing step's XML against the corpus examples. Common issues:
142
+ - Wrong interaction URI (action vs set vs file)
143
+ - Missing required UiAssert arguments (columnAssertions, pageAssertions, resultScope, captureAfter, beforeWait, autoRetry)
144
+ - UiDoAction (set) missing the value argument
145
+ - UiWithScreen navigate="Dont" on the first screen
146
+ - navigate="Always" on Edit/View without sfUiTargetObjectId
147
+ - Incorrect locator URI format
148
+ - connectionId using valueClass="string" instead of valueClass="id"
149
+
150
+ 5. **Apply the fix** — rewrite only the failing step(s). Preserve all other steps unchanged. Write the
151
+ updated XML back to the same file path.
152
+
153
+ 6. **Validate** — call \`provar.testcase.validate\` on the updated file. If new errors appear, fix them
154
+ and re-validate until the file passes clean.
155
+
156
+ 7. **Report** — summarise:
157
+ - The root cause of the failure
158
+ - Exactly what was changed (step name, argument changed, before/after values)
159
+ - Any remaining warnings from validation
160
+
161
+ Begin with step 1: read the file at: ${testcasePath}`,
162
+ },
163
+ },
164
+ ],
165
+ }));
166
+ }
167
+ // ── Prompt: provar.loop.review ────────────────────────────────────────────────
168
+ export function registerLoopReviewPrompt(server) {
169
+ server.prompt('provar.loop.review', 'Review a Provar test case for quality before committing. Runs structural validation, checks against corpus best practices, and reports quality gaps: missing assertions, hardcoded data, missing cleanup, and unmapped steps.', {
170
+ testcasePath: z
171
+ .string()
172
+ .describe('Absolute path to the .testcase XML file to review. Must be within the --allowed-paths configured for this MCP server.'),
173
+ projectPath: z.string().optional().describe('Absolute path to the Provar project root.'),
174
+ }, ({ testcasePath, projectPath }) => ({
175
+ messages: [
176
+ {
177
+ role: 'user',
178
+ content: {
179
+ type: 'text',
180
+ text: `You are a Provar test automation expert. Review the test case at the path below for quality and completeness.
181
+
182
+ ## Test case to review
183
+
184
+ Path: ${testcasePath}
185
+ ${projectPath ? `Provar project root: ${projectPath}` : ''}
186
+
187
+ ## Workflow
188
+
189
+ Follow these steps in order:
190
+
191
+ 1. **Validate** — call \`provar.testcase.validate\` on the file. Note all errors and warnings. Do not stop
192
+ here even if the file is valid — continue the review.
193
+
194
+ 2. **Read the file** — read the XML to understand the test structure: what object is being tested, what
195
+ actions are performed, and what is being asserted.
196
+
197
+ 3. **Get corpus examples** — call \`provar.qualityhub.examples.retrieve\` with keywords describing the
198
+ test scenario (e.g. "create opportunity", "close opportunity"). Use the returned examples as a
199
+ quality baseline. If the response has \`"count": 0\` with a \`"warning"\` field, fall back: read
200
+ the \`provar://docs/step-reference\` MCP resource for step type schemas, then continue the review
201
+ using that as the quality baseline.
202
+
203
+ 4. **Review for quality gaps** — check for each of the following, noting pass or fail:
204
+
205
+ **Coverage**
206
+ - [ ] Does the test assert the outcome of each action? (e.g. after clicking Save, is there a UiAssert?)
207
+ - [ ] Are all required fields verified, not just the ones that were set?
208
+ - [ ] Is there at least one UiAssert or ApexReadObject in the test?
209
+
210
+ **Data quality**
211
+ - [ ] Are test data values parameterised via SetValues rather than hardcoded in multiple steps?
212
+ - [ ] Are dynamic values (dates, IDs) referenced via variables rather than hardcoded strings?
213
+
214
+ **Cleanup**
215
+ - [ ] Is cleanup handled? Either autoCleanup=true on the connection, or ApexDeleteObject steps, or
216
+ a TryCatchFinally with cleanup in the finally clause?
217
+
218
+ **Structure**
219
+ - [ ] Does the first UiWithScreen use navigate="Always" or "IfNecessary"?
220
+ - [ ] Do Edit/View UiWithScreen steps with navigate="Always" include sfUiTargetObjectId?
221
+ - [ ] Are all UiDoAction and UiAssert steps inside UiWithScreen substeps clauses?
222
+
223
+ **Unmapped steps**
224
+ - [ ] Are there any \`<!-- TODO: -->\` comments indicating steps that couldn't be automated?
225
+ Flag these for manual review.
226
+
227
+ 5. **Report** — produce a structured review with three sections:
228
+
229
+ ### Passes
230
+ List what the test does well.
231
+
232
+ ### Issues
233
+ For each gap found, state:
234
+ - What is missing or wrong
235
+ - Why it matters (e.g. "assertion missing after Save means the test won't catch a silent failure")
236
+ - A concrete fix (reference the corpus example if relevant)
237
+
238
+ ### Suggested improvements
239
+ Any non-blocking suggestions (e.g. parameterising a hardcoded value that appears more than once).
240
+
241
+ Begin with step 1: call provar.testcase.validate on the file at: ${testcasePath}`,
242
+ },
243
+ },
244
+ ],
245
+ }));
246
+ }
247
+ // ── Prompt: provar.loop.coverage ─────────────────────────────────────────────
248
+ export function registerLoopCoveragePrompt(server) {
249
+ server.prompt('provar.loop.coverage', 'Analyse test coverage for a Salesforce object. Scans the Provar project test files to identify which CRUD operations, field validations, and UI workflows are covered, then reports gaps with suggested test outlines.', {
250
+ objectName: z
251
+ .string()
252
+ .describe('The Salesforce API object name to analyse (e.g. "Opportunity", "Lead", "Contact", "Account"). Used to scan test cases and query the corpus for expected test patterns.'),
253
+ projectPath: z
254
+ .string()
255
+ .describe('Absolute path to the Provar project root. The tests/ subdirectory will be scanned for .testcase files.'),
256
+ targetOrg: z
257
+ .string()
258
+ .optional()
259
+ .describe('SF org alias or username. If provided, also queries provar.qualityhub.testcase.retrieve to include Quality Hub tests in the coverage analysis.'),
260
+ }, ({ objectName, projectPath, targetOrg }) => ({
261
+ messages: [
262
+ {
263
+ role: 'user',
264
+ content: {
265
+ type: 'text',
266
+ text: `You are a Provar test automation expert. Analyse test coverage for the Salesforce object "${objectName}".
267
+
268
+ ## Provar project
269
+
270
+ Root: ${projectPath}
271
+ Object to analyse: ${objectName}
272
+ ${targetOrg ? `Quality Hub org: ${targetOrg}` : ''}
273
+
274
+ ## Workflow
275
+
276
+ Follow these steps in order:
277
+
278
+ 1. **Scan local test files** — list all .testcase files under ${projectPath}/tests/. For each file that
279
+ references "${objectName}" (search for the string in the file content), read it and extract:
280
+ - The test scenario (from the file name or meta comment)
281
+ - Which operations are covered: API Create, API Read, API Update, API Delete, UI New, UI View,
282
+ UI Edit, UI Delete, UI assertions on fields
283
+ - Which fields are set or asserted
284
+
285
+ ${targetOrg
286
+ ? `2. **Query Quality Hub** — call \`provar.qualityhub.testcase.retrieve\` with target_org="${targetOrg}"
287
+ to retrieve test cases linked to the "${objectName}" object from Quality Hub. Add these to the
288
+ coverage inventory.
289
+
290
+ 3. **Get corpus examples** — call \`provar.qualityhub.examples.retrieve\` with "${objectName.toLowerCase()}"
291
+ as the query to understand what test patterns exist in the corpus for this object.
292
+ If the response has \`"count": 0\` with a \`"warning"\` field, fall back: read the
293
+ \`provar://docs/step-reference\` MCP resource for step type schemas, then continue.`
294
+ : `2. **Get corpus examples** — call \`provar.qualityhub.examples.retrieve\` with "${objectName.toLowerCase()}"
295
+ as the query to understand what test patterns exist in the corpus for this object.
296
+ If the response has \`"count": 0\` with a \`"warning"\` field, fall back: read the
297
+ \`provar://docs/step-reference\` MCP resource for step type schemas, then continue.`}
298
+
299
+ ${targetOrg ? '4' : '3'}. **Build the coverage matrix** — define the standard test scenarios for "${objectName}":
300
+
301
+ **API (Apex) operations**
302
+ - Create: ApexCreateObject with required fields
303
+ - Create: ApexCreateObject with optional/edge-case fields
304
+ - Read: ApexReadObject — verify created record
305
+ - Update: ApexUpdateObject — modify field values
306
+ - Delete: ApexDeleteObject — confirm record removed
307
+ - SOQL: ApexSoqlQuery — query by key fields
308
+
309
+ **UI operations**
310
+ - New: navigate to New screen, fill required fields, save → assert record created
311
+ - View: navigate to View screen → assert field values
312
+ - Edit: navigate to Edit screen, modify fields, save → assert changes persisted
313
+ - Delete: delete via UI → confirm record no longer visible
314
+ - Related lists: any relationships (e.g. Contacts on Account) that have UI tests
315
+
316
+ **Validation rules and required fields**
317
+ - Negative tests: attempt to save with missing required fields → assert error message shown
318
+ - Validation rule triggers: if known validation rules exist, is there a test for each?
319
+
320
+ ${targetOrg ? '5' : '4'}. **Report coverage gaps** — produce a report with three sections:
321
+
322
+ ### Covered
323
+ List each scenario that has at least one test, with the test file name.
324
+
325
+ ### Gaps
326
+ For each missing scenario, state:
327
+ - What is not covered
328
+ - Why it matters (e.g. "No negative test for required fields means validation rule regressions won't be caught")
329
+ - A brief test outline (inputs, expected outcome, which step types to use)
330
+
331
+ ### Suggested next tests
332
+ Rank the top 3-5 gaps by risk. For each, provide:
333
+ - A suggested test case name
334
+ - The key steps (using correct Provar step type names from the reference)
335
+ - Estimated effort (XS / S / M)
336
+
337
+ Begin with step 1: list the .testcase files in ${projectPath}/tests/ and search for "${objectName}".`,
338
+ },
339
+ },
340
+ ],
341
+ }));
342
+ }
343
+ //# sourceMappingURL=loopPrompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopPrompts.js","sourceRoot":"","sources":["../../../src/mcp/prompts/loopPrompts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,iFAAiF;AAEjF,SAAS,WAAW,CAAC,WAA+B;IAClD,OAAO,WAAW;QAChB,CAAC,CAAC,+BAA+B,WAAW,EAAE;QAC9C,CAAC,CAAC,oFAAoF,CAAC;AAC3F,CAAC;AAED,gFAAgF;AAEhF,MAAM,UAAU,0BAA0B,CAAC,MAAiB;IAC1D,MAAM,CAAC,MAAM,CACX,sBAAsB,EACtB,mNAAmN,EACnN;QACE,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,CACP,0QAA0Q,CAC3Q;QACH,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,6GAA6G,CAC9G;QACH,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,sGAAsG,CACvG;QACH,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,6GAA6G,CAC9G;KACJ,EACD,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QACjD,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6Bb,WAAW,CAAC,WAAW,CAAC;KACxB,QAAQ,CAAC,CAAC,CAAC,qBAAqB,QAAQ,WAAW,CAAC,CAAC,CAAC,kDAAkD;;;;;;;;;;;;EAY3G,KAAK;;EAEL,UAAU,CAAC,CAAC,CAAC,mBAAmB,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE;;oFAEiC;iBACzE;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC;AAED,iFAAiF;AAEjF,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,MAAM,CAAC,MAAM,CACX,iBAAiB,EACjB,iMAAiM,EACjM;QACE,YAAY,EAAE,CAAC;aACZ,MAAM,EAAE;aACR,QAAQ,CACP,2IAA2I,CAC5I;QACH,SAAS,EAAE,CAAC;aACT,MAAM,EAAE;aACR,QAAQ,CACP,+LAA+L,CAChM;QACH,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,yFAAyF,CAAC;KACvG,EACD,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;QAC7C,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;;;;QAIV,YAAY;;;;;EAKlB,SAAS;;;EAGT,WAAW,CAAC,CAAC,CAAC,wBAAwB,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCAwCnB,YAAY,EAAE;iBAC1C;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC;AAED,iFAAiF;AAEjF,MAAM,UAAU,wBAAwB,CAAC,MAAiB;IACxD,MAAM,CAAC,MAAM,CACX,oBAAoB,EACpB,+NAA+N,EAC/N;QACE,YAAY,EAAE,CAAC;aACZ,MAAM,EAAE;aACR,QAAQ,CACP,uHAAuH,CACxH;QACH,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;KACzF,EACD,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;QAClC,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;;;;QAIV,YAAY;EAClB,WAAW,CAAC,CAAC,CAAC,wBAAwB,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mEAwDS,YAAY,EAAE;iBACtE;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC;AAED,gFAAgF;AAEhF,MAAM,UAAU,0BAA0B,CAAC,MAAiB;IAC1D,MAAM,CAAC,MAAM,CACX,sBAAsB,EACtB,wNAAwN,EACxN;QACE,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,CACP,wKAAwK,CACzK;QACH,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,QAAQ,CACP,wGAAwG,CACzG;QACH,SAAS,EAAE,CAAC;aACT,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,gJAAgJ,CACjJ;KACJ,EACD,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3C,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,6FAA6F,UAAU;;;;QAIjH,WAAW;qBACE,UAAU;EAC7B,SAAS,CAAC,CAAC,CAAC,oBAAoB,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE;;;;;;gEAMc,WAAW;iBAC1D,UAAU;;;;;;EAOzB,SAAS;wBACP,CAAC,CAAC,4FAA4F,SAAS;2CAChE,UAAU;;;kFAG6B,UAAU,CAAC,WAAW,EAAE;;;uFAGnB;wBACnF,CAAC,CAAC,mFAAmF,UAAU,CAAC,WAAW,EAAE;;;uFAIjH;;EAEE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,6EAA6E,UAAU;;;;;;;;;;;;;;;;;;;;;EAqB5G,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;;;;;;;;;;;;;;;;;iDAiB0B,WAAW,2BAA2B,UAAU,IAAI;iBAC1F;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerCrtMigrationPrompt(server: McpServer): void;
3
+ export declare function registerSeleniumMigrationPrompt(server: McpServer): void;
4
+ export declare function registerPlaywrightMigrationPrompt(server: McpServer): void;
@@ -0,0 +1,207 @@
1
+ /*
2
+ * Copyright (c) 2024 Provar Limited.
3
+ * All rights reserved.
4
+ * Licensed under the BSD 3-Clause license.
5
+ * For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
+ */
7
+ import { z } from 'zod';
8
+ // Source-framework context injected into each migration prompt.
9
+ // Lightweight: just enough to interpret the source. Format knowledge lives
10
+ // in the corpus (provar.qualityhub.examples.retrieve) and the validator
11
+ // (provar.testcase.validate) — not hardcoded here.
12
+ const CRT_CONTEXT = `
13
+ CRT (Copado Robotic Testing) is a keyword-driven framework built on Robot Framework.
14
+ Tests are authored in QEditor using QWords:
15
+ - ClickText <label> → click an element by visible label
16
+ - TypeText <field> <value> → type a value into a field
17
+ - VerifyText <text> → assert text is present on the page
18
+ - SelectDropdown <field> <val> → choose a picklist option
19
+ - OpenBrowser <url> → open a browser session (maps to Salesforce login)
20
+
21
+ Robot Framework sections: *** Keywords *** define reusable blocks; *** Test Cases *** are the test entries.
22
+ Suite Setup/Teardown → login at the start and cleanup at the end.
23
+ `.trim();
24
+ const SELENIUM_CONTEXT = `
25
+ Selenium WebDriver test patterns (Java/Python/JavaScript):
26
+ - driver.get(url) / navigate().to() → navigate to a URL (maps to Salesforce login)
27
+ - findElement(By.linkText/name).click() → click by visible label
28
+ - findElement(...).sendKeys(value) → type into a field
29
+ - Select.selectByVisibleText(val) → select a picklist option
30
+ - findElement(...).getText() + assertion → verify a field value
31
+ - WebDriverWait / ExpectedConditions → wait for element visibility
32
+ - @Before / setUp() → test setup including login
33
+ - @After / tearDown() → cleanup
34
+ `.trim();
35
+ const PLAYWRIGHT_CONTEXT = `
36
+ Playwright test patterns (TypeScript/JavaScript):
37
+ - page.goto(url) / login fixture → navigate to Salesforce (maps to login)
38
+ - getByLabel(label).click() → click by visible label
39
+ - getByRole('button', {name}).click() → click by button name
40
+ - getByLabel(label).fill(value) → fill a field by label
41
+ - locator(selector).fill(value) → fill by XPath/CSS selector
42
+ - locator.selectOption(value) → choose a picklist option
43
+ - expect(locator).toHaveValue(val) → assert a field value
44
+ - expect(locator).toBeVisible() → assert element is visible
45
+ - expect(page).toContainText(text) → assert text on page
46
+ - page.waitForLoadState() / waitForSelector() → wait conditions
47
+ - beforeEach → test setup including login
48
+ `.trim();
49
+ // ── Shared orchestration instructions ────────────────────────────────────────
50
+ function migrationOrchestration(projectPath) {
51
+ const projectHint = projectPath
52
+ ? `The target Provar project is at: ${projectPath}`
53
+ : 'Ask the user for the Provar project path if needed.';
54
+ return `
55
+ ## Migration workflow
56
+
57
+ Follow these steps in order:
58
+
59
+ 1. **Get corpus examples** — call \`provar.qualityhub.examples.retrieve\` with keywords that
60
+ describe the source test's main scenario (e.g. "create opportunity", "close case", "convert lead").
61
+ Use the returned examples as few-shot grounding for the Provar XML format and step patterns.
62
+ If the response has \`"count": 0\` with a \`"warning"\` field (API unavailable or not configured),
63
+ fall back: read the \`provar://docs/step-reference\` MCP resource for step types and attribute
64
+ formats, then continue with generation based on that reference.
65
+
66
+ 2. **Generate the test case** — produce a valid Provar XML test case that faithfully captures
67
+ the intent of the source test. Base the structure entirely on the corpus examples, not on
68
+ prior knowledge of Provar XML. Omit Salesforce login/navigation setup — Provar handles
69
+ that via Connection Manager.
70
+
71
+ 3. **Write the file** — save the generated XML to the appropriate \`tests/\` subdirectory
72
+ inside the Provar project. ${projectHint}
73
+
74
+ 4. **Validate** — call \`provar.testcase.validate\` on the saved file. If it reports errors,
75
+ fix them and re-validate until the file passes clean.
76
+
77
+ 5. **Report** — summarise what was migrated, any steps that could not be mapped (add them
78
+ as \`<!-- TODO: manual step -->\` comments in the XML), and any validation warnings.
79
+ `.trim();
80
+ }
81
+ // ── Prompt: provar.migrate.crt ────────────────────────────────────────────────
82
+ export function registerCrtMigrationPrompt(server) {
83
+ server.prompt('provar.migrate.crt', 'Convert a Copado Robotic Testing (CRT) test — either a QWord step sequence or a Robot Framework .robot file — into a Provar XML test case. Retrieves corpus examples for grounding, generates the test case, then validates it with provar.testcase.validate.', {
84
+ source: z
85
+ .string()
86
+ .describe('The CRT test content to migrate. Accepts either: (1) a numbered QWord step sequence (e.g. "Step 1: ClickText Accounts"), or (2) a Robot Framework .robot file with *** Settings ***, *** Keywords ***, and *** Test Cases *** sections.'),
87
+ projectPath: z
88
+ .string()
89
+ .optional()
90
+ .describe('Absolute path to the Provar project root. Used to locate the tests/ directory when writing the output file.'),
91
+ testName: z
92
+ .string()
93
+ .optional()
94
+ .describe('Optional name for the output Provar test case. Inferred from the source if omitted.'),
95
+ }, ({ source, projectPath, testName }) => ({
96
+ messages: [
97
+ {
98
+ role: 'user',
99
+ content: {
100
+ type: 'text',
101
+ text: `You are a Provar test migration expert. Migrate the following CRT test to Provar.
102
+
103
+ ## Source format — CRT
104
+
105
+ ${CRT_CONTEXT}
106
+
107
+ ${migrationOrchestration(projectPath)}
108
+
109
+ ## Source CRT Test
110
+
111
+ \`\`\`
112
+ ${source}
113
+ \`\`\`
114
+
115
+ ${testName ? `Target test case name: ${testName}` : 'Infer the test case name from the source content.'}
116
+
117
+ Begin with step 1: call provar.qualityhub.examples.retrieve.`,
118
+ },
119
+ },
120
+ ],
121
+ }));
122
+ }
123
+ // ── Prompt: provar.migrate.selenium ──────────────────────────────────────────
124
+ export function registerSeleniumMigrationPrompt(server) {
125
+ server.prompt('provar.migrate.selenium', 'Convert a Selenium WebDriver test (Java, Python, or JavaScript) that tests a Salesforce org into a Provar XML test case. Retrieves corpus examples for grounding, generates the test case, then validates it with provar.testcase.validate.', {
126
+ source: z
127
+ .string()
128
+ .describe('The Selenium test file content to migrate. Accepts Java (JUnit/TestNG), Python (unittest/pytest), or JavaScript (Jest/Mocha) with selenium-webdriver. Include the full file or the relevant test method(s).'),
129
+ projectPath: z
130
+ .string()
131
+ .optional()
132
+ .describe('Absolute path to the Provar project root. Used to locate the tests/ directory when writing the output file.'),
133
+ testName: z
134
+ .string()
135
+ .optional()
136
+ .describe('Optional name for the output Provar test case. Inferred from the source class/method name if omitted.'),
137
+ }, ({ source, projectPath, testName }) => ({
138
+ messages: [
139
+ {
140
+ role: 'user',
141
+ content: {
142
+ type: 'text',
143
+ text: `You are a Provar test migration expert. Migrate the following Selenium WebDriver test to Provar.
144
+
145
+ ## Source format — Selenium WebDriver
146
+
147
+ ${SELENIUM_CONTEXT}
148
+
149
+ ${migrationOrchestration(projectPath)}
150
+
151
+ ## Source Selenium Test
152
+
153
+ \`\`\`
154
+ ${source}
155
+ \`\`\`
156
+
157
+ ${testName ? `Target test case name: ${testName}` : 'Infer the test case name from the class and method name.'}
158
+
159
+ Begin with step 1: call provar.qualityhub.examples.retrieve.`,
160
+ },
161
+ },
162
+ ],
163
+ }));
164
+ }
165
+ // ── Prompt: provar.migrate.playwright ────────────────────────────────────────
166
+ export function registerPlaywrightMigrationPrompt(server) {
167
+ server.prompt('provar.migrate.playwright', 'Convert a Playwright test (TypeScript or JavaScript) that tests a Salesforce org into a Provar XML test case. Retrieves corpus examples for grounding, generates the test case, then validates it with provar.testcase.validate.', {
168
+ source: z
169
+ .string()
170
+ .describe('The Playwright test file content to migrate. Accepts TypeScript or JavaScript using @playwright/test or the playwright library. Include the full file or the relevant test block(s).'),
171
+ projectPath: z
172
+ .string()
173
+ .optional()
174
+ .describe('Absolute path to the Provar project root. Used to locate the tests/ directory when writing the output file.'),
175
+ testName: z
176
+ .string()
177
+ .optional()
178
+ .describe('Optional name for the output Provar test case. Inferred from the test() block description if omitted.'),
179
+ }, ({ source, projectPath, testName }) => ({
180
+ messages: [
181
+ {
182
+ role: 'user',
183
+ content: {
184
+ type: 'text',
185
+ text: `You are a Provar test migration expert. Migrate the following Playwright test to Provar.
186
+
187
+ ## Source format — Playwright
188
+
189
+ ${PLAYWRIGHT_CONTEXT}
190
+
191
+ ${migrationOrchestration(projectPath)}
192
+
193
+ ## Source Playwright Test
194
+
195
+ \`\`\`
196
+ ${source}
197
+ \`\`\`
198
+
199
+ ${testName ? `Target test case name: ${testName}` : 'Infer the test case name from the test() block description.'}
200
+
201
+ Begin with step 1: call provar.qualityhub.examples.retrieve.`,
202
+ },
203
+ },
204
+ ],
205
+ }));
206
+ }
207
+ //# sourceMappingURL=migrationPrompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrationPrompts.js","sourceRoot":"","sources":["../../../src/mcp/prompts/migrationPrompts.ts"],"names":[],"mappings":"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"}