@browserstack/mcp-server 1.2.1 → 1.2.2-beta.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.
- package/README.md +227 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/device-cache.d.ts +1 -0
- package/dist/lib/device-cache.js +28 -0
- package/dist/lib/inmemory-store.d.ts +1 -0
- package/dist/lib/inmemory-store.js +1 -0
- package/dist/lib/instrumentation.js +2 -0
- package/dist/oninitialized.js +4 -1
- package/dist/server-factory.js +3 -1
- package/dist/tools/accessibility.js +238 -78
- package/dist/tools/accessiblity-utils/auth-config.d.ts +39 -0
- package/dist/tools/accessiblity-utils/auth-config.js +125 -0
- package/dist/tools/accessiblity-utils/scanner.d.ts +1 -1
- package/dist/tools/accessiblity-utils/scanner.js +2 -1
- package/dist/tools/add-percy-snapshots.d.ts +5 -0
- package/dist/tools/add-percy-snapshots.js +17 -0
- package/dist/tools/appautomate-utils/appautomate.d.ts +2 -1
- package/dist/tools/appautomate-utils/appautomate.js +12 -9
- package/dist/tools/appautomate.js +56 -7
- package/dist/tools/applive-utils/start-session.d.ts +2 -1
- package/dist/tools/applive-utils/start-session.js +17 -6
- package/dist/tools/applive.d.ts +2 -1
- package/dist/tools/applive.js +21 -17
- package/dist/tools/bstack-sdk.d.ts +2 -15
- package/dist/tools/bstack-sdk.js +7 -124
- package/dist/tools/list-test-files.d.ts +2 -0
- package/dist/tools/list-test-files.js +33 -0
- package/dist/tools/percy-sdk.d.ts +4 -0
- package/dist/tools/percy-sdk.js +88 -0
- package/dist/tools/percy-snapshot-utils/constants.d.ts +16 -0
- package/dist/tools/percy-snapshot-utils/constants.js +500 -0
- package/dist/tools/percy-snapshot-utils/detect-test-files.d.ts +10 -0
- package/dist/tools/percy-snapshot-utils/detect-test-files.js +194 -0
- package/dist/tools/percy-snapshot-utils/types.d.ts +15 -0
- package/dist/tools/percy-snapshot-utils/utils.d.ts +4 -0
- package/dist/tools/percy-snapshot-utils/utils.js +30 -0
- package/dist/tools/sdk-utils/{commands.d.ts → bstack/commands.d.ts} +1 -1
- package/dist/tools/sdk-utils/bstack/commands.js +88 -0
- package/dist/tools/sdk-utils/bstack/configUtils.d.ts +4 -0
- package/dist/tools/sdk-utils/bstack/configUtils.js +66 -0
- package/dist/tools/sdk-utils/bstack/constants.d.ts +58 -0
- package/dist/tools/sdk-utils/{constants.js → bstack/constants.js} +128 -76
- package/dist/tools/sdk-utils/{constants.d.ts → bstack/frameworks.d.ts} +1 -1
- package/dist/tools/sdk-utils/bstack/frameworks.js +57 -0
- package/dist/tools/sdk-utils/bstack/index.d.ts +4 -0
- package/dist/tools/sdk-utils/bstack/index.js +5 -0
- package/dist/tools/sdk-utils/bstack/sdkHandler.d.ts +4 -0
- package/dist/tools/sdk-utils/bstack/sdkHandler.js +74 -0
- package/dist/tools/sdk-utils/common/constants.d.ts +10 -0
- package/dist/tools/sdk-utils/common/constants.js +86 -0
- package/dist/tools/sdk-utils/common/formatUtils.d.ts +5 -0
- package/dist/tools/sdk-utils/common/formatUtils.js +27 -0
- package/dist/tools/sdk-utils/common/index.d.ts +3 -0
- package/dist/tools/sdk-utils/common/index.js +4 -0
- package/dist/tools/sdk-utils/common/instructionUtils.d.ts +8 -0
- package/dist/tools/sdk-utils/common/instructionUtils.js +20 -0
- package/dist/tools/sdk-utils/common/schema.d.ts +61 -0
- package/dist/tools/sdk-utils/common/schema.js +28 -0
- package/dist/tools/sdk-utils/common/types.d.ts +66 -0
- package/dist/tools/sdk-utils/common/types.js +50 -0
- package/dist/tools/sdk-utils/common/utils.d.ts +25 -0
- package/dist/tools/sdk-utils/common/utils.js +84 -0
- package/dist/tools/sdk-utils/handler.d.ts +5 -0
- package/dist/tools/sdk-utils/handler.js +144 -0
- package/dist/tools/sdk-utils/percy-automate/constants.d.ts +11 -0
- package/dist/tools/sdk-utils/percy-automate/constants.js +365 -0
- package/dist/tools/sdk-utils/percy-automate/frameworks.d.ts +8 -0
- package/dist/tools/sdk-utils/percy-automate/frameworks.js +50 -0
- package/dist/tools/sdk-utils/percy-automate/handler.d.ts +3 -0
- package/dist/tools/sdk-utils/percy-automate/handler.js +30 -0
- package/dist/tools/sdk-utils/percy-automate/index.d.ts +1 -0
- package/dist/tools/sdk-utils/percy-automate/index.js +2 -0
- package/dist/tools/sdk-utils/percy-automate/types.d.ts +13 -0
- package/dist/tools/sdk-utils/percy-automate/types.js +1 -0
- package/dist/tools/sdk-utils/percy-bstack/constants.d.ts +4 -0
- package/dist/tools/sdk-utils/{percy → percy-bstack}/constants.js +13 -39
- package/dist/tools/sdk-utils/percy-bstack/frameworks.d.ts +2 -0
- package/dist/tools/sdk-utils/percy-bstack/frameworks.js +27 -0
- package/dist/tools/sdk-utils/percy-bstack/handler.d.ts +4 -0
- package/dist/tools/sdk-utils/percy-bstack/handler.js +99 -0
- package/dist/tools/sdk-utils/percy-bstack/index.d.ts +4 -0
- package/dist/tools/sdk-utils/percy-bstack/index.js +4 -0
- package/dist/tools/sdk-utils/percy-bstack/instructions.d.ts +7 -0
- package/dist/tools/sdk-utils/{percy → percy-bstack}/instructions.js +5 -9
- package/dist/tools/sdk-utils/percy-bstack/types.d.ts +13 -0
- package/dist/tools/sdk-utils/percy-bstack/types.js +5 -0
- package/dist/tools/sdk-utils/percy-web/constants.d.ts +41 -0
- package/dist/tools/sdk-utils/percy-web/constants.js +941 -0
- package/dist/tools/sdk-utils/percy-web/fetchPercyToken.d.ts +4 -0
- package/dist/tools/sdk-utils/percy-web/fetchPercyToken.js +28 -0
- package/dist/tools/sdk-utils/percy-web/frameworks.d.ts +7 -0
- package/dist/tools/sdk-utils/percy-web/frameworks.js +103 -0
- package/dist/tools/sdk-utils/percy-web/handler.d.ts +4 -0
- package/dist/tools/sdk-utils/percy-web/handler.js +27 -0
- package/dist/tools/sdk-utils/percy-web/index.d.ts +4 -0
- package/dist/tools/sdk-utils/percy-web/index.js +4 -0
- package/dist/tools/sdk-utils/percy-web/types.d.ts +12 -0
- package/dist/tools/sdk-utils/percy-web/types.js +1 -0
- package/dist/tools/sdk-utils/types.d.ts +2 -1
- package/dist/tools/sdk-utils/types.js +1 -0
- package/dist/tools/testmanagement-utils/create-testcase.d.ts +4 -0
- package/dist/tools/testmanagement-utils/create-testcase.js +6 -0
- package/package.json +1 -1
- package/dist/tools/sdk-utils/commands.js +0 -65
- package/dist/tools/sdk-utils/instructions.d.ts +0 -6
- package/dist/tools/sdk-utils/instructions.js +0 -99
- package/dist/tools/sdk-utils/percy/constants.d.ts +0 -3
- package/dist/tools/sdk-utils/percy/instructions.d.ts +0 -10
- package/dist/tools/sdk-utils/percy/types.d.ts +0 -5
- /package/dist/tools/{getFailureLogs.d.ts → get-failure-logs.d.ts} +0 -0
- /package/dist/tools/{getFailureLogs.js → get-failure-logs.js} +0 -0
- /package/dist/tools/{sdk-utils/percy → percy-snapshot-utils}/types.js +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { getBrowserStackAuth } from "../../../lib/get-auth.js";
|
|
2
|
+
import { getSDKPrefixCommand } from "./commands.js";
|
|
3
|
+
import { generateBrowserStackYMLInstructions } from "./configUtils.js";
|
|
4
|
+
import { getInstructionsForProjectConfiguration } from "../common/instructionUtils.js";
|
|
5
|
+
export function runBstackSDKOnly(input, config, isPercyAutomate = false) {
|
|
6
|
+
const steps = [];
|
|
7
|
+
const authString = getBrowserStackAuth(config);
|
|
8
|
+
const [username, accessKey] = authString.split(":");
|
|
9
|
+
// Handle frameworks with unique setup instructions that don't use browserstack.yml
|
|
10
|
+
if (input.detectedBrowserAutomationFramework === "cypress" ||
|
|
11
|
+
input.detectedTestingFramework === "webdriverio") {
|
|
12
|
+
const frameworkInstructions = getInstructionsForProjectConfiguration(input.detectedBrowserAutomationFramework, input.detectedTestingFramework, input.detectedLanguage, username, accessKey);
|
|
13
|
+
if (frameworkInstructions) {
|
|
14
|
+
if (frameworkInstructions.setup) {
|
|
15
|
+
steps.push({
|
|
16
|
+
type: "instruction",
|
|
17
|
+
title: "Framework-Specific Setup",
|
|
18
|
+
content: frameworkInstructions.setup,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
if (frameworkInstructions.run && !isPercyAutomate) {
|
|
22
|
+
steps.push({
|
|
23
|
+
type: "instruction",
|
|
24
|
+
title: "Run the tests",
|
|
25
|
+
content: frameworkInstructions.run,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
steps,
|
|
31
|
+
requiresPercy: false,
|
|
32
|
+
missingDependencies: [],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// Default flow using browserstack.yml
|
|
36
|
+
const sdkSetupCommand = getSDKPrefixCommand(input.detectedLanguage, input.detectedTestingFramework, username, accessKey);
|
|
37
|
+
if (sdkSetupCommand) {
|
|
38
|
+
steps.push({
|
|
39
|
+
type: "instruction",
|
|
40
|
+
title: "Install BrowserStack SDK",
|
|
41
|
+
content: sdkSetupCommand,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const ymlInstructions = generateBrowserStackYMLInstructions(input.desiredPlatforms, false, input.projectName);
|
|
45
|
+
if (ymlInstructions) {
|
|
46
|
+
steps.push({
|
|
47
|
+
type: "instruction",
|
|
48
|
+
title: "Configure browserstack.yml",
|
|
49
|
+
content: ymlInstructions,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const frameworkInstructions = getInstructionsForProjectConfiguration(input.detectedBrowserAutomationFramework, input.detectedTestingFramework, input.detectedLanguage, username, accessKey);
|
|
53
|
+
if (frameworkInstructions) {
|
|
54
|
+
if (frameworkInstructions.setup) {
|
|
55
|
+
steps.push({
|
|
56
|
+
type: "instruction",
|
|
57
|
+
title: "Framework-Specific Setup",
|
|
58
|
+
content: frameworkInstructions.setup,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (frameworkInstructions.run && !isPercyAutomate) {
|
|
62
|
+
steps.push({
|
|
63
|
+
type: "instruction",
|
|
64
|
+
title: "Run the tests",
|
|
65
|
+
content: frameworkInstructions.run,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
steps,
|
|
71
|
+
requiresPercy: false,
|
|
72
|
+
missingDependencies: [],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const IMPORTANT_SETUP_WARNING = "IMPORTANT: DO NOT SKIP ANY STEP. All the setup steps described below MUST be executed regardless of any existing configuration or setup. This ensures proper BrowserStack SDK setup.";
|
|
2
|
+
export declare const SETUP_PERCY_DESCRIPTION = "Set up Percy visual testing for your project. This supports both Percy Web Standalone and Percy Automate.";
|
|
3
|
+
export declare const LIST_TEST_FILES_DESCRIPTION = "Lists all test files for a given set of directories.";
|
|
4
|
+
export declare const PERCY_SNAPSHOT_COMMANDS_DESCRIPTION = "Adds Percy snapshot commands to the specified test files.";
|
|
5
|
+
export declare const RUN_ON_BROWSERSTACK_DESCRIPTION = "Set up and run automated web-based tests on BrowserStack using the BrowserStack SDK. Use this tool for functional or integration test setup on BrowserStack only. For any visual testing or Percy integration, use the dedicated Percy setup tool. Example prompts: run this test on browserstack; set up this project for browserstack.";
|
|
6
|
+
export declare const SIMULATE_PERCY_CHANGE_DESCRIPTION = "This tool helps new users simulate a Percy visual change by guiding them to make a visible UI modification, rerun Percy, and verify that the change is detected. Only Percy web is supported";
|
|
7
|
+
export declare const PERCY_REPLACE_REGEX: RegExp;
|
|
8
|
+
export declare const PERCY_SNAPSHOT_INSTRUCTION = "\nInvoke listTestFiles() with the provided directories from user to gather all test files in memory and obtain the generated UUID ---STEP---\nProcess files in STRICT sequential order using tool addPercySnapshotCommands() with below instructions:\n- Start with index 0\n- Then index 1 \n- Then index 2\n- Continue sequentially until the last index\n- DO NOT skip any index numbers\n- DO NOT jump to random indices like 10, 20, 30\n- DO NOT worry about time consuming and any constraints.\n- DO NOT STOP until you add commands in all the files or you reach end of the files.\n";
|
|
9
|
+
export declare const PERCY_SIMULATE_INSTRUCTION = "\nMANDATORY: Aggressive, Accurate Percy Snapshots Integration\n\nPrerequisite: Before making any code changes in the user's repo, switch to a branch named temp-percy (run git init first if the repo is not yet initialized).\n\nYou MUST follow these steps with NO EXCEPTIONS:\n1. Identify 4-5 key test files in the project that are critical for visual testing.\n2. For EACH identified test file, analyze the code to find EVERY location where a Percy snapshot should be called (e.g., after each navigation, UI change, or significant state in tests).\n3. Insert snapshot calls at ALL such points, not just the first or most obvious one.\n\nIteratively update every selected test file with percy snapshot calls at all identified points, ensuring comprehensive coverage of visual changes.";
|
|
10
|
+
export declare const PERCY_SIMULATION_DRIVER_INSTRUCTION = "\nMANDATORY: Step-by-Step Percy Visual Change Simulation\nYou MUST follow these steps with NO EXCEPTIONS:\n\nSTEP 1: At this case we have added Percy snapshot commands to the test files at the appropriate locations (e.g., after navigation, UI change, or significant state). \n- Use ONLY existing snapshot names.\n- Do NOT add any popup injection or visual changes yet.\n- Do NOT run any Percy builds at this stage.\n\nSTEP 2: Run ONE comprehensive baseline Percy build that executes ALL tests containing Percy snapshots in a SINGLE build. This creates one baseline build with all snapshots for comparison. Use a command like: npx percy exec -- python -m pytest tests/ -k 'test_name1 or test_name2 or test_name3' -v to run multiple specific tests in one build.\"\n\nSTEP 3: Modify your test to inject a visible UI change (such as a popup) IMMEDIATELY BEFORE an EXISTING snapshot command (e.g., before percy_snapshot(self.driver, \"screenshot name\")).\n- Do NOT add a new snapshot name for the popup.\n- The popup must appear in an existing snapshot, not a new one.\n- Add this popup code in some test files before the percy_snapshot command you've added, to display the visual changes.\n\n```Javascript\npopup_script = `\nvar popup = document.createElement('div');\npopup.id = 'percy-test-popup';\npopup.style.cssText = popup.style.cssText = `\n /* TODO: Add styles to make the popup large, centered, and visually noticeable.\n Suggested properties: position: fixed; top/left; transform; background; color; font-size; padding; z-index; animation, etc. */\n`;\npopup.innerHTML = 'PERCY TEST<br>VISUAL CHANGE<br>DETECTED!';\ndocument.body.appendChild(popup);\n`;\n\n# Insert this just before the EXISTING snapshot command:\ndriver.execute_script(popup_script)\npercy_snapshot(self.driver, \"Before Adding to Cart\") # (Do NOT change the snapshot name, keep existing one)\n```\n\nSTEP 4: Run a second Percy build.\n- The snapshot names must remain the same as in the baseline.\n- The visual change should now appear in the same snapshot as before.\n- Use the same build command you ran for the baseline.\n\nSTEP 5: Compare the two Percy builds to see the detected visual difference.\n\nSTEP 6: Now ask user if they want to setup percy for full project coverage? If yes, call the \"setupPercyVisualTesting\" tool to enable complete coverage for the entire project.\n\nCONSTRAINTS:\n- Do NOT run any builds until explicitly instructed in the steps.\n- Do NOT add new snapshot names\u2014only use existing ones.\n- Do NOT add popup injection until the baseline is established.\n- Visual changes must appear in EXISTING snapshots, not new ones.\n\nVALIDATION CHECKPOINTS (before proceeding to the next step):\n- Are you adding only snapshot commands (not running builds)?\n- Are you reusing existing snapshot names (not creating new ones)?\n- Have you established the baseline first (before adding visual changes)\n\nCRITICAL: \nDo NOT run tests separately or create multiple builds during baseline establishment. The goal is to have exactly TWO builds total: (1) baseline build with all original snapshots, (2) modified build with the same tests but visual changes injected.\n";
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export const IMPORTANT_SETUP_WARNING = "IMPORTANT: DO NOT SKIP ANY STEP. All the setup steps described below MUST be executed regardless of any existing configuration or setup. This ensures proper BrowserStack SDK setup.";
|
|
2
|
+
export const SETUP_PERCY_DESCRIPTION = "Set up Percy visual testing for your project. This supports both Percy Web Standalone and Percy Automate.";
|
|
3
|
+
export const LIST_TEST_FILES_DESCRIPTION = "Lists all test files for a given set of directories.";
|
|
4
|
+
export const PERCY_SNAPSHOT_COMMANDS_DESCRIPTION = "Adds Percy snapshot commands to the specified test files.";
|
|
5
|
+
export const RUN_ON_BROWSERSTACK_DESCRIPTION = "Set up and run automated web-based tests on BrowserStack using the BrowserStack SDK. Use this tool for functional or integration test setup on BrowserStack only. For any visual testing or Percy integration, use the dedicated Percy setup tool. Example prompts: run this test on browserstack; set up this project for browserstack.";
|
|
6
|
+
export const SIMULATE_PERCY_CHANGE_DESCRIPTION = "This tool helps new users simulate a Percy visual change by guiding them to make a visible UI modification, rerun Percy, and verify that the change is detected. Only Percy web is supported";
|
|
7
|
+
export const PERCY_REPLACE_REGEX = /Invoke listTestFiles\(\) with the provided directories[\s\S]*?- DO NOT STOP until you add commands in all the files or you reach end of the files\./;
|
|
8
|
+
export const PERCY_SNAPSHOT_INSTRUCTION = `
|
|
9
|
+
Invoke listTestFiles() with the provided directories from user to gather all test files in memory and obtain the generated UUID ---STEP---
|
|
10
|
+
Process files in STRICT sequential order using tool addPercySnapshotCommands() with below instructions:
|
|
11
|
+
- Start with index 0
|
|
12
|
+
- Then index 1
|
|
13
|
+
- Then index 2
|
|
14
|
+
- Continue sequentially until the last index
|
|
15
|
+
- DO NOT skip any index numbers
|
|
16
|
+
- DO NOT jump to random indices like 10, 20, 30
|
|
17
|
+
- DO NOT worry about time consuming and any constraints.
|
|
18
|
+
- DO NOT STOP until you add commands in all the files or you reach end of the files.
|
|
19
|
+
`;
|
|
20
|
+
export const PERCY_SIMULATE_INSTRUCTION = `
|
|
21
|
+
MANDATORY: Aggressive, Accurate Percy Snapshots Integration
|
|
22
|
+
|
|
23
|
+
Prerequisite: Before making any code changes in the user's repo, switch to a branch named temp-percy (run git init first if the repo is not yet initialized).
|
|
24
|
+
|
|
25
|
+
You MUST follow these steps with NO EXCEPTIONS:
|
|
26
|
+
1. Identify 4-5 key test files in the project that are critical for visual testing.
|
|
27
|
+
2. For EACH identified test file, analyze the code to find EVERY location where a Percy snapshot should be called (e.g., after each navigation, UI change, or significant state in tests).
|
|
28
|
+
3. Insert snapshot calls at ALL such points, not just the first or most obvious one.
|
|
29
|
+
|
|
30
|
+
Iteratively update every selected test file with percy snapshot calls at all identified points, ensuring comprehensive coverage of visual changes.`;
|
|
31
|
+
export const PERCY_SIMULATION_DRIVER_INSTRUCTION = `
|
|
32
|
+
MANDATORY: Step-by-Step Percy Visual Change Simulation
|
|
33
|
+
You MUST follow these steps with NO EXCEPTIONS:
|
|
34
|
+
|
|
35
|
+
STEP 1: At this case we have added Percy snapshot commands to the test files at the appropriate locations (e.g., after navigation, UI change, or significant state).
|
|
36
|
+
- Use ONLY existing snapshot names.
|
|
37
|
+
- Do NOT add any popup injection or visual changes yet.
|
|
38
|
+
- Do NOT run any Percy builds at this stage.
|
|
39
|
+
|
|
40
|
+
STEP 2: Run ONE comprehensive baseline Percy build that executes ALL tests containing Percy snapshots in a SINGLE build. This creates one baseline build with all snapshots for comparison. Use a command like: npx percy exec -- python -m pytest tests/ -k 'test_name1 or test_name2 or test_name3' -v to run multiple specific tests in one build."
|
|
41
|
+
|
|
42
|
+
STEP 3: Modify your test to inject a visible UI change (such as a popup) IMMEDIATELY BEFORE an EXISTING snapshot command (e.g., before percy_snapshot(self.driver, "screenshot name")).
|
|
43
|
+
- Do NOT add a new snapshot name for the popup.
|
|
44
|
+
- The popup must appear in an existing snapshot, not a new one.
|
|
45
|
+
- Add this popup code in some test files before the percy_snapshot command you've added, to display the visual changes.
|
|
46
|
+
|
|
47
|
+
\`\`\`Javascript
|
|
48
|
+
popup_script = \`
|
|
49
|
+
var popup = document.createElement('div');
|
|
50
|
+
popup.id = 'percy-test-popup';
|
|
51
|
+
popup.style.cssText = popup.style.cssText = \`
|
|
52
|
+
/* TODO: Add styles to make the popup large, centered, and visually noticeable.
|
|
53
|
+
Suggested properties: position: fixed; top/left; transform; background; color; font-size; padding; z-index; animation, etc. */
|
|
54
|
+
\`;
|
|
55
|
+
popup.innerHTML = 'PERCY TEST<br>VISUAL CHANGE<br>DETECTED!';
|
|
56
|
+
document.body.appendChild(popup);
|
|
57
|
+
\`;
|
|
58
|
+
|
|
59
|
+
# Insert this just before the EXISTING snapshot command:
|
|
60
|
+
driver.execute_script(popup_script)
|
|
61
|
+
percy_snapshot(self.driver, "Before Adding to Cart") # (Do NOT change the snapshot name, keep existing one)
|
|
62
|
+
\`\`\`
|
|
63
|
+
|
|
64
|
+
STEP 4: Run a second Percy build.
|
|
65
|
+
- The snapshot names must remain the same as in the baseline.
|
|
66
|
+
- The visual change should now appear in the same snapshot as before.
|
|
67
|
+
- Use the same build command you ran for the baseline.
|
|
68
|
+
|
|
69
|
+
STEP 5: Compare the two Percy builds to see the detected visual difference.
|
|
70
|
+
|
|
71
|
+
STEP 6: Now ask user if they want to setup percy for full project coverage? If yes, call the "setupPercyVisualTesting" tool to enable complete coverage for the entire project.
|
|
72
|
+
|
|
73
|
+
CONSTRAINTS:
|
|
74
|
+
- Do NOT run any builds until explicitly instructed in the steps.
|
|
75
|
+
- Do NOT add new snapshot names—only use existing ones.
|
|
76
|
+
- Do NOT add popup injection until the baseline is established.
|
|
77
|
+
- Visual changes must appear in EXISTING snapshots, not new ones.
|
|
78
|
+
|
|
79
|
+
VALIDATION CHECKPOINTS (before proceeding to the next step):
|
|
80
|
+
- Are you adding only snapshot commands (not running builds)?
|
|
81
|
+
- Are you reusing existing snapshot names (not creating new ones)?
|
|
82
|
+
- Have you established the baseline first (before adding visual changes)
|
|
83
|
+
|
|
84
|
+
CRITICAL:
|
|
85
|
+
Do NOT run tests separately or create multiple builds during baseline establishment. The goal is to have exactly TWO builds total: (1) baseline build with all original snapshots, (2) modified build with the same tests but visual changes injected.
|
|
86
|
+
`;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function formatInstructionsWithNumbers(instructionText, separator = "---STEP---") {
|
|
2
|
+
// Split the instructions by the separator
|
|
3
|
+
const steps = instructionText
|
|
4
|
+
.split(separator)
|
|
5
|
+
.map((step) => step.trim())
|
|
6
|
+
.filter((step) => step.length > 0);
|
|
7
|
+
// If no separators found, treat the entire text as one step
|
|
8
|
+
if (steps.length === 1 && !instructionText.includes(separator)) {
|
|
9
|
+
return {
|
|
10
|
+
formattedSteps: `**Step 1:**\n${instructionText.trim()}`,
|
|
11
|
+
stepCount: 1,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
// Format each step with numbering
|
|
15
|
+
const formattedSteps = steps
|
|
16
|
+
.map((step, index) => {
|
|
17
|
+
return `**Step ${index + 1}:**\n${step.trim()}`;
|
|
18
|
+
})
|
|
19
|
+
.join("\n\n");
|
|
20
|
+
return {
|
|
21
|
+
formattedSteps,
|
|
22
|
+
stepCount: steps.length,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function generateVerificationMessage(stepCount) {
|
|
26
|
+
return `**✅ Verification:**\nPlease verify that you have completed all ${stepCount} steps above to ensure proper setup. If you encounter any issues, double-check each step and ensure all commands executed successfully.`;
|
|
27
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core instruction configuration utilities for runTestsOnBrowserStack tool.
|
|
3
|
+
*/
|
|
4
|
+
import { SDKSupportedLanguage, SDKSupportedBrowserAutomationFramework, SDKSupportedTestingFramework } from "./types.js";
|
|
5
|
+
export declare const getInstructionsForProjectConfiguration: (detectedBrowserAutomationFramework: SDKSupportedBrowserAutomationFramework, detectedTestingFramework: SDKSupportedTestingFramework, detectedLanguage: SDKSupportedLanguage, username: string, accessKey: string) => {
|
|
6
|
+
setup: string;
|
|
7
|
+
run: string;
|
|
8
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core instruction configuration utilities for runTestsOnBrowserStack tool.
|
|
3
|
+
*/
|
|
4
|
+
import { SUPPORTED_CONFIGURATIONS } from "../bstack/frameworks.js";
|
|
5
|
+
const errorMessageSuffix = "Please open an issue at our Github repo: https://github.com/browserstack/browserstack-mcp-server/issues to request support for your project configuration";
|
|
6
|
+
export const getInstructionsForProjectConfiguration = (detectedBrowserAutomationFramework, detectedTestingFramework, detectedLanguage, username, accessKey) => {
|
|
7
|
+
const configuration = SUPPORTED_CONFIGURATIONS[detectedLanguage];
|
|
8
|
+
if (!configuration) {
|
|
9
|
+
throw new Error(`BrowserStack MCP Server currently does not support ${detectedLanguage}, ${errorMessageSuffix}`);
|
|
10
|
+
}
|
|
11
|
+
if (!configuration[detectedBrowserAutomationFramework]) {
|
|
12
|
+
throw new Error(`BrowserStack MCP Server currently does not support ${detectedBrowserAutomationFramework} for ${detectedLanguage}, ${errorMessageSuffix}`);
|
|
13
|
+
}
|
|
14
|
+
if (!configuration[detectedBrowserAutomationFramework][detectedTestingFramework]) {
|
|
15
|
+
throw new Error(`BrowserStack MCP Server currently does not support ${detectedTestingFramework} for ${detectedBrowserAutomationFramework} on ${detectedLanguage}, ${errorMessageSuffix}`);
|
|
16
|
+
}
|
|
17
|
+
const instructionFunction = configuration[detectedBrowserAutomationFramework][detectedTestingFramework]
|
|
18
|
+
.instructions;
|
|
19
|
+
return instructionFunction(username, accessKey);
|
|
20
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { SDKSupportedBrowserAutomationFrameworkEnum, SDKSupportedTestingFrameworkEnum, SDKSupportedLanguageEnum } from "./types.js";
|
|
3
|
+
import { PercyIntegrationTypeEnum } from "./types.js";
|
|
4
|
+
export declare const SetUpPercyParamsShape: {
|
|
5
|
+
projectName: z.ZodString;
|
|
6
|
+
detectedLanguage: z.ZodNativeEnum<typeof SDKSupportedLanguageEnum>;
|
|
7
|
+
detectedBrowserAutomationFramework: z.ZodNativeEnum<typeof SDKSupportedBrowserAutomationFrameworkEnum>;
|
|
8
|
+
detectedTestingFramework: z.ZodNativeEnum<typeof SDKSupportedTestingFrameworkEnum>;
|
|
9
|
+
integrationType: z.ZodNativeEnum<typeof PercyIntegrationTypeEnum>;
|
|
10
|
+
folderPaths: z.ZodArray<z.ZodString, "many">;
|
|
11
|
+
};
|
|
12
|
+
export declare const RunTestsOnBrowserStackParamsShape: {
|
|
13
|
+
projectName: z.ZodString;
|
|
14
|
+
detectedLanguage: z.ZodNativeEnum<typeof SDKSupportedLanguageEnum>;
|
|
15
|
+
detectedBrowserAutomationFramework: z.ZodNativeEnum<typeof SDKSupportedBrowserAutomationFrameworkEnum>;
|
|
16
|
+
detectedTestingFramework: z.ZodNativeEnum<typeof SDKSupportedTestingFrameworkEnum>;
|
|
17
|
+
desiredPlatforms: z.ZodArray<z.ZodEnum<["windows", "macos", "android", "ios"]>, "many">;
|
|
18
|
+
};
|
|
19
|
+
export declare const SetUpPercySchema: z.ZodObject<{
|
|
20
|
+
projectName: z.ZodString;
|
|
21
|
+
detectedLanguage: z.ZodNativeEnum<typeof SDKSupportedLanguageEnum>;
|
|
22
|
+
detectedBrowserAutomationFramework: z.ZodNativeEnum<typeof SDKSupportedBrowserAutomationFrameworkEnum>;
|
|
23
|
+
detectedTestingFramework: z.ZodNativeEnum<typeof SDKSupportedTestingFrameworkEnum>;
|
|
24
|
+
integrationType: z.ZodNativeEnum<typeof PercyIntegrationTypeEnum>;
|
|
25
|
+
folderPaths: z.ZodArray<z.ZodString, "many">;
|
|
26
|
+
}, "strip", z.ZodTypeAny, {
|
|
27
|
+
projectName: string;
|
|
28
|
+
detectedLanguage: SDKSupportedLanguageEnum;
|
|
29
|
+
detectedBrowserAutomationFramework: SDKSupportedBrowserAutomationFrameworkEnum;
|
|
30
|
+
detectedTestingFramework: SDKSupportedTestingFrameworkEnum;
|
|
31
|
+
integrationType: PercyIntegrationTypeEnum;
|
|
32
|
+
folderPaths: string[];
|
|
33
|
+
}, {
|
|
34
|
+
projectName: string;
|
|
35
|
+
detectedLanguage: SDKSupportedLanguageEnum;
|
|
36
|
+
detectedBrowserAutomationFramework: SDKSupportedBrowserAutomationFrameworkEnum;
|
|
37
|
+
detectedTestingFramework: SDKSupportedTestingFrameworkEnum;
|
|
38
|
+
integrationType: PercyIntegrationTypeEnum;
|
|
39
|
+
folderPaths: string[];
|
|
40
|
+
}>;
|
|
41
|
+
export declare const RunTestsOnBrowserStackSchema: z.ZodObject<{
|
|
42
|
+
projectName: z.ZodString;
|
|
43
|
+
detectedLanguage: z.ZodNativeEnum<typeof SDKSupportedLanguageEnum>;
|
|
44
|
+
detectedBrowserAutomationFramework: z.ZodNativeEnum<typeof SDKSupportedBrowserAutomationFrameworkEnum>;
|
|
45
|
+
detectedTestingFramework: z.ZodNativeEnum<typeof SDKSupportedTestingFrameworkEnum>;
|
|
46
|
+
desiredPlatforms: z.ZodArray<z.ZodEnum<["windows", "macos", "android", "ios"]>, "many">;
|
|
47
|
+
}, "strip", z.ZodTypeAny, {
|
|
48
|
+
projectName: string;
|
|
49
|
+
detectedLanguage: SDKSupportedLanguageEnum;
|
|
50
|
+
detectedBrowserAutomationFramework: SDKSupportedBrowserAutomationFrameworkEnum;
|
|
51
|
+
detectedTestingFramework: SDKSupportedTestingFrameworkEnum;
|
|
52
|
+
desiredPlatforms: ("android" | "windows" | "macos" | "ios")[];
|
|
53
|
+
}, {
|
|
54
|
+
projectName: string;
|
|
55
|
+
detectedLanguage: SDKSupportedLanguageEnum;
|
|
56
|
+
detectedBrowserAutomationFramework: SDKSupportedBrowserAutomationFrameworkEnum;
|
|
57
|
+
detectedTestingFramework: SDKSupportedTestingFrameworkEnum;
|
|
58
|
+
desiredPlatforms: ("android" | "windows" | "macos" | "ios")[];
|
|
59
|
+
}>;
|
|
60
|
+
export type SetUpPercyInput = z.infer<typeof SetUpPercySchema>;
|
|
61
|
+
export type RunTestsOnBrowserStackInput = z.infer<typeof RunTestsOnBrowserStackSchema>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { SDKSupportedBrowserAutomationFrameworkEnum, SDKSupportedTestingFrameworkEnum, SDKSupportedLanguageEnum, } from "./types.js";
|
|
3
|
+
import { PercyIntegrationTypeEnum } from "./types.js";
|
|
4
|
+
export const SetUpPercyParamsShape = {
|
|
5
|
+
projectName: z.string().describe("A unique name for your Percy project."),
|
|
6
|
+
detectedLanguage: z.nativeEnum(SDKSupportedLanguageEnum),
|
|
7
|
+
detectedBrowserAutomationFramework: z.nativeEnum(SDKSupportedBrowserAutomationFrameworkEnum),
|
|
8
|
+
detectedTestingFramework: z.nativeEnum(SDKSupportedTestingFrameworkEnum),
|
|
9
|
+
integrationType: z
|
|
10
|
+
.nativeEnum(PercyIntegrationTypeEnum)
|
|
11
|
+
.describe("Specifies whether to integrate with Percy Web or Percy Automate. If not explicitly provided, prompt the user to select the desired integration type."),
|
|
12
|
+
folderPaths: z
|
|
13
|
+
.array(z.string())
|
|
14
|
+
.describe("An array of folder paths to include in which Percy will be integrated. If not provided, strictly inspect the code and return the folders which contain UI test cases."),
|
|
15
|
+
};
|
|
16
|
+
export const RunTestsOnBrowserStackParamsShape = {
|
|
17
|
+
projectName: z
|
|
18
|
+
.string()
|
|
19
|
+
.describe("A single name for your project to organize all your tests. This is required for Percy."),
|
|
20
|
+
detectedLanguage: z.nativeEnum(SDKSupportedLanguageEnum),
|
|
21
|
+
detectedBrowserAutomationFramework: z.nativeEnum(SDKSupportedBrowserAutomationFrameworkEnum),
|
|
22
|
+
detectedTestingFramework: z.nativeEnum(SDKSupportedTestingFrameworkEnum),
|
|
23
|
+
desiredPlatforms: z
|
|
24
|
+
.array(z.enum(["windows", "macos", "android", "ios"]))
|
|
25
|
+
.describe("An array of platforms to run tests on."),
|
|
26
|
+
};
|
|
27
|
+
export const SetUpPercySchema = z.object(SetUpPercyParamsShape);
|
|
28
|
+
export const RunTestsOnBrowserStackSchema = z.object(RunTestsOnBrowserStackParamsShape);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export declare enum PercyIntegrationTypeEnum {
|
|
2
|
+
WEB = "web",
|
|
3
|
+
AUTOMATE = "automate"
|
|
4
|
+
}
|
|
5
|
+
export declare enum SDKSupportedLanguageEnum {
|
|
6
|
+
nodejs = "nodejs",
|
|
7
|
+
python = "python",
|
|
8
|
+
java = "java",
|
|
9
|
+
csharp = "csharp",
|
|
10
|
+
ruby = "ruby"
|
|
11
|
+
}
|
|
12
|
+
export type SDKSupportedLanguage = keyof typeof SDKSupportedLanguageEnum;
|
|
13
|
+
export declare enum SDKSupportedBrowserAutomationFrameworkEnum {
|
|
14
|
+
playwright = "playwright",
|
|
15
|
+
selenium = "selenium",
|
|
16
|
+
cypress = "cypress"
|
|
17
|
+
}
|
|
18
|
+
export type SDKSupportedBrowserAutomationFramework = keyof typeof SDKSupportedBrowserAutomationFrameworkEnum;
|
|
19
|
+
export declare enum SDKSupportedTestingFrameworkEnum {
|
|
20
|
+
jest = "jest",
|
|
21
|
+
codeceptjs = "codeceptjs",
|
|
22
|
+
playwright = "playwright",
|
|
23
|
+
pytest = "pytest",
|
|
24
|
+
robot = "robot",
|
|
25
|
+
behave = "behave",
|
|
26
|
+
cucumber = "cucumber",
|
|
27
|
+
nightwatch = "nightwatch",
|
|
28
|
+
webdriverio = "webdriverio",
|
|
29
|
+
mocha = "mocha",
|
|
30
|
+
junit4 = "junit4",
|
|
31
|
+
junit5 = "junit5",
|
|
32
|
+
testng = "testng",
|
|
33
|
+
cypress = "cypress",
|
|
34
|
+
nunit = "nunit",
|
|
35
|
+
mstest = "mstest",
|
|
36
|
+
xunit = "xunit",
|
|
37
|
+
specflow = "specflow",
|
|
38
|
+
reqnroll = "reqnroll",
|
|
39
|
+
rspec = "rspec",
|
|
40
|
+
serenity = "serenity"
|
|
41
|
+
}
|
|
42
|
+
export declare const SDKSupportedLanguages: SDKSupportedLanguageEnum[];
|
|
43
|
+
export type SDKSupportedTestingFramework = keyof typeof SDKSupportedTestingFrameworkEnum;
|
|
44
|
+
export declare const SDKSupportedTestingFrameworks: SDKSupportedTestingFrameworkEnum[];
|
|
45
|
+
export type ConfigMapping = Partial<Record<SDKSupportedLanguageEnum, Partial<Record<SDKSupportedBrowserAutomationFrameworkEnum, Partial<Record<SDKSupportedTestingFrameworkEnum, {
|
|
46
|
+
instructions: (username: string, accessKey: string) => {
|
|
47
|
+
setup: string;
|
|
48
|
+
run: string;
|
|
49
|
+
};
|
|
50
|
+
}>>>>>>;
|
|
51
|
+
export interface RunTestsStep {
|
|
52
|
+
type: "instruction" | "error" | "warning";
|
|
53
|
+
title: string;
|
|
54
|
+
content: string;
|
|
55
|
+
isError?: boolean;
|
|
56
|
+
}
|
|
57
|
+
export interface RunTestsInstructionResult {
|
|
58
|
+
steps: RunTestsStep[];
|
|
59
|
+
requiresPercy: boolean;
|
|
60
|
+
missingDependencies: string[];
|
|
61
|
+
shouldSkipFormatting?: boolean;
|
|
62
|
+
}
|
|
63
|
+
export declare enum PercyAutomateNotImplementedType {
|
|
64
|
+
LANGUAGE = "language",
|
|
65
|
+
FRAMEWORK = "framework"
|
|
66
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export var PercyIntegrationTypeEnum;
|
|
2
|
+
(function (PercyIntegrationTypeEnum) {
|
|
3
|
+
PercyIntegrationTypeEnum["WEB"] = "web";
|
|
4
|
+
PercyIntegrationTypeEnum["AUTOMATE"] = "automate";
|
|
5
|
+
})(PercyIntegrationTypeEnum || (PercyIntegrationTypeEnum = {}));
|
|
6
|
+
export var SDKSupportedLanguageEnum;
|
|
7
|
+
(function (SDKSupportedLanguageEnum) {
|
|
8
|
+
SDKSupportedLanguageEnum["nodejs"] = "nodejs";
|
|
9
|
+
SDKSupportedLanguageEnum["python"] = "python";
|
|
10
|
+
SDKSupportedLanguageEnum["java"] = "java";
|
|
11
|
+
SDKSupportedLanguageEnum["csharp"] = "csharp";
|
|
12
|
+
SDKSupportedLanguageEnum["ruby"] = "ruby";
|
|
13
|
+
})(SDKSupportedLanguageEnum || (SDKSupportedLanguageEnum = {}));
|
|
14
|
+
export var SDKSupportedBrowserAutomationFrameworkEnum;
|
|
15
|
+
(function (SDKSupportedBrowserAutomationFrameworkEnum) {
|
|
16
|
+
SDKSupportedBrowserAutomationFrameworkEnum["playwright"] = "playwright";
|
|
17
|
+
SDKSupportedBrowserAutomationFrameworkEnum["selenium"] = "selenium";
|
|
18
|
+
SDKSupportedBrowserAutomationFrameworkEnum["cypress"] = "cypress";
|
|
19
|
+
})(SDKSupportedBrowserAutomationFrameworkEnum || (SDKSupportedBrowserAutomationFrameworkEnum = {}));
|
|
20
|
+
export var SDKSupportedTestingFrameworkEnum;
|
|
21
|
+
(function (SDKSupportedTestingFrameworkEnum) {
|
|
22
|
+
SDKSupportedTestingFrameworkEnum["jest"] = "jest";
|
|
23
|
+
SDKSupportedTestingFrameworkEnum["codeceptjs"] = "codeceptjs";
|
|
24
|
+
SDKSupportedTestingFrameworkEnum["playwright"] = "playwright";
|
|
25
|
+
SDKSupportedTestingFrameworkEnum["pytest"] = "pytest";
|
|
26
|
+
SDKSupportedTestingFrameworkEnum["robot"] = "robot";
|
|
27
|
+
SDKSupportedTestingFrameworkEnum["behave"] = "behave";
|
|
28
|
+
SDKSupportedTestingFrameworkEnum["cucumber"] = "cucumber";
|
|
29
|
+
SDKSupportedTestingFrameworkEnum["nightwatch"] = "nightwatch";
|
|
30
|
+
SDKSupportedTestingFrameworkEnum["webdriverio"] = "webdriverio";
|
|
31
|
+
SDKSupportedTestingFrameworkEnum["mocha"] = "mocha";
|
|
32
|
+
SDKSupportedTestingFrameworkEnum["junit4"] = "junit4";
|
|
33
|
+
SDKSupportedTestingFrameworkEnum["junit5"] = "junit5";
|
|
34
|
+
SDKSupportedTestingFrameworkEnum["testng"] = "testng";
|
|
35
|
+
SDKSupportedTestingFrameworkEnum["cypress"] = "cypress";
|
|
36
|
+
SDKSupportedTestingFrameworkEnum["nunit"] = "nunit";
|
|
37
|
+
SDKSupportedTestingFrameworkEnum["mstest"] = "mstest";
|
|
38
|
+
SDKSupportedTestingFrameworkEnum["xunit"] = "xunit";
|
|
39
|
+
SDKSupportedTestingFrameworkEnum["specflow"] = "specflow";
|
|
40
|
+
SDKSupportedTestingFrameworkEnum["reqnroll"] = "reqnroll";
|
|
41
|
+
SDKSupportedTestingFrameworkEnum["rspec"] = "rspec";
|
|
42
|
+
SDKSupportedTestingFrameworkEnum["serenity"] = "serenity";
|
|
43
|
+
})(SDKSupportedTestingFrameworkEnum || (SDKSupportedTestingFrameworkEnum = {}));
|
|
44
|
+
export const SDKSupportedLanguages = Object.values(SDKSupportedLanguageEnum);
|
|
45
|
+
export const SDKSupportedTestingFrameworks = Object.values(SDKSupportedTestingFrameworkEnum);
|
|
46
|
+
export var PercyAutomateNotImplementedType;
|
|
47
|
+
(function (PercyAutomateNotImplementedType) {
|
|
48
|
+
PercyAutomateNotImplementedType["LANGUAGE"] = "language";
|
|
49
|
+
PercyAutomateNotImplementedType["FRAMEWORK"] = "framework";
|
|
50
|
+
})(PercyAutomateNotImplementedType || (PercyAutomateNotImplementedType = {}));
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { PercyIntegrationTypeEnum } from "../common/types.js";
|
|
3
|
+
import { RunTestsInstructionResult, PercyAutomateNotImplementedType } from "./types.js";
|
|
4
|
+
export declare function checkPercyIntegrationSupport(input: {
|
|
5
|
+
integrationType: string;
|
|
6
|
+
detectedLanguage: string;
|
|
7
|
+
detectedTestingFramework?: string;
|
|
8
|
+
detectedBrowserAutomationFramework?: string;
|
|
9
|
+
}): {
|
|
10
|
+
supported: boolean;
|
|
11
|
+
errorMessage?: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function formatToolResult(resultPromise: Promise<RunTestsInstructionResult> | RunTestsInstructionResult): Promise<CallToolResult>;
|
|
14
|
+
export declare function getPercyAutomateNotImplementedMessage(type: PercyAutomateNotImplementedType, input: {
|
|
15
|
+
detectedLanguage: string;
|
|
16
|
+
detectedBrowserAutomationFramework: string;
|
|
17
|
+
}, supported: string[]): string;
|
|
18
|
+
export declare function getBootstrapFailedMessage(error: unknown, context: {
|
|
19
|
+
config: unknown;
|
|
20
|
+
percyMode?: string;
|
|
21
|
+
sdkVersion?: string;
|
|
22
|
+
}): string;
|
|
23
|
+
export declare function percyUnsupportedResult(integrationType: PercyIntegrationTypeEnum, supportCheck?: {
|
|
24
|
+
errorMessage?: string;
|
|
25
|
+
}): CallToolResult;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { PercyIntegrationTypeEnum } from "../common/types.js";
|
|
2
|
+
import { isPercyAutomateFrameworkSupported } from "../percy-automate/frameworks.js";
|
|
3
|
+
import { isPercyWebFrameworkSupported } from "../percy-web/frameworks.js";
|
|
4
|
+
import { formatInstructionsWithNumbers, generateVerificationMessage, } from "./formatUtils.js";
|
|
5
|
+
import { PercyAutomateNotImplementedType, } from "./types.js";
|
|
6
|
+
import { IMPORTANT_SETUP_WARNING } from "./index.js";
|
|
7
|
+
export function checkPercyIntegrationSupport(input) {
|
|
8
|
+
if (input.integrationType === PercyIntegrationTypeEnum.AUTOMATE) {
|
|
9
|
+
const isSupported = isPercyAutomateFrameworkSupported(input.detectedLanguage, input.detectedBrowserAutomationFramework || "", input.detectedTestingFramework || "");
|
|
10
|
+
if (!isSupported) {
|
|
11
|
+
return {
|
|
12
|
+
supported: false,
|
|
13
|
+
errorMessage: `Percy Automate is not supported for this configuration. Language: ${input.detectedLanguage} Testing Framework: ${input.detectedTestingFramework}`,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
else if (input.integrationType === PercyIntegrationTypeEnum.WEB) {
|
|
18
|
+
const isSupported = isPercyWebFrameworkSupported(input.detectedLanguage, input.detectedBrowserAutomationFramework || "");
|
|
19
|
+
if (!isSupported) {
|
|
20
|
+
return {
|
|
21
|
+
supported: false,
|
|
22
|
+
errorMessage: `Percy Web is not supported for this configuration. Language: ${input.detectedLanguage} Browser Automation Framework: ${input.detectedBrowserAutomationFramework}`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return { supported: true };
|
|
27
|
+
}
|
|
28
|
+
export async function formatToolResult(resultPromise) {
|
|
29
|
+
const { steps, requiresPercy, missingDependencies, shouldSkipFormatting } = await resultPromise;
|
|
30
|
+
if (shouldSkipFormatting) {
|
|
31
|
+
return {
|
|
32
|
+
content: steps.map((step) => ({
|
|
33
|
+
type: "text",
|
|
34
|
+
text: step.content,
|
|
35
|
+
})),
|
|
36
|
+
isError: steps.some((s) => s.isError),
|
|
37
|
+
steps,
|
|
38
|
+
requiresPercy,
|
|
39
|
+
missingDependencies,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const combinedInstructions = steps.map((step) => step.content).join("\n");
|
|
43
|
+
const { formattedSteps, stepCount } = formatInstructionsWithNumbers(combinedInstructions);
|
|
44
|
+
const verificationMessage = generateVerificationMessage(stepCount);
|
|
45
|
+
const finalContent = [
|
|
46
|
+
{ type: "text", text: IMPORTANT_SETUP_WARNING },
|
|
47
|
+
{ type: "text", text: formattedSteps },
|
|
48
|
+
{ type: "text", text: verificationMessage },
|
|
49
|
+
];
|
|
50
|
+
return {
|
|
51
|
+
content: finalContent,
|
|
52
|
+
isError: steps.some((s) => s.isError),
|
|
53
|
+
requiresPercy,
|
|
54
|
+
missingDependencies,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export function getPercyAutomateNotImplementedMessage(type, input, supported) {
|
|
58
|
+
if (type === PercyAutomateNotImplementedType.LANGUAGE) {
|
|
59
|
+
return `Percy Automate does not support the language: ${input.detectedLanguage}. Supported languages are: ${supported.join(", ")}.`;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
return `Percy Automate does not support ${input.detectedBrowserAutomationFramework} for ${input.detectedLanguage}. Supported frameworks for ${input.detectedLanguage} are: ${supported.join(", ")}.`;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export function getBootstrapFailedMessage(error, context) {
|
|
66
|
+
return `Failed to bootstrap project with BrowserStack SDK.
|
|
67
|
+
Error: ${error}
|
|
68
|
+
Percy Mode: ${context.percyMode ?? "automate"}
|
|
69
|
+
SDK Version: ${context.sdkVersion ?? "N/A"}
|
|
70
|
+
Please open an issue on GitHub if the problem persists.`;
|
|
71
|
+
}
|
|
72
|
+
export function percyUnsupportedResult(integrationType, supportCheck) {
|
|
73
|
+
const defaultMessage = `Percy ${integrationType} integration is not supported for this configuration.`;
|
|
74
|
+
return {
|
|
75
|
+
content: [
|
|
76
|
+
{
|
|
77
|
+
type: "text",
|
|
78
|
+
text: supportCheck?.errorMessage || defaultMessage,
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
isError: true,
|
|
82
|
+
shouldSkipFormatting: true,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { BrowserStackConfig } from "../../lib/types.js";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
export declare function runTestsOnBrowserStackHandler(rawInput: unknown, config: BrowserStackConfig): Promise<CallToolResult>;
|
|
4
|
+
export declare function setUpPercyHandler(rawInput: unknown, config: BrowserStackConfig): Promise<CallToolResult>;
|
|
5
|
+
export declare function setUpSimulatePercyChangeHandler(rawInput: unknown, config: BrowserStackConfig): Promise<CallToolResult>;
|