@adobe/data-testing 0.9.100 → 0.9.102
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/conformance/assert-state.d.ts +3 -0
- package/dist/conformance/assert-state.js +12 -0
- package/dist/conformance/assert-state.js.map +1 -0
- package/dist/conformance/cases.d.ts +32 -0
- package/dist/conformance/cases.js +11 -0
- package/dist/conformance/cases.js.map +1 -0
- package/dist/conformance/cases.type-test.d.ts +16 -0
- package/dist/conformance/cases.type-test.js +25 -0
- package/dist/conformance/cases.type-test.js.map +1 -0
- package/dist/conformance/discover.d.ts +2 -0
- package/dist/conformance/discover.js +19 -5
- package/dist/conformance/discover.js.map +1 -1
- package/dist/conformance/expect-after.d.ts +3 -0
- package/dist/conformance/expect-after.js +8 -0
- package/dist/conformance/expect-after.js.map +1 -0
- package/dist/conformance/public.d.ts +3 -1
- package/dist/conformance/public.js +4 -1
- package/dist/conformance/public.js.map +1 -1
- package/dist/conformance/refify.d.ts +4 -0
- package/dist/conformance/refify.js +66 -0
- package/dist/conformance/refify.js.map +1 -0
- package/dist/conformance/refify.test.d.ts +1 -0
- package/dist/conformance/refify.test.js +69 -0
- package/dist/conformance/refify.test.js.map +1 -0
- package/dist/conformance/resolve-args.d.ts +3 -0
- package/dist/conformance/resolve-args.js +24 -0
- package/dist/conformance/resolve-args.js.map +1 -0
- package/dist/conformance/run-actions.d.ts +2 -1
- package/dist/conformance/run-actions.js +9 -5
- package/dist/conformance/run-actions.js.map +1 -1
- package/dist/conformance/run-feature.d.ts +2 -1
- package/dist/conformance/run-feature.js +4 -2
- package/dist/conformance/run-feature.js.map +1 -1
- package/dist/conformance/run-spec.d.ts +2 -0
- package/dist/conformance/run-spec.js +19 -6
- package/dist/conformance/run-spec.js.map +1 -1
- package/dist/conformance/run-transactions.d.ts +2 -1
- package/dist/conformance/run-transactions.js +9 -5
- package/dist/conformance/run-transactions.js.map +1 -1
- package/dist/match/assert.js +16 -2
- package/dist/match/assert.js.map +1 -1
- package/dist/match/match.d.ts +9 -1
- package/dist/match/match.js +6 -13
- package/dist/match/match.js.map +1 -1
- package/dist/match/match.test.js +2 -25
- package/dist/match/match.test.js.map +1 -1
- package/dist/match/public.d.ts +1 -1
- package/dist/match/public.js +4 -1
- package/dist/match/public.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import { assert } from "../match/assert.js";
|
|
3
|
+
import { refifyState } from "./refify.js";
|
|
4
|
+
// Assert two States are equal UP TO AN ID-BIJECTION: the `expected` State's spec-ids
|
|
5
|
+
// (entity map keys, and reference fields found via `source`'s component/resource
|
|
6
|
+
// schemas) are refified into correspondence variables, then compared to `actual`.
|
|
7
|
+
// The built-in runners (`runFeature`, `runSpec`, …) call this for you; a feature
|
|
8
|
+
// with a CUSTOM conformance harness — e.g. one that drives an ECS system frame
|
|
9
|
+
// rather than a transaction — uses it directly, passing its store as the schema
|
|
10
|
+
// source: `assertState(toState(store), expected, store)`.
|
|
11
|
+
export const assertState = (actual, expected, source, match) => assert(actual, refifyState(expected, source), match);
|
|
12
|
+
//# sourceMappingURL=assert-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assert-state.js","sourceRoot":"","sources":["../../src/conformance/assert-state.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,WAAW,EAAqB,MAAM,aAAa,CAAC;AAE7D,qFAAqF;AACrF,iFAAiF;AACjF,kFAAkF;AAClF,iFAAiF;AACjF,+EAA+E;AAC/E,gFAAgF;AAChF,0DAA0D;AAC1D,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,MAAe,EACf,QAAiB,EACjB,MAAoB,EACpB,KAAoB,EACd,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Schema } from "@adobe/data/schema";
|
|
2
|
+
import type { Case } from "./types.js";
|
|
3
|
+
type AnyFn = (...args: never[]) => unknown;
|
|
4
|
+
type ArgsOf<F extends AnyFn> = Parameters<F> extends [unknown, infer A, ...unknown[]] ? A : void;
|
|
5
|
+
type ArgsSchemaMismatch = {
|
|
6
|
+
readonly __argsSchemaMismatch: "the transition's args type must be assignable to Schema.ToType<options.args>";
|
|
7
|
+
};
|
|
8
|
+
type CasesOptions<F extends AnyFn, S extends Schema> = {
|
|
9
|
+
readonly name?: never;
|
|
10
|
+
/**
|
|
11
|
+
* Optional schema for this transition's `args`. Conformance uses it for ONE
|
|
12
|
+
* purpose: to identify which argument fields are ENTITY REFERENCES — a field
|
|
13
|
+
* typed with `Entity.schema` — so the runner resolves that spec-id to the entity
|
|
14
|
+
* seeded for it (the args-side counterpart of the component schemas it reads for
|
|
15
|
+
* state). Provide it whenever a transition addresses an entity by id in its
|
|
16
|
+
* `args`; omit it otherwise. Describe only the fields you need identified — an
|
|
17
|
+
* injected service, and any non-reference arg, may be left off. The args type
|
|
18
|
+
* must be assignable to this schema's `Schema.ToType`, so the schema cannot drift
|
|
19
|
+
* from the signature.
|
|
20
|
+
*/
|
|
21
|
+
readonly args?: S & (ArgsOf<F> extends Schema.ToType<S> ? unknown : ArgsSchemaMismatch);
|
|
22
|
+
};
|
|
23
|
+
export type CasesWithOptions<State, F extends AnyFn> = {
|
|
24
|
+
readonly args?: Schema;
|
|
25
|
+
readonly cases: readonly Case<State, ArgsOf<F>>[];
|
|
26
|
+
};
|
|
27
|
+
export interface CasesBuilder<State> {
|
|
28
|
+
<F extends AnyFn>(fn: F, ...cases: readonly Case<State, ArgsOf<NoInfer<F>>>[]): readonly Case<State, ArgsOf<NoInfer<F>>>[];
|
|
29
|
+
<F extends AnyFn, const S extends Schema = Schema>(fn: F, options: CasesOptions<F, S>, ...cases: readonly Case<State, ArgsOf<NoInfer<F>>>[]): CasesWithOptions<State, F>;
|
|
30
|
+
}
|
|
31
|
+
export declare const casesBuilder: <State>() => CasesBuilder<State>;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const casesBuilder = () => {
|
|
2
|
+
const build = (_fn, ...rest) => {
|
|
3
|
+
const first = rest[0];
|
|
4
|
+
// An options object has no `name` (every case does), so it discriminates the
|
|
5
|
+
// two overloads at runtime.
|
|
6
|
+
const isOptions = first !== null && typeof first === "object" && !Array.isArray(first) && !("name" in first);
|
|
7
|
+
return isOptions ? { ...first, cases: rest.slice(1) } : rest;
|
|
8
|
+
};
|
|
9
|
+
return build;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=cases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cases.js","sourceRoot":"","sources":["../../src/conformance/cases.ts"],"names":[],"mappings":"AA8DA,MAAM,CAAC,MAAM,YAAY,GAAG,GAA+B,EAAE;IAC3D,MAAM,KAAK,GAAG,CAAC,GAAU,EAAE,GAAG,IAAwB,EAAW,EAAE;QACjE,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,6EAA6E;QAC7E,4BAA4B;QAC5B,MAAM,SAAS,GACb,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC;QAC7F,OAAO,SAAS,CAAC,CAAC,CAAC,EAAE,GAAI,KAAgB,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3E,CAAC,CAAC;IACF,OAAO,KAA4B,CAAC;AACtC,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type State = {
|
|
2
|
+
readonly entities: ReadonlyMap<number, {
|
|
3
|
+
readonly name: string;
|
|
4
|
+
}>;
|
|
5
|
+
readonly selected: number;
|
|
6
|
+
};
|
|
7
|
+
export declare const good: import("./cases.js").CasesWithOptions<State, (_s: Pick<State, "selected">, args: {
|
|
8
|
+
readonly id: number;
|
|
9
|
+
readonly count: number;
|
|
10
|
+
}) => Pick<State, "selected">>;
|
|
11
|
+
export declare const noArgsCases: readonly import("./types.js").Case<State, void>[];
|
|
12
|
+
export declare const bad: readonly import("./types.js").Case<State, {
|
|
13
|
+
readonly id: number;
|
|
14
|
+
readonly count: number;
|
|
15
|
+
}>[];
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
// Type-level checks for the `cases` builder's args-schema pin.
|
|
3
|
+
import { Entity } from "@adobe/data/ecs";
|
|
4
|
+
import { casesBuilder } from "./cases.js";
|
|
5
|
+
const cases = casesBuilder();
|
|
6
|
+
const reparent = (_s, args) => ({
|
|
7
|
+
selected: args.id,
|
|
8
|
+
});
|
|
9
|
+
const noArgs = (_s) => ({ selected: 0 });
|
|
10
|
+
// A schema whose ToType is assignable-from the args type — accepted.
|
|
11
|
+
export const good = cases(reparent,
|
|
12
|
+
// No `required`: the args type `{ id, count }` is still assignable to the schema's
|
|
13
|
+
// `ToType` (`{ id?, count? }`), and a marked field is detected regardless.
|
|
14
|
+
{ args: { type: "object", properties: { id: Entity.schema, count: { type: "integer" } } } }, { name: "ok", before: {}, args: { id: 1, count: 2 }, after: { selected: 1 } });
|
|
15
|
+
// Options form carries the schema on the value.
|
|
16
|
+
const _hasCases = good.cases;
|
|
17
|
+
// The no-args overload returns a bare array.
|
|
18
|
+
export const noArgsCases = cases(noArgs, { name: "n", before: {}, after: { selected: 0 } });
|
|
19
|
+
const _isArray = noArgsCases;
|
|
20
|
+
// A schema that DIVERGES from the signature (id typed as string) must be rejected:
|
|
21
|
+
// `Schema.ToType<args>.id` is `string`, but the transition's `args.id` is `number`.
|
|
22
|
+
const badArgs = { type: "object", properties: { id: { type: "string" }, count: { type: "integer" } } };
|
|
23
|
+
// @ts-expect-error — args type is not assignable to Schema.ToType<args>
|
|
24
|
+
export const bad = cases(reparent, { args: badArgs }, { name: "bad", before: {}, args: { id: 1, count: 2 }, after: { selected: 1 } });
|
|
25
|
+
//# sourceMappingURL=cases.type-test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cases.type-test.js","sourceRoot":"","sources":["../../src/conformance/cases.type-test.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,+DAA+D;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,MAAM,KAAK,GAAG,YAAY,EAAS,CAAC;AAEpC,MAAM,QAAQ,GAAG,CAAC,EAA2B,EAAE,IAAqD,EAA2B,EAAE,CAAC,CAAC;IACjI,QAAQ,EAAE,IAAI,CAAC,EAAE;CAClB,CAAC,CAAC;AACH,MAAM,MAAM,GAAG,CAAC,EAA2B,EAA2B,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;AAE3F,qEAAqE;AACrE,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,CACvB,QAAQ;AACR,mFAAmF;AACnF,2EAA2E;AAC3E,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,EAC3F,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,CAC9E,CAAC;AACF,gDAAgD;AAChD,MAAM,SAAS,GAA2B,IAAI,CAAC,KAAK,CAAC;AAErD,6CAA6C;AAC7C,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AAC5F,MAAM,QAAQ,GAAuB,WAAW,CAAC;AAEjD,mFAAmF;AACnF,oFAAoF;AACpF,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAW,CAAC;AAChH,wEAAwE;AACxE,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { Schema } from "@adobe/data/schema";
|
|
1
2
|
export interface Discovered {
|
|
2
3
|
readonly fn: (...args: unknown[]) => unknown;
|
|
3
4
|
readonly cases: readonly Record<string, unknown>[];
|
|
5
|
+
readonly argsSchema?: Schema;
|
|
4
6
|
}
|
|
5
7
|
export declare const discoverTransitions: (modules: Record<string, Record<string, unknown>>) => Map<string, Discovered>;
|
|
6
8
|
export declare const discoverDerivations: (modules: Record<string, Record<string, unknown>>) => Map<string, Discovered>;
|
|
@@ -1,20 +1,34 @@
|
|
|
1
|
-
//
|
|
1
|
+
// A `cases` export is either a plain array (no args schema) or the builder's
|
|
2
|
+
// options form `{ args, cases }`. Normalize to a `{ list, argsSchema }` pair.
|
|
3
|
+
const normalizeCases = (raw) => {
|
|
4
|
+
if (Array.isArray(raw))
|
|
5
|
+
return { list: raw };
|
|
6
|
+
if (raw !== null && typeof raw === "object" && Array.isArray(raw.cases)) {
|
|
7
|
+
const { cases, args } = raw;
|
|
8
|
+
return { list: cases, argsSchema: args };
|
|
9
|
+
}
|
|
10
|
+
return { list: [] };
|
|
11
|
+
};
|
|
2
12
|
const scan = (modules, isKind) => {
|
|
3
13
|
const out = new Map();
|
|
4
14
|
for (const [path, module] of Object.entries(modules)) {
|
|
5
15
|
const names = Object.keys(module);
|
|
6
16
|
if (!names.includes("cases"))
|
|
7
17
|
continue;
|
|
8
|
-
const
|
|
9
|
-
if (
|
|
18
|
+
const { list, argsSchema } = normalizeCases(module["cases"]);
|
|
19
|
+
if (list.length === 0)
|
|
10
20
|
continue;
|
|
11
|
-
const first =
|
|
21
|
+
const first = list[0];
|
|
12
22
|
if (typeof first !== "object" || first === null || !isKind(first))
|
|
13
23
|
continue;
|
|
14
24
|
const fnName = names.find((key) => typeof module[key] === "function");
|
|
15
25
|
if (!fnName)
|
|
16
26
|
throw new Error(`${path} exports \`cases\` but no function to pair`);
|
|
17
|
-
out.set(fnName, {
|
|
27
|
+
out.set(fnName, {
|
|
28
|
+
fn: module[fnName],
|
|
29
|
+
cases: list,
|
|
30
|
+
argsSchema,
|
|
31
|
+
});
|
|
18
32
|
}
|
|
19
33
|
return out;
|
|
20
34
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/conformance/discover.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/conformance/discover.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { assertState } from "./assert-state.js";
|
|
2
|
+
// Assert a transform's `after` writes-patch against the actual State. `after` is a
|
|
3
|
+
// delta over `before`, so the expectation is `{ ...before, ...after }`, compared up
|
|
4
|
+
// to an id-bijection (see `assertState`). Shared by every runner that checks an
|
|
5
|
+
// `after` — the pure `runSpec`, and the ecs `runTransactions` / `runActions` — so
|
|
6
|
+
// the merge-and-compare contract lives in one place.
|
|
7
|
+
export const expectAfter = (actual, before, after, source, match) => assertState(actual, { ...before, ...after }, source, match);
|
|
8
|
+
//# sourceMappingURL=expect-after.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expect-after.js","sourceRoot":"","sources":["../../src/conformance/expect-after.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,mFAAmF;AACnF,oFAAoF;AACpF,gFAAgF;AAChF,kFAAkF;AAClF,qDAAqD;AACrD,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,MAAe,EACf,MAAc,EACd,KAAa,EACb,MAAoB,EACpB,KAAoB,EACd,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export type { Case, Cases, DerivationCase, DerivationCases, Effects, ServiceCall } from "./types.js";
|
|
2
|
-
export {
|
|
2
|
+
export { casesBuilder, type CasesBuilder, type CasesWithOptions } from "./cases.js";
|
|
3
3
|
export { runSpec, type SpecRunConfig } from "./run-spec.js";
|
|
4
4
|
export { runTransactions, type TransactionRunConfig } from "./run-transactions.js";
|
|
5
5
|
export { runActions, type ActionRunConfig } from "./run-actions.js";
|
|
6
6
|
export { runComputeds, type ComputedRunConfig } from "./run-computeds.js";
|
|
7
7
|
export { runFeature, type FeatureRunConfig, type Projection } from "./run-feature.js";
|
|
8
|
+
export { assertState } from "./assert-state.js";
|
|
9
|
+
export type { SchemaSource } from "./refify.js";
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { casesBuilder } from "./cases.js";
|
|
2
2
|
export { runSpec } from "./run-spec.js";
|
|
3
3
|
export { runTransactions } from "./run-transactions.js";
|
|
4
4
|
export { runActions } from "./run-actions.js";
|
|
5
5
|
export { runComputeds } from "./run-computeds.js";
|
|
6
6
|
export { runFeature } from "./run-feature.js";
|
|
7
|
+
// For custom conformance harnesses (e.g. an ECS-system frame): compare two States
|
|
8
|
+
// up to an id-bijection, the same way the runners do.
|
|
9
|
+
export { assertState } from "./assert-state.js";
|
|
7
10
|
//# sourceMappingURL=public.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.js","sourceRoot":"","sources":["../../src/conformance/public.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"public.js","sourceRoot":"","sources":["../../src/conformance/public.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAA4C,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,OAAO,EAAsB,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,eAAe,EAA6B,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAE,UAAU,EAAwB,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,YAAY,EAA0B,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAA0C,MAAM,kBAAkB,CAAC;AACtF,kFAAkF;AAClF,sDAAsD;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ref, isRef, isMatcher } from "../match/match.js";
|
|
2
|
+
// Already an open matcher (a `ref`, `anyNumber`, vitest `expect.any`) — refify must
|
|
3
|
+
// not touch it, so a case may still hand-author a matcher where it wants one.
|
|
4
|
+
const isRefOrMatcher = (value) => isRef(value) || isMatcher(value);
|
|
5
|
+
// Replace an entity-reference number with a `ref` keyed by its own spec-id, so two
|
|
6
|
+
// occurrences of the same spec-id (an entity's map key and another entity's field
|
|
7
|
+
// pointing at it, or a singleton `selectedId`) become the same `ref` label and the
|
|
8
|
+
// matcher's bijection makes them line up on one ecs id. Non-reference values recurse
|
|
9
|
+
// structurally by schema so nested reference fields (a bundled `{ parent, order }`)
|
|
10
|
+
// are still found. A value with no schema, or a plain non-reference number, is left
|
|
11
|
+
// exactly as authored.
|
|
12
|
+
const refifyBySchema = (value, schema) => {
|
|
13
|
+
if (isRefOrMatcher(value))
|
|
14
|
+
return value;
|
|
15
|
+
if (schema?.entity && typeof value === "number")
|
|
16
|
+
return ref(String(value));
|
|
17
|
+
if (value === null || typeof value !== "object")
|
|
18
|
+
return value;
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
const items = schema?.items;
|
|
21
|
+
return items ? value.map((v) => refifyBySchema(v, items)) : value;
|
|
22
|
+
}
|
|
23
|
+
const props = schema?.properties;
|
|
24
|
+
if (!props)
|
|
25
|
+
return value;
|
|
26
|
+
const out = { ...value };
|
|
27
|
+
for (const key of Object.keys(out)) {
|
|
28
|
+
if (key in props)
|
|
29
|
+
out[key] = refifyBySchema(out[key], props[key]);
|
|
30
|
+
}
|
|
31
|
+
return out;
|
|
32
|
+
};
|
|
33
|
+
// An id in a map key or a list position is an entity reference by construction (no
|
|
34
|
+
// schema needed) — refify it directly.
|
|
35
|
+
const refifyId = (id) => isRefOrMatcher(id) ? id : typeof id === "number" ? ref(String(id)) : id;
|
|
36
|
+
// One entity value: refify each field against the same-named component schema.
|
|
37
|
+
const refifyEntityValue = (value, componentSchemas) => {
|
|
38
|
+
if (value === null || typeof value !== "object")
|
|
39
|
+
return value;
|
|
40
|
+
const out = { ...value };
|
|
41
|
+
for (const key of Object.keys(out))
|
|
42
|
+
out[key] = refifyBySchema(out[key], componentSchemas[key]);
|
|
43
|
+
return out;
|
|
44
|
+
};
|
|
45
|
+
// Turn a State's authored spec-ids into `ref`s so it compares to an ECS projection
|
|
46
|
+
// up to an id-bijection: every `Map` field is an identity-keyed entity collection
|
|
47
|
+
// (keys are ids, values are entity values), every other field is a singleton
|
|
48
|
+
// resource. The two id sets differ (each side mints its own), so the case author
|
|
49
|
+
// writes plain spec-ids everywhere and this makes them correspond — no hand-authored
|
|
50
|
+
// `Match.ref`. Idempotent: a matcher already in the State passes through untouched.
|
|
51
|
+
export const refifyState = (state, source) => {
|
|
52
|
+
if (state === null || typeof state !== "object")
|
|
53
|
+
return state;
|
|
54
|
+
// A store's componentSchemas is a name→Schema map; the public type erases the
|
|
55
|
+
// keys, so read it as the string-keyed map it is at runtime.
|
|
56
|
+
const componentSchemas = source.componentSchemas;
|
|
57
|
+
const out = {};
|
|
58
|
+
for (const [key, value] of Object.entries(state)) {
|
|
59
|
+
out[key] =
|
|
60
|
+
value instanceof Map
|
|
61
|
+
? new Map([...value].map(([id, v]) => [refifyId(id), refifyEntityValue(v, componentSchemas)]))
|
|
62
|
+
: refifyBySchema(value, componentSchemas[key]);
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=refify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refify.js","sourceRoot":"","sources":["../../src/conformance/refify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
import { matches } from "../match/match.js";
|
|
4
|
+
import { refifyState } from "./refify.js";
|
|
5
|
+
// A store's schema map: `name` is plain, `asset` / `placement.parent` / `selected`
|
|
6
|
+
// are entity references (`Entity.schema` sets `entity: true`), `placement` is a
|
|
7
|
+
// bundle carrying a nested reference. `refifyState` reads exactly these to know
|
|
8
|
+
// which numbers are ids.
|
|
9
|
+
const source = {
|
|
10
|
+
componentSchemas: {
|
|
11
|
+
name: { type: "string" },
|
|
12
|
+
selected: { type: "integer", entity: true },
|
|
13
|
+
asset: { type: "integer", entity: true },
|
|
14
|
+
placement: {
|
|
15
|
+
type: "object",
|
|
16
|
+
properties: { parent: { type: "integer", entity: true }, order: { type: "number" } },
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
// `refifyState(expected, source)` turns the case's spec-ids into `ref`s; `matches`
|
|
21
|
+
// then solves the id-bijection against an ECS projection that minted its OWN ids.
|
|
22
|
+
const conforms = (actual, expected) => matches(actual, refifyState(expected, source));
|
|
23
|
+
describe("refifyState — comparison up to an id-bijection", () => {
|
|
24
|
+
it("matches entity map keys regardless of the actual ids", () => {
|
|
25
|
+
const expected = { entities: new Map([[1, { name: "a" }], [2, { name: "b" }]]) };
|
|
26
|
+
// The ecs minted 100/200 for the same two entities — content pairs, keys need not.
|
|
27
|
+
expect(conforms({ entities: new Map([[100, { name: "a" }], [200, { name: "b" }]]) }, expected)).toBe(true);
|
|
28
|
+
// A value mismatch still fails.
|
|
29
|
+
expect(conforms({ entities: new Map([[100, { name: "a" }], [200, { name: "X" }]]) }, expected)).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
it("lines up a reference field with the entity it names (cross-reference)", () => {
|
|
32
|
+
// Layer 2 references asset 1.
|
|
33
|
+
const expected = { entities: new Map([[1, { name: "asset" }], [2, { name: "layer", asset: 1 }]]) };
|
|
34
|
+
// The ecs minted 10 for the asset and 20 for the layer; layer.asset must be 10.
|
|
35
|
+
expect(conforms({ entities: new Map([[10, { name: "asset" }], [20, { name: "layer", asset: 10 }]]) }, expected)).toBe(true);
|
|
36
|
+
// Same shape but the reference points at the wrong entity — must fail.
|
|
37
|
+
expect(conforms({ entities: new Map([[10, { name: "asset" }], [20, { name: "layer", asset: 20 }]]) }, expected)).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
it("finds a reference nested inside a bundle (placement.parent)", () => {
|
|
40
|
+
const expected = {
|
|
41
|
+
entities: new Map([
|
|
42
|
+
[1, { name: "group" }],
|
|
43
|
+
[2, { name: "child", placement: { parent: 1, order: 0 } }],
|
|
44
|
+
]),
|
|
45
|
+
};
|
|
46
|
+
expect(conforms({ entities: new Map([[7, { name: "group" }], [8, { name: "child", placement: { parent: 7, order: 0 } }]]) }, expected)).toBe(true);
|
|
47
|
+
// A dangling parent (no such entity) fails.
|
|
48
|
+
expect(conforms({ entities: new Map([[7, { name: "group" }], [8, { name: "child", placement: { parent: 99, order: 0 } }]]) }, expected)).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
it("lines up a reference-typed singleton (resource) with an entity key", () => {
|
|
51
|
+
const expected = { selected: 1, entities: new Map([[1, { name: "a" }], [2, { name: "b" }]]) };
|
|
52
|
+
expect(conforms({ selected: 42, entities: new Map([[42, { name: "a" }], [7, { name: "b" }]]) }, expected)).toBe(true);
|
|
53
|
+
// `selected` points at the other entity — fails the correspondence.
|
|
54
|
+
expect(conforms({ selected: 7, entities: new Map([[42, { name: "a" }], [7, { name: "b" }]]) }, expected)).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
it("does not treat a plain (non-reference) number as an id", () => {
|
|
57
|
+
// `order` is a plain number, not an entity ref — a differing order must fail
|
|
58
|
+
// (it is compared literally, never bijected away).
|
|
59
|
+
const expected = { entities: new Map([[1, { name: "a", placement: { parent: 1, order: 3 } }]]) };
|
|
60
|
+
expect(conforms({ entities: new Map([[9, { name: "a", placement: { parent: 9, order: 3 } }]]) }, expected)).toBe(true);
|
|
61
|
+
expect(conforms({ entities: new Map([[9, { name: "a", placement: { parent: 9, order: 4 } }]]) }, expected)).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
it("leaves an already-authored matcher untouched (idempotent)", () => {
|
|
64
|
+
const expected = { entities: new Map([[1, { name: "a", asset: 1 }]]) };
|
|
65
|
+
// refify is safe to run once; keys and refs become `ref`s and still match.
|
|
66
|
+
expect(conforms({ entities: new Map([[5, { name: "a", asset: 5 }]]) }, expected)).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=refify.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refify.test.js","sourceRoot":"","sources":["../../src/conformance/refify.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Resolve a case's `args` for the ecs side: replace each ENTITY-REFERENCE field
|
|
2
|
+
// (found via `argsSchema` — a field whose schema is `Entity.schema`, so
|
|
3
|
+
// `schema.entity` is set) with the entity the runner seeded for that spec-id.
|
|
4
|
+
// Recurses into nested object schemas. With no schema (a transition that addresses
|
|
5
|
+
// no entity) the args pass through unchanged — and the pure spec side never resolves
|
|
6
|
+
// at all, since there the spec-id already IS the entity key.
|
|
7
|
+
export const resolveArgs = (args, argsSchema, resolve) => {
|
|
8
|
+
if (!argsSchema || args === null || typeof args !== "object" || Array.isArray(args))
|
|
9
|
+
return args;
|
|
10
|
+
const props = argsSchema.properties;
|
|
11
|
+
if (!props)
|
|
12
|
+
return args;
|
|
13
|
+
const out = { ...args };
|
|
14
|
+
for (const [key, sub] of Object.entries(props)) {
|
|
15
|
+
if (!(key in out))
|
|
16
|
+
continue;
|
|
17
|
+
if (sub.entity && typeof out[key] === "number")
|
|
18
|
+
out[key] = resolve(out[key]);
|
|
19
|
+
else if (sub.properties && out[key] !== null && typeof out[key] === "object")
|
|
20
|
+
out[key] = resolveArgs(out[key], sub, resolve);
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=resolve-args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-args.js","sourceRoot":"","sources":["../../src/conformance/resolve-args.ts"],"names":[],"mappings":"AAIA,gFAAgF;AAChF,wEAAwE;AACxE,8EAA8E;AAC9E,mFAAmF;AACnF,qFAAqF;AACrF,6DAA6D;AAC7D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAa,EAAE,UAA8B,EAAE,OAAyB,EAAW,EAAE;IAC/G,IAAI,CAAC,UAAU,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACjG,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,CAAC;IACpC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,GAAG,GAA4B,EAAE,GAAI,IAAgC,EAAE,CAAC;IAC9E,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,GAAG,CAAC,MAAM,IAAI,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;aACxE,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IAC/H,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Entity } from "@adobe/data/ecs";
|
|
2
2
|
import type { MatchOptions } from "../match/match.js";
|
|
3
|
+
import type { SchemaSource } from "./refify.js";
|
|
3
4
|
export interface ActionRunConfig<Db, Store, State> {
|
|
4
5
|
readonly makeDb: (services: Record<string, object>) => Db;
|
|
5
6
|
readonly store: (db: Db) => Store;
|
|
@@ -11,4 +12,4 @@ export interface ActionRunConfig<Db, Store, State> {
|
|
|
11
12
|
readonly seedContext?: (db: Db, before: State, args: unknown) => void;
|
|
12
13
|
readonly match?: MatchOptions;
|
|
13
14
|
}
|
|
14
|
-
export declare function runActions<Db, Store, State>(config: ActionRunConfig<Db, Store, State>): void;
|
|
15
|
+
export declare function runActions<Db, Store extends SchemaSource, State>(config: ActionRunConfig<Db, Store, State>): void;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
2
|
import { describe, it } from "vitest";
|
|
3
|
-
import { assert } from "../match/assert.js";
|
|
4
|
-
import { adaptArgs } from "./entity-ref.js";
|
|
5
3
|
import { discoverTransitions, discoverOps } from "./discover.js";
|
|
4
|
+
import { expectAfter } from "./expect-after.js";
|
|
5
|
+
import { resolveArgs } from "./resolve-args.js";
|
|
6
6
|
import { splitAndRecordServices, expectEffects } from "./record-effects.js";
|
|
7
7
|
import { resolver } from "./resolve.js";
|
|
8
8
|
// The single conformance test for every ecs action: each transition's cases run
|
|
@@ -22,9 +22,13 @@ export function runActions(config) {
|
|
|
22
22
|
const db = config.makeDb(services);
|
|
23
23
|
const resolve = resolver(config.fromState(config.store(db), before));
|
|
24
24
|
config.seedContext?.(db, before, testCase.args);
|
|
25
|
-
|
|
26
|
-
//
|
|
27
|
-
|
|
25
|
+
// Resolve entity-reference args (the fields the case's `args` schema marks)
|
|
26
|
+
// to the seeded entities; a transition with no such schema passes through.
|
|
27
|
+
const args = resolveArgs(input, paired.argsSchema, resolve);
|
|
28
|
+
await action(db, args);
|
|
29
|
+
// `after` is a writes patch, compared up to an id-bijection.
|
|
30
|
+
const store = config.store(db);
|
|
31
|
+
expectAfter(config.toState(store), before, testCase.after, store, config.match);
|
|
28
32
|
expectEffects(calls, testCase.effects);
|
|
29
33
|
});
|
|
30
34
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-actions.js","sourceRoot":"","sources":["../../src/conformance/run-actions.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"run-actions.js","sourceRoot":"","sources":["../../src/conformance/run-actions.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAwBxC,gFAAgF;AAChF,2EAA2E;AAC3E,MAAM,UAAU,UAAU,CAAwC,MAAyC;IACzG,MAAM,WAAW,GAAG,mBAAmB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC5D,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM;YAAE,SAAS,CAAC,yEAAyE;QAChG,QAAQ,CAAC,GAAG,IAAI,kBAAkB,EAAE,GAAG,EAAE;YACvC,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACpC,EAAE,CAAC,QAAQ,CAAC,IAAc,EAAE,KAAK,IAAI,EAAE;oBACrC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,sBAAsB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;oBACzE,qDAAqD;oBACrD,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,GAAI,QAAQ,CAAC,MAAiB,EAAW,CAAC;oBACtF,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;oBACnC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;oBACrE,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;oBAChD,4EAA4E;oBAC5E,2EAA2E;oBAC3E,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;oBAC5D,MAAO,MAAuD,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;oBACzE,6DAA6D;oBAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBAC/B,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,MAAgB,EAAE,QAAQ,CAAC,KAAe,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;oBACpG,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAgB,CAAC,CAAC;gBAClD,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Database } from "@adobe/data/ecs";
|
|
2
2
|
import type { Entity } from "@adobe/data/ecs";
|
|
3
3
|
import type { MatchOptions } from "../match/match.js";
|
|
4
|
+
import type { SchemaSource } from "./refify.js";
|
|
4
5
|
export interface Projection<Store, State> {
|
|
5
6
|
readonly fromState: (store: Store, state: State) => ReadonlyMap<unknown, Entity> | void;
|
|
6
7
|
readonly toState: (store: Store) => State;
|
|
@@ -25,6 +26,6 @@ export interface FeatureRunConfig<State, StoreT, Db extends {
|
|
|
25
26
|
readonly computeds?: Record<string, unknown>;
|
|
26
27
|
};
|
|
27
28
|
}
|
|
28
|
-
export declare function runFeature<State, StoreT, Db extends {
|
|
29
|
+
export declare function runFeature<State, StoreT extends SchemaSource, Db extends {
|
|
29
30
|
store: StoreT;
|
|
30
31
|
}>(config: FeatureRunConfig<State, StoreT, Db>): void;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
2
|
import { describe, it } from "vitest";
|
|
3
3
|
import { Database, Store } from "@adobe/data/ecs";
|
|
4
|
-
import { assert } from "../match/assert.js";
|
|
5
4
|
import { runTransactions } from "./run-transactions.js";
|
|
6
5
|
import { runActions } from "./run-actions.js";
|
|
7
6
|
import { runComputeds } from "./run-computeds.js";
|
|
7
|
+
import { expectAfter } from "./expect-after.js";
|
|
8
8
|
export function runFeature(config) {
|
|
9
9
|
const initial = config.state.create();
|
|
10
10
|
const { fromState, toState, toData } = config.projection;
|
|
@@ -52,7 +52,9 @@ export function runFeature(config) {
|
|
|
52
52
|
it(`sample ${index}`, () => {
|
|
53
53
|
const store = makeStore();
|
|
54
54
|
fromState(store, sample);
|
|
55
|
-
|
|
55
|
+
// A full-state round-trip: the whole sample is the expectation (no delta),
|
|
56
|
+
// compared up to an id-bijection.
|
|
57
|
+
expectAfter(toState(store), {}, sample, store, config.match);
|
|
56
58
|
});
|
|
57
59
|
});
|
|
58
60
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-feature.js","sourceRoot":"","sources":["../../src/conformance/run-feature.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"run-feature.js","sourceRoot":"","sources":["../../src/conformance/run-feature.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Database } from "@adobe/data/ecs";
|
|
1
2
|
import type { MatchOptions } from "../match/match.js";
|
|
2
3
|
export interface SpecRunConfig {
|
|
3
4
|
readonly state?: {
|
|
@@ -5,6 +6,7 @@ export interface SpecRunConfig {
|
|
|
5
6
|
};
|
|
6
7
|
readonly transitions: Record<string, Record<string, unknown>>;
|
|
7
8
|
readonly match?: MatchOptions;
|
|
9
|
+
readonly plugin?: Database.Plugin;
|
|
8
10
|
readonly label?: (path: string, fnName: string | undefined) => string;
|
|
9
11
|
}
|
|
10
12
|
export declare const runSpec: (config: SpecRunConfig) => void;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
2
|
import { describe, it } from "vitest";
|
|
3
|
+
import { Store } from "@adobe/data/ecs";
|
|
3
4
|
import { assert } from "../match/assert.js";
|
|
4
|
-
import {
|
|
5
|
+
import { expectAfter } from "./expect-after.js";
|
|
5
6
|
import { recordArgServices, expectEffects } from "./record-effects.js";
|
|
6
7
|
const isDerivationCase = (c) => typeof c === "object" && c !== null && "value" in c;
|
|
7
8
|
// The single pure-spec test for every transform AND derivation in a `data/state/`
|
|
@@ -17,6 +18,12 @@ const isDerivationCase = (c) => typeof c === "object" && c !== null && "value" i
|
|
|
17
18
|
// "No test suite found" — so we register a single no-op so empty discovery is a
|
|
18
19
|
// valid outcome, not an error.
|
|
19
20
|
export const runSpec = (config) => {
|
|
21
|
+
// Reference fields are found from schemas; without a plugin only map keys (an id
|
|
22
|
+
// by construction) refify. A throwaway store surfaces the plugin's component +
|
|
23
|
+
// resource schemas, exactly the source `runFeature`'s runners read.
|
|
24
|
+
const schemaSource = config.plugin
|
|
25
|
+
? { componentSchemas: Store.create(config.plugin).componentSchemas }
|
|
26
|
+
: { componentSchemas: {} };
|
|
20
27
|
const suites = [];
|
|
21
28
|
for (const [path, module] of Object.entries(config.transitions)) {
|
|
22
29
|
const exportNames = Object.keys(module);
|
|
@@ -31,7 +38,10 @@ export const runSpec = (config) => {
|
|
|
31
38
|
suites.push({ kind: "invalid", path, label, exportNames });
|
|
32
39
|
continue;
|
|
33
40
|
}
|
|
34
|
-
|
|
41
|
+
// `cases` is either a plain array or the builder's `{ args, cases }` options
|
|
42
|
+
// form; the pure side ignores the `args` schema (spec-ids need no resolution).
|
|
43
|
+
const rawCases = module["cases"];
|
|
44
|
+
const cases = Array.isArray(rawCases) ? rawCases : (rawCases?.cases ?? []);
|
|
35
45
|
// Empty `cases: []` is not a suite (and would open a Vitest describe with no
|
|
36
46
|
// tests, which fails even when this file has other suites).
|
|
37
47
|
if (cases.length === 0)
|
|
@@ -64,16 +74,19 @@ export const runSpec = (config) => {
|
|
|
64
74
|
}
|
|
65
75
|
const tc = testCase;
|
|
66
76
|
it(tc.name, async () => {
|
|
67
|
-
//
|
|
68
|
-
// wrap injected services
|
|
69
|
-
const { args, calls } = recordArgServices(
|
|
77
|
+
// The pure spec reads args as authored — plain spec-ids that already match
|
|
78
|
+
// the state keys, no resolution. Just wrap injected services to record calls.
|
|
79
|
+
const { args, calls } = recordArgServices(tc.args);
|
|
70
80
|
// Case `before` is a delta over the feature default; `after` a writes patch.
|
|
71
81
|
const before = {
|
|
72
82
|
...(config.state?.create() ?? {}),
|
|
73
83
|
...tc.before,
|
|
74
84
|
};
|
|
75
85
|
const result = (await suite.fn(before, args));
|
|
76
|
-
|
|
86
|
+
// The pure transform mints its own spec-ids, so compare up to an
|
|
87
|
+
// id-bijection too (entity map keys always; reference fields when a
|
|
88
|
+
// `plugin` gave the schemas).
|
|
89
|
+
expectAfter({ ...before, ...result }, before, tc.after, schemaSource, config.match);
|
|
77
90
|
expectEffects(calls, tc.effects);
|
|
78
91
|
});
|
|
79
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-spec.js","sourceRoot":"","sources":["../../src/conformance/run-spec.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"run-spec.js","sourceRoot":"","sources":["../../src/conformance/run-spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Entity } from "@adobe/data/ecs";
|
|
2
2
|
import type { MatchOptions } from "../match/match.js";
|
|
3
|
+
import type { SchemaSource } from "./refify.js";
|
|
3
4
|
export interface TransactionRunConfig<Store, State> {
|
|
4
5
|
readonly createStore: () => Store;
|
|
5
6
|
readonly fromState: (store: Store, before: State) => ReadonlyMap<unknown, Entity> | void;
|
|
@@ -10,4 +11,4 @@ export interface TransactionRunConfig<Store, State> {
|
|
|
10
11
|
readonly seedContext?: (store: Store, before: State, args: unknown) => void;
|
|
11
12
|
readonly match?: MatchOptions;
|
|
12
13
|
}
|
|
13
|
-
export declare function runTransactions<Store, State>(config: TransactionRunConfig<Store, State>): void;
|
|
14
|
+
export declare function runTransactions<Store extends SchemaSource, State>(config: TransactionRunConfig<Store, State>): void;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
2
|
import { describe, it } from "vitest";
|
|
3
|
-
import { assert } from "../match/assert.js";
|
|
4
|
-
import { adaptArgs } from "./entity-ref.js";
|
|
5
3
|
import { discoverTransitions, discoverOps } from "./discover.js";
|
|
4
|
+
import { expectAfter } from "./expect-after.js";
|
|
5
|
+
import { resolveArgs } from "./resolve-args.js";
|
|
6
6
|
import { resolver } from "./resolve.js";
|
|
7
7
|
// The single conformance test for every ecs transaction, proving
|
|
8
8
|
// `toState(apply(fromState(before), args)) ≡ after` for each shared case.
|
|
@@ -20,9 +20,13 @@ export function runTransactions(config) {
|
|
|
20
20
|
const store = config.createStore();
|
|
21
21
|
const resolve = resolver(config.fromState(store, before));
|
|
22
22
|
config.seedContext?.(store, before, testCase.args);
|
|
23
|
-
|
|
24
|
-
//
|
|
25
|
-
|
|
23
|
+
// Resolve entity-reference args (the fields the case's `args` schema marks)
|
|
24
|
+
// to the seeded entities; a transition with no such schema passes through.
|
|
25
|
+
const args = resolveArgs(testCase.args, paired.argsSchema, resolve);
|
|
26
|
+
transaction(store, args);
|
|
27
|
+
// `after` is a writes patch, compared up to an id-bijection (the ecs mints
|
|
28
|
+
// its own ids).
|
|
29
|
+
expectAfter(config.toState(store), before, testCase.after, store, config.match);
|
|
26
30
|
});
|
|
27
31
|
}
|
|
28
32
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-transactions.js","sourceRoot":"","sources":["../../src/conformance/run-transactions.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"run-transactions.js","sourceRoot":"","sources":["../../src/conformance/run-transactions.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AA4BxC,iEAAiE;AACjE,0EAA0E;AAC1E,MAAM,UAAU,eAAe,CAAoC,MAA0C;IAC3G,MAAM,WAAW,GAAG,mBAAmB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC5D,KAAK,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,WAAW,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QACnE,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM;YAAE,SAAS,CAAC,mEAAmE;QAC1F,QAAQ,CAAC,GAAG,IAAI,uBAAuB,EAAE,GAAG,EAAE;YAC5C,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACpC,EAAE,CAAC,QAAQ,CAAC,IAAc,EAAE,GAAG,EAAE;oBAC/B,qDAAqD;oBACrD,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,GAAI,QAAQ,CAAC,MAAiB,EAAW,CAAC;oBACtF,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;oBACnC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;oBAC1D,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;oBACnD,4EAA4E;oBAC5E,2EAA2E;oBAC3E,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;oBACnE,WAA+C,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;oBAC9D,2EAA2E;oBAC3E,gBAAgB;oBAChB,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,MAAgB,EAAE,QAAQ,CAAC,KAAe,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;gBACtG,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
package/dist/match/assert.js
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
-
import { matches } from "./match.js";
|
|
2
|
+
import { matches, refLabel } from "./match.js";
|
|
3
|
+
// A `Map`/`Set` JSON.stringifies to `{}`, which would hide the very entity
|
|
4
|
+
// collections these comparisons are about (two different maps both print `{}`), so
|
|
5
|
+
// render them explicitly. A `ref` matcher prints as `ref(label)` so an id-bijection
|
|
6
|
+
// mismatch is legible.
|
|
7
|
+
const replacer = (_key, value) => {
|
|
8
|
+
if (value instanceof Map)
|
|
9
|
+
return { "«Map»": [...value.entries()] };
|
|
10
|
+
if (value instanceof Set)
|
|
11
|
+
return { "«Set»": [...value.values()] };
|
|
12
|
+
const label = refLabel(value);
|
|
13
|
+
if (label !== undefined)
|
|
14
|
+
return `ref(${label})`;
|
|
15
|
+
return value;
|
|
16
|
+
};
|
|
3
17
|
const show = (value) => {
|
|
4
18
|
try {
|
|
5
|
-
return JSON.stringify(value) ?? String(value);
|
|
19
|
+
return JSON.stringify(value, replacer) ?? String(value);
|
|
6
20
|
}
|
|
7
21
|
catch {
|
|
8
22
|
return String(value);
|
package/dist/match/assert.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assert.js","sourceRoot":"","sources":["../../src/match/assert.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,OAAO,EAAqB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"assert.js","sourceRoot":"","sources":["../../src/match/assert.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAqB,MAAM,YAAY,CAAC;AAElE,2EAA2E;AAC3E,mFAAmF;AACnF,oFAAoF;AACpF,uBAAuB;AACvB,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,KAAc,EAAW,EAAE;IACzD,IAAI,KAAK,YAAY,GAAG;QAAE,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;IACnE,IAAI,KAAK,YAAY,GAAG;QAAE,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;IAClE,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,OAAO,KAAK,GAAG,CAAC;IAChD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,IAAI,GAAG,CAAC,KAAc,EAAU,EAAE;IACtC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;AACH,CAAC,CAAC;AAEF,gFAAgF;AAChF,iFAAiF;AACjF,wCAAwC;AACxC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,MAAe,EAAE,QAAiB,EAAE,OAAsB,EAAQ,EAAE;IACzF,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,CAAC,MAAM,CAAC,iBAAiB,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC/F,CAAC;AACH,CAAC,CAAC"}
|
package/dist/match/match.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
export interface MatchOptions {
|
|
2
2
|
readonly tolerance?: number;
|
|
3
3
|
}
|
|
4
|
+
declare const REF: unique symbol;
|
|
4
5
|
export declare const ref: <T = number>(label: string) => T;
|
|
5
|
-
export declare const
|
|
6
|
+
export declare const isRef: (value: unknown) => value is {
|
|
7
|
+
readonly [REF]: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const refLabel: (value: unknown) => string | undefined;
|
|
10
|
+
export declare const isMatcher: (value: unknown) => value is {
|
|
11
|
+
asymmetricMatch(actual: unknown): boolean;
|
|
12
|
+
};
|
|
6
13
|
export declare const matches: (actual: unknown, expected: unknown, options?: MatchOptions) => boolean;
|
|
14
|
+
export {};
|
package/dist/match/match.js
CHANGED
|
@@ -19,22 +19,15 @@ const REF = Symbol.for("@adobe/data-testing:ref");
|
|
|
19
19
|
// are distinct keys (a shared matcher like `anyNumber` would collapse duplicate map
|
|
20
20
|
// keys); same-label occurrences still assert the same actual id (correspondence).
|
|
21
21
|
export const ref = (label) => ({ [REF]: label });
|
|
22
|
-
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
// injective matcher rather than a pinned number, and two entries must not share a
|
|
28
|
-
// matcher (a shared `anyNumber` would collapse to one map key). Each value gets its
|
|
29
|
-
// own process-unique label, so refMap maps never collide with each other or with a
|
|
30
|
-
// case's own hand-authored `ref` labels. Use `ref(label)` by hand only when a key
|
|
31
|
-
// must CORRESPOND to a reference elsewhere in the same comparison (a `selectedId`).
|
|
32
|
-
let refMapCounter = 0;
|
|
33
|
-
export const refMap = (values) => new Map([...values].map((value) => [ref(`@refMap-${refMapCounter++}`), value]));
|
|
22
|
+
// The single owner of the `ref` contract — `refify` and `assert` reuse these
|
|
23
|
+
// instead of re-deriving the symbol, so there is one place the marker is defined.
|
|
24
|
+
export const isRef = (value) => typeof value === "object" && value !== null && REF in value;
|
|
25
|
+
// The `ref` label, or `undefined` if `value` is not a `ref` — for rendering.
|
|
26
|
+
export const refLabel = (value) => (isRef(value) ? value[REF] : undefined);
|
|
34
27
|
// An asymmetric matcher (this module's `anyNumber`/`anyString`, or vitest's
|
|
35
28
|
// `expect.any(...)`): honored on the EXPECTED side so a case asserts a shape it
|
|
36
29
|
// does not pin. Recognised structurally, so no test framework is imported.
|
|
37
|
-
const isMatcher = (value) => typeof value === "object" &&
|
|
30
|
+
export const isMatcher = (value) => typeof value === "object" &&
|
|
38
31
|
value !== null &&
|
|
39
32
|
typeof value.asymmetricMatch === "function";
|
|
40
33
|
const quantize = (n, tolerance) => {
|
package/dist/match/match.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"match.js","sourceRoot":"","sources":["../../src/match/match.ts"],"names":[],"mappings":"AAAA,uDAAuD;AASvD,kFAAkF;AAClF,+EAA+E;AAC/E,kFAAkF;AAClF,mFAAmF;AACnF,gFAAgF;AAChF,kCAAkC;AAElC,gFAAgF;AAChF,iFAAiF;AACjF,8EAA8E;AAC9E,gFAAgF;AAChF,iFAAiF;AACjF,gFAAgF;AAChF,oFAAoF;AACpF,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAClD,oFAAoF;AACpF,qFAAqF;AACrF,qFAAqF;AACrF,oFAAoF;AACpF,kFAAkF;AAClF,MAAM,CAAC,MAAM,GAAG,GAAG,CAAa,KAAa,EAAK,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"match.js","sourceRoot":"","sources":["../../src/match/match.ts"],"names":[],"mappings":"AAAA,uDAAuD;AASvD,kFAAkF;AAClF,+EAA+E;AAC/E,kFAAkF;AAClF,mFAAmF;AACnF,gFAAgF;AAChF,kCAAkC;AAElC,gFAAgF;AAChF,iFAAiF;AACjF,8EAA8E;AAC9E,gFAAgF;AAChF,iFAAiF;AACjF,gFAAgF;AAChF,oFAAoF;AACpF,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAClD,oFAAoF;AACpF,qFAAqF;AACrF,qFAAqF;AACrF,oFAAoF;AACpF,kFAAkF;AAClF,MAAM,CAAC,MAAM,GAAG,GAAG,CAAa,KAAa,EAAK,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAiB,CAAC;AAExF,6EAA6E;AAC7E,kFAAkF;AAClF,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAc,EAAuC,EAAE,CAC3E,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,CAAC;AAC9D,6EAA6E;AAC7E,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAsB,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AAExG,4EAA4E;AAC5E,gFAAgF;AAChF,2EAA2E;AAC3E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAc,EAA0D,EAAE,CAClG,OAAO,KAAK,KAAK,QAAQ;IACzB,KAAK,KAAK,IAAI;IACd,OAAQ,KAAuC,CAAC,eAAe,KAAK,UAAU,CAAC;AAEjF,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,SAAiB,EAAU,EAAE;IACxD,MAAM,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;IAC7B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,+BAA+B;AAC1F,CAAC,CAAC;AAEF,mFAAmF;AACnF,+EAA+E;AAC/E,+EAA+E;AAC/E,mFAAmF;AACnF,6EAA6E;AAC7E,mFAAmF;AACnF,wEAAwE;AACxE,MAAM,gBAAgB,GAAG,CACvB,MAA0B,EAC1B,QAA4B,EAC5B,OAAqB,EACrB,QAA8B,EACrB,EAAE;IACX,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACpD,MAAM,IAAI,GAAG,IAAI,KAAK,CAAU,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3D,MAAM,IAAI,GAAG,CAAC,CAAS,EAAW,EAAE;QAClC,IAAI,CAAC,KAAK,QAAQ,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,IAAI,IAAI,CAAC,CAAC,CAAC;gBAAE,SAAS;YACtB,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;gBAC3D,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;gBACf,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;oBAAE,OAAO,IAAI,CAAC;gBAC7B,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;YAClB,CAAC;YACD,+EAA+E;YAC/E,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjB,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,QAAQ;gBAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IACF,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAClB,MAAe,EACf,QAAiB,EACjB,OAAqB,EACrB,QAA8B,EACrB,EAAE;IACX,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;QACvE,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE;YAAE,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC;gBAAE,OAAO,KAAK,CAAC,CAAC,YAAY;QAC/F,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,SAAS,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IACjE,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;QAC5C,OAAO,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,QAAQ,YAAY,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,CAAC,MAAM,YAAY,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAC3C,OAAO,gBAAgB,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,QAAQ,YAAY,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,CAAC,MAAM,YAAY,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;QAC3C,+EAA+E;QAC/E,gFAAgF;QAChF,4EAA4E;QAC5E,4EAA4E;QAC5E,4BAA4B;QAC5B,OAAO,gBAAgB,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAC9E,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC5F,CAAC;IACD,IAAI,QAAQ,KAAK,IAAI,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACtD,IACE,MAAM,KAAK,IAAI;YACf,OAAO,MAAM,KAAK,QAAQ;YAC1B,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YACrB,MAAM,YAAY,GAAG;YACrB,MAAM,YAAY,GAAG;YAErB,OAAO,KAAK,CAAC;QACf,MAAM,EAAE,GAAG,QAAmC,CAAC;QAC/C,MAAM,EAAE,GAAG,MAAiC,CAAC;QAC7C,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QACpE,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF,uEAAuE;AACvE,mFAAmF;AACnF,kFAAkF;AAClF,0CAA0C;AAC1C,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAe,EAAE,QAAiB,EAAE,UAAwB,EAAE,EAAW,EAAE,CACjG,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC"}
|
package/dist/match/match.test.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
2
|
import { describe, it, expect } from "vitest";
|
|
3
|
-
import { matches, ref
|
|
3
|
+
import { matches, ref } from "./match.js";
|
|
4
|
+
import { anyNumber, anyString } from "./public.js";
|
|
4
5
|
describe("Match.matches", () => {
|
|
5
6
|
it("compares plain structures deeply", () => {
|
|
6
7
|
expect(matches({ a: 1, b: [2, 3] }, { a: 1, b: [2, 3] })).toBe(true);
|
|
@@ -66,29 +67,5 @@ describe("Match.matches", () => {
|
|
|
66
67
|
expect(matches(dangling, expected)).toBe(false);
|
|
67
68
|
});
|
|
68
69
|
});
|
|
69
|
-
describe("refMap", () => {
|
|
70
|
-
it("matches an identity-keyed entity collection regardless of the actual ids", () => {
|
|
71
|
-
const actual = new Map([
|
|
72
|
-
[10, { name: "a" }],
|
|
73
|
-
[20, { name: "b" }],
|
|
74
|
-
]);
|
|
75
|
-
// Same values, ecs-minted keys — refMap leaves the keys open.
|
|
76
|
-
expect(matches(actual, refMap([{ name: "a" }, { name: "b" }]))).toBe(true);
|
|
77
|
-
// A value mismatch still fails.
|
|
78
|
-
expect(matches(actual, refMap([{ name: "a" }, { name: "c" }]))).toBe(false);
|
|
79
|
-
// Cardinality mismatch fails.
|
|
80
|
-
expect(matches(actual, refMap([{ name: "a" }]))).toBe(false);
|
|
81
|
-
});
|
|
82
|
-
it("keys are distinct — entries never collapse the way a shared matcher would", () => {
|
|
83
|
-
const actual = new Map([
|
|
84
|
-
[1, { v: 1 }],
|
|
85
|
-
[2, { v: 1 }],
|
|
86
|
-
]);
|
|
87
|
-
// Two equal values in two entries: refMap keeps two entries (distinct keys),
|
|
88
|
-
// so both must pair. A single shared `anyNumber` key would collapse to one.
|
|
89
|
-
expect(matches(actual, refMap([{ v: 1 }, { v: 1 }]))).toBe(true);
|
|
90
|
-
expect(matches(new Map([[1, { v: 1 }]]), refMap([{ v: 1 }, { v: 1 }]))).toBe(false);
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
70
|
});
|
|
94
71
|
//# sourceMappingURL=match.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"match.test.js","sourceRoot":"","sources":["../../src/match/match.test.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"match.test.js","sourceRoot":"","sources":["../../src/match/match.test.ts"],"names":[],"mappings":"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"}
|
package/dist/match/public.d.ts
CHANGED
package/dist/match/public.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
-
|
|
2
|
+
// `ref` (id-correspondence) and its solver are internal: the conformance runner's
|
|
3
|
+
// `refify` generates them from schema-marked spec-ids, so no case authors one. The
|
|
4
|
+
// solving machinery stays in `matches`; only the public matchers are re-exported.
|
|
5
|
+
export { matches } from "./match.js";
|
|
3
6
|
export { assert } from "./assert.js";
|
|
4
7
|
export { anyNumber, anyString } from "./matchers.js";
|
|
5
8
|
//# sourceMappingURL=public.js.map
|
package/dist/match/public.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.js","sourceRoot":"","sources":["../../src/match/public.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,
|
|
1
|
+
{"version":3,"file":"public.js","sourceRoot":"","sources":["../../src/match/public.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,kFAAkF;AAClF,mFAAmF;AACnF,kFAAkF;AAClF,OAAO,EAAE,OAAO,EAAqB,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/data-testing",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.102",
|
|
4
4
|
"description": "Conformance-testing utilities (Match + Conformance runners) for @adobe/data ECS features",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"LICENSE"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@adobe/data": "0.9.
|
|
18
|
+
"@adobe/data": "0.9.102"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"vitest": "^1.6.0"
|