Skip to content

Commit 785590f

Browse files
committed
test(spec): three src/ test-budget rows wait on module loads and a doubled parse, not on what they assert
view.test.ts loaded the ./shared, ./ui and ./api entries by await import() inside four cases; app.test.ts loaded typescript inside its compiler-API case. Both loads move to module top, where a clocked window does not count them. The allowOrgOverride absence walk parsed every file holding both the old and the new key name twice; it now parses each file once and reads both names off the one tree. Every expect is unchanged. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VTJ1Sey3QK5wZbayQXfFfH
1 parent f846cc2 commit 785590f

3 files changed

Lines changed: 40 additions & 31 deletions

File tree

‎packages/spec/src/kernel/metadata-type-registry-allow-org-override-absence.test.ts‎

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,36 @@ describe('tree-scoped absence: no TypeScript source in the declared radius reads
5858
&& ts.isIdentifier(node.parent.initializer.expression)
5959
&& node.parent.initializer.expression.text === 'retiredKey';
6060

61-
/** Every CODE reference to `name` in `text`, as `line:col` — identifiers and quoted keys, never comments or prose strings. */
62-
const codeReferences = (fileName: string, text: string, name: string): string[] => {
61+
/**
62+
* Every CODE reference to each of `names` in `text`, as `line:col` per name —
63+
* identifiers and quoted keys, never comments or prose strings. One parse
64+
* serves every name: the walk below asks two names of the same file, and the
65+
* files holding both are the largest in the radius (megabytes each).
66+
*/
67+
const codeReferencesByName = (fileName: string, text: string, names: readonly string[]): Map<string, string[]> => {
6368
const sf = ts.createSourceFile(fileName, text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
64-
const found: string[] = [];
65-
const at = (node: ts.Node) => {
69+
const found = new Map(names.map((name) => [name, [] as string[]]));
70+
const at = (name: string, node: ts.Node) => {
6671
const { line, character } = sf.getLineAndCharacterOfPosition(node.getStart(sf));
67-
found.push(`${line + 1}:${character + 1}`);
72+
found.get(name)!.push(`${line + 1}:${character + 1}`);
6873
};
6974
const visit = (node: ts.Node) => {
70-
if (ts.isIdentifier(node) && node.text === name && !isTombstoneDeclaration(node)) at(node);
71-
else if (ts.isStringLiteral(node) && node.text === name && node.parent) {
75+
if (ts.isIdentifier(node) && found.has(node.text) && !isTombstoneDeclaration(node)) at(node.text, node);
76+
else if (ts.isStringLiteral(node) && found.has(node.text) && node.parent) {
7277
const p = node.parent;
7378
// A quoted key or an element access is a reference; any other string is prose.
7479
if ((ts.isPropertyAssignment(p) && p.name === node)
7580
|| (ts.isElementAccessExpression(p) && p.argumentExpression === node)
76-
|| (ts.isPropertySignature(p) && p.name === node)) at(node);
81+
|| (ts.isPropertySignature(p) && p.name === node)) at(node.text, node);
7782
}
7883
ts.forEachChild(node, visit);
7984
};
8085
visit(sf);
8186
return found;
8287
};
88+
/** Every CODE reference to `name` in `text`, as `line:col`. */
89+
const codeReferences = (fileName: string, text: string, name: string): string[] =>
90+
codeReferencesByName(fileName, text, [name]).get(name)!;
8391

8492
it('the matcher sees a code reference and ignores a mention (anti-vacuity)', () => {
8593
const refs = (src: string) => codeReferences('probe.ts', src, OLD);
@@ -122,9 +130,11 @@ describe('tree-scoped absence: no TypeScript source in the declared radius reads
122130
if ((err as NodeJS.ErrnoException)?.code === 'ENOENT') continue;
123131
throw err;
124132
}
125-
if (text.includes(NEW) && codeReferences(rel, text, NEW).length > 0) newReaders.add(rel);
126-
if (!text.includes(OLD)) continue;
127-
for (const where of codeReferences(rel, text, OLD)) {
133+
const names = [NEW, OLD].filter((name) => text.includes(name));
134+
if (names.length === 0) continue;
135+
const refs = codeReferencesByName(rel, text, names);
136+
if ((refs.get(NEW)?.length ?? 0) > 0) newReaders.add(rel);
137+
for (const where of refs.get(OLD) ?? []) {
128138
(rel === REFUSAL_PIN ? refusalPinReferences : offenders).push(`${rel}:${where}`);
129139
}
130140
}

‎packages/spec/src/ui/app.test.ts‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
import { describe, it, expect } from 'vitest';
2+
// Loaded here, at module top, not inside the compiler-API case below: a
3+
// clocked window measures behaviour, never loading, and `typescript` alone is
4+
// about 300 ms of module load.
5+
import ts from 'typescript';
6+
import { dirname, resolve } from 'node:path';
7+
import { fileURLToPath } from 'node:url';
28
import {
39
AppSchema,
410
AppBrandingSchema,
@@ -1587,11 +1593,7 @@ describe('unknown keys are rejected, not stripped', () => {
15871593
// compiler API and reads its members — the same symbol-identity measurement
15881594
// `check:dual-source-exports` makes, over `src/`, so it runs in `pnpm test`
15891595
// without a build.
1590-
it('the retired gates are gone from the TYPE, not only from the parse (compiler API)', async () => {
1591-
const ts = (await import('typescript')).default;
1592-
const { resolve, dirname } = await import('node:path');
1593-
const { fileURLToPath } = await import('node:url');
1594-
1596+
it('the retired gates are gone from the TYPE, not only from the parse (compiler API)', () => {
15951597
const entry = resolve(dirname(fileURLToPath(import.meta.url)), 'app.zod.ts');
15961598
const program = ts.createProgram([entry], {
15971599
module: ts.ModuleKind.ESNext,

‎packages/spec/src/ui/view.test.ts‎

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ import {
5454
originOf,
5555
} from '../../scripts/lib/export-origins-testkit';
5656

57+
// The three published entries the dual-source pins below compare. Loaded
58+
// here, at module top, and not by an `await import()` inside a case: a clocked
59+
// window measures behaviour, never loading, and these three loads were most
60+
// of this file's test time.
61+
import * as sharedEntry from '../shared/index';
62+
import * as uiEntry from '../ui/index';
63+
import * as apiEntry from '../api/index';
64+
5765
// [#16577] The door that carries the `type: '<layout>'` axis these view
5866
// schemas deliberately leave open — imported so the two-door split is asserted
5967
// from the side that can see both.
@@ -4050,20 +4058,14 @@ describe('HttpMethodSubsetSchema/HttpRequestSchema backward compat', () => {
40504058
// re-exports `./shared`'s const — so the only thing that ever split was the type
40514059
// alias, which is exactly the part runtime cannot see. Hence two layers.
40524060
describe('HttpRequest is single-source across ./shared and ./ui', () => {
4053-
it('both entry points expose the very same schema declaration at runtime', async () => {
4054-
const sharedEntry = await import('../shared/index');
4055-
const uiEntry = await import('../ui/index');
4056-
4061+
it('both entry points expose the very same schema declaration at runtime', () => {
40574062
// Identity, not shape: `lazySchema` returns one Proxy per declaration site,
40584063
// so two declarations could never be `toBe`-equal however alike they look.
40594064
// A re-introduced local `HttpRequestSchema` in view.zod.ts fails here.
40604065
expect(uiEntry.HttpRequestSchema).toBe(sharedEntry.HttpRequestSchema);
40614066
});
40624067

4063-
it('the shared declaration validates identically on both entries', async () => {
4064-
const sharedEntry = await import('../shared/index');
4065-
const uiEntry = await import('../ui/index');
4066-
4068+
it('the shared declaration validates identically on both entries', () => {
40674069
for (const [entry, schema] of [
40684070
['./shared', sharedEntry.HttpRequestSchema],
40694071
['./ui', uiEntry.HttpRequestSchema],
@@ -4154,10 +4156,7 @@ describe('`HttpMethod` is not exported from ./ui', () => {
41544156
expect(originFileOf('./shared', 'HttpMethod')).toBe('src/shared/http.zod.ts');
41554157
});
41564158

4157-
it('keeps the two value ranges distinct: 7 for `HttpMethod`, 5 for `HttpMethodSubsetSchema`', async () => {
4158-
const sharedEntry = await import('../shared/index');
4159-
const apiEntry = await import('../api/index');
4160-
4159+
it('keeps the two value ranges distinct: 7 for `HttpMethod`, 5 for `HttpMethodSubsetSchema`', () => {
41614160
// `./api` re-exports the const, so this is one object seen twice.
41624161
expect(apiEntry.HttpMethod).toBe(sharedEntry.HttpMethod);
41634162

@@ -4173,9 +4172,7 @@ describe('`HttpMethod` is not exported from ./ui', () => {
41734172
expect(sharedEntry.HttpMethodSubsetSchema.options).not.toContain('HEAD');
41744173
});
41754174

4176-
it('rejects `HEAD` at the parse layer — the runtime the ./ui type must not out-promise', async () => {
4177-
const uiEntry = await import('../ui/index');
4178-
4175+
it('rejects `HEAD` at the parse layer — the runtime the ./ui type must not out-promise', () => {
41794176
expect(() => uiEntry.HttpMethodSubsetSchema.parse('HEAD')).toThrow();
41804177
expect(() => uiEntry.HttpMethodSubsetSchema.parse('OPTIONS')).toThrow();
41814178
expect(() => uiEntry.HttpRequestSchema.parse({ url: '/api/data', method: 'HEAD' })).toThrow();

0 commit comments

Comments
 (0)