Skip to content

Commit a46e2a9

Browse files
committed
updates
1 parent a253f7b commit a46e2a9

File tree

3 files changed

+124
-56
lines changed

3 files changed

+124
-56
lines changed

.github/workflows/javascript.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
5151
BROWSERSTACK_LOCAL: 'true'
5252
USE_LOCAL_BROWSER: 'false'
53-
VITEST_BROWSER: ${{ matrix.browser }}
53+
TEST_BROWSER: ${{ matrix.browser }}
5454
steps:
5555
- uses: actions/checkout@v3
5656
- name: Set up Node

scripts/run-browser-tests.js

Lines changed: 95 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,27 @@ require('dotenv').config();
2222
const { execSync } = require('child_process');
2323
const browserstack = require('browserstack-local');
2424

25+
// Browser configurations grouped by browser name
26+
const BROWSER_CONFIGS = {
27+
chrome: [
28+
{ name: 'chrome-windows-latest', browserVersion: 'latest', os: 'Windows', osVersion: '11' },
29+
{ name: 'chrome-windows-102', browserVersion: '102', os: 'Windows', osVersion: '11' },
30+
],
31+
firefox: [
32+
{ name: 'firefox-windows-latest', browserVersion: 'latest', os: 'Windows', osVersion: '11' },
33+
{ name: 'firefox-windows-91', browserVersion: '91', os: 'Windows', osVersion: '11' },
34+
],
35+
edge: [
36+
{ name: 'edge-windows-latest', browserVersion: 'latest', os: 'Windows', osVersion: '11' },
37+
{ name: 'edge-windows-84', browserVersion: '84', os: 'Windows', osVersion: '10' },
38+
],
39+
safari: [
40+
{ name: 'safari-monterey', os: 'OS X', osVersion: 'Monterey' },
41+
// { name: 'safari-ventura', os: 'OS X', osVersion: 'Ventura' },
42+
{ name: 'safari-sonoma', os: 'OS X', osVersion: 'Sonoma' },
43+
]
44+
};
45+
2546
// Determine if we should use local browser or BrowserStack
2647
// Priority: USE_LOCAL_BROWSER env var, then check for BrowserStack credentials
2748
let useLocalBrowser = process.env.USE_LOCAL_BROWSER === 'true';
@@ -90,12 +111,18 @@ function stopTunnel() {
90111
});
91112
}
92113

