@browserstack/mcp-server 1.1.9 → 1.2.0
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/dist/config.d.ts +13 -0
- package/dist/config.js +4 -6
- package/dist/index.d.ts +4 -0
- package/dist/index.js +20 -30
- package/dist/lib/api.d.ts +2 -0
- package/dist/lib/api.js +10 -5
- package/dist/lib/apiClient.d.ts +31 -0
- package/dist/lib/apiClient.js +108 -0
- package/dist/lib/constants.d.ts +17 -0
- package/dist/lib/device-cache.d.ts +9 -0
- package/dist/lib/device-cache.js +3 -3
- package/dist/lib/error.d.ts +7 -0
- package/dist/lib/fuzzy.d.ts +1 -0
- package/dist/lib/get-auth.d.ts +2 -0
- package/dist/lib/get-auth.js +8 -0
- package/dist/lib/inmemory-store.d.ts +1 -0
- package/dist/lib/instrumentation.d.ts +4 -0
- package/dist/lib/instrumentation.js +8 -7
- package/dist/lib/local.d.ts +3 -0
- package/dist/lib/local.js +3 -3
- package/dist/lib/types.d.ts +4 -0
- package/dist/lib/types.js +1 -0
- package/dist/lib/utils.d.ts +4 -0
- package/dist/lib/version-resolver.d.ts +6 -0
- package/dist/logger.d.ts +3 -0
- package/dist/logger.js +20 -4
- package/dist/oninitialized.d.ts +2 -0
- package/dist/oninitialized.js +2 -7
- package/dist/server-factory.d.ts +3 -0
- package/dist/server-factory.js +37 -0
- package/dist/tools/accessibility.d.ts +3 -0
- package/dist/tools/accessibility.js +17 -10
- package/dist/tools/accessiblity-utils/accessibility-rag.d.ts +12 -0
- package/dist/tools/accessiblity-utils/accessibility-rag.js +22 -12
- package/dist/tools/accessiblity-utils/report-fetcher.d.ts +8 -0
- package/dist/tools/accessiblity-utils/report-fetcher.js +26 -16
- package/dist/tools/accessiblity-utils/report-parser.d.ts +23 -0
- package/dist/tools/accessiblity-utils/report-parser.js +3 -3
- package/dist/tools/accessiblity-utils/scanner.d.ts +25 -0
- package/dist/tools/accessiblity-utils/scanner.js +43 -24
- package/dist/tools/appautomate-utils/appautomate.d.ts +42 -0
- package/dist/tools/appautomate-utils/appautomate.js +63 -38
- package/dist/tools/appautomate-utils/types.d.ts +5 -0
- package/dist/tools/appautomate.d.ts +3 -0
- package/dist/tools/appautomate.js +20 -19
- package/dist/tools/applive-utils/device-search.d.ts +6 -0
- package/dist/tools/applive-utils/start-session.d.ts +15 -0
- package/dist/tools/applive-utils/start-session.js +11 -4
- package/dist/tools/applive-utils/types.d.ts +7 -0
- package/dist/tools/applive-utils/upload-app.d.ts +5 -0
- package/dist/tools/applive-utils/upload-app.js +8 -12
- package/dist/tools/applive-utils/version-utils.d.ts +4 -0
- package/dist/tools/applive.d.ts +13 -0
- package/dist/tools/applive.js +6 -6
- package/dist/tools/automate-utils/fetch-screenshots.d.ts +6 -0
- package/dist/tools/automate-utils/fetch-screenshots.js +16 -12
- package/dist/tools/automate.d.ts +9 -0
- package/dist/tools/automate.js +6 -6
- package/dist/tools/bstack-sdk.d.ts +17 -0
- package/dist/tools/bstack-sdk.js +12 -7
- package/dist/tools/failurelogs-utils/app-automate.d.ts +7 -0
- package/dist/tools/failurelogs-utils/app-automate.js +29 -11
- package/dist/tools/failurelogs-utils/automate.d.ts +6 -0
- package/dist/tools/failurelogs-utils/automate.js +27 -12
- package/dist/tools/failurelogs-utils/utils.d.ts +30 -0
- package/dist/tools/getFailureLogs.d.ts +14 -0
- package/dist/tools/getFailureLogs.js +11 -11
- package/dist/tools/live-utils/desktop-filter.d.ts +2 -0
- package/dist/tools/live-utils/mobile-filter.d.ts +2 -0
- package/dist/tools/live-utils/start-session.d.ts +6 -0
- package/dist/tools/live-utils/start-session.js +18 -5
- package/dist/tools/live-utils/types.d.ts +33 -0
- package/dist/tools/live.d.ts +3 -0
- package/dist/tools/live.js +11 -11
- package/dist/tools/observability.d.ts +5 -0
- package/dist/tools/observability.js +14 -11
- package/dist/tools/sdk-utils/commands.d.ts +3 -0
- package/dist/tools/sdk-utils/commands.js +5 -4
- package/dist/tools/sdk-utils/constants.d.ts +2 -0
- package/dist/tools/sdk-utils/constants.js +82 -21
- package/dist/tools/sdk-utils/instructions.d.ts +6 -0
- package/dist/tools/sdk-utils/instructions.js +8 -6
- package/dist/tools/sdk-utils/percy/constants.d.ts +3 -0
- package/dist/tools/sdk-utils/percy/constants.js +1 -0
- package/dist/tools/sdk-utils/percy/instructions.d.ts +10 -0
- package/dist/tools/sdk-utils/percy/types.d.ts +5 -0
- package/dist/tools/sdk-utils/types.d.ts +39 -0
- package/dist/tools/sdk-utils/types.js +1 -0
- package/dist/tools/selfheal-utils/selfheal.d.ts +11 -0
- package/dist/tools/selfheal-utils/selfheal.js +10 -6
- package/dist/tools/selfheal.d.ts +7 -0
- package/dist/tools/selfheal.js +6 -6
- package/dist/tools/testmanagement-utils/TCG-utils/api.d.ts +34 -0
- package/dist/tools/testmanagement-utils/TCG-utils/api.js +57 -44
- package/dist/tools/testmanagement-utils/TCG-utils/config.d.ts +5 -0
- package/dist/tools/testmanagement-utils/TCG-utils/helpers.d.ts +13 -0
- package/dist/tools/testmanagement-utils/TCG-utils/helpers.js +2 -1
- package/dist/tools/testmanagement-utils/TCG-utils/types.d.ts +26 -0
- package/dist/tools/testmanagement-utils/add-test-result.d.ts +42 -0
- package/dist/tools/testmanagement-utils/add-test-result.js +23 -10
- package/dist/tools/testmanagement-utils/create-lca-steps.d.ts +100 -0
- package/dist/tools/testmanagement-utils/create-lca-steps.js +64 -55
- package/dist/tools/testmanagement-utils/create-project-folder.d.ts +31 -0
- package/dist/tools/testmanagement-utils/create-project-folder.js +31 -21
- package/dist/tools/testmanagement-utils/create-testcase.d.ts +122 -0
- package/dist/tools/testmanagement-utils/create-testcase.js +13 -10
- package/dist/tools/testmanagement-utils/create-testrun.d.ts +82 -0
- package/dist/tools/testmanagement-utils/create-testrun.js +11 -8
- package/dist/tools/testmanagement-utils/list-testcases.d.ts +30 -0
- package/dist/tools/testmanagement-utils/list-testcases.js +9 -7
- package/dist/tools/testmanagement-utils/list-testruns.d.ts +22 -0
- package/dist/tools/testmanagement-utils/list-testruns.js +9 -7
- package/dist/tools/testmanagement-utils/poll-lca-status.d.ts +11 -0
- package/dist/tools/testmanagement-utils/poll-lca-status.js +12 -8
- package/dist/tools/testmanagement-utils/testcase-from-file.d.ts +4 -0
- package/dist/tools/testmanagement-utils/testcase-from-file.js +6 -6
- package/dist/tools/testmanagement-utils/update-testrun.d.ts +40 -0
- package/dist/tools/testmanagement-utils/update-testrun.js +11 -7
- package/dist/tools/testmanagement-utils/upload-file.d.ts +20 -0
- package/dist/tools/testmanagement-utils/upload-file.js +8 -6
- package/dist/tools/testmanagement.d.ts +60 -0
- package/dist/tools/testmanagement.js +51 -53
- package/package.json +1 -1
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import
|
|
3
|
-
import config from "../../config.js";
|
|
4
|
-
import { formatAxiosError } from "../../lib/error.js";
|
|
2
|
+
import { apiClient } from "../../lib/apiClient.js";
|
|
5
3
|
import { projectIdentifierToId, testCaseIdentifierToDetails, } from "./TCG-utils/api.js";
|
|
6
4
|
import { pollLCAStatus } from "./poll-lca-status.js";
|
|
5
|
+
import { getBrowserStackAuth } from "../../lib/get-auth.js";
|
|
7
6
|
/**
|
|
8
7
|
* Schema for creating LCA steps for a test case
|
|
9
8
|
*/
|
|
@@ -50,12 +49,12 @@ export const CreateLCAStepsSchema = z.object({
|
|
|
50
49
|
/**
|
|
51
50
|
* Creates LCA (Low Code Automation) steps for a test case in BrowserStack Test Management
|
|
52
51
|
*/
|
|
53
|
-
export async function createLCASteps(args, context) {
|
|
52
|
+
export async function createLCASteps(args, context, config) {
|
|
54
53
|
try {
|
|
55
54
|
// Get the project ID from identifier
|
|
56
|
-
const projectId = await projectIdentifierToId(args.project_identifier);
|
|
55
|
+
const projectId = await projectIdentifierToId(args.project_identifier, config);
|
|
57
56
|
// Get the test case ID and folder ID from identifier
|
|
58
|
-
const { testCaseId, folderId } = await testCaseIdentifierToDetails(projectId, args.test_case_identifier);
|
|
57
|
+
const { testCaseId, folderId } = await testCaseIdentifierToDetails(projectId, args.test_case_identifier, config);
|
|
59
58
|
const url = `https://test-management.browserstack.com/api/v1/projects/${projectId}/test-cases/${testCaseId}/lcnc`;
|
|
60
59
|
const payload = {
|
|
61
60
|
base_url: args.base_url,
|
|
@@ -66,67 +65,53 @@ export async function createLCASteps(args, context) {
|
|
|
66
65
|
version: "v2",
|
|
67
66
|
webhook_path: `https://test-management.browserstack.com/api/v1/projects/${projectId}/test-cases/${testCaseId}/webhooks/lcnc`,
|
|
68
67
|
};
|
|
69
|
-
|
|
68
|
+
await apiClient.post({
|
|
69
|
+
url,
|
|
70
70
|
headers: {
|
|
71
|
-
"API-TOKEN":
|
|
71
|
+
"API-TOKEN": getBrowserStackAuth(config),
|
|
72
72
|
accept: "application/json, text/plain, */*",
|
|
73
73
|
"Content-Type": "application/json",
|
|
74
74
|
},
|
|
75
|
+
body: payload,
|
|
75
76
|
});
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
// Check if user wants to wait for completion
|
|
78
|
+
if (!args.wait_for_completion) {
|
|
79
|
+
return {
|
|
80
|
+
content: [
|
|
81
|
+
{
|
|
82
|
+
type: "text",
|
|
83
|
+
text: `LCA steps creation initiated for test case ${args.test_case_identifier} (ID: ${testCaseId})`,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
type: "text",
|
|
87
|
+
text: "LCA build started. Check the BrowserStack Lowcode Automation UI for completion status.",
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Start polling for LCA build completion
|
|
93
|
+
try {
|
|
94
|
+
const max_wait_minutes = 10; // Maximum wait time in minutes
|
|
95
|
+
const maxWaitMs = max_wait_minutes * 60 * 1000;
|
|
96
|
+
const lcaResult = await pollLCAStatus(projectId, folderId, testCaseId, context, maxWaitMs, // max wait time
|
|
97
|
+
2 * 60 * 1000, // 2 minutes initial wait
|
|
98
|
+
10 * 1000, // 10 seconds interval
|
|
99
|
+
config);
|
|
100
|
+
if (lcaResult && lcaResult.status === "done") {
|
|
79
101
|
return {
|
|
80
102
|
content: [
|
|
81
103
|
{
|
|
82
104
|
type: "text",
|
|
83
|
-
text: `LCA steps
|
|
105
|
+
text: `Successfully created LCA steps for test case ${args.test_case_identifier} (ID: ${testCaseId})`,
|
|
84
106
|
},
|
|
85
107
|
{
|
|
86
108
|
type: "text",
|
|
87
|
-
text:
|
|
109
|
+
text: `LCA build completed! Resource URL: ${lcaResult.resource_path}`,
|
|
88
110
|
},
|
|
89
111
|
],
|
|
90
112
|
};
|
|
91
113
|
}
|
|
92
|
-
|
|
93
|
-
try {
|
|
94
|
-
const max_wait_minutes = 10; // Maximum wait time in minutes
|
|
95
|
-
const maxWaitMs = max_wait_minutes * 60 * 1000;
|
|
96
|
-
const lcaResult = await pollLCAStatus(projectId, folderId, testCaseId, context, maxWaitMs, // max wait time
|
|
97
|
-
2 * 60 * 1000, // 2 minutes initial wait
|
|
98
|
-
10 * 1000);
|
|
99
|
-
if (lcaResult && lcaResult.status === "done") {
|
|
100
|
-
return {
|
|
101
|
-
content: [
|
|
102
|
-
{
|
|
103
|
-
type: "text",
|
|
104
|
-
text: `Successfully created LCA steps for test case ${args.test_case_identifier} (ID: ${testCaseId})`,
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
type: "text",
|
|
108
|
-
text: `LCA build completed! Resource URL: ${lcaResult.resource_path}`,
|
|
109
|
-
},
|
|
110
|
-
],
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
return {
|
|
115
|
-
content: [
|
|
116
|
-
{
|
|
117
|
-
type: "text",
|
|
118
|
-
text: `LCA steps creation initiated for test case ${args.test_case_identifier} (ID: ${testCaseId})`,
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
type: "text",
|
|
122
|
-
text: `Warning: LCA build did not complete within ${max_wait_minutes} minutes. You can check the status later in the BrowserStack Test Management UI.`,
|
|
123
|
-
},
|
|
124
|
-
],
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
catch (pollError) {
|
|
129
|
-
console.error("Error during LCA polling:", pollError);
|
|
114
|
+
else {
|
|
130
115
|
return {
|
|
131
116
|
content: [
|
|
132
117
|
{
|
|
@@ -135,14 +120,26 @@ export async function createLCASteps(args, context) {
|
|
|
135
120
|
},
|
|
136
121
|
{
|
|
137
122
|
type: "text",
|
|
138
|
-
text:
|
|
123
|
+
text: `Warning: LCA build did not complete within ${max_wait_minutes} minutes. You can check the status later in the BrowserStack Test Management UI.`,
|
|
139
124
|
},
|
|
140
125
|
],
|
|
141
126
|
};
|
|
142
127
|
}
|
|
143
128
|
}
|
|
144
|
-
|
|
145
|
-
|
|
129
|
+
catch (pollError) {
|
|
130
|
+
console.error("Error during LCA polling:", pollError);
|
|
131
|
+
return {
|
|
132
|
+
content: [
|
|
133
|
+
{
|
|
134
|
+
type: "text",
|
|
135
|
+
text: `LCA steps creation initiated for test case ${args.test_case_identifier} (ID: ${testCaseId})`,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
type: "text",
|
|
139
|
+
text: "Warning: Error occurred while polling for LCA build completion. Check the BrowserStack Test Management UI for status.",
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
};
|
|
146
143
|
}
|
|
147
144
|
}
|
|
148
145
|
catch (error) {
|
|
@@ -161,6 +158,18 @@ export async function createLCASteps(args, context) {
|
|
|
161
158
|
};
|
|
162
159
|
}
|
|
163
160
|
}
|
|
164
|
-
|
|
161
|
+
const msg = error?.response?.data?.message ||
|
|
162
|
+
error?.response?.data?.error ||
|
|
163
|
+
error?.message ||
|
|
164
|
+
String(error);
|
|
165
|
+
return {
|
|
166
|
+
content: [
|
|
167
|
+
{
|
|
168
|
+
type: "text",
|
|
169
|
+
text: `Failed to create LCA steps: ${msg}`,
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
isError: true,
|
|
173
|
+
};
|
|
165
174
|
}
|
|
166
175
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { BrowserStackConfig } from "../../lib/types.js";
|
|
4
|
+
export declare const CreateProjFoldSchema: z.ZodObject<{
|
|
5
|
+
project_name: z.ZodOptional<z.ZodString>;
|
|
6
|
+
project_description: z.ZodOptional<z.ZodString>;
|
|
7
|
+
project_identifier: z.ZodOptional<z.ZodString>;
|
|
8
|
+
folder_name: z.ZodOptional<z.ZodString>;
|
|
9
|
+
folder_description: z.ZodOptional<z.ZodString>;
|
|
10
|
+
parent_id: z.ZodOptional<z.ZodNumber>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
project_name?: string | undefined;
|
|
13
|
+
project_description?: string | undefined;
|
|
14
|
+
project_identifier?: string | undefined;
|
|
15
|
+
folder_name?: string | undefined;
|
|
16
|
+
folder_description?: string | undefined;
|
|
17
|
+
parent_id?: number | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
project_name?: string | undefined;
|
|
20
|
+
project_description?: string | undefined;
|
|
21
|
+
project_identifier?: string | undefined;
|
|
22
|
+
folder_name?: string | undefined;
|
|
23
|
+
folder_description?: string | undefined;
|
|
24
|
+
parent_id?: number | undefined;
|
|
25
|
+
}>;
|
|
26
|
+
type CreateProjFoldArgs = z.infer<typeof CreateProjFoldSchema>;
|
|
27
|
+
/**
|
|
28
|
+
* Creates a project and/or folder in BrowserStack Test Management.
|
|
29
|
+
*/
|
|
30
|
+
export declare function createProjectOrFolder(args: CreateProjFoldArgs, config: BrowserStackConfig): Promise<CallToolResult>;
|
|
31
|
+
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import config from "../../config.js";
|
|
1
|
+
import { apiClient } from "../../lib/apiClient.js";
|
|
3
2
|
import { z } from "zod";
|
|
4
|
-
import { formatAxiosError } from "../../lib/error.js";
|
|
3
|
+
import { formatAxiosError } from "../../lib/error.js";
|
|
5
4
|
import { projectIdentifierToId } from "../testmanagement-utils/TCG-utils/api.js";
|
|
5
|
+
import { getBrowserStackAuth } from "../../lib/get-auth.js";
|
|
6
6
|
// Schema for combined project/folder creation
|
|
7
7
|
export const CreateProjFoldSchema = z.object({
|
|
8
8
|
project_name: z
|
|
@@ -30,21 +30,29 @@ export const CreateProjFoldSchema = z.object({
|
|
|
30
30
|
/**
|
|
31
31
|
* Creates a project and/or folder in BrowserStack Test Management.
|
|
32
32
|
*/
|
|
33
|
-
export async function createProjectOrFolder(args) {
|
|
33
|
+
export async function createProjectOrFolder(args, config) {
|
|
34
34
|
const { project_name, project_description, project_identifier, folder_name, folder_description, parent_id, } = CreateProjFoldSchema.parse(args);
|
|
35
35
|
if (!project_name && !project_identifier && !folder_name) {
|
|
36
36
|
throw new Error("Provide project_name (to create project), or project_identifier and folder_name (to create folder).");
|
|
37
37
|
}
|
|
38
|
+
const authString = getBrowserStackAuth(config);
|
|
39
|
+
const [username, password] = authString.split(":");
|
|
38
40
|
let projId = project_identifier;
|
|
39
41
|
// Step 1: Create project if project_name provided
|
|
40
42
|
if (project_name) {
|
|
41
43
|
try {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
const authString = getBrowserStackAuth(config);
|
|
45
|
+
const [username, password] = authString.split(":");
|
|
46
|
+
const res = await apiClient.post({
|
|
47
|
+
url: "https://test-management.browserstack.com/api/v2/projects",
|
|
48
|
+
headers: {
|
|
49
|
+
"Content-Type": "application/json",
|
|
50
|
+
Authorization: "Basic " +
|
|
51
|
+
Buffer.from(`${username}:${password}`).toString("base64"),
|
|
52
|
+
},
|
|
53
|
+
body: {
|
|
54
|
+
project: { name: project_name, description: project_description },
|
|
46
55
|
},
|
|
47
|
-
headers: { "Content-Type": "application/json" },
|
|
48
56
|
});
|
|
49
57
|
if (!res.data.success) {
|
|
50
58
|
throw new Error(`Failed to create project: ${JSON.stringify(res.data)}`);
|
|
@@ -53,7 +61,7 @@ export async function createProjectOrFolder(args) {
|
|
|
53
61
|
projId = res.data.project.identifier;
|
|
54
62
|
}
|
|
55
63
|
catch (err) {
|
|
56
|
-
return formatAxiosError(err, "Failed to create project
|
|
64
|
+
return formatAxiosError(err, "Failed to create project.");
|
|
57
65
|
}
|
|
58
66
|
}
|
|
59
67
|
// Step 2: Create folder if folder_name provided
|
|
@@ -61,25 +69,27 @@ export async function createProjectOrFolder(args) {
|
|
|
61
69
|
if (!projId)
|
|
62
70
|
throw new Error("Cannot create folder without project_identifier.");
|
|
63
71
|
try {
|
|
64
|
-
const res = await
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
const res = await apiClient.post({
|
|
73
|
+
url: `https://test-management.browserstack.com/api/v2/projects/${encodeURIComponent(projId)}/folders`,
|
|
74
|
+
headers: {
|
|
75
|
+
"Content-Type": "application/json",
|
|
76
|
+
Authorization: "Basic " +
|
|
77
|
+
Buffer.from(`${username}:${password}`).toString("base64"),
|
|
69
78
|
},
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
body: {
|
|
80
|
+
folder: {
|
|
81
|
+
name: folder_name,
|
|
82
|
+
description: folder_description,
|
|
83
|
+
parent_id,
|
|
84
|
+
},
|
|
74
85
|
},
|
|
75
|
-
headers: { "Content-Type": "application/json" },
|
|
76
86
|
});
|
|
77
87
|
if (!res.data.success) {
|
|
78
88
|
throw new Error(`Failed to create folder: ${JSON.stringify(res.data)}`);
|
|
79
89
|
}
|
|
80
90
|
// Folder created successfully
|
|
81
91
|
const folder = res.data.folder;
|
|
82
|
-
const projectId = await projectIdentifierToId(projId);
|
|
92
|
+
const projectId = await projectIdentifierToId(projId, config);
|
|
83
93
|
return {
|
|
84
94
|
content: [
|
|
85
95
|
{
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { BrowserStackConfig } from "../../lib/types.js";
|
|
4
|
+
interface TestCaseStep {
|
|
5
|
+
step: string;
|
|
6
|
+
result: string;
|
|
7
|
+
}
|
|
8
|
+
interface IssueTracker {
|
|
9
|
+
name: string;
|
|
10
|
+
host: string;
|
|
11
|
+
}
|
|
12
|
+
export interface TestCaseCreateRequest {
|
|
13
|
+
project_identifier: string;
|
|
14
|
+
folder_id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
owner?: string;
|
|
18
|
+
preconditions?: string;
|
|
19
|
+
test_case_steps: TestCaseStep[];
|
|
20
|
+
issues?: string[];
|
|
21
|
+
issue_tracker?: IssueTracker;
|
|
22
|
+
tags?: string[];
|
|
23
|
+
custom_fields?: Record<string, string>;
|
|
24
|
+
}
|
|
25
|
+
export interface TestCaseResponse {
|
|
26
|
+
data: {
|
|
27
|
+
success: boolean;
|
|
28
|
+
test_case: {
|
|
29
|
+
case_type: string;
|
|
30
|
+
priority: string;
|
|
31
|
+
status: string;
|
|
32
|
+
folder_id: number;
|
|
33
|
+
issues: Array<{
|
|
34
|
+
jira_id: string;
|
|
35
|
+
issue_type: string;
|
|
36
|
+
}>;
|
|
37
|
+
tags: string[];
|
|
38
|
+
template: string;
|
|
39
|
+
description: string;
|
|
40
|
+
preconditions: string;
|
|
41
|
+
title: string;
|
|
42
|
+
identifier: string;
|
|
43
|
+
automation_status: string;
|
|
44
|
+
owner: string;
|
|
45
|
+
steps: TestCaseStep[];
|
|
46
|
+
custom_fields: Array<{
|
|
47
|
+
name: string;
|
|
48
|
+
value: string;
|
|
49
|
+
}>;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export declare const CreateTestCaseSchema: z.ZodObject<{
|
|
54
|
+
project_identifier: z.ZodString;
|
|
55
|
+
folder_id: z.ZodString;
|
|
56
|
+
name: z.ZodString;
|
|
57
|
+
description: z.ZodOptional<z.ZodString>;
|
|
58
|
+
owner: z.ZodOptional<z.ZodString>;
|
|
59
|
+
preconditions: z.ZodOptional<z.ZodString>;
|
|
60
|
+
test_case_steps: z.ZodArray<z.ZodObject<{
|
|
61
|
+
step: z.ZodString;
|
|
62
|
+
result: z.ZodString;
|
|
63
|
+
}, "strip", z.ZodTypeAny, {
|
|
64
|
+
step: string;
|
|
65
|
+
result: string;
|
|
66
|
+
}, {
|
|
67
|
+
step: string;
|
|
68
|
+
result: string;
|
|
69
|
+
}>, "many">;
|
|
70
|
+
issues: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
71
|
+
issue_tracker: z.ZodOptional<z.ZodObject<{
|
|
72
|
+
name: z.ZodString;
|
|
73
|
+
host: z.ZodString;
|
|
74
|
+
}, "strip", z.ZodTypeAny, {
|
|
75
|
+
name: string;
|
|
76
|
+
host: string;
|
|
77
|
+
}, {
|
|
78
|
+
name: string;
|
|
79
|
+
host: string;
|
|
80
|
+
}>>;
|
|
81
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
82
|
+
custom_fields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
83
|
+
}, "strip", z.ZodTypeAny, {
|
|
84
|
+
name: string;
|
|
85
|
+
test_case_steps: {
|
|
86
|
+
step: string;
|
|
87
|
+
result: string;
|
|
88
|
+
}[];
|
|
89
|
+
project_identifier: string;
|
|
90
|
+
folder_id: string;
|
|
91
|
+
issues?: string[] | undefined;
|
|
92
|
+
description?: string | undefined;
|
|
93
|
+
tags?: string[] | undefined;
|
|
94
|
+
custom_fields?: Record<string, string> | undefined;
|
|
95
|
+
preconditions?: string | undefined;
|
|
96
|
+
owner?: string | undefined;
|
|
97
|
+
issue_tracker?: {
|
|
98
|
+
name: string;
|
|
99
|
+
host: string;
|
|
100
|
+
} | undefined;
|
|
101
|
+
}, {
|
|
102
|
+
name: string;
|
|
103
|
+
test_case_steps: {
|
|
104
|
+
step: string;
|
|
105
|
+
result: string;
|
|
106
|
+
}[];
|
|
107
|
+
project_identifier: string;
|
|
108
|
+
folder_id: string;
|
|
109
|
+
issues?: string[] | undefined;
|
|
110
|
+
description?: string | undefined;
|
|
111
|
+
tags?: string[] | undefined;
|
|
112
|
+
custom_fields?: Record<string, string> | undefined;
|
|
113
|
+
preconditions?: string | undefined;
|
|
114
|
+
owner?: string | undefined;
|
|
115
|
+
issue_tracker?: {
|
|
116
|
+
name: string;
|
|
117
|
+
host: string;
|
|
118
|
+
} | undefined;
|
|
119
|
+
}>;
|
|
120
|
+
export declare function sanitizeArgs(args: any): any;
|
|
121
|
+
export declare function createTestCase(params: TestCaseCreateRequest, config: BrowserStackConfig): Promise<CallToolResult>;
|
|
122
|
+
export {};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import config from "../../config.js";
|
|
1
|
+
import { apiClient } from "../../lib/apiClient.js";
|
|
3
2
|
import { z } from "zod";
|
|
4
|
-
import { formatAxiosError } from "../../lib/error.js";
|
|
3
|
+
import { formatAxiosError } from "../../lib/error.js";
|
|
5
4
|
import { projectIdentifierToId } from "./TCG-utils/api.js";
|
|
6
5
|
export const CreateTestCaseSchema = z.object({
|
|
7
6
|
project_identifier: z
|
|
@@ -67,15 +66,19 @@ export function sanitizeArgs(args) {
|
|
|
67
66
|
}
|
|
68
67
|
return cleaned;
|
|
69
68
|
}
|
|
70
|
-
|
|
69
|
+
import { getBrowserStackAuth } from "../../lib/get-auth.js";
|
|
70
|
+
export async function createTestCase(params, config) {
|
|
71
71
|
const body = { test_case: params };
|
|
72
|
+
const authString = getBrowserStackAuth(config);
|
|
73
|
+
const [username, password] = authString.split(":");
|
|
72
74
|
try {
|
|
73
|
-
const response = await
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
const response = await apiClient.post({
|
|
76
|
+
url: `https://test-management.browserstack.com/api/v2/projects/${encodeURIComponent(params.project_identifier)}/folders/${encodeURIComponent(params.folder_id)}/test-cases`,
|
|
77
|
+
headers: {
|
|
78
|
+
"Content-Type": "application/json",
|
|
79
|
+
Authorization: "Basic " + Buffer.from(`${username}:${password}`).toString("base64"),
|
|
77
80
|
},
|
|
78
|
-
|
|
81
|
+
body,
|
|
79
82
|
});
|
|
80
83
|
const { data } = response.data;
|
|
81
84
|
if (!data.success) {
|
|
@@ -91,7 +94,7 @@ export async function createTestCase(params) {
|
|
|
91
94
|
};
|
|
92
95
|
}
|
|
93
96
|
const tc = data.test_case;
|
|
94
|
-
const projectId = await projectIdentifierToId(params.project_identifier);
|
|
97
|
+
const projectId = await projectIdentifierToId(params.project_identifier, config);
|
|
95
98
|
return {
|
|
96
99
|
content: [
|
|
97
100
|
{
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { BrowserStackConfig } from "../../lib/types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Schema for creating a test run.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CreateTestRunSchema: z.ZodObject<{
|
|
8
|
+
project_identifier: z.ZodString;
|
|
9
|
+
test_run: z.ZodObject<{
|
|
10
|
+
name: z.ZodString;
|
|
11
|
+
description: z.ZodOptional<z.ZodString>;
|
|
12
|
+
run_state: z.ZodOptional<z.ZodEnum<["new_run", "in_progress", "under_review", "rejected", "done", "closed"]>>;
|
|
13
|
+
issues: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
14
|
+
issue_tracker: z.ZodOptional<z.ZodObject<{
|
|
15
|
+
name: z.ZodString;
|
|
16
|
+
host: z.ZodString;
|
|
17
|
+
}, "strip", z.ZodTypeAny, {
|
|
18
|
+
name: string;
|
|
19
|
+
host: string;
|
|
20
|
+
}, {
|
|
21
|
+
name: string;
|
|
22
|
+
host: string;
|
|
23
|
+
}>>;
|
|
24
|
+
test_cases: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
25
|
+
folder_ids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
|
|
26
|
+
}, "strip", z.ZodTypeAny, {
|
|
27
|
+
name: string;
|
|
28
|
+
issues?: string[] | undefined;
|
|
29
|
+
description?: string | undefined;
|
|
30
|
+
issue_tracker?: {
|
|
31
|
+
name: string;
|
|
32
|
+
host: string;
|
|
33
|
+
} | undefined;
|
|
34
|
+
test_cases?: string[] | undefined;
|
|
35
|
+
run_state?: "new_run" | "in_progress" | "under_review" | "rejected" | "done" | "closed" | undefined;
|
|
36
|
+
folder_ids?: number[] | undefined;
|
|
37
|
+
}, {
|
|
38
|
+
name: string;
|
|
39
|
+
issues?: string[] | undefined;
|
|
40
|
+
description?: string | undefined;
|
|
41
|
+
issue_tracker?: {
|
|
42
|
+
name: string;
|
|
43
|
+
host: string;
|
|
44
|
+
} | undefined;
|
|
45
|
+
test_cases?: string[] | undefined;
|
|
46
|
+
run_state?: "new_run" | "in_progress" | "under_review" | "rejected" | "done" | "closed" | undefined;
|
|
47
|
+
folder_ids?: number[] | undefined;
|
|
48
|
+
}>;
|
|
49
|
+
}, "strip", z.ZodTypeAny, {
|
|
50
|
+
project_identifier: string;
|
|
51
|
+
test_run: {
|
|
52
|
+
name: string;
|
|
53
|
+
issues?: string[] | undefined;
|
|
54
|
+
description?: string | undefined;
|
|
55
|
+
issue_tracker?: {
|
|
56
|
+
name: string;
|
|
57
|
+
host: string;
|
|
58
|
+
} | undefined;
|
|
59
|
+
test_cases?: string[] | undefined;
|
|
60
|
+
run_state?: "new_run" | "in_progress" | "under_review" | "rejected" | "done" | "closed" | undefined;
|
|
61
|
+
folder_ids?: number[] | undefined;
|
|
62
|
+
};
|
|
63
|
+
}, {
|
|
64
|
+
project_identifier: string;
|
|
65
|
+
test_run: {
|
|
66
|
+
name: string;
|
|
67
|
+
issues?: string[] | undefined;
|
|
68
|
+
description?: string | undefined;
|
|
69
|
+
issue_tracker?: {
|
|
70
|
+
name: string;
|
|
71
|
+
host: string;
|
|
72
|
+
} | undefined;
|
|
73
|
+
test_cases?: string[] | undefined;
|
|
74
|
+
run_state?: "new_run" | "in_progress" | "under_review" | "rejected" | "done" | "closed" | undefined;
|
|
75
|
+
folder_ids?: number[] | undefined;
|
|
76
|
+
};
|
|
77
|
+
}>;
|
|
78
|
+
export type CreateTestRunArgs = z.infer<typeof CreateTestRunSchema>;
|
|
79
|
+
/**
|
|
80
|
+
* Creates a test run via BrowserStack Test Management API.
|
|
81
|
+
*/
|
|
82
|
+
export declare function createTestRun(rawArgs: CreateTestRunArgs, config: BrowserStackConfig): Promise<CallToolResult>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import config from "../../config.js";
|
|
1
|
+
import { apiClient } from "../../lib/apiClient.js";
|
|
3
2
|
import { z } from "zod";
|
|
4
3
|
import { formatAxiosError } from "../../lib/error.js";
|
|
4
|
+
import { getBrowserStackAuth } from "../../lib/get-auth.js";
|
|
5
5
|
/**
|
|
6
6
|
* Schema for creating a test run.
|
|
7
7
|
*/
|
|
@@ -44,7 +44,7 @@ export const CreateTestRunSchema = z.object({
|
|
|
44
44
|
/**
|
|
45
45
|
* Creates a test run via BrowserStack Test Management API.
|
|
46
46
|
*/
|
|
47
|
-
export async function createTestRun(rawArgs) {
|
|
47
|
+
export async function createTestRun(rawArgs, config) {
|
|
48
48
|
try {
|
|
49
49
|
const inputArgs = {
|
|
50
50
|
...rawArgs,
|
|
@@ -55,12 +55,15 @@ export async function createTestRun(rawArgs) {
|
|
|
55
55
|
};
|
|
56
56
|
const args = CreateTestRunSchema.parse(inputArgs);
|
|
57
57
|
const url = `https://test-management.browserstack.com/api/v2/projects/${encodeURIComponent(args.project_identifier)}/test-runs`;
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
const authString = getBrowserStackAuth(config);
|
|
59
|
+
const [username, password] = authString.split(":");
|
|
60
|
+
const response = await apiClient.post({
|
|
61
|
+
url,
|
|
62
|
+
headers: {
|
|
63
|
+
"Content-Type": "application/json",
|
|
64
|
+
Authorization: "Basic " + Buffer.from(`${username}:${password}`).toString("base64"),
|
|
62
65
|
},
|
|
63
|
-
|
|
66
|
+
body: { test_run: args.test_run },
|
|
64
67
|
});
|
|
65
68
|
const data = response.data;
|
|
66
69
|
if (!data.success) {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { BrowserStackConfig } from "../../lib/types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Schema for listing test cases with optional filters.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ListTestCasesSchema: z.ZodObject<{
|
|
8
|
+
project_identifier: z.ZodString;
|
|
9
|
+
folder_id: z.ZodOptional<z.ZodString>;
|
|
10
|
+
case_type: z.ZodOptional<z.ZodString>;
|
|
11
|
+
priority: z.ZodOptional<z.ZodString>;
|
|
12
|
+
p: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
project_identifier: string;
|
|
15
|
+
priority?: string | undefined;
|
|
16
|
+
case_type?: string | undefined;
|
|
17
|
+
folder_id?: string | undefined;
|
|
18
|
+
p?: number | undefined;
|
|
19
|
+
}, {
|
|
20
|
+
project_identifier: string;
|
|
21
|
+
priority?: string | undefined;
|
|
22
|
+
case_type?: string | undefined;
|
|
23
|
+
folder_id?: string | undefined;
|
|
24
|
+
p?: number | undefined;
|
|
25
|
+
}>;
|
|
26
|
+
export type ListTestCasesArgs = z.infer<typeof ListTestCasesSchema>;
|
|
27
|
+
/**
|
|
28
|
+
* Calls BrowserStack Test Management to list test cases with filters.
|
|
29
|
+
*/
|
|
30
|
+
export declare function listTestCases(args: ListTestCasesArgs, config: BrowserStackConfig): Promise<CallToolResult>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import config from "../../config.js";
|
|
1
|
+
import { apiClient } from "../../lib/apiClient.js";
|
|
3
2
|
import { z } from "zod";
|
|
4
3
|
import { formatAxiosError } from "../../lib/error.js";
|
|
4
|
+
import { getBrowserStackAuth } from "../../lib/get-auth.js";
|
|
5
5
|
/**
|
|
6
6
|
* Schema for listing test cases with optional filters.
|
|
7
7
|
*/
|
|
@@ -26,7 +26,7 @@ export const ListTestCasesSchema = z.object({
|
|
|
26
26
|
/**
|
|
27
27
|
* Calls BrowserStack Test Management to list test cases with filters.
|
|
28
28
|
*/
|
|
29
|
-
export async function listTestCases(args) {
|
|
29
|
+
export async function listTestCases(args, config) {
|
|
30
30
|
try {
|
|
31
31
|
// Build query string
|
|
32
32
|
const params = new URLSearchParams();
|
|
@@ -39,10 +39,12 @@ export async function listTestCases(args) {
|
|
|
39
39
|
if (args.p !== undefined)
|
|
40
40
|
params.append("p", args.p.toString());
|
|
41
41
|
const url = `https://test-management.browserstack.com/api/v2/projects/${encodeURIComponent(args.project_identifier)}/test-cases?${params.toString()}`;
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
const authString = getBrowserStackAuth(config);
|
|
43
|
+
const [username, password] = authString.split(":");
|
|
44
|
+
const resp = await apiClient.get({
|
|
45
|
+
url,
|
|
46
|
+
headers: {
|
|
47
|
+
Authorization: "Basic " + Buffer.from(`${username}:${password}`).toString("base64"),
|
|
46
48
|
},
|
|
47
49
|
});
|
|
48
50
|
const resp_data = resp.data;
|