Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/lib/api.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import config from "../config.js";
import { DOMAINS } from "./domains.js";

export async function getLatestO11YBuildInfo(
buildName: string,
projectName: string,
) {
const buildsUrl = `https://api-observability.browserstack.com/ext/v1/builds/latest?build_name=${encodeURIComponent(
const buildsUrl = `${DOMAINS.API_OBSERVABILITY}/ext/v1/builds/latest?build_name=${encodeURIComponent(
buildName,
)}&project_name=${encodeURIComponent(projectName)}`;

Expand Down
10 changes: 4 additions & 6 deletions src/lib/device-cache.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from "fs";
import os from "os";
import path from "path";
import { DOMAINS } from "./domains.js";

const CACHE_DIR = path.join(os.homedir(), ".browserstack", "combined_cache");
const CACHE_FILE = path.join(CACHE_DIR, "data.json");
Expand All @@ -13,12 +14,9 @@ export enum BrowserStackProducts {
}

const URLS: Record<BrowserStackProducts, string> = {
[BrowserStackProducts.LIVE]:
"https://www.browserstack.com/list-of-browsers-and-platforms/live.json",
[BrowserStackProducts.APP_LIVE]:
"https://www.browserstack.com/list-of-browsers-and-platforms/app_live.json",
[BrowserStackProducts.APP_AUTOMATE]:
"https://www.browserstack.com/list-of-browsers-and-platforms/app_automate.json",
[BrowserStackProducts.LIVE]: `${DOMAINS.WWW}/list-of-browsers-and-platforms/live.json`,
[BrowserStackProducts.APP_LIVE]: `${DOMAINS.WWW}/list-of-browsers-and-platforms/app_live.json`,
[BrowserStackProducts.APP_AUTOMATE]: `${DOMAINS.WWW}/list-of-browsers-and-platforms/app_automate.json`,
};

/**
Expand Down
17 changes: 17 additions & 0 deletions src/lib/domains.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const DOMAINS = {
API: process.env.API_DOMAIN || "https://api.browserstack.com",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
API: process.env.API_DOMAIN || "https://api.browserstack.com",
API: process.env.BROWSERSTACK_API_DOMAIN || "https://api.browserstack.com",

Add BROWSERSTACK_ prefix to all env vars

API_CLOUD:
process.env.API_CLOUD_DOMAIN || "https://api-cloud.browserstack.com",
TEST_MANAGEMENT:
process.env.TEST_MGMT_DOMAIN || "https://test-management.browserstack.com",
API_OBSERVABILITY:
process.env.API_OBSERVABILITY_DOMAIN ||
"https://api-observability.browserstack.com",
LIVE: process.env.LIVE_DOMAIN || "https://live.browserstack.com",
WWW: process.env.WWW_DOMAIN || "https://www.browserstack.com",
APP_LIVE: process.env.APP_LIVE_DOMAIN || "https://app-live.browserstack.com",
API_ACCESSIBILITY:
process.env.API_ACCESSIBILITY_DOMAIN ||
"https://api-accessibility.browserstack.com",
SCANNER: process.env.SCANNER_DOMAIN || "https://scanner.browserstack.com",
} as const;
3 changes: 2 additions & 1 deletion src/lib/instrumentation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logger from "../logger.js";
import config from "../config.js";
import { createRequire } from "module";
import { DOMAINS } from "./domains.js";
const require = createRequire(import.meta.url);
const packageJson = require("../../package.json");
import axios from "axios";
Expand All @@ -27,7 +28,7 @@ export function trackMCP(
return;
}

const instrumentationEndpoint = "https://api.browserstack.com/sdk/v1/event";
const instrumentationEndpoint = `${DOMAINS.API}/sdk/v1/event`;
const isSuccess = !error;
const mcpClient = clientInfo?.name || "unknown";

Expand Down
5 changes: 3 additions & 2 deletions src/tools/accessibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { AccessibilityScanner } from "./accessiblity-utils/scanner.js";
import { AccessibilityReportFetcher } from "./accessiblity-utils/report-fetcher.js";
import { trackMCP } from "../lib/instrumentation.js";
import { parseAccessibilityReportFromCSV } from "./accessiblity-utils/report-parser.js";
import { DOMAINS } from "../lib/domains.js";

const scanner = new AccessibilityScanner();
const reportFetcher = new AccessibilityReportFetcher();
Expand Down Expand Up @@ -37,7 +38,7 @@ async function runAccessibilityScan(
content: [
{
type: "text",
text: `❌ Accessibility scan "${name}" failed with status: ${status} , check the BrowserStack dashboard for more details [https://scanner.browserstack.com/site-scanner/scan-details/${name}].`,
text: `❌ Accessibility scan "${name}" failed with status: ${status} , check the BrowserStack dashboard for more details [${DOMAINS.SCANNER}/site-scanner/scan-details/${name}].`,
isError: true,
},
],
Expand All @@ -55,7 +56,7 @@ async function runAccessibilityScan(
content: [
{
type: "text",
text: `✅ Accessibility scan "${name}" completed. check the BrowserStack dashboard for more details [https://scanner.browserstack.com/site-scanner/scan-details/${name}].`,
text: `✅ Accessibility scan "${name}" completed. check the BrowserStack dashboard for more details [${DOMAINS.SCANNER}/site-scanner/scan-details/${name}].`,
},
{
type: "text",
Expand Down
5 changes: 3 additions & 2 deletions src/tools/accessiblity-utils/report-fetcher.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import axios from "axios";
import config from "../../config.js";
import { DOMAINS } from "../../lib/domains.js";

interface ReportInitResponse {
success: true;
Expand All @@ -21,7 +22,7 @@ export class AccessibilityReportFetcher {

async getReportLink(scanId: string, scanRunId: string): Promise<string> {
// Initiate CSV link generation
const initUrl = `https://api-accessibility.browserstack.com/api/website-scanner/v1/scans/${scanId}/scan_runs/issues?scan_run_id=${scanRunId}`;
const initUrl = `${DOMAINS.API_ACCESSIBILITY}/api/website-scanner/v1/scans/${scanId}/scan_runs/issues?scan_run_id=${scanRunId}`;
const initResp = await axios.get<ReportInitResponse>(initUrl, {
auth: this.auth,
});
Expand All @@ -33,7 +34,7 @@ export class AccessibilityReportFetcher {
const taskId = initResp.data.data.task_id;

// Fetch the generated CSV link
const reportUrl = `https://api-accessibility.browserstack.com/api/website-scanner/v1/scans/${scanId}/scan_runs/issues?task_id=${encodeURIComponent(
const reportUrl = `${DOMAINS.API_ACCESSIBILITY}/api/website-scanner/v1/scans/${scanId}/scan_runs/issues?task_id=${encodeURIComponent(
taskId,
)}`;
const reportResp = await axios.get<ReportResponse>(reportUrl, {
Expand Down
5 changes: 3 additions & 2 deletions src/tools/accessiblity-utils/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ensureLocalBinarySetup,
killExistingBrowserStackLocalProcesses,
} from "../../lib/local.js";
import { DOMAINS } from "../../lib/domains.js";

export interface AccessibilityScanResponse {
success: boolean;
Expand Down Expand Up @@ -74,7 +75,7 @@ export class AccessibilityScanner {

try {
const { data } = await axios.post<AccessibilityScanResponse>(
"https://api-accessibility.browserstack.com/api/website-scanner/v1/scans",
`${DOMAINS.API_ACCESSIBILITY}/api/website-scanner/v1/scans`,
requestBody,
{ auth: this.auth },
);
Expand All @@ -99,7 +100,7 @@ export class AccessibilityScanner {
): Promise<AccessibilityScanStatus> {
try {
const { data } = await axios.get<AccessibilityScanStatus>(
`https://api-accessibility.browserstack.com/api/website-scanner/v1/scans/${scanId}/scan_runs/${scanRunId}/status`,
`${DOMAINS.API_ACCESSIBILITY}/api/website-scanner/v1/scans/${scanId}/scan_runs/${scanRunId}/status`,
{ auth: this.auth },
);
if (!data.success)
Expand Down
3 changes: 2 additions & 1 deletion src/tools/appautomate-utils/appautomate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import axios from "axios";
import config from "../../config.js";
import FormData from "form-data";
import { customFuzzySearch } from "../../lib/fuzzy.js";
import { DOMAINS } from "../../lib/domains.js";

interface Device {
device: string;
Expand Down Expand Up @@ -135,7 +136,7 @@ export async function uploadApp(appPath: string): Promise<string> {
formData.append("file", fs.createReadStream(filePath));

const response = await axios.post<UploadResponse>(
"https://api-cloud.browserstack.com/app-automate/upload",
`${DOMAINS.API_CLOUD}/app-automate/upload`,
formData,
{
headers: {
Expand Down
3 changes: 2 additions & 1 deletion src/tools/applive-utils/start-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { uploadApp } from "./upload-app.js";
import { findDeviceByName } from "./device-search.js";
import { pickVersion } from "./version-utils.js";
import { DeviceEntry } from "./types.js";
import { DOMAINS } from "../../lib/domains.js";

interface StartSessionArgs {
appPath: string;
Expand Down Expand Up @@ -76,7 +77,7 @@ export async function startSession(args: StartSessionArgs): Promise<string> {
speed: "1",
start: "true",
});
const launchUrl = `https://app-live.browserstack.com/dashboard#${params.toString()}&device=${deviceParam}`;
const launchUrl = `${DOMAINS.APP_LIVE}/dashboard#${params.toString()}&device=${deviceParam}`;

openBrowser(launchUrl);
return launchUrl + note;
Expand Down
4 changes: 2 additions & 2 deletions src/tools/applive-utils/upload-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import axios, { AxiosError } from "axios";
import FormData from "form-data";
import fs from "fs";
import config from "../../config.js";

import { DOMAINS } from "../../lib/domains.js";
interface UploadResponse {
app_url: string;
}
Expand All @@ -17,7 +17,7 @@ export async function uploadApp(filePath: string): Promise<UploadResponse> {

try {
const response = await axios.post<UploadResponse>(
"https://api-cloud.browserstack.com/app-live/upload",
`${DOMAINS.API_CLOUD}/app-live/upload`,
formData,
{
headers: {
Expand Down
3 changes: 2 additions & 1 deletion src/tools/automate-utils/fetch-screenshots.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import config from "../../config.js";
import { assertOkResponse, maybeCompressBase64 } from "../../lib/utils.js";
import { SessionType } from "../../lib/constants.js";
import { DOMAINS } from "../../lib/domains.js";

//Extracts screenshot URLs from BrowserStack session logs
async function extractScreenshotUrls(
Expand All @@ -10,7 +11,7 @@ async function extractScreenshotUrls(
const credentials = `${config.browserstackUsername}:${config.browserstackAccessKey}`;
const auth = Buffer.from(credentials).toString("base64");

const baseUrl = `https://api.browserstack.com/${sessionType === SessionType.Automate ? "automate" : "app-automate"}`;
const baseUrl = `${DOMAINS.API}/${sessionType === SessionType.Automate ? "automate" : "app-automate"}`;

const url = `${baseUrl}/sessions/${sessionId}/logs`;
const response = await fetch(url, {
Expand Down
7 changes: 4 additions & 3 deletions src/tools/failurelogs-utils/app-automate.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import config from "../../config.js";
import { filterLinesByKeywords, validateLogResponse } from "./utils.js";
import { DOMAINS } from "../../lib/domains.js";

const auth = Buffer.from(
`${config.browserstackUsername}:${config.browserstackAccessKey}`,
Expand All @@ -10,7 +11,7 @@ export async function retrieveDeviceLogs(
sessionId: string,
buildId: string,
): Promise<string> {
const url = `https://api.browserstack.com/app-automate/builds/${buildId}/sessions/${sessionId}/deviceLogs`;
const url = `${DOMAINS.API}/app-automate/builds/${buildId}/sessions/${sessionId}/deviceLogs`;

const response = await fetch(url, {
headers: {
Expand All @@ -34,7 +35,7 @@ export async function retrieveAppiumLogs(
sessionId: string,
buildId: string,
): Promise<string> {
const url = `https://api.browserstack.com/app-automate/builds/${buildId}/sessions/${sessionId}/appiumlogs`;
const url = `${DOMAINS.API}/app-automate/builds/${buildId}/sessions/${sessionId}/appiumlogs`;

const response = await fetch(url, {
headers: {
Expand All @@ -58,7 +59,7 @@ export async function retrieveCrashLogs(
sessionId: string,
buildId: string,
): Promise<string> {
const url = `https://api.browserstack.com/app-automate/builds/${buildId}/sessions/${sessionId}/crashlogs`;
const url = `${DOMAINS.API}/app-automate/builds/${buildId}/sessions/${sessionId}/crashlogs`;

const response = await fetch(url, {
headers: {
Expand Down
7 changes: 4 additions & 3 deletions src/tools/failurelogs-utils/automate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
filterLinesByKeywords,
validateLogResponse,
} from "./utils.js";
import { DOMAINS } from "../../lib/domains.js";

const auth = Buffer.from(
`${config.browserstackUsername}:${config.browserstackAccessKey}`,
Expand All @@ -14,7 +15,7 @@ const auth = Buffer.from(
export async function retrieveNetworkFailures(
sessionId: string,
): Promise<string> {
const url = `https://api.browserstack.com/automate/sessions/${sessionId}/networklogs`;
const url = `${DOMAINS.API}/automate/sessions/${sessionId}/networklogs`;

const response = await fetch(url, {
method: "GET",
Expand Down Expand Up @@ -62,7 +63,7 @@ export async function retrieveNetworkFailures(
export async function retrieveSessionFailures(
sessionId: string,
): Promise<string> {
const url = `https://api.browserstack.com/automate/sessions/${sessionId}/logs`;
const url = `${DOMAINS.API}/automate/sessions/${sessionId}/logs`;

const response = await fetch(url, {
headers: {
Expand All @@ -85,7 +86,7 @@ export async function retrieveSessionFailures(
export async function retrieveConsoleFailures(
sessionId: string,
): Promise<string> {
const url = `https://api.browserstack.com/automate/sessions/${sessionId}/consolelogs`;
const url = `${DOMAINS.API}/automate/sessions/${sessionId}/consolelogs`;

const response = await fetch(url, {
headers: {
Expand Down
5 changes: 3 additions & 2 deletions src/tools/live-utils/start-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import logger from "../../logger.js";
import childProcess from "child_process";
import { filterDesktop } from "./desktop-filter.js";
import { filterMobile } from "./mobile-filter.js";
import { DOMAINS } from "../../lib/domains.js";
import {
DesktopSearchArgs,
MobileSearchArgs,
Expand Down Expand Up @@ -71,7 +72,7 @@ function buildDesktopUrl(
local: isLocal ? "true" : "false",
start: "true",
});
return `https://live.browserstack.com/dashboard#${params.toString()}`;
return `${DOMAINS.LIVE}/dashboard#${params.toString()}`;
}

function buildMobileUrl(
Expand All @@ -97,7 +98,7 @@ function buildMobileUrl(
local: isLocal ? "true" : "false",
start: "true",
});
return `https://live.browserstack.com/dashboard#${params.toString()}`;
return `${DOMAINS.LIVE}/dashboard#${params.toString()}`;
}

// ——— Open a browser window ———
Expand Down
4 changes: 2 additions & 2 deletions src/tools/selfheal-utils/selfheal.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { assertOkResponse } from "../../lib/utils.js";
import config from "../../config.js";

import { DOMAINS } from "../../lib/domains.js";
interface SelectorMapping {
originalSelector: string;
healedSelector: string;
Expand All @@ -13,7 +13,7 @@ interface SelectorMapping {
export async function getSelfHealSelectors(sessionId: string) {
const credentials = `${config.browserstackUsername}:${config.browserstackAccessKey}`;
const auth = Buffer.from(credentials).toString("base64");
const url = `https://api.browserstack.com/automate/sessions/${sessionId}/logs`;
const url = `${DOMAINS.API_CLOUD}/automate/sessions/${sessionId}/logs`;

const response = await fetch(url, {
headers: {
Expand Down
5 changes: 3 additions & 2 deletions src/tools/testmanagement-utils/TCG-utils/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from "./types.js";
import { createTestCasePayload } from "./helpers.js";
import config from "../../../config.js";
import { DOMAINS } from "../../../lib/domains.js";

/**
* Fetch default and custom form fields for a project.
Expand Down Expand Up @@ -46,7 +47,7 @@ export async function triggerTestCaseGeneration(
folderId,
projectId,
source,
webhookUrl: `https://test-management.browserstack.com/api/v1/projects/${projectId}/folder/${folderId}/webhooks/tcg`,
webhookUrl: `${DOMAINS.TEST_MANAGEMENT}/api/v1/projects/${projectId}/folder/${folderId}/webhooks/tcg`,
},
{
headers: {
Expand Down Expand Up @@ -343,7 +344,7 @@ export async function bulkCreateTestCases(
export async function projectIdentifierToId(
projectId: string,
): Promise<string> {
const url = `https://test-management.browserstack.com/api/v1/projects/?q=${projectId}`;
const url = `${DOMAINS.TEST_MANAGEMENT}/api/v1/projects/?q=${projectId}`;

const response = await axios.get(url, {
headers: {
Expand Down
15 changes: 7 additions & 8 deletions src/tools/testmanagement-utils/TCG-utils/config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
export const TCG_TRIGGER_URL =
"https://test-management.browserstack.com/api/v1/integration/tcg/test-generation/suggest-test-cases";
export const TCG_POLL_URL =
"https://test-management.browserstack.com/api/v1/integration/tcg/test-generation/test-cases-polling";
export const FETCH_DETAILS_URL =
"https://test-management.browserstack.com/api/v1/integration/tcg/test-generation/fetch-test-case-details";
import { DOMAINS } from "../../../lib/domains.js";

export const TCG_TRIGGER_URL = `${DOMAINS.TEST_MANAGEMENT}/api/v1/integration/tcg/test-generation/suggest-test-cases`;
export const TCG_POLL_URL = `${DOMAINS.TEST_MANAGEMENT}/api/v1/integration/tcg/test-generation/test-cases-polling`;
export const FETCH_DETAILS_URL = `${DOMAINS.TEST_MANAGEMENT}/api/v1/integration/tcg/test-generation/fetch-test-case-details`;
export const FORM_FIELDS_URL = (projectId: string): string =>
`https://test-management.browserstack.com/api/v1/projects/${projectId}/form-fields-v2`;
`${DOMAINS.TEST_MANAGEMENT}/api/v1/projects/${projectId}/form-fields-v2`;
export const BULK_CREATE_URL = (projectId: string, folderId: string): string =>
`https://test-management.browserstack.com/api/v1/projects/${projectId}/folder/${folderId}/bulk-test-cases`;
`${DOMAINS.TEST_MANAGEMENT}/api/v1/projects/${projectId}/folder/${folderId}/bulk-test-cases`;
4 changes: 2 additions & 2 deletions src/tools/testmanagement-utils/add-test-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import config from "../../config.js";
import { z } from "zod";
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
import { formatAxiosError } from "../../lib/error.js";

import { DOMAINS } from "../../lib/domains.js";
/**
* Schema for adding a test result to a test run.
*/
Expand Down Expand Up @@ -36,7 +36,7 @@ export async function addTestResult(
): Promise<CallToolResult> {
try {
const args = AddTestResultSchema.parse(rawArgs);
const url = `https://test-management.browserstack.com/api/v2/projects/${encodeURIComponent(
const url = `${DOMAINS.TEST_MANAGEMENT}/api/v2/projects/${encodeURIComponent(
args.project_identifier,
)}/test-runs/${encodeURIComponent(args.test_run_id)}/results`;

Expand Down
Loading