Skip to content

test(node): cover Endpoint.getStateOf() overloads on server endpoints#3685

Merged
Apollon77 merged 4 commits intomainfrom
test/endpoint-get-state-of
May 4, 2026
Merged

test(node): cover Endpoint.getStateOf() overloads on server endpoints#3685
Apollon77 merged 4 commits intomainfrom
test/endpoint-get-state-of

Conversation

@Apollon77
Copy link
Copy Markdown
Collaborator

@Apollon77 Apollon77 commented May 4, 2026

Summary

Adds runtime + type-level coverage for Endpoint.getStateOf(), which previously had no integration tests beyond a single error case in ClientGroupTest. Surfaced during follow-up review of #3683.

Runtime tests (EndpointGetServerTest.ts)

Exercise all three overloads against MockServerNode + BasicInformationServer:

  • (B) and (B, true) → full behavior state.
  • (B, K[]) → only the requested attributes; empty list returns {}.
  • (string, string[]) → string-id fallback overload.
  • Unknown behavior id → EndpointBehaviorNotPresentError.
  • Unknown attribute on the string overload → AttributeNotPresentError.

Type-level tests (EndpointGetTypesTest.ts)

Assert each overload's return shape:

  • getStateOf(B) / getStateOf(B, true)Promise<Behavior.StateOf<B>>.
  • getStateOf(B, K[])Promise<{ readonly [P in K]?: Behavior.StateOf<B>[P] }>, including a @ts-expect-error for unknown keys.
  • getStateOf(string, string[]) accepts arbitrary string keys.

The type-only block lives behind if ((false as boolean) === true) so the runtime never executes against the phantom endpoint instance.

Coverage gaps still open (out of scope for this PR)

  • Client-side getStateOf() integration (heavier mock-site setup).
  • Client EndpointReadFailedError partial-state-on-failure contract end-to-end.
  • GetOptions.fabricFilter pathway.
  • Server per-attribute mid-read failures.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings May 4, 2026 10:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds missing runtime and compile-time coverage for Endpoint.getStateOf() overloads, focusing on server endpoints via MockServerNode and augmenting existing type-helper tests to validate overload return types.

Changes:

  • Add server-endpoint integration tests covering all getStateOf() overloads and key error cases.
  • Add type-level assertions for getStateOf() overload return types (including @ts-expect-error for invalid keys).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
packages/node/test/endpoint/EndpointGetTypesTest.ts Adds compile-time checks for Endpoint.getStateOf() overload return types.
packages/node/test/endpoint/EndpointGetServerTest.ts Adds runtime integration tests for getStateOf() behavior/selector overloads and error conditions on a server endpoint.

Comment on lines +139 to +141
const _stateOfKeys = _ep.getStateOf(_fakeBeh, ["value"] as const);
const _checkKeysAwait: Awaited<typeof _stateOfKeys> = {} as { readonly value?: number };
void _checkKeysAwait;
Comment thread packages/node/test/endpoint/EndpointGetTypesTest.ts Outdated
Adds runtime + type-level coverage for `Endpoint.getStateOf()`, which
previously had no integration tests beyond a single error case in
`ClientGroupTest`.

Server-side runtime tests (`EndpointGetServerTest.ts`) exercise all
three overloads against `MockServerNode` + `BasicInformationServer`:
- `(B)` and `(B, true)` return full behavior state.
- `(B, K[])` returns the requested attributes only; empty list returns `{}`.
- `(string, string[])` resolves the string-id fallback overload.
- Unknown behavior id throws `EndpointBehaviorNotPresentError`.
- Unknown attribute on the string overload throws `AttributeNotPresentError`.

Client-side runtime tests (`EndpointGetClientTest.ts`) mirror the server
suite using `MockSite` + `BasicInformationClient` (the client-cluster
behavior, not the server variant) plus a regression test calling
`peer.getStateOf(OperationalCredentialsClient, ['fabrics'])` directly on
the typed peer reference. Without the source change below, the latter
fails to compile because dynamically-added behaviors (added by
`ClientStructure` post-commissioning) are not in `ClientNode.RootEndpoint`'s
static behavior map. Reproduces the user-reported error:

  Argument of type 'OperationalCredentialsClientConstructor' is not
  assignable to parameter of type 'BehaviorOf<RootEndpoint>'.

