Skip to content

feat(vue): add @modular-vue/testing (PR-12) - #60

Merged
kibertoad merged 3 commits into
mainfrom
pr-12-modular-vue-testing
Jul 6, 2026
Merged

feat(vue): add @modular-vue/testing (PR-12)#60
kibertoad merged 3 commits into
mainfrom
pr-12-modular-vue-testing

Conversation

@kibertoad

@kibertoad kibertoad commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Phase 1 of the Vue support initiative, PR-12. Ports the testing helpers from @modular-react/testing to a new packages/vue-testing (@modular-vue/testing, 0.1.0). See vue-support-tracker.md.

React sources named per the working agreement (reviewers can diff intent):

Vue file React source
mock-store.ts testing/src/mock-store.ts
resolve-module.ts testing/src/resolve-module.ts
preload-entries.ts testing/src/preload-entries.ts
preload-entries.fixture.ts testing/src/preload-entries.fixture.ts

What's here

  • createMockStore — identical createStore alias over @modular-frontend/core.
  • resolveModule (+ ResolveModuleOptions / ResolveModuleResult) — byte-identical to the React version; it is pure (slot merging, dynamic-slot evaluation, onRegister, ModuleEntry assembly), all framework-neutral.
  • preloadEntries — walks each module's entryPoints and calls preloadEntry (re-exported from @modular-vue/vue) for every lazy: entry, Promise.all-ing them so one rejection doesn't leak sibling unhandled rejections.

Depends on @modular-frontend/core + @modular-vue/vue (the binding, for the preload path) plus a vue ^3.5 peer.

Deviation from the React source (forced by the framework)

