Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/spec/src/root-entry-migrations-split.pin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ function valueGraph(entry: string): Set<string> {
return new Set([...seen].map((f) => relative(SRC, f).split('\\').join('/')));
}

describe('the migration chain is `@objectstack/spec/migrations`, not the root (#20646)', () => {
describe('the migration chain is `@objectstack/spec/migrations`, not the root', () => {
it('the root module exports none of the moved values', () => {
expect(MOVED_VALUES.filter((name) => name in root)).toEqual([]);
});
Expand Down
22 changes: 11 additions & 11 deletions packages/spec/src/stack-artifact-crossref.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ const SEED_ON_CASE = "Seed data references object 'crm_case' which is not define
const GRANT_ON_NOWHERE = `Permission 'sales_rep' grants on object '${NOWHERE}' which is not defined in objects.`;
const SEED_ON_NOWHERE = `Seed data references object '${NOWHERE}' which is not defined in objects.`;

describe('#18202 — the per-stack pass, without the opt-in', () => {
describe('the per-stack pass, without the opt-in', () => {
it('REFUSES an app-owned grant and seed on a module-owned object — the reported defect', () => {
const refused = refusalOf(() => defineStack(appConfig('crm_case', 'crm_case')));
expect(refused?.code).toBe('STACK_CROSS_REFERENCE_INVALID');
Expand All @@ -159,7 +159,7 @@ describe('#18202 — the per-stack pass, without the opt-in', () => {
});
});

describe('#18202 — `artifactObjects` widens exactly the two ARTIFACT-SCOPED classes', () => {
describe('`artifactObjects` widens exactly the two ARTIFACT-SCOPED classes', () => {
it('ACCEPTS the app package once the artifact’s other objects are declared', () => {
const service = serviceStack();
const accepted = refusalOf(() =>
Expand Down Expand Up @@ -227,7 +227,7 @@ describe('#18202 — `artifactObjects` widens exactly the two ARTIFACT-SCOPED cl
});
});

describe('#18202 — the ARTIFACT pass: the refusal MOVED, it did not disappear', () => {
describe('the ARTIFACT pass: the refusal MOVED, it did not disappear', () => {
/** The opt-in is a promise about a composition; this is the composition calling it in. */
const composeClaiming = (name: string) => {
const service = serviceStack();
Expand Down Expand Up @@ -267,7 +267,7 @@ describe('#18202 — the ARTIFACT pass: the refusal MOVED, it did not disappear'
});
});

describe('#18202 — #14122 §6 compatibility: a stack that does not opt in is untouched', () => {
describe('compatibility with the multi-package artifact: a stack that does not opt in is untouched', () => {
it('a single-package stack still refuses its own dangling grant', () => {
const refused = refusalOf(() =>
defineStack(anyStack({
Expand Down Expand Up @@ -303,7 +303,7 @@ describe('#18202 — #14122 §6 compatibility: a stack that does not opt in is u
});
});

describe('#18202 — the object-less leniency the ARTIFACT pass inherits verbatim', () => {
describe('the object-less leniency the ARTIFACT pass inherits verbatim', () => {
/**
* hotcrm#1449's shape: the app package declares NO objects, so
* `validateCrossReferences` early-returns and the ARTIFACT pass skips it for
Expand Down Expand Up @@ -340,7 +340,7 @@ describe('#18202 — the object-less leniency the ARTIFACT pass inherits verbati
* it, `collectArtifactCrossReferenceErrors`'s docstring says it, and these
* fixtures hold it.
*/
describe('#18202 — an input that bypassed the strict parse IS checked at composition', () => {
describe('an input that bypassed the strict parse IS checked at composition', () => {
/** The app package as an unparsed stack: `strict: false` skips every validation. */
const unparsedApp = (grantObject: string, seedObject: string) =>
defineStack(appConfig(grantObject, seedObject), { strict: false });
Expand Down Expand Up @@ -377,7 +377,7 @@ describe('#18202 — an input that bypassed the strict parse IS checked at compo
expect(refused?.issues).toContain(SEED_ON_NOWHERE);
});

it('REFUSES a hand-built stack object before either rule runs — it was never built (#20367 ruling B)', () => {
it('REFUSES a hand-built stack object before either rule runs — it was never built by a stack producer', () => {
// Since ruling B a hand-built object no longer reaches the artifact pass:
// `composeStacks` refuses an input no stack producer built at its step 0,
// naming the input, so the two rules above never get to run on it. The
Expand Down Expand Up @@ -423,7 +423,7 @@ describe('#18202 — an input that bypassed the strict parse IS checked at compo
* before this pass runs — skipping it composed an artifact without that
* stack's grants or seed rows — so those two cases assert the refusal.
*/
describe('#18202 — a malformed collection on an unparsed input is skipped or refused, never a bare TypeError', () => {
describe('a malformed collection on an unparsed input is skipped or refused, never a bare TypeError', () => {
/** Collect `console.warn` for one call, restoring the real one afterwards. */
function warningsDuring(run: () => unknown): { warnings: string[]; thrown: Envelope | null } {
const warnings: string[] = [];
Expand Down Expand Up @@ -454,7 +454,7 @@ describe('#18202 — a malformed collection on an unparsed input is skipped or r
const composeWith = (stack: ReturnType<typeof defineStack>) => () =>
composeStacks([serviceStack(), stack], { manifest: 'preserve' });

it('a non-array `permissions` is refused by the concat pass, never a bare TypeError (#19784)', () => {
it('a non-array `permissions` is refused by the concat pass, never a bare TypeError', () => {
// Map format written onto a built stack (only `defineStack` normalizes it). It
// is NOT iterable, which is what makes this the case that distinguishes a
// guard from a bare `TypeError`: a string value would iterate its
Expand All @@ -465,7 +465,7 @@ describe('#18202 — a malformed collection on an unparsed input is skipped or r
expect(thrown?.status).toBe(422);
});

it('a non-array `data` is refused by the concat pass, never a bare TypeError (#19784)', () => {
it('a non-array `data` is refused by the concat pass, never a bare TypeError', () => {
const { thrown } = warningsDuring(composeWith(malformed({ data: 42 })));
expect(thrown?.code).toBe('STACK_SCHEMA_INVALID');
expect(thrown?.status).toBe(422);
Expand Down Expand Up @@ -511,7 +511,7 @@ describe('#18202 — a malformed collection on an unparsed input is skipped or r
* This block is the fence on that qualifier: if the early return is ever
* removed, the qualifier becomes wrong and these tests say so.
*/
describe('#18202 — a composition of ONE package never reaches the artifact pass', () => {
describe('a composition of ONE package never reaches the artifact pass', () => {
const claiming = () => defineStack(appConfig(NOWHERE, NOWHERE), { artifactObjects: [NOWHERE] });

it('accepts a one-input composition whose claim names an object nothing defines', () => {
Expand Down
6 changes: 3 additions & 3 deletions packages/spec/src/stack-artifact-packages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ describe('ADR-0130 D4 — each `packages` entry is an OBJECT wrapping its manife
expect(issueAt(result, ['packages'])?.code).toBe('invalid_type');
});

it('refuses `packages: null` — `.optional()` admits `undefined`, not `null` (#19926)', () => {
it('refuses `packages: null` — `.optional()` admits `undefined`, not `null`', () => {
// `null` is a present, non-array `packages`: malformed, not absent. Every
// reader of the key refuses it too (`INVALID_ARTIFACT_PACKAGES`); the rule
// is stated once, beside `AssembledPackageBodySchema`.
Expand Down Expand Up @@ -322,7 +322,7 @@ describe('ADR-0130 D4 — `packages` has a declared composition rule', () => {
]);
});

it('refuses `packages: null` on any input when composing two or more stacks (#19926)', () => {
it('refuses `packages: null` on any input when composing two or more stacks', () => {
// The concat pass skips `undefined` alone: `null` is malformed, not
// absent, and is refused with the strict parse's own envelope rather than
// composed as if the stack declared no packages. `strict: false` is the
Expand Down Expand Up @@ -352,7 +352,7 @@ describe('ADR-0130 D4 — `packages` has a declared composition rule', () => {
expect(composed.packages.map((p) => p.manifest.id)).toEqual(['com.example.crm.cpq']);
});

it('does not warn about an undeclared composition rule (#5005 rule 3)', () => {
it('does not warn about an undeclared composition rule', () => {
composeStacks([
raw({ manifest: crmManifest, packages: [{ manifest: crmManifest }] }),
raw({ manifest: cpqManifest }),
Expand Down
4 changes: 2 additions & 2 deletions packages/spec/src/stack-cross-reference-envelope.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const stackWith = (extra: Record<string, unknown>) =>
*/
const rows: Array<{ label: string; config: Record<string, unknown>; message: string }> = [
{
label: 'hooks[].object (#14122 §4 rule R4)',
label: 'hooks[].object (the hook-ownership rule)',
config: {
hooks: [{ name: 'probe_hook', object: MISSING, events: ['afterInsert'], handler: 'noop' }],
},
Expand Down Expand Up @@ -135,7 +135,7 @@ const rows: Array<{ label: string; config: Record<string, unknown>; message: str
},
];

describe('#14552 — defineStack cross-reference refusals carry an ADR-0112 envelope', () => {
describe('defineStack cross-reference refusals carry an ADR-0112 envelope', () => {
for (const row of rows) {
describe(row.label, () => {
it('refuses with code STACK_CROSS_REFERENCE_INVALID and status 422', () => {
Expand Down
8 changes: 4 additions & 4 deletions packages/spec/src/stack-dev-logins.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const issuesOf = (verdict: ReturnType<typeof parse>): string[] =>

// ─── GREEN — what is writable now, and was not before ───────────────

describe('#17556 accept — an application may declare its own first-run credentials', () => {
describe('accept — an application may declare its own first-run credentials', () => {
it('accepts a full `devLogins` entry and carries every field through the parse', () => {
const verdict = parse({
...base(),
Expand Down Expand Up @@ -113,7 +113,7 @@ describe('#17556 accept — an application may declare its own first-run credent

// ─── RED — the entry is strict from birth, and says so usefully ─────

describe('#17556 refuse — a `devLogins` entry is closed against unknown keys', () => {
describe('refuse — a `devLogins` entry is closed against unknown keys', () => {
it('refuses an undeclared key inside an entry, at the entry`s path', () => {
const verdict = parse({ ...base(), devLogins: [{ email: 'a@b.example', totallyBogus: 1 }] });
expect(verdict.success).toBe(false);
Expand Down Expand Up @@ -150,7 +150,7 @@ describe('#17556 refuse — a `devLogins` entry is closed against unknown keys',

// ─── DARK CONTROL — the door did not open, two keys were declared ───

describe('#17556 control — the top-level door is still strict everywhere else', () => {
describe('control — the top-level door is still strict everywhere else', () => {
it('a neighbouring undeclared key still refuses, so the accept above is about these two keys', () => {
// If this went green the reading "devHint/devLogins are now writable" would
// be indistinguishable from "the strict close regressed".
Expand All @@ -171,7 +171,7 @@ describe('#17556 control — the top-level door is still strict everywhere else'

// ─── COMPOSITION — both publishers' personas survive; hints refuse ──

describe('#17556 compose — personas concatenate, a contradicting hint is named', () => {
describe('compose — personas concatenate, a contradicting hint is named', () => {
const hiring = () => defineStack({
manifest,
devHint: 'seed first',
Expand Down
12 changes: 6 additions & 6 deletions packages/spec/src/stack-email-template-locale-floor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ afterEach(() => {
vi.restoreAllMocks();
});

describe('#17614 — the floor tag is one named constant, not two spellings', () => {
describe('the floor tag is one named constant, not two spellings', () => {
it('is the schema default for `locale`, so a row that omits the key HAS the floor', () => {
expect(EMAIL_TEMPLATE_FLOOR_LOCALE).toBe('en-US');
const parsed = EmailTemplateDefinitionSchema.parse({
Expand All @@ -90,7 +90,7 @@ describe('#17614 — the floor tag is one named constant, not two spellings', ()
// A published declaration promising a loud permanent refusal where the
// runtime performs a silent fill is the defect; both call shapes must stay
// named, so the promise cannot quietly go unconditional again.
it('[#18056] scopes the dead-letter promise to a call that NAMES a locale, and states the other case', () => {
it('scopes the dead-letter promise to a call that NAMES a locale, and states the other case', () => {
const text = String(EmailTemplateDefinitionSchema.shape.locale.description ?? '');
expect(text).toMatch(/NAMES a locale/);
expect(text).toMatch(/lowest locale tag/);
Expand All @@ -99,7 +99,7 @@ describe('#17614 — the floor tag is one named constant, not two spellings', ()
});
});

describe('#17614 — defineStack reports a bundle with no `en-US` floor', () => {
describe('defineStack reports a bundle with no `en-US` floor', () => {
it('reports the trap: every supportedLocales tag authored, none of them the floor', () => {
const { warns, value } = warningsOf(stack(['en', 'zh-CN', 'ja-JP', 'es-ES'].map((l) => tpl(l)), THE_TRAP));
const hits = floorWarns(warns);
Expand Down Expand Up @@ -130,7 +130,7 @@ describe('#17614 — defineStack reports a bundle with no `en-US` floor', () =>
});
});

describe('#17614 — and stays silent where the bundle HAS a floor (the controls)', () => {
describe('and stays silent where the bundle HAS a floor (the controls)', () => {
// ⛔ Every case in THIS block is a bundle that genuinely carries the floor
// row. The shapes that are floorless and silent anyway are the guard's scope
// boundary and live in their own block below — filing them here read as
Expand All @@ -156,7 +156,7 @@ describe('#17614 — and stays silent where the bundle HAS a floor (the controls

});

describe('#17614 — warn-once bookkeeping', () => {
describe('the no-floor report: warn-once bookkeeping', () => {
it('warns once for one bundle, however many times the same stack is defined', () => {
const first = warningsOf(stack([tpl('pt-BR')], { defaultLocale: 'pt-BR', supportedLocales: ['pt-BR'] }));
const second = warningsOf(stack([tpl('pt-BR')], { defaultLocale: 'pt-BR', supportedLocales: ['pt-BR'] }));
Expand All @@ -176,7 +176,7 @@ describe('#17614 — warn-once bookkeeping', () => {
// enforce-or-remove question and is not decided here; what is closed is the
// silence being undeclared and unpinned.

describe('#18056 — the guard\'s declared scope boundary', () => {
describe('the floor guard\'s declared scope boundary', () => {
it('early return 1: a stack with no `i18n` block is never examined, floorless or not', () => {
const { warns, value } = warningsOf(stack([tpl('en', 'acme.scope_no_i18n')]));
expect(floorWarns(warns)).toEqual([]);
Expand Down
Loading
Loading