Skip to content

Commit 1974be6

Browse files
authored
🤖 ci: add smoke test to catch MockBrowserWindow regressions (#875)
Adds an npm-based smoke test to CI that validates IPC and WebSocket functionality, catching bugs like the `isDestroyed()` regression before they reach users. **Changes:** - `scripts/smoke-test.sh` - Runs the app headlessly and tests IPC channels + WebSocket connectivity - `.github/workflows/ci.yml` - New `npm-smoke-test` job in merge queue (port 3001, parallel with docker smoke test) _Generated with `mux`_
1 parent 8f162fb commit 1974be6

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

.github/workflows/ci.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,43 @@ jobs:
238238
if: always()
239239
run: docker rm -f mux-test || true
240240

241+
mux-server-smoke-test:
242+
name: Mux Server Smoke Test
243+
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-16' || 'ubuntu-latest' }}
244+
# Tests oRPC/WebSocket flows that catch MockBrowserWindow bugs
245+
steps:
246+
- name: Checkout code
247+
uses: actions/checkout@v4
248+
with:
249+
fetch-depth: 0 # Required for git describe to find tags
250+
251+
- uses: ./.github/actions/setup-mux
252+
253+
- name: Build application
254+
run: make build
255+
256+
- name: Pack npm package
257+
run: npm pack
258+
259+
- name: Run smoke test
260+
env:
261+
SERVER_PORT: 3001
262+
SERVER_HOST: localhost
263+
STARTUP_TIMEOUT: 30
264+
run: |
265+
# Find the actual tarball name (version may vary)
266+
TARBALL=$(ls mux-*.tgz | head -1)
267+
PACKAGE_TARBALL="$TARBALL" ./scripts/smoke-test.sh
268+
269+
- name: Upload server logs on failure
270+
if: failure()
271+
uses: actions/upload-artifact@v4
272+
with:
273+
name: mux-server-smoke-test-logs
274+
path: /tmp/tmp.*/server.log
275+
if-no-files-found: warn
276+
retention-days: 7
277+
241278
check-codex-comments:
242279
name: Check Codex Comments
243280
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-16' || 'ubuntu-latest' }}

scripts/smoke-test.sh

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,5 +172,96 @@ fi
172172

173173
log_info "✅ Root endpoint is accessible"
174174

175+
# Test oRPC functionality - this exercises MockBrowserWindow methods like isDestroyed()
176+
# Uses Node.js with @orpc/client since oRPC uses its own RPC protocol (not simple REST)
177+
log_info "Testing oRPC endpoints via HTTP and WebSocket..."
178+
179+
# Create a temporary git repo for the test project
180+
PROJECT_DIR=$(mktemp -d)
181+
git init -b main "$PROJECT_DIR" >/dev/null 2>&1
182+
git -C "$PROJECT_DIR" config user.email "test@example.com"
183+
git -C "$PROJECT_DIR" config user.name "Test User"
184+
touch "$PROJECT_DIR/README.md"
185+
git -C "$PROJECT_DIR" add .
186+
git -C "$PROJECT_DIR" commit -m "Initial commit" >/dev/null 2>&1
187+
188+
# Run oRPC tests via Node.js using the installed mux package's dependencies
189+
# The mux package includes @orpc/client which we can use
190+
node -e "
191+
const { RPCLink } = require('@orpc/client/fetch');
192+
const { createORPCClient } = require('@orpc/client');
193+
const WebSocket = require('ws');
194+
195+
const ORPC_URL = 'http://${SERVER_HOST}:${SERVER_PORT}/orpc';
196+
const WS_URL = 'ws://${SERVER_HOST}:${SERVER_PORT}/orpc/ws';
197+
const PROJECT_DIR = '$PROJECT_DIR';
198+
199+
async function runTests() {
200+
// Test 1: HTTP oRPC client - create project
201+
console.log('Testing oRPC project creation via HTTP...');
202+
const httpLink = new RPCLink({ url: ORPC_URL });
203+
const client = createORPCClient(httpLink);
204+
205+
const projectResult = await client.projects.create({ projectPath: PROJECT_DIR });
206+
if (!projectResult.success) {
207+
throw new Error('Project creation failed: ' + JSON.stringify(projectResult));
208+
}
209+
console.log('✅ Project created via oRPC HTTP');
210+
211+
// Test 2: HTTP oRPC client - create workspace
212+
console.log('Testing oRPC workspace creation via HTTP...');
213+
const workspaceResult = await client.workspace.create({
214+
projectPath: PROJECT_DIR,
215+
branchName: 'smoke-test-branch',
216+
trunkBranch: 'main'
217+
});
218+
if (!workspaceResult.success) {
219+
throw new Error('Workspace creation failed: ' + JSON.stringify(workspaceResult));
220+
}
221+
console.log('✅ Workspace created via oRPC HTTP (id: ' + workspaceResult.metadata.id + ')');
222+
223+
// Test 3: WebSocket connection
224+
console.log('Testing oRPC WebSocket connection...');
225+
await new Promise((resolve, reject) => {
226+
const ws = new WebSocket(WS_URL);
227+
const timeout = setTimeout(() => {
228+
ws.close();
229+
reject(new Error('WebSocket connection timed out'));
230+
}, 5000);
231+
232+
ws.on('open', () => {
233+
console.log('✅ WebSocket connected successfully');
234+
clearTimeout(timeout);
235+
ws.close();
236+
resolve();
237+
});
238+
239+
ws.on('error', (err) => {
240+
clearTimeout(timeout);
241+
reject(new Error('WebSocket error: ' + err.message));
242+
});
243+
});
244+
245+
console.log('🎉 All oRPC tests passed!');
246+
}
247+
248+
runTests().catch(err => {
249+
console.error('oRPC test failed:', err.message);
250+
process.exit(1);
251+
});
252+
" 2>&1
253+
254+
ORPC_EXIT_CODE=$?
255+
if [[ $ORPC_EXIT_CODE -ne 0 ]]; then
256+
log_error "oRPC tests failed"
257+
rm -rf "$PROJECT_DIR"
258+
exit 1
259+
fi
260+
261+
log_info "✅ oRPC HTTP and WebSocket tests passed"
262+
263+
# Cleanup test project
264+
rm -rf "$PROJECT_DIR"
265+
175266
# All tests passed
176267
log_info "🎉 All smoke tests passed!"

0 commit comments

Comments
 (0)