Skip to content

Commit a6948c6

Browse files
committed
chore: Run browser contract tests in CI.
1 parent 13ac90e commit a6948c6

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
name: Browser SDK Contract Tests
2+
3+
on:
4+
push:
5+
branches: [main, 'feat/**']
6+
paths-ignore:
7+
- '**.md'
8+
pull_request:
9+
branches: [main, 'feat/**']
10+
paths-ignore:
11+
- '**.md'
12+
13+
jobs:
14+
browser-contract-tests:
15+
runs-on: ubuntu-latest
16+
17+
strategy:
18+
matrix:
19+
node-version: [18, 22]
20+
21+
steps:
22+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
23+
24+
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6
25+
with:
26+
node-version: ${{ matrix.node-version }}
27+
registry-url: 'https://registry.npmjs.org'
28+
29+
- id: shared
30+
name: Shared CI Steps
31+
uses: ./actions/ci
32+
with:
33+
workspace_name: '@launchdarkly/js-client-sdk'
34+
workspace_path: packages/sdk/browser
35+
36+
- name: Install Playwright browsers
37+
run: npx playwright install --with-deps chromium
38+
39+
- name: Install contract test dependencies
40+
run: |
41+
yarn workspace browser-contract-test-adapter install --no-immutable
42+
yarn workspace browser-contract-test-service install --no-immutable
43+
44+
- name: Build contract test adapter
45+
run: yarn workspace browser-contract-test-adapter run build
46+
47+
- name: Build contract test entity (browser app)
48+
run: yarn workspace browser-contract-test-service run build
49+
50+
- name: Start contract test adapter in background
51+
run: |
52+
yarn workspace browser-contract-test-adapter run start > /tmp/adapter.log 2>&1 &
53+
echo $! > /tmp/adapter.pid
54+
55+
- name: Serve browser app with http-server
56+
run: |
57+
npx http-server packages/sdk/browser/contract-tests/entity/dist -p 5173 --cors > /tmp/http-server.log 2>&1 &
58+
echo $! > /tmp/http-server.pid
59+
60+
- name: Wait for services to be ready
61+
run: |
62+
echo "Waiting for adapter on port 8001..."
63+
for i in {1..30}; do
64+
if nc -z localhost 8001; then
65+
echo "Adapter WebSocket ready"
66+
break
67+
fi
68+
if [ $i -eq 30 ]; then
69+
echo "Timeout waiting for adapter"
70+
cat /tmp/adapter.log
71+
exit 1
72+
fi
73+
sleep 1
74+
done
75+
76+
echo "Waiting for HTTP server on port 5173..."
77+
for i in {1..30}; do
78+
if curl -s http://localhost:5173 > /dev/null; then
79+
echo "HTTP server ready"
80+
break
81+
fi
82+
if [ $i -eq 30 ]; then
83+
echo "Timeout waiting for HTTP server"
84+
cat /tmp/http-server.log
85+
exit 1
86+
fi
87+
sleep 1
88+
done
89+
90+
- name: Open browser app in headless Chromium
91+
run: |
92+
node packages/sdk/browser/contract-tests/open-browser.mjs http://localhost:5173 > /tmp/playwright.log 2>&1 &
93+
echo $! > /tmp/playwright.pid
94+
sleep 5 # Give the browser time to initialize and connect via WebSocket
95+
96+
- name: Run contract tests
97+
run: |
98+
mkdir -p /tmp/sdk-test-harness
99+
git clone https://github.com/launchdarkly/sdk-test-harness.git /tmp/sdk-test-harness
100+
cd /tmp/sdk-test-harness
101+
go build -o test-harness .
102+
./test-harness -url http://localhost:8000 -debug -stop-service-at-end --skip-from=$GITHUB_WORKSPACE/packages/sdk/browser/contract-tests/suppressions.txt
103+
env:
104+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
105+
106+
- name: Print logs on failure
107+
if: failure()
108+
run: |
109+
echo "=== Adapter Log ==="
110+
cat /tmp/adapter.log || echo "No adapter log"
111+
echo "=== HTTP Server Log ==="
112+
cat /tmp/http-server.log || echo "No http-server log"
113+
echo "=== Playwright Log ==="
114+
cat /tmp/playwright.log || echo "No playwright log"
115+
116+
- name: Cleanup
117+
if: always()
118+
run: |
119+
[ -f /tmp/playwright.pid ] && kill $(cat /tmp/playwright.pid) || true
120+
[ -f /tmp/http-server.pid ] && kill $(cat /tmp/http-server.pid) || true
121+
[ -f /tmp/adapter.pid ] && kill $(cat /tmp/adapter.pid) || true
122+
pkill -f "playwright" || true
123+
pkill -f "http-server" || true
124+
pkill -f "browser-contract-test-adapter" || true
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* Opens a headless browser and navigates to the contract test entity page.
5+
* Keeps the browser open until the process is terminated.
6+
*
7+
* Usage: node open-browser.mjs [url]
8+
* Default URL: http://localhost:5173
9+
*/
10+
11+
import { chromium } from 'playwright';
12+
13+
const url = process.argv[2] || 'http://localhost:5173';
14+
15+
console.log(`Opening headless browser at ${url}...`);
16+
17+
const browser = await chromium.launch({
18+
headless: true,
19+
args: ['--no-sandbox', '--disable-setuid-sandbox']
20+
});
21+
22+
const context = await browser.newContext();
23+
const page = await context.newPage();
24+
25+
// Log console messages from the browser
26+
page.on('console', (msg) => {
27+
console.log(`[Browser Console] ${msg.type()}: ${msg.text()}`);
28+
});
29+
30+
// Log page errors
31+
page.on('pageerror', (error) => {
32+
console.error(`[Browser Error] ${error.message}`);
33+
});
34+
35+
await page.goto(url);
36+
37+
console.log('Browser is open and running. Press Ctrl+C to close.');
38+
39+
// Keep the process alive
40+
await new Promise(() => {
41+
// Intentionally never resolve - keeps browser open until process is killed
42+
});

0 commit comments

Comments
 (0)