Skip to content

Commit 24dd079

Browse files
committed
test: add deeper smoke tests for binary and npm bundle
Add smoke tests beyond --help that exercise lazy-loaded code paths (SQLite, telemetry, auth DB, Ink sidecar). This catches require resolution and bundle bugs that --help alone misses. CI build smoke tests (ci.yml): - build-binary: run `auth status` (unauthenticated) after build - exercises SQLite init, schema migrations, telemetry lazy import - asserts exit code 10 (AUTH_NOT_AUTHENTICATED) - build-npm: same test via `node dist/bin.cjs auth status` E2E bundle tests (bundle.test.ts): - auth status: SQLite + telemetry + auth DB via npm bundle - cli defaults: SQLite metadata KV store without auth - Ink sidecar import: verify dist/ink-app.js loads and exports mountApp Closes #1010
1 parent 70460bc commit 24dd079

2 files changed

Lines changed: 112 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,29 @@ jobs:
309309
else
310310
./dist-bin/sentry-${{ matrix.target }} --help
311311
fi
312+
- name: Smoke test (deep — SQLite, telemetry, auth DB)
313+
if: matrix.can-test
314+
shell: bash
315+
run: |
316+
if [[ "${{ matrix.target }}" == "windows-x64" ]]; then
317+
BIN=./dist-bin/sentry-windows-x64.exe
318+
else
319+
BIN=./dist-bin/sentry-${{ matrix.target }}
320+
fi
321+
# auth status without a token exercises SQLite init, schema
322+
# migrations, telemetry lazy import, and the CJS require chain.
323+
# Expected: exit 10 (AUTH_NOT_AUTHENTICATED), NOT a crash/syntax error.
324+
OUTPUT=$($BIN auth status 2>&1) && EXIT_CODE=$? || EXIT_CODE=$?
325+
if [[ $EXIT_CODE -ne 10 ]]; then
326+
echo "::error::Expected exit code 10 (not authenticated), got $EXIT_CODE"
327+
echo "$OUTPUT"
328+
exit 1
329+
fi
330+
if ! echo "$OUTPUT" | grep -qi "not authenticated"; then
331+
echo "::error::Expected 'not authenticated' in output, got:"
332+
echo "$OUTPUT"
333+
exit 1
334+
fi
312335
- name: Upload binary artifact
313336
uses: actions/upload-artifact@v7
314337
with:
@@ -710,6 +733,23 @@ jobs:
710733
run: pnpm run bundle
711734
- name: Smoke test (Node.js)
712735
run: node dist/bin.cjs --help
736+
- name: Smoke test (Node.js — deep)
737+
shell: bash
738+
run: |
739+
# auth status without a token exercises SQLite init, schema
740+
# migrations, telemetry lazy import, and the CJS require chain.
741+
# Expected: exit 10 (AUTH_NOT_AUTHENTICATED), NOT a crash/syntax error.
742+
OUTPUT=$(node dist/bin.cjs auth status 2>&1) && EXIT_CODE=$? || EXIT_CODE=$?
743+
if [[ $EXIT_CODE -ne 10 ]]; then
744+
echo "::error::Expected exit code 10 (not authenticated), got $EXIT_CODE"
745+
echo "$OUTPUT"
746+
exit 1
747+
fi
748+
if ! echo "$OUTPUT" | grep -qi "not authenticated"; then
749+
echo "::error::Expected 'not authenticated' in output, got:"
750+
echo "$OUTPUT"
751+
exit 1
752+
fi
713753
- run: npm pack
714754
- name: Upload artifact
715755
if: matrix.node == '22'

test/e2e/bundle.test.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { spawn } from "node:child_process";
99
import { existsSync, rmSync } from "node:fs";
1010
import { readFile } from "node:fs/promises";
1111
import { join } from "node:path";
12+
import { pathToFileURL } from "node:url";
1213
import { afterAll, beforeAll, describe, expect, test } from "vitest";
1314

