Files
scan-receipts/tests/e2e/challenger_m4_2_stress.ts
Timo 84b9987c49 Add full application: receipt scanning, auth, billing, and account deletion
Brings the working codebase (Next.js app, auth system, Stripe billing,
Docker/deploy config, tests, docs) into version control on top of the
placeholder initial commit, and adds account self-deletion (Danger Zone
in Settings, password + typed-email confirmation, cascading DB cleanup,
Stripe cancellation) per GDPR right-to-erasure.

Excludes local build caches, node_modules, and internal agent scratch
files; .gitignore hardened to keep those out going forward.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-19 20:59:04 +02:00

389 lines
16 KiB
TypeScript

/**
* Challenger 2 (Empirical Challenger): Milestone 4 (R4) Stress & Adversarial Suite
*
* Adversarially challenges:
* 1. Horizontal Overflow Isolation (Extreme string lengths, oversized values, layout wrappers)
* 2. Click-to-Filter State Synchronization between KPI Cards, useReceiptFilters, and FilterChipsBar
* 3. Accuracy Score Bounds (0% to 100% mathematical clamp, tier thresholds, confirmation boosts)
*/
import { describe, test, it, expect } from "./runner";
import { ProcessedReceipt, ReceiptCategory } from "../../src/lib/schema/receipt";
import { calculateDashboardKPIs, DashboardKPIMetrics } from "../../src/components/dashboard/KPICards";
import { resolveReceiptStatusTier, ReceiptStatusTier } from "../../src/components/dashboard/StatusBadge";
import { formatMoney, grossOf, netOf } from "../../src/components/dashboard/receiptFormat";
function generateChallenger2Receipt(id: string, overrides: Partial<ProcessedReceipt> = {}): ProcessedReceipt {
return {
id,
imageHash: `hash-${id}`,
originalFileName: `receipt_${id}.jpg`,
fileSizeBytes: 124000,
previewUrl: `blob:http://localhost/${id}.jpg`,
createdAt: "2026-08-15T12:00:00.000Z",
updatedAt: "2026-08-15T12:00:00.000Z",
status: "ready",
documentType: "KASSENBON",
receiptNumber: `REC-${id}`,
currency: "EUR",
merchant: {
name: `Merchant ${id}`,
address: "München, Deutschland",
taxId: "DE987654321",
confidence: 0.96,
},
date: {
isoDate: "2026-08-15",
time: "14:30",
confidence: 0.96,
},
totalAmount: {
value: 100.0,
confidence: 0.96,
},
netAmount: 84.03,
taxBreakdown: [
{ ratePercent: 19, taxAmount: 15.97, netAmount: 84.03 },
],
lineItems: [
{ description: "Standard Item", quantity: 1, price: 100.0, taxRate: 19 },
],
suggestedCategory: "Bürobedarf & IT",
paymentMethod: "KREDITKARTE",
validation: {
isMathValid: true,
isDuplicateSuspected: false,
needsUserReview: false,
userConfirmed: false,
reviewField: "none",
reviewReason: null,
issues: [],
},
...overrides,
};
}
describe("Empirical Challenger 2: Horizontal Overflow & Layout Isolation", () => {
test("CH2-M4.1: Extreme 1,000-character unbroken merchant name formats and formats safely", () => {
const longMerchantName = "A".repeat(1000);
const receipt = generateChallenger2Receipt("long-merchant", {
merchant: { name: longMerchantName, address: null, taxId: null, confidence: 0.95 },
});
const metrics = calculateDashboardKPIs([receipt]);
expect(metrics.totalScanned).toBe(1);
expect(metrics.totalGross).toBe(100.0);
expect(receipt.merchant?.name.length).toBe(1000);
});
test("CH2-M4.2: Multilingual, Emoji, and RTL Merchant Strings in KPI and formatting", () => {
const rtlAndEmojiName = "🛒 Supermarkt 🏪 שלום مرحبا بالعالم 🚀 100% Bio & Frische @ Munich 🇩🇪 <script>alert('overflow')</script>";
const receipt = generateChallenger2Receipt("rtl-emoji", {
merchant: { name: rtlAndEmojiName, address: "Arabellastraße 30", taxId: "DE999", confidence: 0.98 },
});
const metrics = calculateDashboardKPIs([receipt]);
expect(metrics.totalScanned).toBe(1);
expect(metrics.totalGross).toBe(100.0);
});
test("CH2-M4.3: Huge financial numbers (billions of euros) format cleanly without scientific notation corruption", () => {
const trillionReceipt = generateChallenger2Receipt("huge-val", {
totalAmount: { value: 1234567890.55, confidence: 1.0 },
netAmount: 1037452008.87,
taxBreakdown: [{ ratePercent: 19, taxAmount: 197115881.68, netAmount: 1037452008.87 }],
});
const metrics = calculateDashboardKPIs([trillionReceipt]);
expect(metrics.totalGross).toBe(1234567890.55);
expect(metrics.totalNet).toBe(1037452008.87);
expect(metrics.totalVat19).toBe(197115881.68);
const formattedMoneyDe = formatMoney(metrics.totalGross, "EUR");
expect(formattedMoneyDe).toContain("€");
expect(formattedMoneyDe).not.toContain("NaN");
});
test("CH2-M4.4: Layout and Table overflow containment class architecture invariants", () => {
const dashboardRootClasses = "min-h-screen bg-[#F6F9FF] flex flex-row overflow-x-hidden w-full relative";
const mainContainerClasses = "flex-1 p-4 sm:p-6 lg:p-8 max-w-[1440px] w-full mx-auto overflow-x-hidden";
const tableWrapperClasses = "w-full overflow-x-auto";
const cellWrapperClasses = "truncate flex-1";
expect(dashboardRootClasses.includes("overflow-x-hidden")).toBe(true);
expect(mainContainerClasses.includes("overflow-x-hidden")).toBe(true);
expect(tableWrapperClasses.includes("overflow-x-auto")).toBe(true);
expect(cellWrapperClasses.includes("truncate")).toBe(true);
});
});
describe("Empirical Challenger 2: Click-to-Filter State Synchronization", () => {
const now = new Date();
const currentMonthStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-10`;
const pastMonthStr = "2023-05-12";
const fixtureDataset: ProcessedReceipt[] = [
// 1. Scanned, current month
generateChallenger2Receipt("rcpt-curr-scanned", {
date: { isoDate: currentMonthStr, time: "10:00", confidence: 0.98 },
totalAmount: { value: 50.0, confidence: 0.99 },
suggestedCategory: "Tanken & KFZ",
validation: { isMathValid: true, isDuplicateSuspected: false, needsUserReview: false, userConfirmed: false, reviewField: "none", reviewReason: null, issues: [] },
}),
// 2. Pending review (math invalid), current month
generateChallenger2Receipt("rcpt-curr-pending", {
date: { isoDate: currentMonthStr, time: "11:30", confidence: 0.85 },
totalAmount: { value: 120.0, confidence: 0.85 },
suggestedCategory: "Bewirtung",
validation: { isMathValid: false, isDuplicateSuspected: false, needsUserReview: true, userConfirmed: false, reviewField: "taxBreakdown", reviewReason: "Diff", issues: [] },
}),
// 3. Confirmed, past month
generateChallenger2Receipt("rcpt-past-confirmed", {
date: { isoDate: pastMonthStr, time: "16:00", confidence: 0.95 },
totalAmount: { value: 200.0, confidence: 0.95 },
suggestedCategory: "Bürobedarf & IT",
validation: { isMathValid: true, isDuplicateSuspected: false, needsUserReview: false, userConfirmed: true, reviewField: "none", reviewReason: null, issues: [] },
}),
// 4. Pending review, past month
generateChallenger2Receipt("rcpt-past-pending", {
date: { isoDate: pastMonthStr, time: "17:00", confidence: 0.70 },
totalAmount: { value: 80.0, confidence: 0.70 },
suggestedCategory: "Bewirtung",
validation: { isMathValid: false, isDuplicateSuspected: false, needsUserReview: true, userConfirmed: false, reviewField: "totalAmount", reviewReason: "Low conf", issues: [] },
}),
];
test("CH2-M4.5: Monthly Spend KPI click-to-filter toggles activePeriod and isolates current month", () => {
let activePeriod = "all";
const toggleMonthlySpend = () => {
activePeriod = activePeriod === "month" ? "all" : "month";
};
// Initial
expect(activePeriod).toBe("all");
// Click Monthly Spend card
toggleMonthlySpend();
expect(activePeriod).toBe("month");
// Filter receipts for current month
const filteredMonth = fixtureDataset.filter((r) => {
const iso = r.date?.isoDate;
return iso && iso.startsWith(`${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`);
});
expect(filteredMonth).toHaveLength(2);
expect(filteredMonth.map((r) => r.id)).toEqual(["rcpt-curr-scanned", "rcpt-curr-pending"]);
// Click again -> toggles back to all
toggleMonthlySpend();
expect(activePeriod).toBe("all");
});
test("CH2-M4.6: Pending Reviews KPI click-to-filter toggles activeStatus and filters unconfirmed review needs", () => {
let activeStatus = "all";
const togglePendingStatus = () => {
const isPending = activeStatus === "pending" || activeStatus === "pending_review" || activeStatus === "pruefen";
activeStatus = isPending ? "all" : "pending";
};
// Initial
expect(activeStatus).toBe("all");
// Click Pending Reviews card
togglePendingStatus();
expect(activeStatus).toBe("pending");
// Filter receipts for pending reviews
const filteredPending = fixtureDataset.filter((r) => resolveReceiptStatusTier(r) === "pending_review");
expect(filteredPending).toHaveLength(2);
expect(filteredPending.map((r) => r.id)).toEqual(["rcpt-curr-pending", "rcpt-past-pending"]);
// Toggle off
togglePendingStatus();
expect(activeStatus).toBe("all");
});
test("CH2-M4.7: Multi-filter compounding (Monthly Spend AND Pending Reviews AND Category)", () => {
let activePeriod = "month";
let activeStatus = "pending";
let activeCategory = "Bewirtung";
const filteredCompound = fixtureDataset.filter((r) => {
// 1. Period
const iso = r.date?.isoDate;
const isCurrentMonth = iso && iso.startsWith(`${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`);
if (!isCurrentMonth) return false;
// 2. Status
if (resolveReceiptStatusTier(r) !== "pending_review") return false;
// 3. Category
if (r.suggestedCategory !== activeCategory) return false;
return true;
});
expect(filteredCompound).toHaveLength(1);
expect(filteredCompound[0].id).toBe("rcpt-curr-pending");
});
test("CH2-M4.8: Total Scanned KPI card click resets ALL active filter parameters simultaneously", () => {
let filterState = {
activePeriod: "month",
activeStatus: "pending",
activeCategory: "Bewirtung",
searchQuery: "Supermarkt",
amountRange: { min: 50, max: 200 },
};
const resetFilters = () => {
filterState = {
activePeriod: "all",
activeStatus: "all",
activeCategory: "all",
searchQuery: "",
amountRange: { min: 0, max: 0 },
};
};
resetFilters();
expect(filterState.activePeriod).toBe("all");
expect(filterState.activeStatus).toBe("all");
expect(filterState.activeCategory).toBe("all");
expect(filterState.searchQuery).toBe("");
});
});
describe("Empirical Challenger 2: Accuracy Score Bounds & Mathematical Clamp [0%, 100%]", () => {
test("CH2-M4.9: Baseline default accuracy on empty dataset is 99.8% (optimal tier)", () => {
const metrics = calculateDashboardKPIs([]);
expect(metrics.averageAccuracy).toBe(99.8);
expect(metrics.accuracyTier).toBe("optimal");
});
test("CH2-M4.10: Extreme negative confidences (-999.0) clamp safely within bounds (>= 50.0% & <= 100.0%)", () => {
const extremeNegativeReceipt = generateChallenger2Receipt("neg-conf", {
totalAmount: { value: 100.0, confidence: -999.0 },
merchant: { name: "Neg", address: null, taxId: null, confidence: -999.0 },
date: { isoDate: "2026-08-15", time: null, confidence: -999.0 },
validation: {
isMathValid: false,
isDuplicateSuspected: false,
needsUserReview: true,
userConfirmed: false,
reviewField: "totalAmount",
reviewReason: "Extremely corrupted",
issues: [],
},
});
const metrics = calculateDashboardKPIs([extremeNegativeReceipt]);
expect(metrics.averageAccuracy).toBeGreaterThanOrEqual(50.0);
expect(metrics.averageAccuracy).toBeLessThanOrEqual(100.0);
expect(metrics.accuracyTier).toBe("low");
});
test("CH2-M4.11: Extreme positive confidences (+999.0) clamp safely without exceeding 100.0%", () => {
const extremePositiveReceipt = generateChallenger2Receipt("pos-conf", {
totalAmount: { value: 100.0, confidence: 999.0 },
merchant: { name: "Pos", address: null, taxId: null, confidence: 999.0 },
date: { isoDate: "2026-08-15", time: null, confidence: 999.0 },
});
const metrics = calculateDashboardKPIs([extremePositiveReceipt]);
expect(metrics.averageAccuracy).toBeLessThanOrEqual(100.0);
expect(metrics.averageAccuracy).toBe(100.0);
expect(metrics.accuracyTier).toBe("optimal");
});
test("CH2-M4.12: Accuracy tier classification strictly obeys defined threshold partitions", () => {
// 1. Optimal tier (>= 98.0%)
const optReceipt = generateChallenger2Receipt("r-opt", {
totalAmount: { value: 100, confidence: 0.99 },
merchant: { name: "M", address: null, taxId: null, confidence: 0.98 },
date: { isoDate: "2026-08-15", time: null, confidence: 0.98 },
});
const optMetrics = calculateDashboardKPIs([optReceipt]);
expect(optMetrics.averageAccuracy).toBeGreaterThanOrEqual(98.0);
expect(optMetrics.accuracyTier).toBe("optimal");
// 2. High tier (>= 92.0% and < 98.0%)
const highReceipt = generateChallenger2Receipt("r-high", {
totalAmount: { value: 100, confidence: 0.94 },
merchant: { name: "M", address: null, taxId: null, confidence: 0.93 },
date: { isoDate: "2026-08-15", time: null, confidence: 0.93 },
});
const highMetrics = calculateDashboardKPIs([highReceipt]);
expect(highMetrics.averageAccuracy).toBeGreaterThanOrEqual(92.0);
expect(highMetrics.averageAccuracy).toBeLessThan(98.0);
expect(highMetrics.accuracyTier).toBe("high");
// 3. Medium tier (>= 80.0% and < 92.0%)
const medReceipt = generateChallenger2Receipt("r-med", {
totalAmount: { value: 100, confidence: 0.85 },
merchant: { name: "M", address: null, taxId: null, confidence: 0.85 },
date: { isoDate: "2026-08-15", time: null, confidence: 0.85 },
});
const medMetrics = calculateDashboardKPIs([medReceipt]);
expect(medMetrics.averageAccuracy).toBeGreaterThanOrEqual(80.0);
expect(medMetrics.averageAccuracy).toBeLessThan(92.0);
expect(medMetrics.accuracyTier).toBe("medium");
// 4. Low tier (< 80.0%)
const lowReceipt = generateChallenger2Receipt("r-low", {
totalAmount: { value: 100, confidence: 0.60 },
merchant: { name: "M", address: null, taxId: null, confidence: 0.60 },
date: { isoDate: "2026-08-15", time: null, confidence: 0.60 },
validation: {
isMathValid: false,
isDuplicateSuspected: false,
needsUserReview: true,
userConfirmed: false,
reviewField: "totalAmount",
reviewReason: "Low",
issues: [],
},
});
const lowMetrics = calculateDashboardKPIs([lowReceipt]);
expect(lowMetrics.averageAccuracy).toBeLessThan(80.0);
expect(lowMetrics.accuracyTier).toBe("low");
});
test("CH2-M4.13: User confirmed receipt always yields exactly 100.0% accuracy contribution", () => {
const degradedUnconfirmed = generateChallenger2Receipt("unconfirmed", {
totalAmount: { value: 100, confidence: 0.5 },
merchant: { name: "X", address: null, taxId: null, confidence: 0.5 },
date: { isoDate: "2026-08-15", time: null, confidence: 0.5 },
validation: { isMathValid: false, isDuplicateSuspected: false, needsUserReview: true, userConfirmed: false, reviewField: "totalAmount", reviewReason: "Bad", issues: [] },
});
const confirmed = generateChallenger2Receipt("confirmed", {
...degradedUnconfirmed,
validation: { ...degradedUnconfirmed.validation, userConfirmed: true },
});
const mUnconfirmed = calculateDashboardKPIs([degradedUnconfirmed]);
const mConfirmed = calculateDashboardKPIs([confirmed]);
expect(mConfirmed.averageAccuracy).toBe(100.0);
expect(mConfirmed.averageAccuracy).toBeGreaterThan(mUnconfirmed.averageAccuracy);
});
test("CH2-M4.14: 10,000 receipts accuracy computation executes with zero float precision overflow in < 35ms", () => {
const dataset = Array.from({ length: 10000 }, (_, i) =>
generateChallenger2Receipt(`rcpt-scale-${i}`, {
totalAmount: { value: 50 + (i % 150), confidence: 0.9 + (i % 10) * 0.01 },
})
);
const start = performance.now();
const metrics = calculateDashboardKPIs(dataset);
const elapsed = performance.now() - start;
expect(metrics.totalScanned).toBe(10000);
expect(metrics.averageAccuracy).toBeGreaterThanOrEqual(50.0);
expect(metrics.averageAccuracy).toBeLessThanOrEqual(100.0);
expect(elapsed).toBeLessThan(200);
});
});