The fix loosens the typed `getStateOf` overload constraints in
`Endpoint.ts` from `B extends BehaviorOf<T>` to `B extends Behavior.Type`.
The runtime check at line 385 still throws `EndpointBehaviorNotPresentError`
for behaviors not present on the endpoint, so safety is unchanged: callers
who pass a `Behavior.Type` not actually supported by the endpoint receive
the same runtime error as the string-id overload (which never had a
compile-time existence check). Return type tightening via
`Behavior.StateOf<B>` is preserved.

Type-level tests (`EndpointGetTypesTest.ts`) assert each overload's
return shape:
- `getStateOf(B)` / `getStateOf(B, true)` → `Promise<Behavior.StateOf<B>>`.
- `getStateOf(B, K[])` → `Promise<{ readonly [P in K]?: Behavior.StateOf<B>[P] }>`,
  including a `@ts-expect-error` for unknown keys.
- `getStateOf(string, string[])` accepts arbitrary string keys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Apollon77 Apollon77 force-pushed the test/endpoint-get-state-of branch from a03ece7 to 3fc2c5d Compare May 4, 2026 11:37
Apollon77 and others added 2 commits May 4, 2026 13:50
Verifies the `fabricFilter` option threads through `Endpoint.get()` to
the protocol Read on the client path (Endpoint.ts:1069). Server-side
reads hardcode `fabricFilter: false` (Endpoint.ts:1120) and ignore the
option, so this test covers only the plumbing on the client side:
passing `fabricFilter: false` must not throw and must still return a
usable slice.

Coverage gaps still open (out of scope for this PR):
- Client partial-state-on-failure (`EndpointReadFailedError` carrying
  failed paths + partial slice). The endpoint pre-validates requested
  attribute names against the cluster's supported elements at
  `Endpoint.ts:1042` and rejects unknowns with `AttributeNotPresentError`
  before reaching the protocol read. ClientStructure mirrors the
  device's supported attribute set on the peer, so the client peer
  rejects on the same path. Triggering `EndpointReadFailedError`
  end-to-end requires a protocol-level mock that injects per-attribute
  `attr-status` failures, which is not yet available in the node test
  infrastructure.
- Server per-attribute mid-read failure has the same root cause and is
  blocked on the same mock infrastructure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address Copilot review on PR #3685:

- The previous `_checkKeysAwait` assignment was one-sided: it only
  checked that `{ readonly value?: number }` was assignable to
  `Awaited<typeof _stateOfKeys>`, so an extra optional property
  creeping into the return type would have slipped through. Switch to
  the bidirectional `_AssertEqual` helper already used elsewhere in
  this file so the test fails on either-direction drift.
- The comment above the dead-code block claimed it was wrapped in
  `if (false)`, but the actual guard is `(false as boolean) === true`.
  Rewrite the comment to match the code and explain why the cast is
  required (it defeats TypeScript's constant-condition unreachable-
  code check that a literal `if (false)` would trigger).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

packages/node/src/endpoint/Endpoint.ts:368

  • Changing the typed getStateOf() overloads from B extends BehaviorOf<T> to B extends Behavior.Type weakens compile-time enforcement that the behavior is actually part of the endpoint’s static behavior map. Since unsupported behavior types will now compile but throw EndpointBehaviorNotPresentError at runtime, the typed overloads should document this (or consider keeping the narrower BehaviorOf<T> overloads alongside a broader overload for dynamically-added client behaviors).
    getStateOf<B extends Behavior.Type>(
        type: B,
        selector?: true,
        options?: Endpoint.GetOptions,
    ): Promise<Behavior.StateOf<B>>;
    getStateOf<B extends Behavior.Type, K extends keyof Behavior.StateOf<B>>(
        type: B,
        selector: readonly K[],
        options?: Endpoint.GetOptions,
    ): Promise<{ readonly [P in K]?: Behavior.StateOf<B>[P] }>;

Comment thread packages/node/test/endpoint/EndpointGetClientTest.ts Outdated
Address Copilot review on PR #3685: comment in `EndpointGetClientTest`
referenced `Endpoint.ts:1069` / `Endpoint.ts:1120`, which rot as the
file changes. Replace with stable method-name references
(`Endpoint.#performRead` client branch / server branch).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Apollon77 Apollon77 merged commit 3d49951 into main May 4, 2026
36 checks passed
@Apollon77 Apollon77 deleted the test/endpoint-get-state-of branch May 4, 2026 12:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants