From a193e404be67570023a61e89d3fb698296e272f7 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Sun, 5 Jul 2026 12:36:09 -0700 Subject: [PATCH] test: add expectTypeOf coverage for src/* type exports Enables Vitest's typecheck runner (scoped to tests/unit/**/*.test-d.ts) so it runs alongside the regular suite via `vitest run`, and adds type-level assertions for every exported type/signature in src/*: the intersect action, intersectAttachment, createIntersectionGroup, createIntersectionObserver, and both components' prop/bindable shapes. --- tests/unit/types.test-d.ts | 126 +++++++++++++++++++++++++++++++++++++ vitest.config.ts | 4 ++ 2 files changed, 130 insertions(+) create mode 100644 tests/unit/types.test-d.ts diff --git a/tests/unit/types.test-d.ts b/tests/unit/types.test-d.ts new file mode 100644 index 0000000..a07dc62 --- /dev/null +++ b/tests/unit/types.test-d.ts @@ -0,0 +1,126 @@ +import type { Component, ComponentProps } from "svelte"; +import type { Action } from "svelte/action"; +import type { Attachment } from "svelte/attachments"; +import type { + IntersectActionOptions, + IntersectGroupNodeOptions, + IntersectGroupSharedOptions, + IntersectionGroup, + IntersectionObserverState, +} from "svelte-intersection-observer"; +import IntersectionObserverComponent, { + createIntersectionGroup, + createIntersectionObserver, + intersect, + intersectAttachment, + MultipleIntersectionObserver, +} from "svelte-intersection-observer"; +import type { IntersectionObserverProps } from "svelte-intersection-observer/IntersectionObserver.svelte"; +import type { MultipleIntersectionObserverProps } from "svelte-intersection-observer/MultipleIntersectionObserver.svelte"; +import { expectTypeOf, test } from "vitest"; + +test("IntersectActionOptions accepts the documented shape", () => { + expectTypeOf().toEqualTypeOf<{ + root?: null | HTMLElement; + rootMargin?: string; + threshold?: number | number[]; + once?: boolean; + skip?: boolean; + }>(); +}); + +test("intersect is a Svelte action dispatching observe/intersect handlers", () => { + expectTypeOf(intersect).toEqualTypeOf< + Action< + HTMLElement, + IntersectActionOptions | undefined, + { + onobserve?: (event: CustomEvent) => void; + onintersect?: ( + event: CustomEvent< + IntersectionObserverEntry & { isIntersecting: true } + >, + ) => void; + } + > + >(); +}); + +test("intersectAttachment returns an Attachment", () => { + expectTypeOf(intersectAttachment).toEqualTypeOf< + (getOptions?: () => IntersectActionOptions) => Attachment + >(); +}); + +test("IntersectGroupSharedOptions covers only the observer-wide options", () => { + expectTypeOf().toEqualTypeOf<{ + root?: null | HTMLElement; + rootMargin?: string; + threshold?: number | number[]; + }>(); +}); + +test("IntersectGroupNodeOptions covers only the per-node options", () => { + expectTypeOf().toEqualTypeOf<{ + once?: boolean; + skip?: boolean; + onobserve?: (entry: IntersectionObserverEntry) => void; + onintersect?: ( + entry: IntersectionObserverEntry & { isIntersecting: true }, + ) => void; + }>(); +}); + +test("IntersectionGroup.attach accepts node options and returns an Attachment", () => { + expectTypeOf() + .toHaveProperty("attach") + .toEqualTypeOf< + (options?: IntersectGroupNodeOptions) => Attachment + >(); +}); + +test("createIntersectionGroup returns an IntersectionGroup", () => { + expectTypeOf(createIntersectionGroup).toEqualTypeOf< + (getSharedOptions?: () => IntersectGroupSharedOptions) => IntersectionGroup + >(); +}); + +test("IntersectionObserverState exposes readonly intersecting/entry and an attach Attachment", () => { + expectTypeOf().toEqualTypeOf<{ + readonly intersecting: boolean; + readonly entry: null | IntersectionObserverEntry; + attach: Attachment; + }>(); +}); + +test("createIntersectionObserver returns an IntersectionObserverState", () => { + expectTypeOf(createIntersectionObserver).toEqualTypeOf< + (getOptions?: () => IntersectActionOptions) => IntersectionObserverState + >(); +}); + +test("default export is the IntersectionObserver component with its bindable props", () => { + expectTypeOf(IntersectionObserverComponent).toEqualTypeOf< + Component< + IntersectionObserverProps, + Record, + "intersecting" | "entry" | "observer" + > + >(); + expectTypeOf< + ComponentProps + >().toEqualTypeOf(); +}); + +test("MultipleIntersectionObserver component exposes its bindable props", () => { + expectTypeOf(MultipleIntersectionObserver).toEqualTypeOf< + Component< + MultipleIntersectionObserverProps, + Record, + "elementIntersections" | "elementEntries" | "observer" + > + >(); + expectTypeOf< + ComponentProps + >().toEqualTypeOf(); +}); diff --git a/vitest.config.ts b/vitest.config.ts index 93dcfdc..d69a13e 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -23,5 +23,9 @@ export default defineConfig({ environment: "jsdom", include: ["tests/unit/**/*.test.ts"], setupFiles: ["./tests/unit/setup.ts"], + typecheck: { + enabled: true, + include: ["tests/unit/**/*.test-d.ts"], + }, }, });