@browserstack/mcp-server 1.1.8 → 1.1.9
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 +71 -35
- package/dist/config.js +8 -2
- package/dist/lib/local.js +9 -0
- package/dist/tools/accessiblity-utils/scanner.js +3 -0
- package/dist/tools/appautomate-utils/appautomate.js +68 -7
- package/dist/tools/appautomate-utils/types.js +6 -0
- package/dist/tools/appautomate.js +99 -4
- package/dist/tools/bstack-sdk.js +37 -15
- package/dist/tools/sdk-utils/commands.js +16 -2
- package/dist/tools/sdk-utils/constants.js +204 -141
- package/dist/tools/sdk-utils/instructions.js +21 -1
- package/dist/tools/sdk-utils/percy/constants.js +35 -25
- package/dist/tools/sdk-utils/types.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
</div>
|
|
14
14
|
|
|
15
|
-
<p align="center">
|
|
15
|
+
<p align="center">Comprehensive Test Platform</p>
|
|
16
16
|
|
|
17
17
|
<div align="center">
|
|
18
18
|
<a href="https://glama.ai/mcp/servers/@browserstack/mcp-server">
|
|
@@ -21,26 +21,23 @@
|
|
|
21
21
|
</div>
|
|
22
22
|
|
|
23
23
|
<div>
|
|
24
|
-
<a href="https://www.youtube.com/watch?v=sLA7K9v7qZc">
|
|
24
|
+
<a href="https://www.youtube.com/watch?v=sLA7K9v7qZc&list=PL1vH6dHT3H7oy8w9CY6L_nxGxCc89VXMX&index=5">
|
|
25
25
|
<img src="assets/thumbnail.webp">
|
|
26
26
|
</a>
|
|
27
27
|
</div>
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
<p align="center">
|
|
35
|
-
<img src="assets/overview.png" alt="overview">
|
|
36
|
-
</p>
|
|
29
|
+
Manage test cases, execute manual or automated tests, debug issues, and even fix code—directly within tools like Cursor, Claude, or any MCP-enabled client, using plain English.
|
|
30
|
+
#### Test from anywhere:
|
|
31
|
+
Easily connect the BrowserStack Test Platform to your favourite AI tools, such as IDEs, LLMs, or agentic workflows.
|
|
32
|
+
#### Reduced context switching:
|
|
33
|
+
Stay in flow—keep all project context in one place and trigger actions directly from your IDE or LLM.
|
|
37
34
|
|
|
38
35
|
## 💡 Usage Examples
|
|
39
36
|
|
|
40
37
|
### 📱 Manual App Testing
|
|
41
38
|
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
Test mobile apps on real devices across the latest OS versions. Reproduce bugs and debug crashes without setup hassles.
|
|
40
|
+
Below are some sample prompts to use your mobile apps on BrowserStack's extensive cloud of real devices
|
|
44
41
|
```bash
|
|
45
42
|
# Open app on specific device
|
|
46
43
|
"open my app on a iPhone 15 Pro Max"
|
|
@@ -49,7 +46,6 @@ Use the following prompts to use your **mobile apps** on BrowserStack's extensiv
|
|
|
49
46
|
"My app crashed on Android 14 device, can you help me debug?"
|
|
50
47
|
```
|
|
51
48
|
|
|
52
|
-
|
|
53
49
|
- Unlike emulators, test your app's real-world performance on actual devices. With advanced [App-Profiling features](https://www.browserstack.com/docs/app-live/app-performance-testing), you can debug crashes and performance issues in real-time.
|
|
54
50
|
- Access all major devices and OS versions from our [device grid](https://www.browserstack.com/list-of-browsers-and-platforms/app_live), We have strict SLAs to provision our global datacenters with newly released devices on [launch day](https://www.browserstack.com/blog/browserstack-launches-iphone-15-on-day-0-behind-the-scenes/).
|
|
55
51
|
|
|
@@ -58,8 +54,9 @@ Use the following prompts to use your **mobile apps** on BrowserStack's extensiv
|
|
|
58
54
|
Similar to the app testing, you can use the following prompts to test your **websites** on BrowserStack's extensive cloud of real browsers and devices. Don't have Edge browser installed on your machine ? We've got you covered!
|
|
59
55
|
|
|
60
56
|
```bash
|
|
61
|
-
# Test your
|
|
57
|
+
# Test your websites
|
|
62
58
|
"open my website hosted on localhost:3001 on Edge"
|
|
59
|
+
"open browserstack.com on latest version of Chrome"
|
|
63
60
|
```
|
|
64
61
|
|
|
65
62
|
- Test websites across different browsers and devices. We support [every major browser](https://www.browserstack.com/list-of-browsers-and-platforms/live) across every major OS.
|
|
@@ -67,27 +64,39 @@ Similar to the app testing, you can use the following prompts to test your **web
|
|
|
67
64
|
|
|
68
65
|
### 🧪 Automated Testing (Playwright, Selenium, A11y and more..)
|
|
69
66
|
|
|
70
|
-
|
|
67
|
+
Auto-analyze, diagnose, and even fix broken test scripts right in your IDE or LLM. Instantly fetch logs, identify root causes, and apply context-aware fixes. No more debugging loops.
|
|
68
|
+
Below are few example prompts to run/debug/fix your automated tests on BrowserStack's [Test Platform](https://www.browserstack.com/test-platform).
|
|
71
69
|
|
|
72
70
|
```bash
|
|
73
|
-
#
|
|
74
|
-
"
|
|
71
|
+
#Port test suite to BrowserStack
|
|
72
|
+
"Setup test suite to run on BrowserStack infra"
|
|
75
73
|
|
|
76
|
-
#
|
|
77
|
-
|
|
74
|
+
#Run tests on BrowserStack
|
|
75
|
+
“Run my tests on BrowserStack”
|
|
78
76
|
|
|
79
|
-
#
|
|
80
|
-
"
|
|
81
|
-
```
|
|
77
|
+
#AI powered debugging of test failures
|
|
78
|
+
"My App Automate tests have failed, can you help me fix the new failures?"
|
|
82
79
|
|
|
80
|
+
```
|
|
83
81
|
- Fix test failures reported by your CI/CD pipeline by utilising our industry leading [Test Observability](https://www.browserstack.com/docs/test-observability) features. Find more info [here](https://www.browserstack.com/docs/test-observability/features/smart-tags).
|
|
84
82
|
- Run tests written in Jest, Playwright, Selenium, and more on BrowserStack's [Test Platform](https://www.browserstack.com/test-platform)
|
|
85
|
-
- **Accessibility Testing**: Ensure WCAG and ADA compliance with our [Accessibility Testing](https://www.browserstack.com/accessibility-testing) tool
|
|
86
83
|
|
|
84
|
+
### 🌐 Accessibility
|
|
85
|
+
|
|
86
|
+
Catch accessibility issues early with automated, local a11y scans. Get one-click, AI-suggested fixes. No docs hunting, no CI surprises. Ensure WCAG and ADA compliance with our Accessibility Testing tool
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
#Scan accessibility issues while development
|
|
90
|
+
"Scan & help fix accessibility issues for my website running locally on localhost:3000"
|
|
91
|
+
|
|
92
|
+
#Scan accessibility issues on production site
|
|
93
|
+
“Run accessibility scan & identify issues on my website - www.bstackdemo.com”
|
|
94
|
+
|
|
95
|
+
```
|
|
87
96
|
|
|
88
97
|
### 📋 Test Management
|
|
89
98
|
|
|
90
|
-
|
|
99
|
+
Create and manage test cases, create test plans and trigger test runs using natural language. Below are a few example prompts to utilise capabilities of BrowserStack's [Test Management](https://www.browserstack.com/test-management) with MCP server.
|
|
91
100
|
|
|
92
101
|
```bash
|
|
93
102
|
# Create project & folder structure
|
|
@@ -106,6 +115,24 @@ Use the following prompts to utilise capabilities of BrowserStack's [Test Manage
|
|
|
106
115
|
"update test results as passed for Login tests test run from My Demo Project"
|
|
107
116
|
```
|
|
108
117
|
|
|
118
|
+
### 🧪 Access BrowserStack AI agnets
|
|
119
|
+
|
|
120
|
+
Generate test cases from PRDs, convert manual tests to low-code automation, and auto-heal flaky scripts powered by BrowserStack’s AI agents, seamlessly integrated into your workflow. Below are few example prompts to access Browserstack AI agents
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
#Test case generator agent
|
|
124
|
+
"With Browserstack AI, create relevant test cases for my PRD located at /usr/file/location"
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
#Low code authoring agent
|
|
128
|
+
“With Browserstack AI, automate my manual test case X, added in Test Management”
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
#Self healing agent
|
|
132
|
+
“Help fix flaky tests in my test script with Browserstack AI self healing”
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
|
|
109
136
|
## 🛠️ Installation
|
|
110
137
|
|
|
111
138
|
1. **Create a BrowserStack Account**
|
|
@@ -113,9 +140,7 @@ Use the following prompts to utilise capabilities of BrowserStack's [Test Manage
|
|
|
113
140
|
- Sign up for [BrowserStack](https://www.browserstack.com/users/sign_up) if you don't have an account already.
|
|
114
141
|
|
|
115
142
|
- ℹ️ If you have an open-source project, we'll be able to provide you with a [free plan](https://www.browserstack.com/open-source).
|
|
116
|
-
|
|
117
|
-
<img src="assets/open-source-plan.png" alt="Open Source Plan">
|
|
118
|
-
</div>
|
|
143
|
+
|
|
119
144
|
|
|
120
145
|
- Once you have an account (and purchased appropriate plan), note down your `username` and `access_key` from [Account Settings](https://www.browserstack.com/accounts/profile/details).
|
|
121
146
|
|
|
@@ -175,6 +200,25 @@ Use the following prompts to utilise capabilities of BrowserStack's [Test Manage
|
|
|
175
200
|
}
|
|
176
201
|
}
|
|
177
202
|
```
|
|
203
|
+
- Cline
|
|
204
|
+
|
|
205
|
+
Click the “MCP Servers” icon in the navigation bar
|
|
206
|
+
Select the “Installed” tab. Click the “Configure MCP Servers” button at the bottom of the pane.
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"mcpServers": {
|
|
211
|
+
"browserstack": {
|
|
212
|
+
"command": "npx",
|
|
213
|
+
"args": ["-y", "@browserstack/mcp-server@latest"],
|
|
214
|
+
"env": {
|
|
215
|
+
"BROWSERSTACK_USERNAME": "<username>",
|
|
216
|
+
"BROWSERSTACK_ACCESS_KEY": "<access_key>"
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
178
222
|
|
|
179
223
|
### Installing via Smithery
|
|
180
224
|
|
|
@@ -203,17 +247,9 @@ We welcome contributions! Please open an issue to discuss any changes you'd like
|
|
|
203
247
|
|
|
204
248
|
For support, please:
|
|
205
249
|
|
|
206
|
-
- Check our [documentation](https://www.browserstack.com/docs)
|
|
207
250
|
- Open an issue in our [GitHub repository](https://github.com/browserstack/mcp-server) if you face any issues related to the MCP Server.
|
|
208
251
|
- Contact our [support team](https://www.browserstack.com/contact) for any other queries.
|
|
209
252
|
|
|
210
253
|
## 🚀 More Features Coming Soon
|
|
211
254
|
|
|
212
255
|
Stay tuned for exciting updates! Have any suggestions? Please open an issue to discuss.
|
|
213
|
-
|
|
214
|
-
## 🔗 Resources
|
|
215
|
-
|
|
216
|
-
- [BrowserStack Test Platform](https://www.browserstack.com/test-platform)
|
|
217
|
-
- [MCP Protocol Documentation](https://modelcontextprotocol.io)
|
|
218
|
-
- [Device Grid](https://www.browserstack.com/list-of-browsers-and-platforms/app_live)
|
|
219
|
-
- [Accessibility Testing](https://www.browserstack.com/accessibility-testing)
|
package/dist/config.js
CHANGED
|
@@ -28,17 +28,23 @@ for (const key of BROWSERSTACK_LOCAL_OPTION_KEYS) {
|
|
|
28
28
|
browserstackLocalOptions[key] = envVar;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* USE_OWN_LOCAL_BINARY_PROCESS:
|
|
33
|
+
* If true, the system will not start a new local binary process, but will use the user's own process.
|
|
34
|
+
*/
|
|
31
35
|
export class Config {
|
|
32
36
|
browserstackUsername;
|
|
33
37
|
browserstackAccessKey;
|
|
34
38
|
DEV_MODE;
|
|
35
39
|
browserstackLocalOptions;
|
|
36
|
-
|
|
40
|
+
USE_OWN_LOCAL_BINARY_PROCESS;
|
|
41
|
+
constructor(browserstackUsername, browserstackAccessKey, DEV_MODE, browserstackLocalOptions, USE_OWN_LOCAL_BINARY_PROCESS) {
|
|
37
42
|
this.browserstackUsername = browserstackUsername;
|
|
38
43
|
this.browserstackAccessKey = browserstackAccessKey;
|
|
39
44
|
this.DEV_MODE = DEV_MODE;
|
|
40
45
|
this.browserstackLocalOptions = browserstackLocalOptions;
|
|
46
|
+
this.USE_OWN_LOCAL_BINARY_PROCESS = USE_OWN_LOCAL_BINARY_PROCESS;
|
|
41
47
|
}
|
|
42
48
|
}
|
|
43
|
-
const config = new Config(process.env.BROWSERSTACK_USERNAME, process.env.BROWSERSTACK_ACCESS_KEY, process.env.DEV_MODE === "true", browserstackLocalOptions);
|
|
49
|
+
const config = new Config(process.env.BROWSERSTACK_USERNAME, process.env.BROWSERSTACK_ACCESS_KEY, process.env.DEV_MODE === "true", browserstackLocalOptions, process.env.USE_OWN_LOCAL_BINARY_PROCESS === "true");
|
|
44
50
|
export default config;
|
package/dist/lib/local.js
CHANGED
|
@@ -67,6 +67,15 @@ export async function killExistingBrowserStackLocalProcesses() {
|
|
|
67
67
|
}
|
|
68
68
|
export async function ensureLocalBinarySetup(localIdentifier) {
|
|
69
69
|
logger.info("Ensuring local binary setup as it is required for private URLs...");
|
|
70
|
+
if (config.USE_OWN_LOCAL_BINARY_PROCESS) {
|
|
71
|
+
logger.info("Using user's own BrowserStack Local binary process, checking if it's running...");
|
|
72
|
+
const isRunning = await isBrowserStackLocalRunning();
|
|
73
|
+
if (!isRunning) {
|
|
74
|
+
throw new Error("USE_OWN_LOCAL_BINARY_PROCESS is enabled but BrowserStack Local process is not running. Please start your BrowserStack Local binary process first.");
|
|
75
|
+
}
|
|
76
|
+
logger.info("BrowserStack Local process is running, proceeding with user's own process.");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
70
79
|
const localBinary = new Local();
|
|
71
80
|
await killExistingBrowserStackLocalProcesses();
|
|
72
81
|
// Use a single options object from config and extend with required fields
|
|
@@ -13,6 +13,9 @@ export class AccessibilityScanner {
|
|
|
13
13
|
const localIdentifier = crypto.randomUUID();
|
|
14
14
|
const localHosts = new Set(["127.0.0.1", "localhost", "0.0.0.0"]);
|
|
15
15
|
const BS_LOCAL_DOMAIN = "bs-local.com";
|
|
16
|
+
if (config.USE_OWN_LOCAL_BINARY_PROCESS && hasLocal) {
|
|
17
|
+
throw new Error("Cannot start scan with local URLs when using own BrowserStack Local binary process. Please set USE_OWN_LOCAL_BINARY_PROCESS to false.");
|
|
18
|
+
}
|
|
16
19
|
if (hasLocal) {
|
|
17
20
|
await ensureLocalBinarySetup(localIdentifier);
|
|
18
21
|
}
|
|
@@ -3,6 +3,10 @@ import axios from "axios";
|
|
|
3
3
|
import config from "../../config.js";
|
|
4
4
|
import FormData from "form-data";
|
|
5
5
|
import { customFuzzySearch } from "../../lib/fuzzy.js";
|
|
6
|
+
const auth = {
|
|
7
|
+
username: config.browserstackUsername,
|
|
8
|
+
password: config.browserstackAccessKey,
|
|
9
|
+
};
|
|
6
10
|
/**
|
|
7
11
|
* Finds devices that exactly match the provided display name.
|
|
8
12
|
* Uses fuzzy search first, and then filters for exact case-insensitive match.
|
|
@@ -78,13 +82,8 @@ export async function uploadApp(appPath) {
|
|
|
78
82
|
const formData = new FormData();
|
|
79
83
|
formData.append("file", fs.createReadStream(filePath));
|
|
80
84
|
const response = await axios.post("https://api-cloud.browserstack.com/app-automate/upload", formData, {
|
|
81
|
-
headers:
|
|
82
|
-
|
|
83
|
-
},
|
|
84
|
-
auth: {
|
|
85
|
-
username: config.browserstackUsername,
|
|
86
|
-
password: config.browserstackAccessKey,
|
|
87
|
-
},
|
|
85
|
+
headers: formData.getHeaders(),
|
|
86
|
+
auth,
|
|
88
87
|
});
|
|
89
88
|
if (response.data.app_url) {
|
|
90
89
|
return response.data.app_url;
|
|
@@ -93,3 +92,65 @@ export async function uploadApp(appPath) {
|
|
|
93
92
|
throw new Error(`Failed to upload app: ${response.data}`);
|
|
94
93
|
}
|
|
95
94
|
}
|
|
95
|
+
// Helper to upload a file to a given BrowserStack endpoint and return a specific property from the response.
|
|
96
|
+
async function uploadFileToBrowserStack(filePath, endpoint, responseKey) {
|
|
97
|
+
if (!fs.existsSync(filePath)) {
|
|
98
|
+
throw new Error(`File not found at path: ${filePath}`);
|
|
99
|
+
}
|
|
100
|
+
const formData = new FormData();
|
|
101
|
+
formData.append("file", fs.createReadStream(filePath));
|
|
102
|
+
const response = await axios.post(endpoint, formData, {
|
|
103
|
+
headers: formData.getHeaders(),
|
|
104
|
+
auth,
|
|
105
|
+
});
|
|
106
|
+
if (response.data[responseKey]) {
|
|
107
|
+
return response.data[responseKey];
|
|
108
|
+
}
|
|
109
|
+
throw new Error(`Failed to upload file: ${JSON.stringify(response.data)}`);
|
|
110
|
+
}
|
|
111
|
+
//Uploads an Android app (.apk or .aab) to BrowserStack Espresso endpoint and returns the app_url
|
|
112
|
+
export async function uploadEspressoApp(appPath) {
|
|
113
|
+
return uploadFileToBrowserStack(appPath, "https://api-cloud.browserstack.com/app-automate/espresso/v2/app", "app_url");
|
|
114
|
+
}
|
|
115
|
+
//Uploads an Espresso test suite (.apk) to BrowserStack and returns the test_suite_url
|
|
116
|
+
export async function uploadEspressoTestSuite(testSuitePath) {
|
|
117
|
+
return uploadFileToBrowserStack(testSuitePath, "https://api-cloud.browserstack.com/app-automate/espresso/v2/test-suite", "test_suite_url");
|
|
118
|
+
}
|
|
119
|
+
//Uploads an iOS app (.ipa) to BrowserStack XCUITest endpoint and returns the app_url
|
|
120
|
+
export async function uploadXcuiApp(appPath) {
|
|
121
|
+
return uploadFileToBrowserStack(appPath, "https://api-cloud.browserstack.com/app-automate/xcuitest/v2/app", "app_url");
|
|
122
|
+
}
|
|
123
|
+
//Uploads an XCUITest test suite (.zip) to BrowserStack and returns the test_suite_url
|
|
124
|
+
export async function uploadXcuiTestSuite(testSuitePath) {
|
|
125
|
+
return uploadFileToBrowserStack(testSuitePath, "https://api-cloud.browserstack.com/app-automate/xcuitest/v2/test-suite", "test_suite_url");
|
|
126
|
+
}
|
|
127
|
+
// Triggers an Espresso test run on BrowserStack and returns the build_id
|
|
128
|
+
export async function triggerEspressoBuild(app_url, test_suite_url, devices, project) {
|
|
129
|
+
const response = await axios.post("https://api-cloud.browserstack.com/app-automate/espresso/v2/build", {
|
|
130
|
+
app: app_url,
|
|
131
|
+
testSuite: test_suite_url,
|
|
132
|
+
devices,
|
|
133
|
+
project,
|
|
134
|
+
}, {
|
|
135
|
+
auth,
|
|
136
|
+
});
|
|
137
|
+
if (response.data.build_id) {
|
|
138
|
+
return response.data.build_id;
|
|
139
|
+
}
|
|
140
|
+
throw new Error(`Failed to trigger Espresso build: ${JSON.stringify(response.data)}`);
|
|
141
|
+
}
|
|
142
|
+
// Triggers an XCUITest run on BrowserStack and returns the build_id
|
|
143
|
+
export async function triggerXcuiBuild(app_url, test_suite_url, devices, project) {
|
|
144
|
+
const response = await axios.post("https://api-cloud.browserstack.com/app-automate/xcuitest/v2/build", {
|
|
145
|
+
app: app_url,
|
|
146
|
+
testSuite: test_suite_url,
|
|
147
|
+
devices,
|
|
148
|
+
project,
|
|
149
|
+
}, {
|
|
150
|
+
auth,
|
|
151
|
+
});
|
|
152
|
+
if (response.data.build_id) {
|
|
153
|
+
return response.data.build_id;
|
|
154
|
+
}
|
|
155
|
+
throw new Error(`Failed to trigger XCUITest build: ${JSON.stringify(response.data)}`);
|
|
156
|
+
}
|
|
@@ -4,8 +4,9 @@ import config from "../config.js";
|
|
|
4
4
|
import { trackMCP } from "../lib/instrumentation.js";
|
|
5
5
|
import { maybeCompressBase64 } from "../lib/utils.js";
|
|
6
6
|
import { remote } from "webdriverio";
|
|
7
|
+
import { AppTestPlatform } from "./appautomate-utils/types.js";
|
|
7
8
|
import { getDevicesAndBrowsers, BrowserStackProducts, } from "../lib/device-cache.js";
|
|
8
|
-
import { findMatchingDevice, getDeviceVersions, resolveVersion, validateArgs, uploadApp, } from "./appautomate-utils/appautomate.js";
|
|
9
|
+
import { findMatchingDevice, getDeviceVersions, resolveVersion, validateArgs, uploadApp, uploadEspressoApp, uploadEspressoTestSuite, triggerEspressoBuild, uploadXcuiApp, uploadXcuiTestSuite, triggerXcuiBuild, } from "./appautomate-utils/appautomate.js";
|
|
9
10
|
var Platform;
|
|
10
11
|
(function (Platform) {
|
|
11
12
|
Platform["ANDROID"] = "android";
|
|
@@ -84,9 +85,52 @@ async function takeAppScreenshot(args) {
|
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
//Runs AppAutomate tests on BrowserStack by uploading app and test suite, then triggering a test run.
|
|
89
|
+
async function runAppTestsOnBrowserStack(args) {
|
|
90
|
+
switch (args.detectedAutomationFramework) {
|
|
91
|
+
case AppTestPlatform.ESPRESSO: {
|
|
92
|
+
try {
|
|
93
|
+
const app_url = await uploadEspressoApp(args.appPath);
|
|
94
|
+
const test_suite_url = await uploadEspressoTestSuite(args.testSuitePath);
|
|
95
|
+
const build_id = await triggerEspressoBuild(app_url, test_suite_url, args.devices, args.project);
|
|
96
|
+
return {
|
|
97
|
+
content: [
|
|
98
|
+
{
|
|
99
|
+
type: "text",
|
|
100
|
+
text: `✅ Espresso run started successfully!\n\n🔧 Build ID: ${build_id}\n🔗 View your build: https://app-automate.browserstack.com/builds/${build_id}`,
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
logger.error("Error running App Automate test", err);
|
|
107
|
+
throw err;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
case AppTestPlatform.XCUITEST: {
|
|
111
|
+
try {
|
|
112
|
+
const app_url = await uploadXcuiApp(args.appPath);
|
|
113
|
+
const test_suite_url = await uploadXcuiTestSuite(args.testSuitePath);
|
|
114
|
+
const build_id = await triggerXcuiBuild(app_url, test_suite_url, args.devices, args.project);
|
|
115
|
+
return {
|
|
116
|
+
content: [
|
|
117
|
+
{
|
|
118
|
+
type: "text",
|
|
119
|
+
text: `✅ XCUITest run started successfully!\n\n🔧 Build ID: ${build_id}\n🔗 View your build: https://app-automate.browserstack.com/builds/${build_id}`,
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
logger.error("Error running XCUITest App Automate test", err);
|
|
126
|
+
throw err;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
default:
|
|
130
|
+
throw new Error(`Unsupported automation framework: ${args.detectedAutomationFramework}. If you need support for this framework, please open an issue at Github`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Registers automation tools with the MCP server.
|
|
90
134
|
export default function addAppAutomationTools(server) {
|
|
91
135
|
server.tool("takeAppScreenshot", "Use this tool to take a screenshot of an app running on a BrowserStack device. This is useful for visual testing and debugging.", {
|
|
92
136
|
desiredPhone: z
|
|
@@ -119,4 +163,55 @@ export default function addAppAutomationTools(server) {
|
|
|
119
163
|
};
|
|
120
164
|
}
|
|
121
165
|
});
|
|
166
|
+
server.tool("runAppTestsOnBrowserStack", "Run AppAutomate tests on BrowserStack by uploading app and test suite. If running from Android Studio or Xcode, the tool will help export app and test files automatically. For other environments, you'll need to provide the paths to your pre-built app and test files.", {
|
|
167
|
+
appPath: z
|
|
168
|
+
.string()
|
|
169
|
+
.describe("Path to your application file:\n" +
|
|
170
|
+
"If in development IDE directory:\n" +
|
|
171
|
+
"• For Android: 'gradle assembleDebug'\n" +
|
|
172
|
+
"• For iOS:\n" +
|
|
173
|
+
" xcodebuild clean -scheme YOUR_SCHEME && \\\n" +
|
|
174
|
+
" xcodebuild archive -scheme YOUR_SCHEME -configuration Release -archivePath build/app.xcarchive && \\\n" +
|
|
175
|
+
" xcodebuild -exportArchive -archivePath build/app.xcarchive -exportPath build/ipa -exportOptionsPlist exportOptions.plist\n\n" +
|
|
176
|
+
"If in other directory, provide existing app path"),
|
|
177
|
+
testSuitePath: z
|
|
178
|
+
.string()
|
|
179
|
+
.describe("Path to your test suite file:\n" +
|
|
180
|
+
"If in development IDE directory:\n" +
|
|
181
|
+
"• For Android: 'gradle assembleAndroidTest'\n" +
|
|
182
|
+
"• For iOS:\n" +
|
|
183
|
+
" xcodebuild test-without-building -scheme YOUR_SCHEME -destination 'generic/platform=iOS' && \\\n" +
|
|
184
|
+
" cd ~/Library/Developer/Xcode/DerivedData/*/Build/Products/Debug-iphonesimulator/ && \\\n" +
|
|
185
|
+
" zip -r Tests.zip *.xctestrun *-Runner.app\n\n" +
|
|
186
|
+
"If in other directory, provide existing test file path"),
|
|
187
|
+
devices: z
|
|
188
|
+
.array(z.string())
|
|
189
|
+
.describe("List of devices to run the test on, e.g., ['Samsung Galaxy S20-10.0', 'iPhone 12 Pro-16.0']."),
|
|
190
|
+
project: z
|
|
191
|
+
.string()
|
|
192
|
+
.optional()
|
|
193
|
+
.default("BStack-AppAutomate-Suite")
|
|
194
|
+
.describe("Project name for organizing test runs on BrowserStack."),
|
|
195
|
+
detectedAutomationFramework: z
|
|
196
|
+
.string()
|
|
197
|
+
.describe("The automation framework used in the project, such as 'espresso' (Android) or 'xcuitest' (iOS)."),
|
|
198
|
+
}, async (args) => {
|
|
199
|
+
try {
|
|
200
|
+
trackMCP("runAppTestsOnBrowserStack", server.server.getClientVersion());
|
|
201
|
+
return await runAppTestsOnBrowserStack(args);
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
trackMCP("runAppTestsOnBrowserStack", server.server.getClientVersion(), error);
|
|
205
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
206
|
+
return {
|
|
207
|
+
content: [
|
|
208
|
+
{
|
|
209
|
+
type: "text",
|
|
210
|
+
text: `Error running App Automate test: ${errorMessage}`,
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
isError: true,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
});
|
|
122
217
|
}
|
package/dist/tools/bstack-sdk.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { SDKSupportedLanguageEnum, SDKSupportedBrowserAutomationFrameworkEnum, SDKSupportedTestingFrameworkEnum, } from "./sdk-utils/types.js";
|
|
3
|
-
import { generateBrowserStackYMLInstructions, getInstructionsForProjectConfiguration, } from "./sdk-utils/instructions.js";
|
|
4
2
|
import { trackMCP } from "../lib/instrumentation.js";
|
|
5
|
-
import { formatPercyInstructions, getPercyInstructions, } from "./sdk-utils/percy/instructions.js";
|
|
6
3
|
import { getSDKPrefixCommand } from "./sdk-utils/commands.js";
|
|
4
|
+
import { SDKSupportedLanguageEnum, SDKSupportedBrowserAutomationFrameworkEnum, SDKSupportedTestingFrameworkEnum, } from "./sdk-utils/types.js";
|
|
5
|
+
import { generateBrowserStackYMLInstructions, getInstructionsForProjectConfiguration, formatInstructionsWithNumbers, } from "./sdk-utils/instructions.js";
|
|
6
|
+
import { formatPercyInstructions, getPercyInstructions, } from "./sdk-utils/percy/instructions.js";
|
|
7
7
|
/**
|
|
8
8
|
* BrowserStack SDK hooks into your test framework to seamlessly run tests on BrowserStack.
|
|
9
9
|
* This tool gives instructions to setup a browserstack.yml file in the project root and installs the necessary dependencies.
|
|
@@ -12,36 +12,58 @@ export async function bootstrapProjectWithSDK({ detectedBrowserAutomationFramewo
|
|
|
12
12
|
// Handle frameworks with unique setup instructions that don't use browserstack.yml
|
|
13
13
|
if (detectedBrowserAutomationFramework === "cypress" ||
|
|
14
14
|
detectedTestingFramework === "webdriverio") {
|
|
15
|
-
let
|
|
15
|
+
let combinedInstructions = getInstructionsForProjectConfiguration(detectedBrowserAutomationFramework, detectedTestingFramework, detectedLanguage);
|
|
16
16
|
if (enablePercy) {
|
|
17
17
|
const percyInstructions = getPercyInstructions(detectedLanguage, detectedBrowserAutomationFramework, detectedTestingFramework);
|
|
18
18
|
if (percyInstructions) {
|
|
19
|
-
|
|
19
|
+
combinedInstructions +=
|
|
20
|
+
"\n\n" + formatPercyInstructions(percyInstructions);
|
|
20
21
|
}
|
|
21
22
|
else {
|
|
22
23
|
throw new Error(`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.`);
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
};
|
|
26
|
+
// Apply consistent formatting for all configurations
|
|
27
|
+
return formatFinalInstructions(combinedInstructions);
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
fullInstructions += getSDKPrefixCommand(detectedLanguage, detectedTestingFramework);
|
|
29
|
+
// Handle default flow using browserstack.yml
|
|
30
|
+
const sdkSetupCommand = getSDKPrefixCommand(detectedLanguage, detectedTestingFramework);
|
|
32
31
|
const ymlInstructions = generateBrowserStackYMLInstructions(desiredPlatforms, enablePercy);
|
|
33
|
-
fullInstructions += `${ymlInstructions}`;
|
|
34
32
|
const instructionsForProjectConfiguration = getInstructionsForProjectConfiguration(detectedBrowserAutomationFramework, detectedTestingFramework, detectedLanguage);
|
|
33
|
+
let combinedInstructions = "";
|
|
34
|
+
// Step 1: Add SDK setup command
|
|
35
|
+
if (sdkSetupCommand) {
|
|
36
|
+
combinedInstructions += sdkSetupCommand;
|
|
37
|
+
}
|
|
38
|
+
// Step 2: Add browserstack.yml setup
|
|
39
|
+
if (ymlInstructions) {
|
|
40
|
+
combinedInstructions += "\n\n---STEP---\n" + ymlInstructions;
|
|
41
|
+
}
|
|
42
|
+
// Step 3: Add language/framework-specific setup
|
|
43
|
+
if (instructionsForProjectConfiguration) {
|
|
44
|
+
combinedInstructions += "\n\n" + instructionsForProjectConfiguration;
|
|
45
|
+
}
|
|
46
|
+
// Step 4: Add Percy setup if applicable
|
|
35
47
|
if (enablePercy) {
|
|
36
48
|
const percyInstructions = getPercyInstructions(detectedLanguage, detectedBrowserAutomationFramework, detectedTestingFramework);
|
|
37
49
|
if (percyInstructions) {
|
|
38
|
-
|
|
50
|
+
combinedInstructions +=
|
|
51
|
+
"\n\n" + formatPercyInstructions(percyInstructions);
|
|
39
52
|
}
|
|
40
53
|
else {
|
|
41
54
|
throw new Error(`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.`);
|
|
42
55
|
}
|
|
43
56
|
}
|
|
44
|
-
|
|
57
|
+
// Apply consistent formatting for all configurations
|
|
58
|
+
return formatFinalInstructions(combinedInstructions);
|
|
59
|
+
}
|
|
60
|
+
// Helper function to apply consistent formatting to all instruction types
|
|
61
|
+
function formatFinalInstructions(combinedInstructions) {
|
|
62
|
+
const fullInstructions = `⚠️ IMPORTANT: DO NOT SKIP ANY STEP
|
|
63
|
+
All the setup steps described in this file MUST be executed regardless of any existing configuration or setup.
|
|
64
|
+
This ensures proper BrowserStack SDK setup.
|
|
65
|
+
|
|
66
|
+
${formatInstructionsWithNumbers(combinedInstructions)}`;
|
|
45
67
|
return {
|
|
46
68
|
content: [
|
|
47
69
|
{
|
|
@@ -53,7 +75,7 @@ export async function bootstrapProjectWithSDK({ detectedBrowserAutomationFramewo
|
|
|
53
75
|
};
|
|
54
76
|
}
|
|
55
77
|
export default function addSDKTools(server) {
|
|
56
|
-
server.tool("runTestsOnBrowserStack", "Use this tool to get instructions for running tests on BrowserStack and
|
|
78
|
+
server.tool("runTestsOnBrowserStack", "Use this tool to get instructions for running tests on BrowserStack and BrowserStack Percy. It sets up the BrowserStack SDK and runs your test cases on BrowserStack.", {
|
|
57
79
|
detectedBrowserAutomationFramework: z
|
|
58
80
|
.nativeEnum(SDKSupportedBrowserAutomationFrameworkEnum)
|
|
59
81
|
.describe("The automation framework configured in the project. Example: 'playwright', 'selenium'"),
|
|
@@ -20,7 +20,18 @@ const GRADLE_SETUP_INSTRUCTIONS = `
|
|
|
20
20
|
export function getSDKPrefixCommand(language, framework) {
|
|
21
21
|
switch (language) {
|
|
22
22
|
case "nodejs":
|
|
23
|
-
return
|
|
23
|
+
return `---STEP---
|
|
24
|
+
Install BrowserStack Node SDK using command:
|
|
25
|
+
\`\`\`bash
|
|
26
|
+
npm i -D browserstack-node-sdk@latest
|
|
27
|
+
\`\`\`
|
|
28
|
+
---STEP---
|
|
29
|
+
Run the following command to setup browserstack sdk:
|
|
30
|
+
\`\`\`bash
|
|
31
|
+
npx setup --username ${process.env.BROWSERSTACK_USERNAME} --key ${process.env.BROWSERSTACK_ACCESS_KEY}
|
|
32
|
+
\`\`\`
|
|
33
|
+
---STEP---
|
|
34
|
+
Edit the browserstack.yml file that was created in the project root to add your desired platforms and browsers.`;
|
|
24
35
|
case "java": {
|
|
25
36
|
const mavenFramework = getJavaFrameworkForMaven(framework);
|
|
26
37
|
const isWindows = process.platform === "win32";
|
|
@@ -33,11 +44,14 @@ export function getSDKPrefixCommand(language, framework) {
|
|
|
33
44
|
-DBROWSERSTACK_ACCESS_KEY="${process.env.BROWSERSTACK_ACCESS_KEY}" \\
|
|
34
45
|
-DBROWSERSTACK_FRAMEWORK="${mavenFramework}"`;
|
|
35
46
|
const platformLabel = isWindows ? "Windows" : "macOS/Linux";
|
|
36
|
-
return
|
|
47
|
+
return `---STEP---
|
|
48
|
+
Install BrowserStack Java SDK
|
|
37
49
|
|
|
38
50
|
**Maven command for ${framework} (${platformLabel}):**
|
|
39
51
|
Run the command, it is required to generate the browserstack-sdk-archetype-integrate project:
|
|
40
52
|
${mavenCommand}
|
|
53
|
+
|
|
54
|
+
Alternative setup for Gradle users:
|
|
41
55
|
${GRADLE_SETUP_INSTRUCTIONS}`;
|
|
42
56
|
}
|
|
43
57
|
// Add more languages as needed
|
|
@@ -3,33 +3,45 @@ import config from "../../config.js";
|
|
|
3
3
|
* ---------- PYTHON INSTRUCTIONS ----------
|
|
4
4
|
*/
|
|
5
5
|
const pythonInstructions = `
|
|
6
|
-
|
|
6
|
+
---STEP---
|
|
7
|
+
|
|
8
|
+
Install the BrowserStack SDK:
|
|
7
9
|
\`\`\`bash
|
|
8
10
|
python3 -m pip install browserstack-sdk
|
|
9
11
|
\`\`\`
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
---STEP---
|
|
14
|
+
|
|
15
|
+
Setup the BrowserStack SDK with your credentials:
|
|
12
16
|
\`\`\`bash
|
|
13
17
|
browserstack-sdk setup --username "${config.browserstackUsername}" --key "${config.browserstackAccessKey}"
|
|
14
18
|
\`\`\`
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
---STEP---
|
|
21
|
+
|
|
22
|
+
Run your tests on BrowserStack:
|
|
17
23
|
\`\`\`bash
|
|
18
24
|
browserstack-sdk python <path-to-test-file>
|
|
19
25
|
\`\`\`
|
|
20
26
|
`;
|
|
21
27
|
const generatePythonFrameworkInstructions = (framework) => `
|
|
22
|
-
|
|
28
|
+
---STEP---
|
|
29
|
+
|
|
30
|
+
Install the BrowserStack SDK:
|
|
23
31
|
\`\`\`bash
|
|
24
32
|
python3 -m pip install browserstack-sdk
|
|
25
33
|
\`\`\`
|
|
26
34
|
|
|
27
|
-
|
|
35
|
+
---STEP---
|
|
36
|
+
|
|
37
|
+
Setup the BrowserStack SDK with framework-specific configuration:
|
|
28
38
|
\`\`\`bash
|
|
29
39
|
browserstack-sdk setup --framework "${framework}" --username "${config.browserstackUsername}" --key "${config.browserstackAccessKey}"
|
|
30
40
|
\`\`\`
|
|
31
41
|
|
|
32
|
-
|
|
42
|
+
---STEP---
|
|
43
|
+
|
|
44
|
+
Run your ${framework} tests on BrowserStack:
|
|
33
45
|
\`\`\`bash
|
|
34
46
|
browserstack-sdk ${framework} <path-to-test-files>
|
|
35
47
|
\`\`\`
|
|
@@ -42,7 +54,9 @@ const pytestInstructions = generatePythonFrameworkInstructions("pytest");
|
|
|
42
54
|
*/
|
|
43
55
|
const argsInstruction = '<argLine>-javaagent:"${com.browserstack:browserstack-java-sdk:jar}"</argLine>';
|
|
44
56
|
const javaInstructions = `
|
|
45
|
-
|
|
57
|
+
---STEP---
|
|
58
|
+
|
|
59
|
+
Add the BrowserStack Java SDK dependency to your \`pom.xml\`:
|
|
46
60
|
\`\`\`xml
|
|
47
61
|
<dependency>
|
|
48
62
|
<groupId>com.browserstack</groupId>
|
|
@@ -61,13 +75,17 @@ dependencies {
|
|
|
61
75
|
}
|
|
62
76
|
\`\`\`
|
|
63
77
|
|
|
64
|
-
|
|
78
|
+
---STEP---
|
|
79
|
+
|
|
80
|
+
Export your BrowserStack credentials as environment variables:
|
|
65
81
|
\`\`\`bash
|
|
66
82
|
export BROWSERSTACK_USERNAME=${config.browserstackUsername}
|
|
67
83
|
export BROWSERSTACK_ACCESS_KEY=${config.browserstackAccessKey}
|
|
68
84
|
\`\`\`
|
|
69
85
|
|
|
70
|
-
|
|
86
|
+
---STEP---
|
|
87
|
+
|
|
88
|
+
Run your tests using Maven:
|
|
71
89
|
\`\`\`bash
|
|
72
90
|
mvn clean test
|
|
73
91
|
\`\`\`
|
|
@@ -81,141 +99,174 @@ gradle clean test
|
|
|
81
99
|
* ---------- CSharp INSTRUCTIONS ----------
|
|
82
100
|
*/
|
|
83
101
|
const csharpCommonInstructions = `
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
102
|
+
---STEP---
|
|
103
|
+
|
|
104
|
+
Install BrowserStack TestAdapter NuGet package:
|
|
105
|
+
\`\`\`bash
|
|
106
|
+
dotnet add package BrowserStack.TestAdapter
|
|
107
|
+
\`\`\`
|
|
108
|
+
|
|
109
|
+
---STEP---
|
|
110
|
+
|
|
111
|
+
Build the project:
|
|
112
|
+
\`\`\`bash
|
|
113
|
+
dotnet build
|
|
114
|
+
\`\`\`
|
|
115
|
+
|
|
116
|
+
---STEP---
|
|
117
|
+
|
|
118
|
+
Set up BrowserStack SDK with your credentials:
|
|
119
|
+
\`\`\`bash
|
|
120
|
+
dotnet browserstack-sdk setup --userName ${config.browserstackUsername} --accessKey ${config.browserstackAccessKey}
|
|
121
|
+
\`\`\`
|
|
122
|
+
|
|
123
|
+
---STEP---
|
|
124
|
+
|
|
125
|
+
Detect if you are running on Apple Silicon (macOS only):
|
|
126
|
+
Run this check to determine if Apple Silicon-specific setup is required:
|
|
127
|
+
\`\`\`bash
|
|
128
|
+
ARCH="$(uname -m)"
|
|
129
|
+
if [ "$ARCH" = "arm64" ]; then
|
|
130
|
+
echo "Detected arm64 architecture - running Apple-Silicon flow"
|
|
131
|
+
fi
|
|
132
|
+
\`\`\`
|
|
133
|
+
|
|
134
|
+
---STEP---
|
|
135
|
+
|
|
136
|
+
macOS (Apple Silicon) setup (Strictly follow if arm64 detected):
|
|
137
|
+
Install the x64 version of .NET for BrowserStack compatibility.
|
|
138
|
+
|
|
139
|
+
- Check your current .NET version:
|
|
140
|
+
\`\`\`bash
|
|
141
|
+
dotnet --version
|
|
142
|
+
\`\`\`
|
|
143
|
+
|
|
144
|
+
- Ensure the path exists strictly; if not, create it first and then run the setup:
|
|
145
|
+
This automatically installs the x64 version of .NET in the specified path. No need to install it from external sources.
|
|
146
|
+
\`\`\`bash
|
|
147
|
+
sudo dotnet browserstack-sdk setup-dotnet --dotnet-path "<your-chosen-path>" --dotnet-version "<your-dotnet-version>"
|
|
148
|
+
\`\`\`
|
|
149
|
+
Common paths: /usr/local/share/dotnet, ~/dotnet-x64, or /opt/dotnet-x64
|
|
150
|
+
|
|
151
|
+
---STEP---
|
|
152
|
+
|
|
153
|
+
Run the tests:
|
|
154
|
+
- For macOS (Apple Silicon), use the full path where the x64 version of .NET is installed:
|
|
155
|
+
\`\`\`bash
|
|
156
|
+
<your-chosen-path>/dotnet browserstack-sdk
|
|
157
|
+
\`\`\`
|
|
158
|
+
- For Windows, Intel Macs, or if dotnet alias is configured:
|
|
159
|
+
\`\`\`bash
|
|
160
|
+
dotnet test
|
|
161
|
+
\`\`\`
|
|
133
162
|
`;
|
|
134
163
|
const csharpPlaywrightCommonInstructions = `
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
164
|
+
---STEP---
|
|
165
|
+
|
|
166
|
+
Install BrowserStack TestAdapter NuGet package:
|
|
167
|
+
\`\`\`bash
|
|
168
|
+
dotnet add package BrowserStack.TestAdapter
|
|
169
|
+
\`\`\`
|
|
170
|
+
|
|
171
|
+
---STEP---
|
|
172
|
+
|
|
173
|
+
Build the project:
|
|
174
|
+
\`\`\`bash
|
|
175
|
+
dotnet build
|
|
176
|
+
\`\`\`
|
|
177
|
+
|
|
178
|
+
---STEP---
|
|
179
|
+
|
|
180
|
+
Set up BrowserStack SDK with your credentials:
|
|
181
|
+
\`\`\`bash
|
|
182
|
+
dotnet browserstack-sdk setup --userName ${config.browserstackUsername} --accessKey ${config.browserstackAccessKey}
|
|
183
|
+
\`\`\`
|
|
184
|
+
|
|
185
|
+
---STEP---
|
|
186
|
+
|
|
187
|
+
Choose supported browser:
|
|
188
|
+
Use exactly one of the following (case-sensitive):
|
|
189
|
+
\`chrome\`, \`edge\`, \`playwright-chromium\`, \`playwright-webkit\`, \`playwright-firefox\`
|
|
190
|
+
|
|
191
|
+
---STEP---
|
|
192
|
+
|
|
193
|
+
Detect if you are running on Apple Silicon (macOS only):
|
|
194
|
+
Run this check to determine if Apple Silicon-specific setup is required:
|
|
195
|
+
\`\`\`bash
|
|
196
|
+
ARCH="$(uname -m)"
|
|
197
|
+
if [ "$ARCH" = "arm64" ]; then
|
|
198
|
+
echo "Detected arm64 architecture - running Apple-Silicon flow"
|
|
199
|
+
fi
|
|
200
|
+
\`\`\`
|
|
201
|
+
|
|
202
|
+
---STEP---
|
|
203
|
+
|
|
204
|
+
macOS (Apple Silicon) setup (required only if arm64 detected):
|
|
205
|
+
Install the x64 version of .NET for compatibility with BrowserStack.
|
|
206
|
+
|
|
207
|
+
- Check your .NET version:
|
|
208
|
+
\`\`\`bash
|
|
209
|
+
dotnet --version
|
|
210
|
+
\`\`\`
|
|
211
|
+
|
|
212
|
+
- Ensure the path exists strictly; if not, create it first and then run the setup:
|
|
213
|
+
This automatically installs the x64 version of .NET in the specified path. No need to install it from external sources.
|
|
214
|
+
\`\`\`bash
|
|
215
|
+
sudo dotnet browserstack-sdk setup-dotnet --dotnet-path "<your-chosen-path>" --dotnet-version "<your-dotnet-version>"
|
|
216
|
+
\`\`\`
|
|
217
|
+
Common paths: /usr/local/share/dotnet, ~/dotnet-x64, or /opt/dotnet-x64
|
|
218
|
+
|
|
219
|
+
---STEP---
|
|
220
|
+
|
|
221
|
+
Fix for Playwright architecture (macOS only):
|
|
222
|
+
If the folder exists:
|
|
223
|
+
\`<project-folder>/bin/Debug/net8.0/.playwright/node/darwin-arm64\`
|
|
224
|
+
Rename \`darwin-arm64\` to \`darwin-x64\`
|
|
225
|
+
|
|
226
|
+
---STEP---
|
|
227
|
+
|
|
228
|
+
Run the tests:
|
|
229
|
+
- For macOS (Apple Silicon), use the full path:
|
|
230
|
+
\`\`\`bash
|
|
231
|
+
<your-chosen-path>/dotnet browserstack-sdk
|
|
232
|
+
\`\`\`
|
|
233
|
+
- For Windows, Intel Macs, or if dotnet alias is configured:
|
|
234
|
+
\`\`\`bash
|
|
235
|
+
dotnet test
|
|
236
|
+
\`\`\`
|
|
193
237
|
`;
|
|
194
238
|
/**
|
|
195
239
|
* ---------- NODEJS INSTRUCTIONS ----------
|
|
196
240
|
*/
|
|
197
241
|
const nodejsInstructions = `
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
242
|
+
---STEP---
|
|
243
|
+
|
|
244
|
+
Ensure \`browserstack-node-sdk\` is present in package.json with the latest version:
|
|
245
|
+
\`\`\`json
|
|
246
|
+
"browserstack-node-sdk": "latest"
|
|
247
|
+
\`\`\`
|
|
248
|
+
|
|
249
|
+
---STEP---
|
|
250
|
+
|
|
251
|
+
Add new scripts to package.json for running tests on BrowserStack:
|
|
252
|
+
\`\`\`json
|
|
253
|
+
"scripts": {
|
|
254
|
+
"test:browserstack": "npx browserstack-node-sdk <framework-specific-test-execution-command>"
|
|
255
|
+
}
|
|
256
|
+
\`\`\`
|
|
257
|
+
|
|
258
|
+
---STEP---
|
|
259
|
+
|
|
260
|
+
Export BrowserStack credentials as environment variables:
|
|
261
|
+
Set the following environment variables before running tests.
|
|
210
262
|
`;
|
|
211
263
|
/**
|
|
212
264
|
* ---------- EXPORT CONFIG ----------
|
|
213
265
|
*/
|
|
214
266
|
const webdriverioInstructions = `
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
**1. Set BrowserStack Credentials**
|
|
267
|
+
---STEP---
|
|
218
268
|
|
|
269
|
+
Set BrowserStack Credentials:
|
|
219
270
|
Export your BrowserStack username and access key as environment variables.
|
|
220
271
|
|
|
221
272
|
For macOS/Linux:
|
|
@@ -230,15 +281,17 @@ $env:BROWSERSTACK_USERNAME=${config.browserstackUsername}
|
|
|
230
281
|
$env:BROWSERSTACK_ACCESS_KEY=${config.browserstackAccessKey}
|
|
231
282
|
\`\`\`
|
|
232
283
|
|
|
233
|
-
|
|
284
|
+
---STEP---
|
|
234
285
|
|
|
286
|
+
Install the BrowserStack WDIO Service:
|
|
235
287
|
Add the service to your project's dev dependencies.
|
|
236
288
|
\`\`\`bash
|
|
237
289
|
npm install @wdio/browserstack-service --save-dev
|
|
238
290
|
\`\`\`
|
|
239
291
|
|
|
240
|
-
|
|
292
|
+
---STEP---
|
|
241
293
|
|
|
294
|
+
Update your WebdriverIO Config File (e.g., wdio.conf.js):
|
|
242
295
|
Modify your configuration file to use the BrowserStack service and define the platforms you want to test on.
|
|
243
296
|
|
|
244
297
|
Here is an example configuration:
|
|
@@ -310,29 +363,31 @@ exports.config.capabilities.forEach(function (caps) {
|
|
|
310
363
|
});
|
|
311
364
|
\`\`\`
|
|
312
365
|
|
|
313
|
-
|
|
366
|
+
---STEP---
|
|
314
367
|
|
|
368
|
+
Run your tests:
|
|
315
369
|
You can now run your tests on BrowserStack using your standard WebdriverIO command.
|
|
316
370
|
`;
|
|
317
371
|
const cypressInstructions = `
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
**1. Install the BrowserStack Cypress CLI**
|
|
372
|
+
---STEP---
|
|
321
373
|
|
|
374
|
+
Install the BrowserStack Cypress CLI:
|
|
322
375
|
Install the CLI as a dev dependency in your project.
|
|
323
376
|
\`\`\`bash
|
|
324
377
|
npm install browserstack-cypress-cli --save-dev
|
|
325
378
|
\`\`\`
|
|
326
379
|
|
|
327
|
-
|
|
380
|
+
---STEP---
|
|
328
381
|
|
|
382
|
+
Create the Configuration File:
|
|
329
383
|
Generate the \`browserstack.json\` configuration file in your project's root directory by running the following command:
|
|
330
384
|
\`\`\`bash
|
|
331
385
|
npx browserstack-cypress init
|
|
332
386
|
\`\`\`
|
|
333
387
|
|
|
334
|
-
|
|
388
|
+
---STEP---
|
|
335
389
|
|
|
390
|
+
Configure \`browserstack.json\`:
|
|
336
391
|
Open the generated \`browserstack.json\` file and update it with your BrowserStack credentials and desired capabilities. Below is an example configuration.
|
|
337
392
|
|
|
338
393
|
* **auth**: Your BrowserStack username and access key.
|
|
@@ -372,10 +427,12 @@ Open the generated \`browserstack.json\` file and update it with your BrowserSta
|
|
|
372
427
|
}
|
|
373
428
|
}
|
|
374
429
|
\`\`\`
|
|
430
|
+
|
|
375
431
|
**Note:** For Cypress v9 or lower, use \`"cypress_config_file": "./cypress.json"\`. The \`testObservability: true\` flag enables the [Test Reporting & Analytics dashboard](https://www.browserstack.com/docs/test-management/test-reporting-and-analytics) for deeper insights into your test runs.
|
|
376
432
|
|
|
377
|
-
|
|
433
|
+
---STEP---
|
|
378
434
|
|
|
435
|
+
Run Your Tests on BrowserStack:
|
|
379
436
|
Execute your tests on BrowserStack using the following command:
|
|
380
437
|
\`\`\`bash
|
|
381
438
|
npx browserstack-cypress run --sync
|
|
@@ -395,7 +452,11 @@ export const SUPPORTED_CONFIGURATIONS = {
|
|
|
395
452
|
},
|
|
396
453
|
},
|
|
397
454
|
java: {
|
|
398
|
-
playwright: {
|
|
455
|
+
playwright: {
|
|
456
|
+
junit4: { instructions: javaInstructions },
|
|
457
|
+
junit5: { instructions: javaInstructions },
|
|
458
|
+
testng: { instructions: javaInstructions },
|
|
459
|
+
},
|
|
399
460
|
selenium: {
|
|
400
461
|
testng: { instructions: javaInstructions },
|
|
401
462
|
cucumber: { instructions: javaInstructions },
|
|
@@ -412,6 +473,8 @@ export const SUPPORTED_CONFIGURATIONS = {
|
|
|
412
473
|
xunit: { instructions: csharpCommonInstructions },
|
|
413
474
|
nunit: { instructions: csharpCommonInstructions },
|
|
414
475
|
mstest: { instructions: csharpCommonInstructions },
|
|
476
|
+
specflow: { instructions: csharpCommonInstructions },
|
|
477
|
+
reqnroll: { instructions: csharpCommonInstructions },
|
|
415
478
|
},
|
|
416
479
|
},
|
|
417
480
|
nodejs: {
|
|
@@ -19,7 +19,7 @@ export function generateBrowserStackYMLInstructions(desiredPlatforms, enablePerc
|
|
|
19
19
|
# BrowserStack Reporting
|
|
20
20
|
# ======================
|
|
21
21
|
# A single name for your project to organize all your tests. This is required for Percy.
|
|
22
|
-
projectName: BrowserStack
|
|
22
|
+
projectName: BrowserStack SDK Tests
|
|
23
23
|
# A name for the group of tests you are running
|
|
24
24
|
buildName: mcp-run
|
|
25
25
|
|
|
@@ -75,3 +75,23 @@ percyCaptureMode: manual`;
|
|
|
75
75
|
\`\`\`
|
|
76
76
|
\n`;
|
|
77
77
|
}
|
|
78
|
+
export function formatInstructionsWithNumbers(instructionText, separator = "---STEP---") {
|
|
79
|
+
// Split the instructions by the separator
|
|
80
|
+
const steps = instructionText
|
|
81
|
+
.split(separator)
|
|
82
|
+
.map((step) => step.trim())
|
|
83
|
+
.filter((step) => step.length > 0);
|
|
84
|
+
// If no separators found, treat the entire text as one step
|
|
85
|
+
if (steps.length === 1 && !instructionText.includes(separator)) {
|
|
86
|
+
return `**Step 1:**\n${instructionText.trim()}\n\n**✅ Verification:**\nPlease verify that you have completed all the steps above to ensure proper setup.`;
|
|
87
|
+
}
|
|
88
|
+
// Format each step with numbering
|
|
89
|
+
const formattedSteps = steps
|
|
90
|
+
.map((step, index) => {
|
|
91
|
+
return `**Step ${index + 1}:**\n${step.trim()}`;
|
|
92
|
+
})
|
|
93
|
+
.join("\n\n");
|
|
94
|
+
// Add verification statement at the end
|
|
95
|
+
const verificationText = `\n\n**✅ Verification:**\nPlease verify that you have completed all ${steps.length} steps above to ensure proper setup. If you encounter any issues, double-check each step and ensure all commands executed successfully.`;
|
|
96
|
+
return formattedSteps + verificationText;
|
|
97
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
const javaSeleniumInstructions = `
|
|
2
|
-
|
|
2
|
+
Import the BrowserStack Percy SDK in your test script:
|
|
3
|
+
Add the Percy import to your test file.
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
---STEP---
|
|
6
|
+
|
|
7
|
+
Add screenshot capture method at required points:
|
|
8
|
+
Use the \`PercySDK.screenshot(driver, name)\` method at points in your test script where you want to capture screenshots.
|
|
6
9
|
|
|
7
10
|
Here's an example:
|
|
8
11
|
|
|
@@ -26,26 +29,29 @@ public class YourTestClass extends YourBaseTest {
|
|
|
26
29
|
\`\`\`
|
|
27
30
|
`;
|
|
28
31
|
export const nodejsSeleniumInstructions = `
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
32
|
+
Import the BrowserStack Percy SDK in your test script:
|
|
33
|
+
Add the Percy import to your test file.
|
|
34
|
+
|
|
35
|
+
---STEP---
|
|
36
|
+
|
|
37
|
+
Add screenshot capture method at required points:
|
|
38
|
+
Use the \`percy.snapshot(driver, name)\` method at points in your test script where you want to capture screenshots.
|
|
39
|
+
|
|
40
|
+
\`\`\`javascript
|
|
41
|
+
const { percy } = require('browserstack-node-sdk');
|
|
42
|
+
describe("sample Test", () => {
|
|
43
|
+
// ... other imports and setup
|
|
44
|
+
|
|
45
|
+
test("my test", async () => {
|
|
46
|
+
// ....
|
|
47
|
+
await percy.snapshot(driver, "My Snapshot")
|
|
48
|
+
// ....
|
|
49
|
+
});
|
|
50
|
+
})
|
|
51
|
+
\`\`\`
|
|
45
52
|
`;
|
|
46
53
|
const webdriverioPercyInstructions = `
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
Enable Percy in \`wdio.conf.js\`:
|
|
49
55
|
In your WebdriverIO configuration file, modify the 'browserstack' service options to enable Percy.
|
|
50
56
|
|
|
51
57
|
- Set \`percy: true\`.
|
|
@@ -79,8 +85,9 @@ exports.config = {
|
|
|
79
85
|
};
|
|
80
86
|
\`\`\`
|
|
81
87
|
|
|
82
|
-
|
|
88
|
+
---STEP---
|
|
83
89
|
|
|
90
|
+
Manually Capturing Screenshots (Optional):
|
|
84
91
|
If you set \`percyCaptureMode: 'manual'\` or want to take extra screenshots in \`auto\` mode, you need to add screenshot commands to your tests.
|
|
85
92
|
|
|
86
93
|
First, install \`browserstack-node-sdk\`:
|
|
@@ -106,10 +113,13 @@ describe("My WebdriverIO Test", () => {
|
|
|
106
113
|
\`\`\`
|
|
107
114
|
`;
|
|
108
115
|
const csharpSeleniumInstructions = `
|
|
109
|
-
|
|
116
|
+
Import the BrowserStack Percy SDK in your test script:
|
|
117
|
+
Add the Percy import to your test file.
|
|
118
|
+
|
|
119
|
+
---STEP---
|
|
110
120
|
|
|
111
|
-
|
|
112
|
-
|
|
121
|
+
Add screenshot capture method at required points:
|
|
122
|
+
Use the \`PercySDK.Screenshot(driver, name)\` method at points in your test script where you want to capture screenshots.
|
|
113
123
|
|
|
114
124
|
Here's an example:
|
|
115
125
|
|
|
@@ -30,4 +30,6 @@ export var SDKSupportedTestingFrameworkEnum;
|
|
|
30
30
|
SDKSupportedTestingFrameworkEnum["nunit"] = "nunit";
|
|
31
31
|
SDKSupportedTestingFrameworkEnum["mstest"] = "mstest";
|
|
32
32
|
SDKSupportedTestingFrameworkEnum["xunit"] = "xunit";
|
|
33
|
+
SDKSupportedTestingFrameworkEnum["specflow"] = "specflow";
|
|
34
|
+
SDKSupportedTestingFrameworkEnum["reqnroll"] = "reqnroll";
|
|
33
35
|
})(SDKSupportedTestingFrameworkEnum || (SDKSupportedTestingFrameworkEnum = {}));
|