diff --git a/.changeset/COMPT-33-test-suite.md b/.changeset/COMPT-33-test-suite.md new file mode 100644 index 0000000..4fc4e55 --- /dev/null +++ b/.changeset/COMPT-33-test-suite.md @@ -0,0 +1,13 @@ +--- +'@ciscode/hooks-kit': patch +--- + +test(COMPT-33): full test suite for all 12 hooks + +- Consolidate all hook tests under src/hooks/__tests__/ +- Cover all 12 hooks: useDebounce, useLocalStorage, useSessionStorage, + useMediaQuery, useWindowSize, useClickOutside, useIntersectionObserver, + usePrevious, useToggle, useInterval, useTimeout, useIsFirstRender +- Use vitest fake timers for useDebounce, useInterval, useTimeout, useWindowSize +- Verify all acceptance criteria per COMPT-33 definition of done +- Coverage ≥ 85% lines across all hooks diff --git a/.github/instructions/copilot-instructions.md b/.github/instructions/copilot-instructions.md index 4e256f2..af4e50d 100644 --- a/.github/instructions/copilot-instructions.md +++ b/.github/instructions/copilot-instructions.md @@ -19,8 +19,8 @@ - **State & Storage** (COMPT-30 ✅) — `useDebounce`, `useLocalStorage`, `useSessionStorage` - **DOM & Events** (COMPT-31 ✅) — `useMediaQuery`, `useWindowSize`, `useClickOutside`, `useIntersectionObserver` -<<<<<<< HEAD - **Async & Lifecycle** (COMPT-32 ✅) — `usePrevious`, `useToggle`, `useInterval`, `useTimeout`, `useIsFirstRender` +- **Test Suite** (COMPT-33 ✅) — Full coverage for all 12 hooks, all tests in `src/hooks/__tests__/` ### Module Responsibilities: @@ -54,7 +54,20 @@ src/ │ ├── useInterval.ts # COMPT-32 ✅ │ ├── useTimeout.ts # COMPT-32 ✅ │ ├── useIsFirstRender.ts # COMPT-32 ✅ - │ └── index.ts # Hook barrel + │ ├── index.ts # Hook barrel + │ └── __tests__/ # All hook tests (COMPT-33 ✅) + │ ├── useDebounce.test.ts + │ ├── useLocalStorage.test.ts + │ ├── useSessionStorage.test.ts + │ ├── useMediaQuery.test.ts + │ ├── useWindowSize.test.ts + │ ├── useClickOutside.test.ts + │ ├── useIntersectionObserver.test.ts + │ ├── usePrevious.test.ts + │ ├── useToggle.test.ts + │ ├── useInterval.test.ts + │ ├── useTimeout.test.ts + │ └── useIsFirstRender.test.ts ├── utils/ # Framework-agnostic utils │ ├── noop.ts │ └── index.ts diff --git a/src/hooks/useClickOutside.test.ts b/src/hooks/__tests__/useClickOutside.test.ts similarity index 97% rename from src/hooks/useClickOutside.test.ts rename to src/hooks/__tests__/useClickOutside.test.ts index ff556b9..6d5f792 100644 --- a/src/hooks/useClickOutside.test.ts +++ b/src/hooks/__tests__/useClickOutside.test.ts @@ -1,7 +1,7 @@ import { act, renderHook } from '@testing-library/react'; import { useRef } from 'react'; import { describe, expect, it, vi } from 'vitest'; -import { useClickOutside } from './useClickOutside'; +import { useClickOutside } from '../useClickOutside'; function mountClickOutside(element: HTMLDivElement, handler: ReturnType) { return renderHook(() => { diff --git a/src/hooks/useDebounce.test.ts b/src/hooks/__tests__/useDebounce.test.ts similarity index 97% rename from src/hooks/useDebounce.test.ts rename to src/hooks/__tests__/useDebounce.test.ts index 504f555..fa2ea89 100644 --- a/src/hooks/useDebounce.test.ts +++ b/src/hooks/__tests__/useDebounce.test.ts @@ -1,6 +1,6 @@ import { act, renderHook } from '@testing-library/react'; import { afterEach, describe, expect, it, vi } from 'vitest'; -import { useDebounce } from './useDebounce'; +import { useDebounce } from '../useDebounce'; describe('useDebounce', () => { afterEach(() => { diff --git a/src/hooks/useIntersectionObserver.test.ts b/src/hooks/__tests__/useIntersectionObserver.test.ts similarity index 97% rename from src/hooks/useIntersectionObserver.test.ts rename to src/hooks/__tests__/useIntersectionObserver.test.ts index f262b06..5b64fe7 100644 --- a/src/hooks/useIntersectionObserver.test.ts +++ b/src/hooks/__tests__/useIntersectionObserver.test.ts @@ -1,7 +1,7 @@ import { act, renderHook } from '@testing-library/react'; import { useRef } from 'react'; import { afterEach, describe, expect, it, vi } from 'vitest'; -import { useIntersectionObserver } from './useIntersectionObserver'; +import { useIntersectionObserver } from '../useIntersectionObserver'; type IntersectionCallback = (entries: IntersectionObserverEntry[]) => void; diff --git a/src/hooks/useLocalStorage.test.ts b/src/hooks/__tests__/useLocalStorage.test.ts similarity index 93% rename from src/hooks/useLocalStorage.test.ts rename to src/hooks/__tests__/useLocalStorage.test.ts index e48abf1..78a2ea0 100644 --- a/src/hooks/useLocalStorage.test.ts +++ b/src/hooks/__tests__/useLocalStorage.test.ts @@ -1,7 +1,7 @@ import { act, renderHook } from '@testing-library/react'; import { afterEach, describe, expect, expectTypeOf, it, vi } from 'vitest'; -import { readStorageValue } from './storage'; -import { useLocalStorage } from './useLocalStorage'; +import { readStorageValue } from '../storage'; +import { useLocalStorage } from '../useLocalStorage'; describe('useLocalStorage', () => { afterEach(() => { diff --git a/src/hooks/useMediaQuery.test.ts b/src/hooks/__tests__/useMediaQuery.test.ts similarity index 97% rename from src/hooks/useMediaQuery.test.ts rename to src/hooks/__tests__/useMediaQuery.test.ts index 9f03c7e..6985b15 100644 --- a/src/hooks/useMediaQuery.test.ts +++ b/src/hooks/__tests__/useMediaQuery.test.ts @@ -1,6 +1,6 @@ import { act, renderHook } from '@testing-library/react'; import { afterEach, describe, expect, it, vi } from 'vitest'; -import { useMediaQuery } from './useMediaQuery'; +import { useMediaQuery } from '../useMediaQuery'; type ChangeHandler = () => void; diff --git a/src/hooks/useSessionStorage.test.ts b/src/hooks/__tests__/useSessionStorage.test.ts similarity index 93% rename from src/hooks/useSessionStorage.test.ts rename to src/hooks/__tests__/useSessionStorage.test.ts index 8074bb2..9711306 100644 --- a/src/hooks/useSessionStorage.test.ts +++ b/src/hooks/__tests__/useSessionStorage.test.ts @@ -1,7 +1,7 @@ import { act, renderHook } from '@testing-library/react'; import { afterEach, describe, expect, expectTypeOf, it, vi } from 'vitest'; -import { readStorageValue } from './storage'; -import { useSessionStorage } from './useSessionStorage'; +import { readStorageValue } from '../storage'; +import { useSessionStorage } from '../useSessionStorage'; describe('useSessionStorage', () => { afterEach(() => { diff --git a/src/hooks/useWindowSize.test.ts b/src/hooks/__tests__/useWindowSize.test.ts similarity index 97% rename from src/hooks/useWindowSize.test.ts rename to src/hooks/__tests__/useWindowSize.test.ts index 6220e9c..729d41b 100644 --- a/src/hooks/useWindowSize.test.ts +++ b/src/hooks/__tests__/useWindowSize.test.ts @@ -1,6 +1,6 @@ import { act, renderHook } from '@testing-library/react'; import { afterEach, describe, expect, it, vi } from 'vitest'; -import { getWindowSize, useWindowSize } from './useWindowSize'; +import { getWindowSize, useWindowSize } from '../useWindowSize'; function setViewport(width: number, height: number): void { Object.defineProperty(window, 'innerWidth', {