@browserstack/mcp-server 1.2.8-beta.1 → 1.2.8-beta.2
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.
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { BrowserStackConfig } from "../../lib/types.js";
|
|
4
|
+
export interface TestCaseUpdateRequest {
|
|
5
|
+
project_identifier: string;
|
|
6
|
+
test_case_identifier: string;
|
|
7
|
+
name?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
preconditions?: string;
|
|
10
|
+
test_case_steps?: Array<{
|
|
11
|
+
step: string;
|
|
12
|
+
result: string;
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
export declare const UpdateTestCaseSchema: z.ZodObject<{
|
|
16
|
+
project_identifier: z.ZodString;
|
|
17
|
+
test_case_identifier: z.ZodString;
|
|
18
|
+
name: z.ZodOptional<z.ZodString>;
|
|
19
|
+
description: z.ZodOptional<z.ZodString>;
|
|
20
|
+
preconditions: z.ZodOptional<z.ZodString>;
|
|
21
|
+
test_case_steps: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
22
|
+
step: z.ZodString;
|
|
23
|
+
result: z.ZodString;
|
|
24
|
+
}, "strip", z.ZodTypeAny, {
|
|
25
|
+
step: string;
|
|
26
|
+
result: string;
|
|
27
|
+
}, {
|
|
28
|
+
step: string;
|
|
29
|
+
result: string;
|
|
30
|
+
}>, "many">>;
|
|
31
|
+
}, "strip", z.ZodTypeAny, {
|
|
32
|
+
project_identifier: string;
|
|
33
|
+
test_case_identifier: string;
|
|
34
|
+
name?: string | undefined;
|
|
35
|
+
description?: string | undefined;
|
|
36
|
+
test_case_steps?: {
|
|
37
|
+
step: string;
|
|
38
|
+
result: string;
|
|
39
|
+
}[] | undefined;
|
|
40
|
+
preconditions?: string | undefined;
|
|
41
|
+
}, {
|
|
42
|
+
project_identifier: string;
|
|
43
|
+
test_case_identifier: string;
|
|
44
|
+
name?: string | undefined;
|
|
45
|
+
description?: string | undefined;
|
|
46
|
+
test_case_steps?: {
|
|
47
|
+
step: string;
|
|
48
|
+
result: string;
|
|
49
|
+
}[] | undefined;
|
|
50
|
+
preconditions?: string | undefined;
|
|
51
|
+
}>;
|
|
52
|
+
/**
|
|
53
|
+
* Updates an existing test case in BrowserStack Test Management.
|
|
54
|
+
*/
|
|
55
|
+
export declare function updateTestCase(params: TestCaseUpdateRequest, config: BrowserStackConfig): Promise<CallToolResult>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { apiClient } from "../../lib/apiClient.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { formatAxiosError } from "../../lib/error.js";
|
|
4
|
+
import { projectIdentifierToId } from "./TCG-utils/api.js";
|
|
5
|
+
import { getTMBaseURL } from "../../lib/tm-base-url.js";
|
|
6
|
+
import { getBrowserStackAuth } from "../../lib/get-auth.js";
|
|
7
|
+
import logger from "../../logger.js";
|
|
8
|
+
export const UpdateTestCaseSchema = z.object({
|
|
9
|
+
project_identifier: z
|
|
10
|
+
.string()
|
|
11
|
+
.describe("The ID of the BrowserStack project containing the test case to update."),
|
|
12
|
+
test_case_identifier: z
|
|
13
|
+
.string()
|
|
14
|
+
.describe("The ID of the test case to update. This can be found using the listTestCases tool."),
|
|
15
|
+
name: z.string().optional().describe("Updated name of the test case."),
|
|
16
|
+
description: z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Updated brief description of the test case."),
|
|
20
|
+
preconditions: z
|
|
21
|
+
.string()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Updated preconditions for the test case."),
|
|
24
|
+
test_case_steps: z
|
|
25
|
+
.array(z.object({
|
|
26
|
+
step: z.string().describe("The action to perform in this step."),
|
|
27
|
+
result: z.string().describe("The expected result of this step."),
|
|
28
|
+
}))
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("Updated list of test case steps with expected results."),
|
|
31
|
+
});
|
|
32
|
+
/**
|
|
33
|
+
* Updates an existing test case in BrowserStack Test Management.
|
|
34
|
+
*/
|
|
35
|
+
export async function updateTestCase(params, config) {
|
|
36
|
+
const authString = getBrowserStackAuth(config);
|
|
37
|
+
const [username, password] = authString.split(":");
|
|
38
|
+
// Build the request body with only the fields to update
|
|
39
|
+
const testCaseBody = {};
|
|
40
|
+
if (params.name !== undefined) {
|
|
41
|
+
testCaseBody.name = params.name;
|
|
42
|
+
}
|
|
43
|
+
if (params.description !== undefined) {
|
|
44
|
+
testCaseBody.description = params.description;
|
|
45
|
+
}
|
|
46
|
+
if (params.preconditions !== undefined) {
|
|
47
|
+
testCaseBody.preconditions = params.preconditions;
|
|
48
|
+
}
|
|
49
|
+
if (params.test_case_steps !== undefined) {
|
|
50
|
+
testCaseBody.steps = params.test_case_steps;
|
|
51
|
+
}
|
|
52
|
+
const body = { test_case: testCaseBody };
|
|
53
|
+
try {
|
|
54
|
+
const tmBaseUrl = await getTMBaseURL(config);
|
|
55
|
+
const response = await apiClient.patch({
|
|
56
|
+
url: `${tmBaseUrl}/api/v2/projects/${encodeURIComponent(params.project_identifier)}/test-cases/${encodeURIComponent(params.test_case_identifier)}`,
|
|
57
|
+
headers: {
|
|
58
|
+
"Content-Type": "application/json",
|
|
59
|
+
Authorization: "Basic " + Buffer.from(`${username}:${password}`).toString("base64"),
|
|
60
|
+
},
|
|
61
|
+
body,
|
|
62
|
+
});
|
|
63
|
+
const { data } = response.data;
|
|
64
|
+
if (!data.success) {
|
|
65
|
+
return {
|
|
66
|
+
content: [
|
|
67
|
+
{
|
|
68
|
+
type: "text",
|
|
69
|
+
text: `Failed to update test case: ${JSON.stringify(response.data)}`,
|
|
70
|
+
isError: true,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
isError: true,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
const tc = data.test_case;
|
|
77
|
+
// Convert project identifier to project ID for dashboard URL
|
|
78
|
+
const projectId = await projectIdentifierToId(params.project_identifier, config);
|
|
79
|
+
return {
|
|
80
|
+
content: [
|
|
81
|
+
{
|
|
82
|
+
type: "text",
|
|
83
|
+
text: `Test case successfully updated:
|
|
84
|
+
|
|
85
|
+
**Test Case Details:**
|
|
86
|
+
- **ID**: ${tc.identifier}
|
|
87
|
+
- **Name**: ${tc.title}
|
|
88
|
+
- **Description**: ${tc.description || "N/A"}
|
|
89
|
+
- **Case Type**: ${tc.case_type}
|
|
90
|
+
- **Priority**: ${tc.priority}
|
|
91
|
+
- **Status**: ${tc.status}
|
|
92
|
+
|
|
93
|
+
**View on BrowserStack Dashboard:**
|
|
94
|
+
https://test-management.browserstack.com/projects/${projectId}/folders/${tc.folder_id}/test-cases/${tc.identifier}
|
|
95
|
+
|
|
96
|
+
The test case has been updated successfully and is now available in your BrowserStack Test Management project.`,
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
logger.error("Failed to update test case: %s", err);
|
|
103
|
+
logger.error("Error details:", JSON.stringify(err.response?.data || err.message));
|
|
104
|
+
if (err.response?.status === 404) {
|
|
105
|
+
return {
|
|
106
|
+
content: [
|
|
107
|
+
{
|
|
108
|
+
type: "text",
|
|
109
|
+
text: `Test case not found. Please verify the project_identifier ("${params.project_identifier}") and test_case_identifier ("${params.test_case_identifier}") are correct. Make sure to use actual values, not placeholders like "your_project_id".
|
|
110
|
+
|
|
111
|
+
Error details: ${JSON.stringify(err.response?.data || err.message)}`,
|
|
112
|
+
isError: true,
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
isError: true,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (err.response?.status === 403) {
|
|
119
|
+
return {
|
|
120
|
+
content: [
|
|
121
|
+
{
|
|
122
|
+
type: "text",
|
|
123
|
+
text: "Access denied. You don't have permission to update this test case.",
|
|
124
|
+
isError: true,
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
isError: true,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
const errorMessage = formatAxiosError(err, "Failed to update test case");
|
|
131
|
+
return {
|
|
132
|
+
content: [
|
|
133
|
+
{
|
|
134
|
+
type: "text",
|
|
135
|
+
text: `Failed to update test case: ${errorMessage}. Please verify your credentials and try again.`,
|
|
136
|
+
isError: true,
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
isError: true,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -3,6 +3,7 @@ import { z } from "zod";
|
|
|
3
3
|
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
4
4
|
import { CreateProjFoldSchema } from "./testmanagement-utils/create-project-folder.js";
|
|
5
5
|
import { TestCaseCreateRequest } from "./testmanagement-utils/create-testcase.js";
|
|
6
|
+
import { TestCaseUpdateRequest } from "./testmanagement-utils/update-testcase.js";
|
|
6
7
|
import { ListTestCasesSchema } from "./testmanagement-utils/list-testcases.js";
|
|
7
8
|
import { CreateTestRunSchema } from "./testmanagement-utils/create-testrun.js";
|
|
8
9
|
import { ListTestRunsSchema } from "./testmanagement-utils/list-testruns.js";
|
|
@@ -20,6 +21,10 @@ export declare function createProjectOrFolderTool(args: z.infer<typeof CreatePro
|
|
|
20
21
|
* Creates a test case in BrowserStack Test Management.
|
|
21
22
|
*/
|
|
22
23
|
export declare function createTestCaseTool(args: TestCaseCreateRequest, config: BrowserStackConfig, server: McpServer): Promise<CallToolResult>;
|
|
24
|
+
/**
|
|
25
|
+
* Updates an existing test case in BrowserStack Test Management.
|
|
26
|
+
*/
|
|
27
|
+
export declare function updateTestCaseTool(args: TestCaseUpdateRequest, config: BrowserStackConfig, server: McpServer): Promise<CallToolResult>;
|
|
23
28
|
/**
|
|
24
29
|
* Lists test cases in a project with optional filters (status, priority, custom fields, etc.)
|
|
25
30
|
*/
|
|
@@ -2,6 +2,7 @@ import { trackMCP } from "../lib/instrumentation.js";
|
|
|
2
2
|
import logger from "../logger.js";
|
|
3
3
|
import { createProjectOrFolder, CreateProjFoldSchema, } from "./testmanagement-utils/create-project-folder.js";
|
|
4
4
|
import { createTestCase as createTestCaseAPI, sanitizeArgs, CreateTestCaseSchema, } from "./testmanagement-utils/create-testcase.js";
|
|
5
|
+
import { updateTestCase as updateTestCaseAPI, UpdateTestCaseSchema, } from "./testmanagement-utils/update-testcase.js";
|
|
5
6
|
import { listTestCases, ListTestCasesSchema, } from "./testmanagement-utils/list-testcases.js";
|
|
6
7
|
import { CreateTestRunSchema, createTestRun, } from "./testmanagement-utils/create-testrun.js";
|
|
7
8
|
import { ListTestRunsSchema, listTestRuns, } from "./testmanagement-utils/list-testruns.js";
|
|
@@ -60,6 +61,29 @@ export async function createTestCaseTool(args, config, server) {
|
|
|
60
61
|
};
|
|
61
62
|
}
|
|
62
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Updates an existing test case in BrowserStack Test Management.
|
|
66
|
+
*/
|
|
67
|
+
export async function updateTestCaseTool(args, config, server) {
|
|
68
|
+
try {
|
|
69
|
+
trackMCP("updateTestCase", server.server.getClientVersion(), undefined, config);
|
|
70
|
+
return await updateTestCaseAPI(args, config);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
logger.error("Failed to update test case: %s", err);
|
|
74
|
+
trackMCP("updateTestCase", server.server.getClientVersion(), err, config);
|
|
75
|
+
return {
|
|
76
|
+
content: [
|
|
77
|
+
{
|
|
78
|
+
type: "text",
|
|
79
|
+
text: `Failed to update test case: ${err instanceof Error ? err.message : "Unknown error"}. Please open an issue on GitHub if the problem persists`,
|
|
80
|
+
isError: true,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
isError: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
63
87
|
/**
|
|
64
88
|
* Lists test cases in a project with optional filters (status, priority, custom fields, etc.)
|
|
65
89
|
*/
|
|
@@ -245,6 +269,7 @@ export default function addTestManagementTools(server, config) {
|
|
|
245
269
|
const tools = {};
|
|
246
270
|
tools.createProjectOrFolder = server.tool("createProjectOrFolder", "Create a project and/or folder in BrowserStack Test Management.", CreateProjFoldSchema.shape, (args) => createProjectOrFolderTool(args, config, server));
|
|
247
271
|
tools.createTestCase = server.tool("createTestCase", "Use this tool to create a test case in BrowserStack Test Management.", CreateTestCaseSchema.shape, (args) => createTestCaseTool(args, config, server));
|
|
272
|
+
tools.updateTestCase = server.tool("updateTestCase", "Use this tool to update an existing test case in BrowserStack Test Management. Allows editing test case details like name, description, steps, owner, priority, and more.", UpdateTestCaseSchema.shape, (args) => updateTestCaseTool(args, config, server));
|
|
248
273
|
tools.listTestCases = server.tool("listTestCases", "List test cases in a project with optional filters (status, priority, custom fields, etc.)", ListTestCasesSchema.shape, (args) => listTestCasesTool(args, config, server));
|
|
249
274
|
tools.createTestRun = server.tool("createTestRun", "Create a test run in BrowserStack Test Management.", CreateTestRunSchema.shape, (args) => createTestRunTool(args, config, server));
|
|
250
275
|
tools.listTestRuns = server.tool("listTestRuns", "List test runs in a project with optional filters (date ranges, assignee, state, etc.)", ListTestRunsSchema.shape, (args) => listTestRunsTool(args, config, server));
|