Skip to content

Refactor: Centralize Domain URLs via DOMAINS Object for Improved Configurability #63

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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.BROWSERSTACK_API_DOMAIN || "https://api.browserstack.com",
API_CLOUD:
process.env.BROWSERSTACK_API_CLOUD_DOMAIN || "https://api-cloud.browserstack.com",
TEST_MANAGEMENT:
process.env.BROWSERSTACK_TEST_MGMT_DOMAIN || "https://test-management.browserstack.com",
API_OBSERVABILITY:
process.env.BROWSERSTACK_API_OBSERVABILITY_DOMAIN ||
"https://api-observability.browserstack.com",
LIVE: process.env.BROWSERSTACK_LIVE_DOMAIN || "https://live.browserstack.com",
WWW: process.env.BROWSERSTACK_WWW_DOMAIN || "https://www.browserstack.com",
APP_LIVE: process.env.BROWSERSTACK_APP_LIVE_DOMAIN || "https://app-live.browserstack.com",
API_ACCESSIBILITY:
process.env.BROWSERSTACK_API_ACCESSIBILITY_DOMAIN ||
"https://api-accessibility.browserstack.com",
SCANNER: process.env.BROWSERSTACK_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