React.lazy's synchronous-thenable trick does not port, matching the PR-11 resolve-entry.ts deviation. Vue's defineAsyncComponent resolves through its own async state on mount, so preloadEntries warms the resolver's WeakMap cache (saving the re-import) but not the extra microtask. Two adjustments in the ported test:

  • The React "resolves synchronously" case is replaced by one asserting the post-preload cached path replays without re-importing.
  • The vi.mock case asserts on the normalized component's displayName directly, since Vue's preload() resolves to the unwrapped default (React's resolved to the { default } module record).

Verification

  • pnpm --filter @modular-vue/testing test — 15 tests pass (6 resolve-module, 9 preload-entries).
  • pnpm --filter @modular-vue/testing typecheck — passes.
  • pnpm --filter @modular-vue/testing build — JS + dts emit clean.
  • Tracker updated in the same commit: PR-12 marked done, status board and top-of-file status line updated to "Phase 1 complete".

Summary by CodeRabbit

  • New Features

    • Added a new Vue testing package for headless module testing.
    • Introduced helpers to resolve modules and preload lazy module entries for faster, more reliable test setup.
    • Added a mock store helper for easier test-friendly state management.
  • Documentation

    • Updated the Vue support tracker to reflect Phase 1 completion and detailed progress for the testing package.

Port the testing helpers from @modular-react/testing to a new
packages/vue-testing (@modular-vue/testing, 0.1.0):

- createMockStore: identical createStore alias over @modular-frontend/core.
- resolveModule: byte-identical to the React version (pure slot merging,
  dynamic-slot evaluation, onRegister, ModuleEntry assembly).
- preloadEntries: walks each module's entryPoints and preloads every lazy
  entry via preloadEntry (re-exported from @modular-vue/vue).

The synchronous-thenable trick from React.lazy does not port (matching the
PR-11 resolve-entry.ts deviation): Vue's defineAsyncComponent resolves through
its own async state, so preloadEntries warms the resolver cache but not the
extra microtask. The React synchronous-resolution test is replaced by a
cached-replay test; the vi.mock test asserts on the normalized component's
displayName (Vue's preload() resolves to the unwrapped default).

15 tests pass (6 resolve-module, 9 preload-entries); typecheck and vite build
(JS + dts) pass. Tracker updated: PR-12 done, Phase 1 complete.
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kibertoad, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 13 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9acfa9db-a0d4-42fe-912e-d919c4b522d9

📥 Commits

Reviewing files that changed from the base of the PR and between 137e059 and 7c422e1.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (24)
  • docs/vue-support-tracker.md
  • packages/frontend-testing/package.json
  • packages/frontend-testing/src/index.ts
  • packages/frontend-testing/src/mock-store.ts
  • packages/frontend-testing/src/resolve-module.test.ts
  • packages/frontend-testing/src/resolve-module.ts
  • packages/frontend-testing/tsconfig.json
  • packages/frontend-testing/vite.config.ts
  • packages/react-router-testing/package.json
  • packages/react-router-testing/src/index.ts
  • packages/react-router-testing/src/resolve-module.test.ts
  • packages/react-router-testing/src/resolve-module.ts
  • packages/react-router-testing/vite.config.ts
  • packages/tanstack-router-testing/package.json
  • packages/tanstack-router-testing/src/index.ts
  • packages/tanstack-router-testing/src/resolve-module.test.ts
  • packages/tanstack-router-testing/src/resolve-module.ts
  • packages/tanstack-router-testing/vite.config.ts
  • packages/testing/package.json
  • packages/testing/src/index.ts
  • packages/testing/vite.config.ts
  • packages/vue-testing/package.json
  • packages/vue-testing/src/index.ts
  • packages/vue-testing/vite.config.ts
📝 Walkthrough

Walkthrough

This PR introduces a new @modular-vue/testing package providing createMockStore, resolveModule, and preloadEntries test helpers, with associated package/build configuration, exports, tests, and fixtures. The tracker documentation is updated to mark this work as complete.

Changes

Vue testing package

Layer / File(s) Summary
Package manifest and build config
packages/vue-testing/package.json, packages/vue-testing/tsconfig.json, packages/vue-testing/vite.config.ts
Adds ESM package manifest with build/dev/test/typecheck scripts, workspace dev/peer dependencies, tsconfig extending base config excluding tests/fixtures, and Vite library build config externalizing Vue-related packages.
Mock store helper and exports
packages/vue-testing/src/mock-store.ts, packages/vue-testing/src/index.ts
Adds createMockStore wrapping createStore as a Zustand-compatible test helper, and consolidates package exports including resolveModule, preloadEntries, and re-exported preloadEntry.
resolveModule implementation and tests
packages/vue-testing/src/resolve-module.ts, packages/vue-testing/src/resolve-module.test.ts
Adds resolveModule for headless module testing, resolving static/dynamic slots, constructing a ModuleEntry, invoking onRegister lifecycle, and returning slots/entry/onRegisterCalled; includes test coverage.
preloadEntries implementation and tests
packages/vue-testing/src/preload-entries.ts, packages/vue-testing/src/preload-entries.fixture.ts, packages/vue-testing/src/preload-entries.test.ts
Adds preloadEntries to eagerly preload lazy module entry points via Promise.all, plus a mockable fixture and tests covering caching, idempotency, rejection propagation, and mock hoisting.
Tracker documentation
docs/vue-support-tracker.md
Updates the Phase 1 status to complete, expands the PR-12 write-up, and marks the status board row as done.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Test
  participant preloadEntries
  participant ModuleDescriptor
  participant preloadEntry

  Test->>preloadEntries: call(modules)
  preloadEntries->>ModuleDescriptor: read entryPoints
  loop each lazy entry
    preloadEntries->>preloadEntry: preloadEntry(entry)
    preloadEntry-->>preloadEntries: resolved import
  end
  preloadEntries-->>Test: Promise.all resolved
Loading
sequenceDiagram
  participant Test
  participant resolveModule
  participant buildSlotsManifest
  participant ModuleDescriptor

  Test->>resolveModule: call(module, options)
  resolveModule->>buildSlotsManifest: build(module, defaults)
  buildSlotsManifest-->>resolveModule: slots
  resolveModule->>ModuleDescriptor: evaluate dynamicSlots(deps)
  ModuleDescriptor-->>resolveModule: merged slots
  resolveModule->>ModuleDescriptor: onRegister(deps)
  ModuleDescriptor-->>resolveModule: onRegisterCalled
  resolveModule-->>Test: {slots, entry, onRegisterCalled}
Loading

Possibly related PRs

  • kibertoad/modular-react#32: Implements the same preloadEntries helper pattern with tests/fixtures and preloadEntry re-export for the React testing package.

Suggested labels: minor

Suggested reviewers: diogomiguel

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: adding the @modular-vue/testing package for PR-12.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pr-12-modular-vue-testing

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

kibertoad added 2 commits July 6, 2026 15:35
Address PR-12 review: resolveModule and createMockStore were byte-identical,
framework-neutral copies in @modular-react/testing and @modular-vue/testing
(pure over @modular-frontend/core). Extract them into a shared
@modular-frontend/testing package that both bindings re-export, so slot
resolution and mock-store fixes land in one place. Mirrors the earlier
journeys-engine / compositions-engine extractions. preloadEntries stays
per-binding since it imports the binding's preloadEntry.

Also fix stale JSDoc that referenced React-only renderModule() in the Vue
testing sources.

- new packages/frontend-testing (@modular-frontend/testing 0.1.0) with
  mock-store, resolve-module, and the resolve-module test suite (6 tests)
- @modular-react/testing and @modular-vue/testing re-export the neutral
  helpers, keep their own preload-entries (9 tests each)
- build, typecheck, and tests pass for all three packages
…r-frontend/testing

Extends the shared-testing extraction to the router bindings.
@react-router-modules/testing and @tanstack-react-modules/testing carried
their own byte-identical resolveModule (same slot-resolution logic, only the
core import path and a doc line differed). Both now re-export it from
@modular-frontend/testing; the router ModuleDescriptor is assignable to the
shared generic, so caller ergonomics are unchanged (typecheck + suites pass).

createMockStore stays local in each router package: it wraps zustand's
createStore and returns StoreApi<T>, a different implementation than the
frontend-core store, so it is not shareable.

- delete resolve-module.ts from both router-testing packages (~69 lines each)
- re-export resolveModule + option/result types from @modular-frontend/testing
- point each resolve-module.test.ts at the shared package
- add @modular-frontend/testing dep/peer + vite external to both
- typecheck, tests (9 each), and build (JS + dts) pass for both packages
@kibertoad
kibertoad merged commit 807b489 into main Jul 6, 2026
18 of 19 checks passed
@kibertoad
kibertoad deleted the pr-12-modular-vue-testing branch July 6, 2026 12:45
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