Add specs for experimental overlay internals - #655
Open
fpigeonjr wants to merge 2 commits into
Open
Conversation
Add unit specs for the CDK-style overlay positioning and scroll-strategy internals under experimental/patterns/layout/components/core/overlay/, raising coverage on files that were previously at or near 0%: - connected-position-strategy.ts: 0% -> 95.45% stmts - overlay-ref.ts: 0% -> 96.42% stmts - global-position-strategy.ts: 0% -> 100% stmts - overlay-directives.ts: 3.30% -> 93.47% stmts - block-scroll-strategy.ts: 0% -> 100% stmts - close-scroll-strategy.ts: 0% -> 100% stmts - reposition-scroll-strategy.ts: 0% -> 100% stmts - scroll-dispatcher.ts: 6.82% -> 97.72% stmts Also fixes a latent bug in ScrollDispatcher.scrolled(): the throttled branch used the RxJS 5-style auditTime.call(observable, ms) form, which under RxJS 7 returns an operator function rather than an Observable and throws on subscribe(). Every current caller passes a 0ms delay, so the branch was effectively dead code and untested. Switched to observable.pipe(auditTime(ms)) so the throttled path actually works and is now covered by a spec. Specs construct the units directly (fake collaborators, jsdom fixtures) rather than through TestBed, matching these files' narrow public surface (apply()/dispose()/enable()/disable() etc.) per the issue's guidance. Closes #634
There was a problem hiding this comment.
Pull request overview
Adds unit specs for the experimental CDK-style overlay internals (positioning + scroll strategies) under src/ui-kit/experimental/patterns/layout/components/core/overlay/, and includes a small RxJS-7 compatibility fix in ScrollDispatcher.scrolled().
Changes:
- Adds 8 new colocated spec files covering overlay directives, overlay ref behavior, position strategies, and scroll strategies/dispatcher.
- Fixes
ScrollDispatcher.scrolled()throttling path to useobservable.pipe(auditTime(ms))instead of the RxJS-5-styleauditTime.call(...). - Improves coverage for the targeted overlay internals without modifying
coverage-floor.json(per repo ratchet guidance).
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/ui-kit/experimental/patterns/layout/components/core/overlay/scroll/scroll-dispatcher.ts | RxJS 7-safe auditTime usage for throttled scrolled notifications. |
| src/ui-kit/experimental/patterns/layout/components/core/overlay/scroll/scroll-dispatcher.spec.ts | New unit coverage for ScrollDispatcher registration, global listener lifecycle, and throttling behavior. |
| src/ui-kit/experimental/patterns/layout/components/core/overlay/scroll/reposition-scroll-strategy.spec.ts | New unit coverage for reposition strategy attach/enable/disable semantics and throttle passthrough. |
| src/ui-kit/experimental/patterns/layout/components/core/overlay/scroll/close-scroll-strategy.spec.ts | New unit coverage for close-on-scroll behavior and subscription lifecycle. |
| src/ui-kit/experimental/patterns/layout/components/core/overlay/scroll/block-scroll-strategy.spec.ts | New unit coverage for scroll blocking and style restoration behavior. |
| src/ui-kit/experimental/patterns/layout/components/core/overlay/position/global-position-strategy.spec.ts | New unit coverage for fluent setters, wrapper behavior, and disposal. |
| src/ui-kit/experimental/patterns/layout/components/core/overlay/position/connected-position-strategy.spec.ts | New unit coverage for preferred/fallback positioning, direction handling, offsets, and position change emissions. |
| src/ui-kit/experimental/patterns/layout/components/core/overlay/overlay-ref.spec.ts | New unit coverage for attach/detach/dispose flows, sizing/positioning updates, and backdrop behaviors. |
| src/ui-kit/experimental/patterns/layout/components/core/overlay/overlay-directives.spec.ts | New unit coverage for OverlayOrigin and ConnectedOverlayDirective configuration and open/close behavior. |
Suppressed comments (2)
src/ui-kit/experimental/patterns/layout/components/core/overlay/scroll/scroll-dispatcher.spec.ts:92
- This test creates multiple
scrolled()subscriptions but doesn't unsubscribe them, which can leave global listeners running and affect subsequent tests. Unsubscribe both subscriptions at the end of the test.
it("shares a single global listener across multiple subscriptions", () => {
const dispatcher = new ScrollDispatcher(ngZone, createFakePlatform());
dispatcher.scrolled(0, vi.fn());
dispatcher.scrolled(0, vi.fn());
src/ui-kit/experimental/patterns/layout/components/core/overlay/scroll/scroll-dispatcher.spec.ts:117
- This test leaves the registered
Scrollablesubscription (and the dispatcher's global listeners) active after the assertion. Add explicit cleanup after the expectation so this test doesn't leak listeners/state into later tests.
it("keeps the global listener alive while a Scrollable is still registered", () => {
const dispatcher = new ScrollDispatcher(ngZone, createFakePlatform());
const scrollable = createFakeScrollable();
dispatcher.register(scrollable as unknown as Scrollable);
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- block-scroll-strategy.spec.ts: delete the document.body scrollHeight/ scrollWidth own-property overrides in afterEach so they don't leak into later tests (afterEach only restored HTMLElement.prototype descriptors). - scroll-dispatcher.spec.ts: capture and unsubscribe every Subscription returned by scrolled() so global scroll/resize listeners don't leak across tests; replace the real setTimeout wait in the auditTime debouncing test with Vitest fake timers for determinism. - overlay-ref.spec.ts: wrap the detachBackdrop() transitionend test in fake timers and flush the pending 500ms fallback setTimeout so no timer is left running after the test.
fpigeonjr
marked this pull request as ready for review
August 28, 2026 18:11
divyabairavarasu
approved these changes
Aug 28, 2026
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds unit specs for the CDK-style overlay positioning and scroll-strategy internals under
src/ui-kit/experimental/patterns/layout/components/core/overlay/, closing the coverage gap called out in the parent epic (#576).Coverage moved from at-or-near 0% to meaningfully covered for every targeted file:
connected-position-strategy.tsoverlay-ref.tsglobal-position-strategy.tsoverlay-directives.tsblock-scroll-strategy.tsclose-scroll-strategy.tsreposition-scroll-strategy.tsscroll-dispatcher.tsRepo-wide coverage improved from 53.56%/39.77%/50.31%/52.84% (stmts/branches/fns/lines) to 59.22%/44.33%/55.63%/58.68%.
coverage-floor.jsonis intentionally not touched — raising the ratchet is a separate, deliberatecoverage:bumpcommit perAGENTS.md.Specs added (one file per source unit, colocated):
overlay-directives.spec.tsoverlay-ref.spec.tsposition/connected-position-strategy.spec.tsposition/global-position-strategy.spec.tsscroll/block-scroll-strategy.spec.tsscroll/close-scroll-strategy.spec.tsscroll/reposition-scroll-strategy.spec.tsscroll/scroll-dispatcher.spec.tsSpecs construct the units directly with fake collaborators and jsdom fixtures rather than through
TestBed, matching these files' narrow public surface (apply()/dispose()/enable()/disable()/etc.) per the issue's guidance to favor testing through the public interface over reaching into private state.Incidental bug fix:
ScrollDispatcher.scrolled()'s throttled branch used the RxJS 5-styleauditTime.call(observable, ms)form. Under RxJS 7 (this repo's version), that returns an operator function rather than an Observable, so calling.subscribe()on the result throws. Every current caller passes a0msdelay, so the branch was effectively dead code and untested — which is also why it showed up as part of this coverage gap. Fixed by switching toobservable.pipe(auditTime(ms)), and the throttled path is now covered by a spec (scroll-dispatcher.spec.ts, "applies auditTime debouncing when a positive delay is provided").Motivation and Context
Closes #634
Type of Change (Select One and Apply Label)
bugfixlabelenhancementlabelbreakinglabelmaintenancelabelHow to Test
npm ci && npm ci --prefix test-appcd test-app && npx vitest run --coverage --config vitest.config.mts— runs the full spec suite; expectTest Files 114 passed (114)/Tests 758 passed (758).npm run coverage:check(from repo root) — confirms the ratcheting coverage-floor gate still passes and has improved.npm run format:check/npm run lint:baseline/npm --prefix test-app run lint:baseline— confirm no new formatting or lint-warning regressions.Expected result: All specs pass, per-file coverage for the 8 target files moves off their previous baselines (see table above), and the coverage-floor gate passes with all four metrics improved over the recorded floor.
Screenshots (if appropriate)
N/A — test/spec changes only, no UI impact.
Checklist
gh-<number>-<slug>)format:checkpasses (npm run format:check)lintpasses (npm run lint)buildpasses (cd test-app && npm run build)cd test-app && npm test)