Skip to content

Commit b445504

Browse files
authored
Merge pull request #80 from tech-sushant/cont-regression
refactor: improve SDK setup instructions and bootstrap flow for clarity and consistency
2 parents e4cd5b4 + 979f908 commit b445504

File tree

5 files changed

+337
-181
lines changed

5 files changed

+337
-181
lines changed

src/tools/bstack-sdk.ts

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
22
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
33
import { z } from "zod";
4+
import { trackMCP } from "../lib/instrumentation.js";
5+
import { getSDKPrefixCommand } from "./sdk-utils/commands.js";
6+
47
import {
58
SDKSupportedBrowserAutomationFramework,
69
SDKSupportedLanguage,
@@ -9,16 +12,18 @@ import {
912
SDKSupportedBrowserAutomationFrameworkEnum,
1013
SDKSupportedTestingFrameworkEnum,
1114
} from "./sdk-utils/types.js";
15+
1216
import {
1317
generateBrowserStackYMLInstructions,
1418
getInstructionsForProjectConfiguration,
19+
formatInstructionsWithNumbers,
1520
} from "./sdk-utils/instructions.js";
16-
import { trackMCP } from "../lib/instrumentation.js";
21+
1722
import {
1823
formatPercyInstructions,
1924
getPercyInstructions,
2025
} from "./sdk-utils/percy/instructions.js";
21-
import { getSDKPrefixCommand } from "./sdk-utils/commands.js";
26+
2227

2328
/**
2429
* BrowserStack SDK hooks into your test framework to seamlessly run tests on BrowserStack.
@@ -42,33 +47,35 @@ export async function bootstrapProjectWithSDK({
4247
detectedBrowserAutomationFramework === "cypress" ||
4348
detectedTestingFramework === "webdriverio"
4449
) {
45-
let instructions = getInstructionsForProjectConfiguration(
50+
let combinedInstructions = getInstructionsForProjectConfiguration(
4651
detectedBrowserAutomationFramework,
4752
detectedTestingFramework,
4853
detectedLanguage,
4954
);
55+
5056
if (enablePercy) {
5157
const percyInstructions = getPercyInstructions(
5258
detectedLanguage,
5359
detectedBrowserAutomationFramework,
5460
detectedTestingFramework,
5561
);
62+
5663
if (percyInstructions) {
57-
instructions += formatPercyInstructions(percyInstructions);
64+
combinedInstructions +=
65+
"\n\n" + formatPercyInstructions(percyInstructions);
5866
} else {
5967
throw new Error(
6068
`Percy is currently not supported through MCP for ${detectedLanguage} with ${detectedTestingFramework}. If you want to run the test cases without Percy, disable Percy and run it again.`,
6169
);
6270
}
6371
}
64-
return {
65-
content: [{ type: "text", text: instructions, isError: false }],
66-
};
72+
73+
// Apply consistent formatting for all configurations
74+
return formatFinalInstructions(combinedInstructions);
6775
}
6876

69-
let fullInstructions = "";
70-
// Add language-dependent prefix command
71-
fullInstructions += getSDKPrefixCommand(
77+
// Handle default flow using browserstack.yml
78+
const sdkSetupCommand = getSDKPrefixCommand(
7279
detectedLanguage,
7380
detectedTestingFramework,
7481
);
@@ -77,7 +84,6 @@ export async function bootstrapProjectWithSDK({
7784
desiredPlatforms,
7885
enablePercy,
7986
);
80-
fullInstructions += `${ymlInstructions}`;
8187

8288
const instructionsForProjectConfiguration =
8389
getInstructionsForProjectConfiguration(
@@ -86,22 +92,52 @@ export async function bootstrapProjectWithSDK({
8692
detectedLanguage,
8793
);
8894

95+
let combinedInstructions = "";
96+
97+
// Step 1: Add SDK setup command
98+
if (sdkSetupCommand) {
99+
combinedInstructions += sdkSetupCommand;
100+
}
101+
102+
// Step 2: Add browserstack.yml setup
103+
if (ymlInstructions) {
104+
combinedInstructions += "\n\n---STEP---\n" + ymlInstructions;
105+
}
106+
107+
// Step 3: Add language/framework-specific setup
108+
if (instructionsForProjectConfiguration) {
109+
combinedInstructions += "\n\n" + instructionsForProjectConfiguration;
110+
}
111+
112+
// Step 4: Add Percy setup if applicable
89113
if (enablePercy) {
90114
const percyInstructions = getPercyInstructions(
91115
detectedLanguage,
92116
detectedBrowserAutomationFramework,
93117
detectedTestingFramework,
94118
);
119+
95120
if (percyInstructions) {
96-
fullInstructions += formatPercyInstructions(percyInstructions);
121+
combinedInstructions +=
122+
"\n\n" + formatPercyInstructions(percyInstructions);
97123
} else {
98124
throw new Error(
99125
`Percy is currently not supported through MCP for ${detectedLanguage} with ${detectedTestingFramework}. If you want to run the test cases without Percy, disable Percy and run it again.`,
100126
);
101127
}
102128
}
103129

104-
fullInstructions += `\n\nAfter setting up the files above, follow these final steps:\n${instructionsForProjectConfiguration}`;
130+
// Apply consistent formatting for all configurations
131+
return formatFinalInstructions(combinedInstructions);
132+
}
133+
134+
// Helper function to apply consistent formatting to all instruction types
135+
function formatFinalInstructions(combinedInstructions: string): CallToolResult {
136+
const fullInstructions = `⚠️ IMPORTANT: DO NOT SKIP ANY STEP
137+
All the setup steps described in this file MUST be executed regardless of any existing configuration or setup.
138+
This ensures proper BrowserStack SDK setup.
139+
140+
${formatInstructionsWithNumbers(combinedInstructions)}`;
105141

106142
return {
107143
content: [
@@ -124,21 +160,25 @@ export default function addSDKTools(server: McpServer) {
124160
.describe(
125161
"The automation framework configured in the project. Example: 'playwright', 'selenium'",
126162
),
163+
127164
detectedTestingFramework: z
128165
.nativeEnum(SDKSupportedTestingFrameworkEnum)
129166
.describe(
130167
"The testing framework used in the project. Be precise with framework selection Example: 'webdriverio', 'jest', 'pytest', 'junit4', 'junit5', 'mocha'",
131168
),
169+
132170
detectedLanguage: z
133171
.nativeEnum(SDKSupportedLanguageEnum)
134172
.describe(
135173
"The programming language used in the project. Example: 'nodejs', 'python', 'java', 'csharp'",
136174
),
175+
137176
desiredPlatforms: z
138177
.array(z.enum(["windows", "macos", "android", "ios"]))
139178
.describe(
140179
"The platforms the user wants to test on. Always ask this to the user, do not try to infer this.",
141180
),
181+
142182
enablePercy: z
143183
.boolean()
144184
.optional()
@@ -147,16 +187,20 @@ export default function addSDKTools(server: McpServer) {
147187
"Set to true if the user wants to enable Percy for visual testing. Defaults to false.",
148188
),
149189
},
190+
150191
async (args) => {
151192
try {
152193
trackMCP("runTestsOnBrowserStack", server.server.getClientVersion()!);
153194

154195
return await bootstrapProjectWithSDK({
155196
detectedBrowserAutomationFramework:
156197
args.detectedBrowserAutomationFramework as SDKSupportedBrowserAutomationFramework,
198+
157199
detectedTestingFramework:
158200
args.detectedTestingFramework as SDKSupportedTestingFramework,
201+
159202
detectedLanguage: args.detectedLanguage as SDKSupportedLanguage,
203+
160204
desiredPlatforms: args.desiredPlatforms,
161205
enablePercy: args.enablePercy,
162206
});
@@ -166,6 +210,7 @@ export default function addSDKTools(server: McpServer) {
166210
server.server.getClientVersion()!,
167211
error,
168212
);
213+
169214
return {
170215
content: [
171216
{

src/tools/sdk-utils/commands.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,18 @@ export function getSDKPrefixCommand(
2828
): string {
2929
switch (language) {
3030
case "nodejs":
31-
return `Install BrowserStack Node SDK\nusing command | npm i -D browserstack-node-sdk@latest\n| and then run following command to setup browserstack sdk:\n npx setup --username ${process.env.BROWSERSTACK_USERNAME} --key ${process.env.BROWSERSTACK_ACCESS_KEY}\n\n. This will create browserstack.yml file in the project root. Edit the file to add your desired platforms and browsers. If the file is not created :\n`;
31+
return `---STEP---
32+
Install BrowserStack Node SDK using command:
33+
\`\`\`bash
34+
npm i -D browserstack-node-sdk@latest
35+
\`\`\`
36+
---STEP---
37+
Run the following command to setup browserstack sdk:
38+
\`\`\`bash
39+
npx setup --username ${process.env.BROWSERSTACK_USERNAME} --key ${process.env.BROWSERSTACK_ACCESS_KEY}
40+
\`\`\`
41+
---STEP---
42+
Edit the browserstack.yml file that was created in the project root to add your desired platforms and browsers.`;
3243

3344
case "java": {
3445
const mavenFramework = getJavaFrameworkForMaven(framework);
@@ -45,11 +56,14 @@ export function getSDKPrefixCommand(
4556

4657
const platformLabel = isWindows ? "Windows" : "macOS/Linux";
4758

48-
return `Install BrowserStack Java SDK
59+
return `---STEP---
60+
Install BrowserStack Java SDK
4961
5062
**Maven command for ${framework} (${platformLabel}):**
5163
Run the command, it is required to generate the browserstack-sdk-archetype-integrate project:
5264
${mavenCommand}
65+
66+
Alternative setup for Gradle users:
5367
${GRADLE_SETUP_INSTRUCTIONS}`;
5468
}
5569

0 commit comments

Comments
 (0)