From cbe7412a58819a969a406ed3a04202533155edbc Mon Sep 17 00:00:00 2001 From: Danijel Martinek Date: Tue, 19 May 2026 21:24:02 +0000 Subject: [PATCH] fix(scripts): exempt Storybook stories from coverage:diff gate Story files are excluded from vitest by design (they run in Storybook runner, not vitest). Add *.stories.{ts,tsx} to ALLOWED_GLOBS so the L1 diff gate doesn't flag them as "new untested file". Also add error-handling test for useOptionalConsent rethrow path (cookie-consent-banner lines 52-53) achieving 100% statement coverage. Co-Authored-By: Claude Sonnet 4.6 --- coverage/summary.json | 32 +++++----- ...e-consent-banner-unexpected-error.test.tsx | 61 +++++++++++++++++++ scripts/coverage/diff.mjs | 2 + scripts/coverage/diff.test.mjs | 15 +++++ 4 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 packages/core-ui/src/cookie-consent-banner/cookie-consent-banner-unexpected-error.test.tsx diff --git a/coverage/summary.json b/coverage/summary.json index 8449633..90a2913 100644 --- a/coverage/summary.json +++ b/coverage/summary.json @@ -1,16 +1,16 @@ { - "generatedAt": "2026-05-19T21:20:25.856Z", - "commit": "de17803", + "generatedAt": "2026-05-19T21:23:46.645Z", + "commit": "1b6f2d1", "repo": { - "statements": 97.34, - "branches": 91.98, + "statements": 97.38, + "branches": 92.08, "functions": 97.09, - "lines": 97.34, + "lines": 97.38, "counts": { - "lf": 5742, - "lh": 5589, - "brf": 1147, - "brh": 1055, + "lf": 5758, + "lh": 5607, + "brf": 1149, + "brh": 1058, "fnf": 344, "fnh": 334 } @@ -115,15 +115,15 @@ } }, "@repo/core-ui": { - "statements": 99.49, - "branches": 90.2, + "statements": 100, + "branches": 91.35, "functions": 100, - "lines": 99.49, + "lines": 100, "counts": { - "lf": 396, - "lh": 394, - "brf": 102, - "brh": 92, + "lf": 412, + "lh": 412, + "brf": 104, + "brh": 95, "fnf": 18, "fnh": 18 } diff --git a/packages/core-ui/src/cookie-consent-banner/cookie-consent-banner-unexpected-error.test.tsx b/packages/core-ui/src/cookie-consent-banner/cookie-consent-banner-unexpected-error.test.tsx new file mode 100644 index 0000000..83a7287 --- /dev/null +++ b/packages/core-ui/src/cookie-consent-banner/cookie-consent-banner-unexpected-error.test.tsx @@ -0,0 +1,61 @@ +/** + * Isolated test file for the error-re-throw path in useOptionalConsent. + * Uses vi.mock to make useConsent throw a non-ConsentContextError so that + * lines 52-53 (the `throw e` branch) are exercised. + */ +import { describe, it, expect, vi } from "vitest"; +import { Component, type ReactNode } from "react"; +import { render, screen } from "@testing-library/react"; + +vi.mock("@repo/core-consent/react", () => ({ + useConsent: vi.fn(() => { + throw new Error("unexpected-non-consent-error"); + }), + ConsentContextError: class ConsentContextError extends Error { + constructor() { + super("no provider"); + this.name = "ConsentContextError"; + } + }, +})); + +import { CookieConsentBanner } from "./cookie-consent-banner"; + +class ErrorBoundary extends Component< + { children: ReactNode }, + { caught: string | null } +> { + constructor(props: { children: ReactNode }) { + super(props); + this.state = { caught: null }; + } + + static getDerivedStateFromError(error: Error) { + return { caught: error.message }; + } + + render() { + if (this.state.caught) { + return
{this.state.caught}
; + } + return this.props.children; + } +} + +describe("CookieConsentBanner — useOptionalConsent rethrows non-ConsentContextError", () => { + it("surfaces unexpected render errors through an error boundary", () => { + const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {}); + + render( + + + , + ); + + expect(screen.getByTestId("caught")).toHaveTextContent( + "unexpected-non-consent-error", + ); + + consoleSpy.mockRestore(); + }); +}); diff --git a/scripts/coverage/diff.mjs b/scripts/coverage/diff.mjs index 35a9723..156c4f1 100644 --- a/scripts/coverage/diff.mjs +++ b/scripts/coverage/diff.mjs @@ -32,6 +32,8 @@ import { execSync } from "node:child_process"; const ALLOWED_GLOBS = [ // Test artifacts /\.test\.(ts|tsx|js|mjs)$/, + // Storybook story files — excluded from vitest by design; tested in Storybook runner + /\.stories\.(ts|tsx)$/, /\/__factories__\//, /\/__contracts__\//, /\/__fixtures__\//, diff --git a/scripts/coverage/diff.test.mjs b/scripts/coverage/diff.test.mjs index 1ad7dec..0ca2193 100644 --- a/scripts/coverage/diff.test.mjs +++ b/scripts/coverage/diff.test.mjs @@ -210,6 +210,21 @@ describe("computeDiffCoverage", () => { assert.equal(result.summary.filesChanged, 3); }); + test("skips Storybook story files (.stories.ts/.stories.tsx — excluded from vitest coverage)", () => { + const lcov = parseLcov(lcovText); + const diff = new Map([ + [ + "packages/core-ui/src/cookie-consent-banner/cookie-consent-banner.stories.tsx", + new Set([1, 2, 3, 4, 5]), + ], + ["packages/core-ui/src/atoms/button/button.stories.ts", new Set([1, 2])], + ]); + const result = computeDiffCoverage(diff, lcov); + assert.equal(result.status, "pass"); + assert.equal(result.summary.filesGated, 0); + assert.equal(result.summary.filesChanged, 2); + }); + test("skips packages/core-testing/ (tooling package, no lcov generated)", () => { const lcov = parseLcov(lcovText); const diff = new Map([