@hydranium/conformance 1.0.0-next.25 → 1.0.0-next.251

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/README.md CHANGED
@@ -1,34 +1,22 @@
1
1
  # `@hydranium/conformance`
2
2
 
3
- The protocol conformance kit — a TCK — for the
4
- [Hydranium](https://github.com/eclipse-emfcloud/hydranium) framework.
5
-
6
- A TCK is a test suite you do not write: the framework ships the checks, and **you run them against
7
- your own server** to prove it actually speaks each head's protocol. You supply two things — a way to
8
- stand a server up (`connect`) and per-language fixtures (a valid and an invalid model) — and the kit
9
- emits one test per check in your own test runner, alongside your own suites.
10
-
11
- Install it if you are building a Hydranium head and want a protocol contract you did not have to
12
- author, and that keeps checking you as the framework moves.
3
+ The protocol conformance kit of the
4
+ [Hydranium](https://github.com/eclipse-emfcloud/hydranium) framework. You
5
+ install it as a dev dependency to check that your server speaks each head's
6
+ protocol: you supply a way to start the server and a few models, and the kit
7
+ adds one test per check to your own test runner.
13
8
 
14
9
  ## What it gives you
15
10
 
16
- - **Per-head batteries**, one subpath each: `/data`, `/lsp` and `/glsp`. Importing one never pulls
17
- another head's protocol types in, so an LSP-only adopter takes no data-head surface.
18
- - **Driver ports rather than adapters.** Each slice names a minimal port — `DataConformanceDriver`,
19
- `LspConformanceDriver`, `GlspConformanceDriver<TAction>` — spelled in `@hydranium/protocol` types,
20
- plain coordinates and tiny structural minima. The framework's own harnesses
21
- (`DataServerHarness`, `LspHarness`, `GlspHarness`) satisfy them **structurally, with no adapter**,
22
- and so can a hand-rolled driver.
23
- - **Runner-agnostic core.** `ConformanceCheck`, `ConformanceRunner` and `emitConformanceSuite` name
24
- no test runner and assert with `node:assert/strict`; the thin `/vitest` and `/jest` adapters bind
25
- `describe` / `it` / `it.skip` / `afterAll`.
26
- - **Skips that are visible, not silent.** A check whose optional fixture input is absent is emitted
27
- as a named `it.skip`, and every suite prints a ran-vs-skipped summary (`formatSummary`), so a
28
- half-wired adopter reads as _skipped_ rather than as a green run.
29
- - **A false-green guard in the fixture type.** `LanguageFixture` requires **both** a `valid` and an
30
- `invalid` model, so an "invalid" model that in fact parses clean fails the diagnostics checks
31
- instead of passing vacuously.
11
+ - A battery of checks per head, data, LSP and GLSP, that you run against your
12
+ own server rather than write.
13
+ - A driver port per head that the framework's test harnesses already satisfy,
14
+ so you can pass a harness in, or write a driver of your own.
15
+ - Adapters for vitest and Jest; the checks themselves name no test runner.
16
+ - Skips you can see: a check whose optional input you did not supply shows up
17
+ skipped with its reason, and each suite prints what ran and what was skipped.
18
+ - A guard against a false green: every language needs an invalid model, so a
19
+ model that parses clean fails the diagnostics checks.
32
20
 
33
21
  ## Install
34
22
 
@@ -36,62 +24,66 @@ author, and that keeps checking you as the framework moves.
36
24
  npm install --save-dev @hydranium/conformance
37
25
  ```
38
26
 
39
- `@hydranium/protocol` is a required peer. The two runners are **optional** peers — `vitest` and
40
- `@jest/globals` — so you install only the one you use, and the core never loads the other. The
41
- package has no runtime dependencies of its own.
42
-
43
- ## Subpaths
27
+ | Peer | Range |
28
+ | --------------------- | ------------- |
29
+ | `@hydranium/protocol` | `^1.0.0-next` |
30
+ | `@jest/globals` | `^29.0.0` |
31
+ | `vitest` | `^4.0.0` |
44
32
 
45
- | Subpath | Contents |
46
- | ---------- | ----------------------------------------------------------- |
47
- | `.` | Fixture model + check/runner primitives. No head, no runner. |
48
- | `./data` | Data-head driver port + `buildDataChecks`. |
49
- | `./lsp` | LSP-head driver port + `buildLspChecks`. |
50
- | `./glsp` | GLSP-head driver port + `buildGlspChecks`. |
51
- | `./vitest` | Vitest adapter: `run{Data,Lsp,Glsp}Conformance`. |
52
- | `./jest` | Jest adapter: the same three entry points. |
53
-
54
- Each named subpath also resolves as `@hydranium/conformance/lib/<name>`, so a consumer on classic
55
- `moduleResolution: "Node"` can reach it. The root barrel deliberately re-exports none of the slices.
33
+ `vitest` and `@jest/globals` are optional peers: install the runner you use.
56
34
 
57
35
  ## Usage
58
36
 
59
- In one test file per head, call the `run*Conformance` function from your runner's adapter subpath —
60
- `@hydranium/conformance/vitest` or `@hydranium/conformance/jest`. Both adapters also re-export the
61
- slice types (driver ports, options, fixtures), so a suite needs a single import site.
62
-
63
- Each takes `connect` plus `languages`:
64
-
65
- - **`connect`** returns a freshly wired driver and is called **once per check**, so checks cannot
66
- interfere; the kit disposes the driver afterwards. The data slice wants a server already ready; the
67
- LSP slice drives the `initialize` handshake itself, so `connect` must **not** pre-initialise; the
68
- GLSP slice drives `start()`.
69
- - **`languages`** is an array of `LanguageFixture`: `valid` and `invalid` (both read by every
70
- slice), plus two opt-ins — `edit` (data slice only: a replacement text and an `expect(root)`
71
- predicate, because only you know what "the edit landed" means for your grammar) and
72
- `completionPosition` (LSP slice only). A fixture's `uri` and `text` may be thunks, resolved after
73
- `connect`, which is how each check gets pristine input in a workspace `connect` just created.
74
-
75
- The GLSP slice is generic over your action type and takes `GlspFixture` per diagram type — the
76
- fixture builds the native actions and the kit matches responses by `kind`, so no `@eclipse-glsp/*`
77
- type enters the kit.
78
-
79
- Then run your normal test command:
80
-
81
- ```bash
82
- npx vitest run test/data-conformance.integration.test.ts
83
- ```
84
-
85
- The suite prints, per head, how many checks ran and which were skipped and why. For where this sits
86
- among the framework's test layers, see [`docs/contributing/testing.md`](../../docs/contributing/testing.md).
37
+ Write one test file per head, and call the `run*Conformance` function from
38
+ your runner's adapter, `@hydranium/conformance/vitest` or
39
+ `@hydranium/conformance/jest`. The adapter also exports the driver ports, the
40
+ options and `GlspFixture`; `LanguageFixture` comes from the package root.
41
+
42
+ Each function takes `connect` and `languages`:
43
+
44
+ - **`connect`** returns a freshly wired driver. The kit calls it once per check
45
+ and disposes the driver afterwards, so checks cannot interfere. The data
46
+ slice wants the server ready, and saves documents beside each fixture's
47
+ `valid`, so give each check a workspace the kit may write to and throw away.
48
+ The LSP slice drives the `initialize` handshake itself, so `connect` must not
49
+ initialise. The GLSP slice calls `start()` itself.
50
+ - **`languages`** is an array of `LanguageFixture`. `valid` and `invalid` are
51
+ required, and every slice reads them. Every other field is opt-in: when you
52
+ leave it out, its checks report skipped with a named reason. The
53
+ `LanguageFixture` type says, per field, which slice reads it and what
54
+ supplying it claims. A fixture's `uri` and `text` may be functions, read
55
+ after `connect`, so they can point into the workspace `connect` just made.
56
+
57
+ The GLSP slice is generic over your action type and takes a `GlspFixture` per
58
+ diagram type. The fixture builds your native actions, and the kit matches the
59
+ responses by `kind`.
60
+
61
+ For where the kit fits among your other tests, see *Test your language* in
62
+ [Adopting Hydranium](https://github.com/eclipse-emfcloud/hydranium/blob/main/docs/ADOPTING.md).
63
+
64
+ ## Entry points
65
+
66
+ | Subpath | Use it for | Runs in |
67
+ | ---------- | ------------------------------------------------------------ | ------- |
68
+ | `.` | `LanguageFixture` and the runner-agnostic check primitives. | Node |
69
+ | `./data` | The data-head checks and driver port. | Node |
70
+ | `./lsp` | The LSP-head checks and driver port. | Node |
71
+ | `./glsp` | The GLSP-head checks and driver port. | Node |
72
+ | `./vitest` | Run the checks under vitest. | Node |
73
+ | `./jest` | Run the checks under Jest. | Node |
74
+
75
+ The subpaths need a TypeScript `moduleResolution` that reads `exports`
76
+ (`NodeNext` or `Bundler`); see *Requirements* in
77
+ [Adopting Hydranium](https://github.com/eclipse-emfcloud/hydranium/blob/main/docs/ADOPTING.md).
87
78
 
88
79
  ## Status
89
80
 
90
- Alpha — pre-v0, not yet published. The check batteries are being populated incrementally and the
91
- driver ports are not yet stable — a new check can turn a passing adopter red by design. See the
92
- [repository README](../../README.md) for the current status and known limitations.
81
+ Alpha: every release is a prerelease that may break the API, so pin an exact
82
+ version. Guides and known limitations:
83
+ [Adopting Hydranium](https://github.com/eclipse-emfcloud/hydranium/blob/main/docs/ADOPTING.md).
93
84
 
94
85
  ## License
95
86
 
96
87
  `MIT` — see this package's [`LICENSE`](./LICENSE), and the repository
97
- [`NOTICE.md`](../../NOTICE.md) for third-party notices.
88
+ [`NOTICE.md`](https://github.com/eclipse-emfcloud/hydranium/blob/main/NOTICE.md)
89
+ for third-party notices.
@@ -7,28 +7,40 @@
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
9
  import { type TransferDiagnostic, type TransferElement } from '@hydranium/protocol';
10
- import type { DataServerProtocol, TransferDocumentUpdatedEvent } from '@hydranium/protocol/data';
10
+ import type { DataServerProtocol, ReferenceServerProtocol, TransferDocumentsBuiltEvent, TransferDocumentUpdatedEvent } from '@hydranium/protocol/data';
11
11
  import { type Harness } from '@hydranium/protocol/testing';
12
12
  import type { ConformanceCheck } from '../conformance-suite.js';
13
13
  import { type LanguageFixture } from '../model.js';
14
14
  /**
15
15
  * The data-server driver port — a live, connected, READY data-server exposed
16
- * through its protocol-native proxy plus the captured client-side update
17
- * events. The kit names only `@hydranium/protocol` types, so a
16
+ * through its protocol-native proxy plus the captured client-side
17
+ * notifications. The kit names only `@hydranium/protocol` types, so a
18
18
  * `DataServerHarness` satisfies the port structurally (it has `proxy` +
19
- * `events` + `dispose`) with NO adapter. `extends Harness` gives the kit the
19
+ * `events`, `builds` and `dispose`) with NO adapter. `extends Harness` gives the kit the
20
20
  * universal `dispose()` teardown.
21
21
  *
22
- * The kit seeds documents purely through the proxy: `updateModelDocument` is
23
- * an upsert (it creates a cold URI from the payload, not just modifies an
24
- * existing one), so the slice needs no services-level open hook. The adopter
25
- * only has to stand the server up READY in its `connect` — see
26
- * {@link DataConformanceOptions.connect}.
22
+ * The kit seeds documents purely through the proxy, as client sessions: it
23
+ * registers one with `createSession`, opens the document, or creates it with
24
+ * `createModelDocument` when there is no file to open, and writes it. So the
25
+ * head under test must implement sessions, and the slice needs no
26
+ * services-level open hook. The adopter only has to stand the server up READY
27
+ * in its `connect` — see {@link DataConformanceOptions.connect}.
27
28
  */
28
29
  export interface DataConformanceDriver<TTransfer extends TransferElement, TDiagnostic extends TransferDiagnostic = TransferDiagnostic> extends Harness {
29
30
  readonly proxy: DataServerProtocol<TTransfer, TDiagnostic>;
30
- /** Captured `onDocumentUpdated` events, append order — the subscription check's observation target. */
31
+ /** Captured `onDocumentUpdated` events, in append order. */
31
32
  readonly events: ReadonlyArray<TransferDocumentUpdatedEvent<TTransfer, TDiagnostic>>;
33
+ /** Captured `onDocumentsBuilt` events, append order — the cascade check's observation target. */
34
+ readonly builds: ReadonlyArray<TransferDocumentsBuiltEvent>;
35
+ /**
36
+ * The opt-in reference surface, when the head serves it.
37
+ *
38
+ * Separate from {@link proxy} because `ReferenceServerProtocol` is NOT part
39
+ * of `DataServerProtocol` — a head may serve documents and no references at
40
+ * all. Absent means the reference check reports skipped with a named reason
41
+ * rather than failing a head that never claimed the surface.
42
+ */
43
+ readonly references?: ReferenceServerProtocol;
32
44
  }
33
45
  /** Options for `runDataConformance`. */
34
46
  export interface DataConformanceOptions<TTransfer extends TransferElement, TDiagnostic extends TransferDiagnostic = TransferDiagnostic> {
@@ -37,6 +49,10 @@ export interface DataConformanceOptions<TTransfer extends TransferElement, TDiag
37
49
  * once per check for isolation; the kit disposes it after the check. The
38
50
  * adopter must initialise the workspace before returning, so `waitForReady`
39
51
  * resolves rather than hanging.
52
+ *
53
+ * Some checks save documents beside each fixture's `valid`, and nothing in
54
+ * the protocol deletes a file, so give each check a workspace the kit may
55
+ * write to and throw away.
40
56
  */
41
57
  readonly connect: () => DataConformanceDriver<TTransfer, TDiagnostic> | Promise<DataConformanceDriver<TTransfer, TDiagnostic>>;
42
58
  /** Per-language fixtures; the grammar-bearing checks run once per language. */
@@ -52,6 +68,13 @@ export interface DataConformanceOptions<TTransfer extends TransferElement, TDiag
52
68
  * from "never implemented" without the adopter saying which it is.
53
69
  */
54
70
  readonly expectsProjects?: boolean;
71
+ /**
72
+ * Open another connection to the same server as `driver`, for the check
73
+ * that a connection's sessions end with it while the server lives on. That
74
+ * check disposes `driver` and needs its `dispose` to close the connection as
75
+ * the server sees it. Absent, the check reports skipped.
76
+ */
77
+ readonly attach?: (driver: DataConformanceDriver<TTransfer, TDiagnostic>) => DataConformanceDriver<TTransfer, TDiagnostic> | Promise<DataConformanceDriver<TTransfer, TDiagnostic>>;
55
78
  /** Suite title override. Default `'conformance: data-server'`. */
56
79
  readonly suiteTitle?: string;
57
80
  }
@@ -62,7 +85,7 @@ export interface DataConformanceOptions<TTransfer extends TransferElement, TDiag
62
85
  * unit tests; adopters call `runDataConformance`.
63
86
  *
64
87
  * `LanguageFixture.edit` is read HERE and nowhere else in the kit, and is
65
- * optional: its two checks report skipped when it is absent. See
88
+ * optional: every check that needs one reports skipped when it is absent. See
66
89
  * {@link LanguageFixture} for which slice reads which field.
67
90
  */
68
91
  export declare function buildDataChecks<TTransfer extends TransferElement, TDiagnostic extends TransferDiagnostic = TransferDiagnostic>(options: DataConformanceOptions<TTransfer, TDiagnostic>): ConformanceCheck[];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAWlF,OAAO,EAAoB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtG,OAAO,KAAK,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AACjG,OAAO,EAAE,KAAK,OAAO,EAAW,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,KAAK,eAAe,EAAiC,MAAM,aAAa,CAAC;AAElF;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,qBAAqB,CACnC,SAAS,SAAS,eAAe,EACjC,WAAW,SAAS,kBAAkB,GAAG,kBAAkB,CAC5D,SAAQ,OAAO;IACd,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC3D,uGAAuG;IACvG,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,4BAA4B,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;CACvF;AAED,wCAAwC;AACxC,MAAM,WAAW,sBAAsB,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,SAAS,kBAAkB,GAAG,kBAAkB;IACnI;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,qBAAqB,CAAC,SAAS,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,qBAAqB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;IAC/H,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IACnD;;;;;;;;;OASG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,kEAAkE;IAClE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC/B;AAeD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,SAAS,kBAAkB,GAAG,kBAAkB,EAC3H,OAAO,EAAE,sBAAsB,CAAC,SAAS,EAAE,WAAW,CAAC,GACvD,gBAAgB,EAAE,CAsMpB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAWlF,OAAO,EAWJ,KAAK,kBAAkB,EACvB,KAAK,eAAe,EAEtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EACT,kBAAkB,EAClB,uBAAuB,EACvB,2BAA2B,EAC3B,4BAA4B,EAC9B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,KAAK,OAAO,EAAW,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,KAAK,eAAe,EAAiC,MAAM,aAAa,CAAC;AAElF;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,qBAAqB,CACnC,SAAS,SAAS,eAAe,EACjC,WAAW,SAAS,kBAAkB,GAAG,kBAAkB,CAC5D,SAAQ,OAAO;IACd,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC3D,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,4BAA4B,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;IACrF,iGAAiG;IACjG,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,2BAA2B,CAAC,CAAC;IAC5D;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,uBAAuB,CAAC;CAChD;AAED,wCAAwC;AACxC,MAAM,WAAW,sBAAsB,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,SAAS,kBAAkB,GAAG,kBAAkB;IACnI;;;;;;;;;OASG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,qBAAqB,CAAC,SAAS,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,qBAAqB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;IAC/H,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IACnD;;;;;;;;;OASG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,CACf,MAAM,EAAE,qBAAqB,CAAC,SAAS,EAAE,WAAW,CAAC,KACnD,qBAAqB,CAAC,SAAS,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,qBAAqB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;IAC5G,kEAAkE;IAClE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC/B;AA6HD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,SAAS,kBAAkB,GAAG,kBAAkB,EAC3H,OAAO,EAAE,sBAAsB,CAAC,SAAS,EAAE,WAAW,CAAC,GACvD,gBAAgB,EAAE,CAq8BpB"}