Skip to content

Commit 9172fa2

Browse files
hotlongclaude
andauthored
test(showcase): put e2e/global-setup.ts in a tsc program and fix what that reads (#8178)
The package include was `e2e/**/*.spec.ts`, so `e2e/global-setup.ts` — the fixture that authenticates the whole smoke run — was read by no tsc program at all, and the coverage gate counts test files so nothing else covered it either. Widen the glob to the wholesale `e2e/**/*` and fix the 6 errors that exposes at their source rather than excluding them: - file-local `declare const process` in global-setup.ts, the idiom already used by objectstack.config.ts, src/system/self-url.ts and the three e2e specs (3x TS2339); - `mkdirSync`/`writeFileSync` on the `node:fs` shim and a minimal `node:path` module declaration (TS2305 / TS2724 / TS2591). The shim moves `test/node-shim.d.ts` -> `types/node-shim.d.ts`: both trees depend on it now, and under the old name a narrowing for the test layer would have broken the e2e program with nothing in the path to warn the author. `playwright.config.ts` was dark in exactly the same way and takes the same one-liner. `vitest.config.ts` is deliberately left out — its `vitest/config` import transitively pulls in the whole of `@types/node`, the type surface this package is deliberately without. All changes are type-level (`declare` statements erase at emit, `.d.ts` files emit nothing), so the smoke run's runtime behaviour is unchanged. Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1020238 commit 9172fa2

9 files changed

Lines changed: 76 additions & 35 deletions

examples/app-showcase/e2e/bulk-capability-gate.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { test, expect } from '@playwright/test';
2727
*/
2828

2929
// Ambient `process` for the env read below — the showcase tsconfig doesn't pull
30-
// in `@types/node`, and the package-global shim in test/node-shim.d.ts declares
30+
// in `@types/node`, and the package-global shim in types/node-shim.d.ts declares
3131
// only `cwd()`. Same idiom (and same reason) as the declarations in
3232
// objectstack.config.ts and src/system/self-url.ts: keeps `pnpm typecheck` green
3333
// without widening the type surface. Playwright provides the real `process`.

examples/app-showcase/e2e/detail-shapes.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { test, expect } from '@playwright/test';
2727
*/
2828

2929
// Ambient `process` for the env reads below — the showcase tsconfig doesn't pull
30-
// in `@types/node`, and the package-global shim in test/node-shim.d.ts declares
30+
// in `@types/node`, and the package-global shim in types/node-shim.d.ts declares
3131
// only `cwd()`. Same idiom (and same reason) as the declarations in
3232
// objectstack.config.ts and src/system/self-url.ts: keeps `pnpm typecheck` green
3333
// without widening the type surface. Playwright provides the real `process`.

examples/app-showcase/e2e/global-setup.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ import { request } from '@playwright/test';
22
import { mkdirSync, writeFileSync } from 'node:fs';
33
import { dirname } from 'node:path';
44

5+
// Ambient `process` with `env` — types/node-shim.d.ts declares the global as
6+
// `{ cwd(): string }` only, so each module that reads env widens it locally.
7+
// Same one-liner as the specs beside this file and objectstack.config.ts.
8+
// Declared above the block comment below so that comment stays attached to the
9+
// first emitted statement.
10+
declare const process: { env: Record<string, string | undefined> };
11+
512
/**
613
* Auth for the showcase smoke: sign in against the backend (better-auth) and
714
* persist a Playwright storageState. The console (served at :3000/_console)

examples/app-showcase/e2e/showcase-smoke.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { test, expect } from '@playwright/test';
88
*/
99

1010
// Ambient `process` for the env read below — the showcase tsconfig doesn't pull
11-
// in `@types/node`, and the package-global shim in test/node-shim.d.ts declares
11+
// in `@types/node`, and the package-global shim in types/node-shim.d.ts declares
1212
// only `cwd()`. Same idiom (and same reason) as the declarations in
1313
// objectstack.config.ts and src/system/self-url.ts: keeps `pnpm typecheck` green
1414
// without widening the type surface. Playwright provides the real `process`.

examples/app-showcase/playwright.config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { defineConfig, devices } from '@playwright/test';
22

3+
// Ambient `process` with `env` — types/node-shim.d.ts declares the global as
4+
// `{ cwd(): string }` only, so each module that reads env widens it locally.
5+
// Declared above the block comment below so that comment stays attached to the
6+
// first emitted statement.
7+
declare const process: { env: Record<string, string | undefined> };
8+
39
/**
410
* Showcase smoke — drives the console (served by the backend at /_console)
511
* across every nav surface. `webServer` boots the real backend so CI only needs

examples/app-showcase/test/connector-self-url.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {
3131
* detect the bug, so both halves are required.
3232
*/
3333

34-
// Ambient `process` with `env` — test/node-shim.d.ts declares the global as
34+
// Ambient `process` with `env` — types/node-shim.d.ts declares the global as
3535
// `{ cwd(): string }` only, and this module-scoped declaration shadows it
3636
// rather than widening the shared shim (the same idiom objectstack.config.ts
3737
// uses for its own env reads).

examples/app-showcase/test/node-shim.d.ts

Lines changed: 0 additions & 17 deletions
This file was deleted.

examples/app-showcase/tsconfig.json

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,30 @@
1010
"outDir": "./dist",
1111
"rootDir": "."
1212
},
13-
// `e2e/**/*.spec.ts`, NOT `e2e/**/*` (#7923). This package took the widened-
14-
// `include` route rather than a sibling `tsconfig.test.json` because its
15-
// `rootDir` is already the package root, so nothing here needs neutralising —
16-
// the same repair #7312 applied to app-crm / app-todo.
13+
// This package took the widened-`include` route rather than a sibling
14+
// `tsconfig.test.json` because its `rootDir` is already the package root, so
15+
// nothing here needs neutralising — the same repair #7312 applied to
16+
// app-crm / app-todo.
1717
//
18-
// The glob is spec-scoped on purpose, and it is the trap the TEST_DEBT entry
19-
// that this change deletes was written to warn about: `e2e/**/*` would also
20-
// pull in `e2e/global-setup.ts`, a Playwright fixture rather than a test,
21-
// which carries 6 errors of its own (3 `process.env` reads plus 3 gaps in
22-
// test/node-shim.d.ts — no `mkdirSync`/`writeFileSync` on the `node:fs` shim
23-
// and no `node:path` module at all). Billing the test layer for a non-test
24-
// file is what the ledger note measured around, so the repair holds the same
25-
// line. `global-setup.ts` therefore stays outside this program; it is filed
26-
// separately rather than silently folded in here.
27-
"include": ["src/**/*", "objectstack.config.ts", "test/**/*", "e2e/**/*.spec.ts"]
18+
// `e2e/**/*` is deliberately wholesale, not `e2e/**/*.spec.ts` (#8062): the
19+
// spec-scoped form left `e2e/global-setup.ts` — the fixture that authenticates
20+
// the whole smoke run — read by no tsc program at all, and the coverage gate
21+
// counts test files, so nothing else had an opinion on it either. The 6 errors
22+
// the narrow glob was avoiding are fixed at their source rather than excluded
23+
// (file-local `declare const process`, plus the `node:fs`/`node:path` members
24+
// in types/node-shim.d.ts), so the wholesale form now costs nothing.
25+
//
26+
// `playwright.config.ts` is named for the same reason: it configures that same
27+
// smoke lane and was dark in exactly the same way. `vitest.config.ts` is NOT
28+
// named — its `vitest/config` import transitively drags in the whole of
29+
// `@types/node`, which is precisely the type surface this package is
30+
// deliberately without (see types/node-shim.d.ts).
31+
"include": [
32+
"src/**/*",
33+
"objectstack.config.ts",
34+
"playwright.config.ts",
35+
"types/**/*",
36+
"test/**/*",
37+
"e2e/**/*"
38+
]
2839
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
// Minimal ambient surface for the node builtins this package touches. The
4+
// showcase tsconfig deliberately omits `@types/node` (see the ambient
5+
// `process` note in objectstack.config.ts); the real implementations come from
6+
// the runtime — vitest for `test/`, the Playwright runner for `e2e/`.
7+
//
8+
// It lives in `types/`, not `test/`, because both trees depend on it: `test/`
9+
// for `existsSync`/`readFileSync`/`readdirSync` and the `process.cwd()` global,
10+
// `e2e/` for `mkdirSync`/`writeFileSync`/`dirname` in global-setup.ts. Under the
11+
// old `test/` name, narrowing it for the test layer would have broken the e2e
12+
// program with nothing in the path to warn the author.
13+
//
14+
// Declare only the members actually imported. Staying narrower than
15+
// `@types/node` is the point: it IS installed at the workspace root and would
16+
// resolve if this package named it in `compilerOptions.types`, at the cost of
17+
// the whole node global surface the package is deliberately without.
18+
19+
declare module 'node:fs' {
20+
export function existsSync(path: string): boolean;
21+
export function readFileSync(path: string, encoding: 'utf8'): string;
22+
export function readdirSync(
23+
path: string,
24+
options: { withFileTypes: true },
25+
): Array<{ name: string; isDirectory(): boolean }>;
26+
export function mkdirSync(path: string, options: { recursive: true }): string | undefined;
27+
export function writeFileSync(path: string, data: string): void;
28+
}
29+
30+
declare module 'node:path' {
31+
export function dirname(path: string): string;
32+
}
33+
34+
declare const process: { cwd(): string };

0 commit comments

Comments
 (0)