Skip to content

test(combobox-web): characterisation tests at the selector seam and typed test mocks - #2499

Open
r0b1n wants to merge 6 commits into
mainfrom
feat/combobox-selector-safety-net
Open

r0b1n wants to merge 6 commits into
mainfrom
feat/combobox-selector-safety-net

Conversation

@r0b1n

@r0b1n r0b1n commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Pull request type

  • Test related change
  • Build related changes (test utils)

Description

Unit test improvements for combobox-web, with no production code change and no dependency on any other work. Everything here is useful on its own.

Characterisation tests at the selector seam. The selectors, options providers and captions providers under src/helpers/ are the combobox model, and they were only tested indirectly through the React components. This PR adds tests written against the current behaviour for every family (association single and multi, enumeration and boolean, static, database single and multi), plus getSelector, BaseOptionsProvider filtering, LazyLoadProvider, datasourceFilter and the useGetSelector hook seam. Shared props fixture in src/helpers/__tests__/fixtures.ts. OpenSpec change combobox-selector-safety-net in the package.

Before After
Suites 6 16
Tests 61 194
Snapshots 5 5, untouched

A mutation check (one deliberate break per family, reverted) confirmed each family is caught. Behaviour the tests found questionable is pinned with a // Quirk: comment and rated in the change's design.md. Three are real bugs for their own follow-up changes: stale currentId in the static selector on external clear, descending chip sort when the datasource has no sort order, and the database multi selector never forcing the boxes style.

Test utils (@mendix/widget-plugin-test-utils, source compatible for all existing callers): actionValue takes the action type as a type parameter so actions with parameters need no cast; ListValueBuilder gains withLimit and withSortOrder, and its isUnavailable now sets the unavailable status (it set loading, unused until now); listAttribute accepts an optional typed id. Each addition has a test.

Spec hygiene. The new specs and the two existing component specs build their mocks through the builders and typed props objects instead of casting mocks to ad-hoc shapes. pnpm exec tsc --noEmit -p tsconfig.json is clean in the package; Jest runs through swc without type checking, so this is worth running before pushing specs.

Agent documentation. docs/requirements/backend-structure.md records that simple-type widget props are constants for the lifetime of a widget instance, with the consequence for stores and tests.

Testing

  • pnpm run test in combobox-web: 16 suites, 194 tests, 5 snapshots unchanged (no -u).
  • pnpm run test in widget-plugin-test-utils: 52 tests.
  • pnpm run lint in both: 0 errors, remaining warnings pre-existing in untouched files.
  • No CHANGELOG entry, nothing user-facing changes.

@r0b1n
r0b1n force-pushed the feat/combobox-selector-safety-net branch from d7cf817 to b6e38a2 Compare October 30, 2026 08:34
@r0b1n
r0b1n force-pushed the feat/combobox-selector-safety-net branch from 4720a03 to e251deb Compare October 30, 2026 08:57
@r0b1n r0b1n changed the title test(combobox-web): headless combobox design docs and selector safety net test(combobox-web): characterisation tests at the selector seam and typed test mocks Oct 30, 2026
@r0b1n
r0b1n force-pushed the feat/combobox-selector-safety-net branch from e251deb to ca117d9 Compare October 30, 2026 08:58
@r0b1n
r0b1n marked this pull request as ready for review October 30, 2026 09:36
@r0b1n
r0b1n requested a review from a team as a code owner October 30, 2026 09:36
@github-actions

This comment has been minimized.

r0b1n added 6 commits October 30, 2026 14:30
Simple-type props only change on a redeploy, never between re-renders.
Stores can read them once as plain fields and tests must not change them
between renders.
Covers every selector family, getSelector, BaseOptionsProvider filtering,
LazyLoadProvider, datasourceFilter and the useGetSelector hook with tests
written against the current behaviour, so the helpers layer can be
refactored safely. Pinned quirks are marked in the tests and rated in the
OpenSpec change. Suite goes from 61 to 194 tests, snapshots untouched.
LazyLoadProvider.spec passed string literals where ValueStatus is expected
and useGetSelector.spec cast an ActionValue to an incompatible type. Jest
runs through swc without type checking, so only tsc --noEmit saw it.
…list builder

actionValue takes the ActionValue type as a type parameter so actions with
parameters need no cast. ListValueBuilder gains withLimit and withSortOrder,
and isUnavailable now sets the unavailable status instead of loading.
listAttribute accepts an optional attribute id.
…of casts

The characterisation specs set status, items, limit, sort order, validation
and attribute ids by casting mocks to ad-hoc shapes. They now use the
builders, the typed attrId helper and the generic actionValue. No
expectation changed.
The lazy loading scenario in SingleSelection and MultiSelection built an
untyped props object with an enum cast. It is now a ComboboxContainerProps
and the cast and its import are gone.
@r0b1n
r0b1n force-pushed the feat/combobox-selector-safety-net branch from ca117d9 to 2a2a4ee Compare October 30, 2026 13:30
@github-actions

Copy link
Copy Markdown
Contributor

AI Code Review

✅ Approved — no issues found


What was reviewed

Package Change
combobox-web 12 new or updated specs plus the shared fixtures.ts. They cover the association, enum/bool, static and database selectors, getSelector, BaseOptionsProvider, LazyLoadProvider, datasourceFilter and useGetSelector. The two existing component specs now use builders. The package also gets an OpenSpec change under openspec/changes/combobox-selector-safety-net, which sits inside the package as required.
widget-plugin-test-utils actionValue<T> takes a type parameter. ListValueBuilder gains withLimit and withSortOrder. ListValueBuilder.isUnavailable now sets the Unavailable status. listAttribute accepts an optional typed id. A test covers each addition.
docs/requirements/backend-structure.md Documents that simple-type props are constants for the lifetime of a widget instance.

Skipped (out of scope): none

CI: pending: Run code quality check, sigridci, triage, Plan E2E matrix · unrelated failures: security/snyk (external scanner, and the diff touches no production code)


Questions

  • ListValueBuilder.isUnavailable() used to set the Loading status and now sets Unavailable. Nothing outside the new specs calls it, so I found no regression. Can you confirm no other branch or package relies on the old behaviour?

Positives

  • The PR changes tests, test utilities and docs only, with no production code and no XML contract changes. A changelog entry is correctly not required.
  • The new specs build mocks with the shared builders (ListValueBuilder, ReferenceValueBuilder and others) and typed props. They avoid ad-hoc casts.
  • Questionable current behaviour is pinned with // Quirk: comments and rated in design.md, so follow-up fixes can reference it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant