3fd149556aba
fix: resolve 27 pre-existing tsc errors in test files — SharedArrayBuffer/Mock drift, unused vars, circular chrome type (v4.0.0)
- time
- 2026-06-12 17:36 UTC · 4 months ago
- machine
- koh2
- agent
- claude-sonnet-4-6
- session
- tsc cleanup
- parent
- 40ffe3171e9b
↓ peach-browser-3fd14955.tar.gzatlas at this save
files changed14 files
src/background/clipboard.double-failure.test.ts+2 −2src/background/license.verification.test.ts+2 −2src/background/messages.batch-sanitize.test.ts+1 −1src/background/messages.edit-origin.test.ts+1 −1src/background/ml.predictbatch.test.ts+3 −3src/background/passkey.ed25519.test.ts+4 −4src/background/vault.consolidate-passkeys.test.ts+1 −1src/background/vault.corruption.test.ts+1 −3src/background/vault.purge-trash.test.ts+1 −1src/background/vault.rotate-sync-identity.test.ts+2 −2src/crypto/argon2id.kat.test.ts+2 −2src/popup/codex/codex.multistripe.test.ts+0 −10src/shared/backup.nfc-fallback.test.ts+2 −2src/shared/sync.disconnect.test.ts+3 −3src/background/clipboard.double-failure.test.ts+2 −2
@@ -114,7 +114,7 @@114114 // Even when we skip writing, the alarm must fire to clear the clipboard later.115115 it("T-037b: alreadyWritten=true → alarm is still created for auto-clear", async () => {116116 const { copyToClipboard } = await import("./clipboard");117- const alarmsMock = chrome.alarms as { create: ReturnType<typeof vi.fn> };117+ const alarmsMock = chrome.alarms as unknown as { create: ReturnType<typeof vi.fn> };118118 119119 await copyToClipboard("secret-value", "Password", true);120120 @@ -141,7 +141,7 @@141141 // executeScript already fails (no tabs in mock)142142 143143 const { copyToClipboard } = await import("./clipboard");144- const alarmsMock = chrome.alarms as { create: ReturnType<typeof vi.fn> };144+ const alarmsMock = chrome.alarms as unknown as { create: ReturnType<typeof vi.fn> };145145 146146 // Must not throw even when both paths fail147147 await expect(copyToClipboard("secret", "Password", false)).resolves.toBeUndefined();src/background/license.verification.test.ts+2 −2
@@ -134,7 +134,7 @@134134 return { valid: false, plan: "free" };135135 }136136 137- const pubKey = await (crypto.subtle as Record<string, Function>).importKey(137+ const pubKey = await (crypto.subtle as unknown as Record<string, Function>).importKey(138138 "raw",139139 hexToBytes(pubKeyHex),140140 { name: "Ed25519" },@@ -142,7 +142,7 @@142142 ["verify"],143143 ) as CryptoKey;144144 145- const isValid = await (crypto.subtle as Record<string, Function>).verify(145+ const isValid = await (crypto.subtle as unknown as Record<string, Function>).verify(146146 "Ed25519",147147 pubKey,148148 signature,src/background/messages.batch-sanitize.test.ts+1 −1
@@ -157,7 +157,7 @@157157 const added = await vault.batchAddEntries([maliciousDraft]);158158 expect(added).toHaveLength(1);159159 // Bug this catches: prototype pollution persists in the saved entry160- expect((added[0] as Record<string, unknown>).poisoned).toBeUndefined();160+ expect((added[0] as unknown as Record<string, unknown>).poisoned).toBeUndefined();161161 expect(Object.getPrototypeOf(added[0])).toBe(Object.prototype);162162 });163163 src/background/messages.edit-origin.test.ts+1 −1
@@ -53,7 +53,7 @@5353 id: "test-extension-id",5454 getURL: vi.fn((path: string) => `chrome-extension://test-extension-id/${path}`),5555 },56- } as unknown as typeof chrome;56+ } as unknown as typeof globalThis.chrome;5757 return { storage, chrome };5858 }5959 src/background/ml.predictbatch.test.ts+3 −3
@@ -134,7 +134,7 @@134134 it("T-030e: extreme positive feature values → no NaN or Infinity in output", () => {135135 const extremeFeatures: MLFieldFeatures = {} as MLFieldFeatures;136136 for (const key of Object.keys(zeroFeatures()) as (keyof MLFieldFeatures)[]) {137- (extremeFeatures as Record<string, number>)[key] = 1000;137+ (extremeFeatures as unknown as Record<string, number>)[key] = 1000;138138 }139139 140140 const result = predictBatch([extremeFeatures]);@@ -146,7 +146,7 @@146146 it("T-030f: extreme negative feature values → no NaN or Infinity", () => {147147 const extremeNeg: MLFieldFeatures = {} as MLFieldFeatures;148148 for (const key of Object.keys(zeroFeatures()) as (keyof MLFieldFeatures)[]) {149- (extremeNeg as Record<string, number>)[key] = -1000;149+ (extremeNeg as unknown as Record<string, number>)[key] = -1000;150150 }151151 152152 const result = predictBatch([extremeNeg]);@@ -158,7 +158,7 @@158158 const mixed: MLFieldFeatures = {} as MLFieldFeatures;159159 let i = 0;160160 for (const key of Object.keys(zeroFeatures()) as (keyof MLFieldFeatures)[]) {161- (mixed as Record<string, number>)[key] = i % 2 === 0 ? 1e6 : -1e6;161+ (mixed as unknown as Record<string, number>)[key] = i % 2 === 0 ? 1e6 : -1e6;162162 i++;163163 }164164 src/background/passkey.ed25519.test.ts+4 −4
@@ -176,10 +176,10 @@176176 it("T-015f: Ed25519 signature verifies against the generated public key", async () => {177177 const authData = new Uint8Array(37).fill(0xcc);178178 const clientDataHash = new Uint8Array(32).fill(0xdd);179- const sig = await signPasskeyAssertion(keypair.privateKeyJwk, -8, authData, clientDataHash);179+ const sig = new Uint8Array(await signPasskeyAssertion(keypair.privateKeyJwk, -8, authData, clientDataHash));180180 181181 // Reconstruct the public key for verification from the JWK 'x' coordinate.182- const rawPub = base64urlDecode(keypair.privateKeyJwk.x!);182+ const rawPub = new Uint8Array(base64urlDecode(keypair.privateKeyJwk.x!));183183 const pubKey = await crypto.subtle.importKey(184184 "raw",185185 rawPub,@@ -207,9 +207,9 @@207207 it("T-015g: signature does not verify against a different clientDataHash (replay check)", async () => {208208 const authData = new Uint8Array(37).fill(0xee);209209 const clientDataHash = new Uint8Array(32).fill(0xff);210- const sig = await signPasskeyAssertion(keypair.privateKeyJwk, -8, authData, clientDataHash);210+ const sig = new Uint8Array(await signPasskeyAssertion(keypair.privateKeyJwk, -8, authData, clientDataHash));211211 212- const rawPub = base64urlDecode(keypair.privateKeyJwk.x!);212+ const rawPub = new Uint8Array(base64urlDecode(keypair.privateKeyJwk.x!));213213 const pubKey = await crypto.subtle.importKey(214214 "raw",215215 rawPub,src/background/vault.consolidate-passkeys.test.ts+1 −1
@@ -45,7 +45,7 @@4545 },4646 alarms: { clear: vi.fn(), create: vi.fn(), onAlarm: { addListener: vi.fn() } },4747 idle: { setDetectionInterval: vi.fn(), onStateChanged: { addListener: vi.fn() } },48- } as unknown as typeof chrome;48+ } as unknown as typeof globalThis.chrome;4949 return { storage, chrome };5050 }5151 src/background/vault.corruption.test.ts+1 −3
@@ -19,8 +19,6 @@1919 2020 import { beforeAll, describe, expect, it, vi } from "vitest";2121 22-type StorageShape = Record<string, unknown>;23-2422 // ---------------------------------------------------------------------------2523 // Helpers: build StoredVault objects for specific scenarios2624 // ---------------------------------------------------------------------------@@ -35,7 +33,7 @@3533 3634 async function aesGcmEncrypt(3735 key: CryptoKey,38- nonce: Uint8Array,36+ nonce: Uint8Array<ArrayBuffer>,3937 plaintext: string,4038 aadTag = "slot_a_v1",4139 ): Promise<{ ciphertext: string; tag: string }> {src/background/vault.purge-trash.test.ts+1 −1
@@ -45,7 +45,7 @@4545 },4646 alarms: { clear: vi.fn(), create: vi.fn(), onAlarm: { addListener: vi.fn() } },4747 idle: { setDetectionInterval: vi.fn(), onStateChanged: { addListener: vi.fn() } },48- } as unknown as typeof chrome;48+ } as unknown as typeof globalThis.chrome;4949 return { storage, chrome };5050 }5151 src/background/vault.rotate-sync-identity.test.ts+2 −2
@@ -25,7 +25,7 @@2525 2626 function makeChromeStorageMock(): {2727 storage: StorageShape;28- chrome: typeof chrome;28+ chrome: typeof globalThis.chrome;2929 } {3030 const storage: StorageShape = {};3131 const chrome = {@@ -63,7 +63,7 @@6363 setDetectionInterval: vi.fn(),6464 onStateChanged: { addListener: vi.fn() },6565 },66- } as unknown as typeof chrome;66+ } as unknown as typeof globalThis.chrome;6767 return { storage, chrome };6868 }6969 src/crypto/argon2id.kat.test.ts+2 −2
@@ -56,7 +56,7 @@5656 5757 // If you have not yet run the generation script, mark this test as skipped5858 // and uncomment the KAT vector once generated.59-const KAT_AVAILABLE = KAT_EXPECTED_HEX !== "REPLACE_ME_WITH_ACTUAL_HASH_FROM_GEN_SCRIPT";59+const KAT_AVAILABLE = (KAT_EXPECTED_HEX as string) !== "REPLACE_ME_WITH_ACTUAL_HASH_FROM_GEN_SCRIPT";6060 6161 describe("T-019: Argon2id known-answer test + parameter assertion", () => {6262 // T-019a: deriveKey output matches the KAT vector exactly.@@ -64,7 +64,7 @@6464 // test fails — alerting the developer before a parameter regression ships.6565 it(6666 "T-019a: deriveKey('testpassword', salt=0xAB×16) matches KAT vector (m=65536, t=3, p=4)",67- KAT_AVAILABLE ? undefined : { skip: "KAT vector not yet generated (run gen-argon2id-kat.ts)" },67+ KAT_AVAILABLE ? undefined : { skip: true },6868 async () => {6969 if (!KAT_AVAILABLE) return;7070 const salt = new Uint8Array(16).fill(0xab);src/popup/codex/codex.multistripe.test.ts+0 −10
@@ -19,7 +19,6 @@1919 import { deflate } from "pako";2020 import { describe, expect, it } from "vitest";2121 import {22- CHUNK_SIZE,2322 MAX_DATA_SHARDS_PER_STRIPE,2423 CodexError,2524 computeParityShards,@@ -76,15 +75,6 @@7675 for (let i = 0; i < r.parityChunks.length; i++) {7776 chunks.set(r.dataShards + i, r.parityChunks[i]!);7877 }79- return { chunks, dataShards: r.dataShards, totalChunks: r.totalChunks };80-}81-82-function encodeResultToStripeChunksWithoutParity(r: EncodeResult): StripeChunks {83- const chunks = new Map<number, Uint8Array>();84- for (let i = 0; i < r.dataChunks.length; i++) {85- chunks.set(i, r.dataChunks[i]!);86- }87- // Parity shards omitted: RS decoder must reconstruct them (erasure mode)8878 return { chunks, dataShards: r.dataShards, totalChunks: r.totalChunks };8979 }9080 src/shared/backup.nfc-fallback.test.ts+2 −2
@@ -16,7 +16,7 @@1616 importEntriesFromPeachJson,1717 derivePeachExportKey,1818 } from "./backup";19-import { decrypt, encrypt } from "../background/aes";19+import { encrypt } from "../background/aes";2020 import type { VaultEntry } from "./types";2121 2222 // Use explicit Unicode escapes so the byte sequences are unambiguous regardless@@ -28,7 +28,7 @@2828 const NFC_PASSWORD = "café";2929 3030 // Sanity-check the assumptions at module load time.31-if (NFD_PASSWORD === NFC_PASSWORD) {31+if ((NFD_PASSWORD as string) === NFC_PASSWORD) {3232 throw new Error("Test assumption broken: NFD and NFC passwords are identical on this platform");3333 }3434 if (NFD_PASSWORD.normalize("NFC") !== NFC_PASSWORD) {src/shared/sync.disconnect.test.ts+3 −3
@@ -31,8 +31,8 @@3131 binaryType: string;3232 onmessage: ((ev: MessageEvent) => void) | null;3333 onerror: (() => void) | null;34- onclose: (() => void) | null;35- onopen: (() => void) | null;34+ onclose: ((ev: Event) => void) | null;35+ onopen: ((ev: Event) => void) | null;3636 sentFrames: ArrayBuffer[];3737 send(data: ArrayBuffer | Uint8Array): void;3838 close(): void;@@ -52,7 +52,7 @@5252 sentFrames: [],5353 send(data: ArrayBuffer | Uint8Array) {5454 if (data instanceof Uint8Array) {55- instance.sentFrames.push(data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength));55+ instance.sentFrames.push(data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength) as ArrayBuffer);5656 } else {5757 instance.sentFrames.push(data);5858 }