1415
function noop(): void {
@@ -45,6 +46,7 @@ async function spawnCollect(
4546

4647
const ROOT_DIR = join(import.meta.dirname, "../..");
4748
const BUNDLE_PATH = join(ROOT_DIR, "dist/bin.cjs");
49+
const INK_APP_PATH = join(ROOT_DIR, "dist/ink-app.js");
4850

4951
describe("npm bundle", () => {
5052
beforeAll(async () => {
@@ -149,4 +151,74 @@ describe("npm bundle", () => {
149151
const output = stdout + stderr;
150152
expect(output.length).toBeGreaterThan(0);
151153
}, 15_000); // Allow up to 15s for cold Node.js JIT startup on slow CI runners
154+
155+
test("bundle exercises SQLite and auth DB (auth status)", async () => {
156+
// Run `auth status` without a token — exercises SQLite initialization,
157+
// schema migrations, auth DB reads, and telemetry lazy import.
158+
// This catches lazy-import and require-resolution bugs that --version misses.
159+
const { stdout, stderr, exitCode } = await spawnCollect(
160+
"node",
161+
[BUNDLE_PATH, "auth", "status"],
162+
{
163+
cwd: ROOT_DIR,
164+
env: {
165+
...process.env,
166+
// Do NOT set SENTRY_CLI_NO_TELEMETRY — we want to exercise telemetry init
167+
SENTRY_AUTH_TOKEN: "",
168+
SENTRY_TOKEN: "",
169+
},
170+
}
171+
);
172+
173+
const output = stdout + stderr;
174+
175+
// Must exit 10 (AUTH_NOT_AUTHENTICATED), not crash
176+
expect(exitCode).toBe(10);
177+
expect(output.toLowerCase()).toContain("not authenticated");
178+
179+
// Must not contain Node.js module resolution errors
180+
expect(output).not.toContain("Cannot find module");
181+
expect(output).not.toContain("MODULE_NOT_FOUND");
182+
expect(output).not.toContain("ERR_MODULE_NOT_FOUND");
183+
}, 15_000);
184+
185+
test("bundle exercises SQLite with cli defaults", async () => {
186+
// `cli defaults` (no args) reads all defaults from SQLite — exercises
187+
// DB init and the metadata KV store without requiring auth.
188+
const { stdout, stderr, exitCode } = await spawnCollect(
189+
"node",
190+
[BUNDLE_PATH, "cli", "defaults"],
191+
{
192+
cwd: ROOT_DIR,
193+
env: {
194+
...process.env,
195+
SENTRY_AUTH_TOKEN: "",
196+
SENTRY_TOKEN: "",
197+
},
198+
}
199+
);
200+
201+
const output = stdout + stderr;
202+
203+
// Should succeed — cli defaults with no args just shows current state
204+
expect(exitCode).toBe(0);
205+
206+
// Must not contain module resolution errors
207+
expect(output).not.toContain("Cannot find module");
208+
expect(output).not.toContain("MODULE_NOT_FOUND");
209+
}, 15_000);
210+
211+
test("Ink sidecar can be imported and exports mountApp", async () => {
212+
// The Ink sidecar (dist/ink-app.js) is a pre-bundled self-contained ESM
213+
// module that ships with the npm package. Verify it exists, can be imported
214+
// by Node, and exports mountApp as a function. This catches sidecar
215+
// bundling/resolution bugs — the exact class of bug where `with { type: "file" }`
216+
// crashed in tsx dev mode.
217+
expect(existsSync(INK_APP_PATH)).toBe(true);
218+
219+
// Node requires a file:// URL for dynamic import of absolute ESM paths
220+
const sidecar = await import(pathToFileURL(INK_APP_PATH).href);
221+
222+
expect(typeof sidecar.mountApp).toBe("function");
223+
}, 15_000);
152224
});

0 commit comments

Comments
 (0)