93-
let hasFailures = false;
94-
95114
async function runTests() {
96115
try {
97116
// Get browser name from environment variable (default to chrome)
98-
const browserName = process.env.VITEST_BROWSER || 'chrome';
117+
const browserName = (process.env.TEST_BROWSER || 'chrome').toLowerCase();
118+
119+
// Get configs for this browser
120+
const configs = BROWSER_CONFIGS[browserName];
121+
if (!configs || configs.length === 0) {
122+
console.error(`Error: No configurations found for browser '${browserName}'`);
123+
console.error(`Available browsers: ${Object.keys(BROWSER_CONFIGS).join(', ')}`);
124+
process.exit(1);
125+
}
99126

100127
// Only start tunnel if using BrowserStack
101128
if (!useLocalBrowser) {
@@ -104,47 +131,84 @@ async function runTests() {
104131
console.log('Using local browser mode - no BrowserStack connection needed');
105132
}
106133

107-
console.log(`\n${'='.repeat(80)}`);
108-
console.log(`Running tests on ${useLocalBrowser ? 'local' : 'BrowserStack'}: ${browserName}`);
134+
console.log('\n' + '='.repeat(80));
135+
console.log(`Running tests for browser: ${browserName}`);
136+
console.log(`Total configurations: ${configs.length}`);
137+
console.log('='.repeat(80) + '\n');
138+
139+
const results = [];
140+
141+
// Run each config serially
142+
for (const config of configs) {
143+
console.log(`\n${'='.repeat(80)}`);
144+
console.log(`Running: ${config.name}`);
145+
console.log(`Browser: ${browserName}${config.browserVersion ? ` ${config.browserVersion}` : ''}`);
146+
console.log(`OS: ${config.os} ${config.osVersion}`);
147+
console.log('='.repeat(80));
148+
149+
// Set environment variables for this config
150+
const env = {
151+
...process.env,
152+
USE_LOCAL_BROWSER: useLocalBrowser ? 'true' : 'false',
153+
TEST_BROWSER: browserName,
154+
TEST_BROWSER_VERSION: config.browserVersion || '',
155+
TEST_OS_NAME: config.os,
156+
TEST_OS_VERSION: config.osVersion,
157+
};
158+
159+
try {
160+
// Run vitest with the browser config
161+
execSync('npm run test-vitest -- --config vitest.browser.config.mts', {
162+
stdio: 'inherit',
163+
env,
164+
});
165+
166+
console.log(`\n✓ ${config.name} passed!`);
167+
results.push({ config: config.name, success: true });
168+
} catch (error) {
169+
console.error(`\n✗ ${config.name} failed`);
170+
results.push({ config: config.name, success: false });
171+
}
172+
}
173+
174+
// Print summary
175+
console.log('\n' + '='.repeat(80));
176+
console.log(`Browser test summary for ${browserName}:`);
109177
console.log('='.repeat(80));
110178

111-
// Set environment variables
112-
const env = {
113-
...process.env,
114-
USE_LOCAL_BROWSER: useLocalBrowser ? 'true' : 'false',
115-
VITEST_BROWSER: browserName,
116-
};
117-
118-
try {
119-
// Run vitest with the browser config
120-
execSync('npm run test-vitest -- --config vitest.browser.config.mts', {
121-
stdio: 'inherit',
122-
env,
123-
});
124-
125-
console.log(`\n✓ ${browserName} tests passed!`);
126-
} catch (error) {
127-
console.error(`\n✗ ${browserName} tests failed`);
128-
hasFailures = true;
129-
}
179+
const failures = [];
180+
const successes = [];
130181

131-
console.log(`\n${'='.repeat(80)}`);
132-
console.log('Browser test summary:');
182+
results.forEach(({ config, success }) => {
183+
if (success) {
184+
successes.push(config);
185+
console.log(`✓ ${config}: PASSED`);
186+
} else {
187+
failures.push(config);
188+
console.error(`✗ ${config}: FAILED`);
189+
}
190+
});
191+
192+
console.log('='.repeat(80));
193+
console.log(`Total: ${results.length} configurations`);
194+
console.log(`Passed: ${successes.length}`);
195+
console.log(`Failed: ${failures.length}`);
133196
console.log('='.repeat(80));
134197

135-
if (hasFailures) {
136-
console.error(`${browserName} tests failed. See above for details.`);
198+
// Exit with failure if any config failed
199+
if (failures.length > 0) {
200+
console.error(`\nSome ${browserName} configurations failed. See above for details.`);
201+
process.exit(1);
137202
} else {
138-
console.log(`${browserName} tests passed!`);
203+
console.log(`\nAll ${browserName} configurations passed!`);
204+
process.exit(0);
139205
}
140206
} finally {
141207
// Only stop tunnel if using BrowserStack
142208
if (!useLocalBrowser) {
143209
await stopTunnel();
144210
}
145211
}
146-
147-
process.exit(hasFailures ? 1 : 0);
148212
}
149213

150214
// Run the tests

vitest.browser.config.mts

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -170,23 +170,19 @@ const useLocalBrowser = process.env.USE_LOCAL_BROWSER === 'true';
170170
// };
171171
// }
172172

173-
// Define browser configurations
174-
// BroadcastChannel API support: Safari 15.4+, Edge 84+, Firefox 91+, Chrome 102+, Opera 76+
175-
const allBrowserConfigs = [
176-
{ name: 'chrome', browserName: 'chrome', os: 'Windows', osVersion: '11' },
177-
{ name: 'firefox', browserName: 'firefox', os: 'Windows', osVersion: '11' },
178-
{ name: 'edge', browserName: 'edge', os: 'Windows', osVersion: '11' },
179-
{ name: 'safari', browserName: 'safari', os: 'OS X', osVersion: 'Monterey' },
180-
{ name: 'opera', browserName: 'opera', os: 'Windows', osVersion: '11' },
181-
];
182-
183-
// Get browser from VITEST_BROWSER env var (default to chrome)
184-
const browserName = process.env.VITEST_BROWSER || 'chrome';
185-
const browserConfig = allBrowserConfigs.find(c => c.name === browserName.toLowerCase());
186-
187-
if (!browserConfig) {
188-
throw new Error(`Browser "${browserName}" not found. Available: ${allBrowserConfigs.map(c => c.name).join(', ')}`);
189-
}
173+
// Get browser configuration from TEST_* environment variables
174+
const testBrowser = process.env.TEST_BROWSER || 'chrome';
175+
const testBrowserVersion = process.env.TEST_BROWSER_VERSION || 'latest';
176+
const testOsName = process.env.TEST_OS_NAME || 'Windows';
177+
const testOsVersion = process.env.TEST_OS_VERSION || '11';
178+
179+
const browserConfig = {
180+
name: testBrowser,
181+
browserName: testBrowser,
182+
browserVersion: testBrowserVersion,
183+
os: testOsName,
184+
osVersion: testOsVersion,
185+
};
190186

191187
const browserConfigs = [browserConfig];
192188

@@ -205,7 +201,7 @@ function buildLocalCapabilities(browserName: string) {
205201
}
206202

207203
// Build BrowserStack capabilities
208-
function buildBrowserStackCapabilities(config: typeof allBrowserConfigs[0]) {
204+
function buildBrowserStackCapabilities(config: typeof browserConfig) {
209205
return {
210206
browserName: config.browserName,
211207
// 'goog:chromeOptions': {
@@ -218,15 +214,15 @@ function buildBrowserStackCapabilities(config: typeof allBrowserConfigs[0]) {
218214
'bstack:options': {
219215
os: config.os,
220216
osVersion: config.osVersion,
221-
browserVersion: 'latest',
217+
browserVersion: config.browserVersion,
222218
buildName: process.env.VITEST_BUILD_NAME || 'Vitest Browser Tests',
223219
projectName: 'Optimizely JavaScript SDK',
224-
sessionName: `${config.browserName} on ${config.os} ${config.osVersion}`,
220+
sessionName: `${config.browserName} ${config.browserVersion} on ${config.os} ${config.osVersion}`,
225221
local: process.env.BROWSERSTACK_LOCAL === 'true' ? true : false,
226222
// debug: true,
227223
networkLogs: false,
228224
consoleLogs: 'verbose' as const,
229-
idleTimeout: 300, // 5 minutes idle timeout
225+
idleTimeout: 600, // 10 minutes idle timeout
230226
},
231227
};
232228
}
@@ -239,6 +235,8 @@ function buildBrowserInstances() {
239235
browser: config.browserName,
240236
capabilities: buildLocalCapabilities(config.browserName),
241237
logLevel: 'error' as const,
238+
connectionRetryTimeout: 180000, // 3 minutes
239+
connectionRetryCount: 3,
242240
}));
243241
} else {
244242
// BrowserStack remote configurations - all browsers
@@ -251,6 +249,8 @@ function buildBrowserInstances() {
251249
key: key,
252250
capabilities: buildBrowserStackCapabilities(config),
253251
logLevel: 'error' as const,
252+
connectionRetryTimeout: 180000, // 3 minutes
253+
connectionRetryCount: 3,
254254
}));
255255
}
256256
}
@@ -452,6 +452,9 @@ export default defineConfig({
452452
},
453453
},
454454
test: {
455+
api: {
456+
port: Math.floor(Math.random() * 30001) + 30000,
457+
},
455458
isolate: false,
456459
fileParallelism: true,
457460
browser: {
@@ -461,8 +464,9 @@ export default defineConfig({
461464
// Vitest 3 browser mode configuration
462465
instances: buildBrowserInstances(),
463466
// Increase browser connection timeout for Safari on BrowserStack (default is 60s)
464-
connectTimeout: 180000, // 3 minutes to allow Safari to connect through BrowserStack Local tunnel
467+
connectTimeout: 360000, // 6 minutes to allow Safari to connect through BrowserStack Local tunnel
465468
},
469+
retry: 2, // Retry failed tests up to 2 times
466470
reporters: [
467471
'default',
468472
{
@@ -490,8 +494,8 @@ export default defineConfig({
490494
return true;
491495
},
492496
setupFiles: ['./vitest.setup.ts'],
493-
testTimeout: 120000, // 2 minutes timeout for stability
494-
hookTimeout: 120000,
497+
testTimeout: 240000, // 4 minutes timeout for stability
498+
hookTimeout: 240000,
495499
// pool: 'forks', // Use forks pool to avoid threading issues with BrowserStack
496500
// bail: 1, // Stop on first failure to avoid cascading errors
497501
// Include all .spec.ts files in lib directory, but exclude react_native tests

0 commit comments

Comments
 (0)