Skip to content

Commit a401fb4

Browse files
committed
test: add GRO-1273 gtm smoke, integration, and regression coverage
1 parent 13bce8c commit a401fb4

11 files changed

Lines changed: 1243 additions & 29 deletions

File tree

.github/workflows/ci.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout
14+
uses: actions/checkout@v4
15+
16+
- name: Setup pnpm
17+
uses: pnpm/action-setup@v4
18+
with:
19+
version: 10
20+
21+
- name: Setup Node
22+
uses: actions/setup-node@v4
23+
with:
24+
node-version: 22
25+
cache: pnpm
26+
27+
- name: Install dependencies
28+
run: pnpm install --frozen-lockfile
29+
30+
- name: Lint
31+
run: pnpm lint
32+
33+
- name: Regression tests
34+
run: pnpm test:regression
35+
36+
- name: Integration tests
37+
run: pnpm test:integration
38+
39+
- name: Install Playwright Chromium
40+
run: pnpm exec playwright install --with-deps chromium
41+
42+
- name: Smoke tests
43+
run: pnpm test:smoke

app/api/agent/route.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,24 @@ import { CoreMessage, generateObject, LanguageModelV1, UserContent } from "ai";
44
import { z } from "zod";
55
import { ObserveResult, Stagehand } from "@browserbasehq/stagehand";
66

7-
const ANTHROPIC_MODEL =
8-
process.env.ANTHROPIC_MODEL || "claude-sonnet-4-6";
9-
const LLMClient = anthropic(ANTHROPIC_MODEL);
7+
export const DEFAULT_ANTHROPIC_MODEL = "claude-sonnet-4-6";
8+
9+
const ANTHROPIC_MODEL_PATTERN = /^claude[-\w.]*$/i;
10+
11+
export function resolveAnthropicModel(rawModel?: string): string {
12+
if (!rawModel) {
13+
return DEFAULT_ANTHROPIC_MODEL;
14+
}
15+
16+
const normalizedModel = rawModel.trim();
17+
if (!normalizedModel || !ANTHROPIC_MODEL_PATTERN.test(normalizedModel)) {
18+
return DEFAULT_ANTHROPIC_MODEL;
19+
}
20+
21+
return normalizedModel;
22+
}
23+
24+
const LLMClient = anthropic(resolveAnthropicModel(process.env.ANTHROPIC_MODEL));
1025

1126
const BANNED_URLS = [
1227
"gemini.browserbase.com",

app/api/session/route.ts

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const offsetRanges: {
4040
{ min: 5, max: 24, region: "ap-southeast-1" }, // UTC+5 to UTC+24
4141
];
4242

43-
function getClosestRegion(timezone?: string): BrowserbaseRegion {
43+
export function getClosestRegion(timezone?: string): BrowserbaseRegion {
4444
try {
4545
if (!timezone) {
4646
return "us-west-2"; // Default if no timezone provided
@@ -76,42 +76,61 @@ function getClosestRegion(timezone?: string): BrowserbaseRegion {
7676
}
7777
}
7878

79+
export function buildBrowserSettings(contextId: string): {
80+
advancedStealth: boolean;
81+
context: { id: string; persist: boolean };
82+
} {
83+
return {
84+
advancedStealth: true,
85+
context: {
86+
id: contextId,
87+
persist: true,
88+
},
89+
};
90+
}
91+
92+
export function buildSessionCreateParams({
93+
projectId,
94+
timezone,
95+
contextId,
96+
}: {
97+
projectId: string;
98+
timezone?: string;
99+
contextId: string;
100+
}) {
101+
return {
102+
projectId,
103+
browserSettings: buildBrowserSettings(contextId),
104+
keepAlive: true,
105+
region: getClosestRegion(timezone),
106+
} as const;
107+
}
108+
79109
async function createSession(timezone?: string, contextId?: string) {
80110
const bb = new Browserbase({
81111
apiKey: process.env.BROWSERBASE_API_KEY!,
82112
});
83-
const browserSettings: {
84-
advancedStealth: boolean;
85-
context?: { id: string; persist: boolean };
86-
} = {
87-
advancedStealth: true,
88-
};
89-
if (contextId) {
90-
browserSettings.context = {
91-
id: contextId,
92-
persist: true,
93-
};
94-
} else {
113+
let sessionContextId = contextId;
114+
115+
if (!sessionContextId) {
95116
const context = await bb.contexts.create({
96117
projectId: process.env.BROWSERBASE_PROJECT_ID!,
97118
});
98-
browserSettings.context = {
99-
id: context.id,
100-
persist: true,
101-
};
119+
sessionContextId = context.id;
102120
}
103121

104122
console.log("timezone ", timezone);
105123
console.log("getClosestRegion(timezone)", getClosestRegion(timezone));
106-
const session = await bb.sessions.create({
107-
projectId: process.env.BROWSERBASE_PROJECT_ID!,
108-
browserSettings,
109-
keepAlive: true,
110-
region: getClosestRegion(timezone),
111-
});
124+
const session = await bb.sessions.create(
125+
buildSessionCreateParams({
126+
projectId: process.env.BROWSERBASE_PROJECT_ID!,
127+
timezone,
128+
contextId: sessionContextId!,
129+
})
130+
);
112131
return {
113132
session,
114-
contextId: browserSettings.context?.id,
133+
contextId: sessionContextId,
115134
};
116135
}
117136

package.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
"dev": "next dev --turbopack",
77
"build": "next build",
88
"start": "next start",
9-
"lint": "next lint"
9+
"lint": "next lint",
10+
"test:regression": "vitest run tests/regression",
11+
"test:integration": "vitest run tests/integration",
12+
"test:smoke": "playwright test",
13+
"test": "pnpm test:regression && pnpm test:integration && pnpm test:smoke"
1014
},
1115
"dependencies": {
1216
"@ai-sdk/anthropic": "^1.2.11",
@@ -28,6 +32,7 @@
2832
"zod": "^3.22.4"
2933
},
3034
"devDependencies": {
35+
"@playwright/test": "^1.50.0",
3136
"@eslint/eslintrc": "^3",
3237
"@types/node": "^20",
3338
"@types/react": "^19",
@@ -36,6 +41,7 @@
3641
"eslint-config-next": "15.1.6",
3742
"postcss": "^8",
3843
"tailwindcss": "^3.4.1",
39-
"typescript": "^5"
44+
"typescript": "^5",
45+
"vitest": "^2.1.8"
4046
}
4147
}

playwright.config.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { defineConfig } from "@playwright/test";
2+
3+
const port = 3005;
4+
const baseURL = `http://127.0.0.1:${port}`;
5+
6+
export default defineConfig({
7+
testDir: "./tests/smoke",
8+
timeout: 45_000,
9+
fullyParallel: true,
10+
use: {
11+
baseURL,
12+
headless: true,
13+
},
14+
webServer: {
15+
command: `pnpm exec next dev --turbopack --port ${port}`,
16+
url: baseURL,
17+
reuseExistingServer: !process.env.CI,
18+
timeout: 180_000,
19+
},
20+
});

0 commit comments

Comments
 (0)