From 050dc162db3aadaa8cc0dcc058c2dc23fc4f5d6c Mon Sep 17 00:00:00 2001 From: chriz-cloud Date: Tue, 20 Oct 2026 01:31:28 +0100 Subject: [PATCH 1/4] Fix #907: Add shared test data factory for mock invoices Ad-hoc mockInvoice objects were duplicated with drifting shapes across test files. Add src/test/factories.ts with createMockInvoice() and migrate stores.test.ts to use it as a concrete example. --- src/__tests__/stores.test.ts | 15 +++------------ src/test/factories.ts | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 src/test/factories.ts diff --git a/src/__tests__/stores.test.ts b/src/__tests__/stores.test.ts index 025fa2dd..5a98633c 100644 --- a/src/__tests__/stores.test.ts +++ b/src/__tests__/stores.test.ts @@ -2,18 +2,9 @@ import { beforeEach, describe, expect, it } from "vitest"; import { useWalletStore } from "@/lib/stores/walletStore"; import { useInvoiceStore } from "@/lib/stores/invoiceStore"; import { useUIStore } from "@/lib/stores/uiStore"; -import type { Invoice } from "@stellar-split/sdk"; - -const mockInvoice: Invoice = { - id: "1", - creator: "GABC", - recipients: [{ address: "GDEF", amount: 10_000_000n }], - token: "token", - deadline: 9999999999, - funded: 0n, - status: "Pending", - payments: [], -}; +import { createMockInvoice } from "@/test/factories"; + +const mockInvoice = createMockInvoice(); beforeEach(() => { useWalletStore.setState({ diff --git a/src/test/factories.ts b/src/test/factories.ts new file mode 100644 index 00000000..88a6b5c0 --- /dev/null +++ b/src/test/factories.ts @@ -0,0 +1,23 @@ +/** + * Shared test data factories / fixtures. + * + * Several test files hand-roll ad-hoc `mockInvoice` objects with slightly + * different (and sometimes inconsistent) shapes. This module centralizes a + * baseline factory so new and existing tests can build on one consistent + * shape via overrides, instead of copy-pasting and drifting. + */ +import type { Invoice } from "@stellar-split/sdk"; + +export function createMockInvoice(overrides: Partial = {}): Invoice { + return { + id: "1", + creator: "GABC", + recipients: [{ address: "GDEF", amount: 10_000_000n }], + token: "token", + deadline: 9999999999, + funded: 0n, + status: "Pending", + payments: [], + ...overrides, + } as Invoice; +} From c96008a7799b6c8b28b47992cbe790daec4ad505 Mon Sep 17 00:00:00 2001 From: chriz-cloud Date: Tue, 20 Oct 2026 01:32:04 +0100 Subject: [PATCH 2/4] Fix #906: Add snapshot test for StatusBadge component Vitest supports toMatchSnapshot but no snapshot tests existed. Add a concrete snapshot test for StatusBadge, a small stable presentational component, covering two prop variants. --- .../__tests__/StatusBadge.snapshot.test.tsx | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/components/__tests__/StatusBadge.snapshot.test.tsx diff --git a/src/components/__tests__/StatusBadge.snapshot.test.tsx b/src/components/__tests__/StatusBadge.snapshot.test.tsx new file mode 100644 index 00000000..d8887cf5 --- /dev/null +++ b/src/components/__tests__/StatusBadge.snapshot.test.tsx @@ -0,0 +1,20 @@ +import { describe, it, expect } from "vitest"; +import { render } from "@testing-library/react"; +import StatusBadge from "@/components/StatusBadge"; + +/** + * Snapshot test for StatusBadge — a small, stable, presentational + * component (no internal randomness, derives entirely from props via + * STATUS_CONFIG). Guards against unintended markup/className regressions. + */ +describe("StatusBadge (snapshot)", () => { + it("renders a Pending badge consistently", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + + it("renders a Released badge at lg size consistently", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); +}); From 03fdd3093a53d160dc2dd713de849edd8c612777 Mon Sep 17 00:00:00 2001 From: chriz-cloud Date: Tue, 20 Oct 2026 01:32:16 +0100 Subject: [PATCH 3/4] Fix #905: Extend axe a11y gate to cover the Settings page Automated WCAG 2.1 AA checks (@axe-core/playwright) already exist for Home/Dashboard/New Invoice but not for every key page. Add Settings to the audited page list. --- e2e/a11y.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e/a11y.spec.ts b/e2e/a11y.spec.ts index 8a22d717..9d6d4513 100644 --- a/e2e/a11y.spec.ts +++ b/e2e/a11y.spec.ts @@ -14,6 +14,7 @@ const PAGES: Array<{ path: string; name: string }> = [ { path: '/', name: 'Home' }, { path: '/dashboard', name: 'Dashboard' }, { path: '/invoice/new', name: 'New Invoice' }, + { path: '/settings', name: 'Settings' }, ]; async function runAxe(page: Page) { From 97cba9bd366c320075e4aa2a7cf93eb51317483d Mon Sep 17 00:00:00 2001 From: chriz-cloud Date: Tue, 20 Oct 2026 01:32:47 +0100 Subject: [PATCH 4/4] Fix #904: Report Core Web Vitals to Sentry for performance monitoring Sentry tracing was configured (tracesSampleRate) but Core Web Vitals (CLS, LCP, INP, TTFB, FCP) were never captured. Add a WebVitalsReporter using next/web-vitals that forwards each metric to Sentry as a measurement, giving real-user performance benchmarking. --- src/app/layout.tsx | 2 ++ src/components/WebVitalsReporter.tsx | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/components/WebVitalsReporter.tsx diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 633ba9b7..b47b6fd9 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -25,6 +25,7 @@ import OfflineBanner from "@/components/OfflineBanner"; import WalletSecurityCenter from "@/components/security/WalletSecurityCenter"; import { getNonce } from "@/lib/csp"; import TransitionProvider from "@/components/layout/TransitionProvider"; +import WebVitalsReporter from "@/components/WebVitalsReporter"; const themeBootstrap = ` (function () { @@ -132,6 +133,7 @@ export default function RootLayout({ + diff --git a/src/components/WebVitalsReporter.tsx b/src/components/WebVitalsReporter.tsx new file mode 100644 index 00000000..73ec4114 --- /dev/null +++ b/src/components/WebVitalsReporter.tsx @@ -0,0 +1,18 @@ +"use client"; + +import { useReportWebVitals } from "next/web-vitals"; +import * as Sentry from "@sentry/nextjs"; + +/** + * Forwards Core Web Vitals (CLS, LCP, FID/INP, TTFB, FCP) to Sentry as + * measurements on the active span, so real-user performance can be + * monitored and benchmarked over time alongside the existing Sentry + * tracing (tracesSampleRate) setup. + */ +export default function WebVitalsReporter() { + useReportWebVitals((metric) => { + Sentry.setMeasurement(metric.name, metric.value, "millisecond"); + }); + + return null; +}