Files
quak/test/crypto/init.test.ts
sneak 676d42c5eb Phase 2 red: crypto primitive tests and stub modules
Tests for the entire crypto/ public surface, written against the API
shape declared in the README. The accompanying src/crypto/ modules are
stubs that throw 'not implemented' so the test files compile and tests
fail with clear errors rather than module-not-found.

Tests cover:
  * init() resolves and is idempotent
  * fromBase64 / toBase64 / toBase64URL round-trips, including URL-safe
    input with stripped padding (the form Ente uses for auth tokens)
  * deriveKEK matches sodium.crypto_pwhash with Argon2id parameters
  * deriveLoginSubkey matches sodium.crypto_kdf_derive_from_key with
    subkey id 1 and ctx 'loginctx', truncated to 16 bytes
  * decryptBox round-trips, rejects tampering, wrong key, wrong nonce
  * decryptSealed round-trips, rejects wrong keypair and tampering
  * Secretstream pull decrypts multi-chunk streams in order, exposes
    per-chunk tags, rejects tampering, wrong key, and out-of-order chunks
  * Constants STREAM_CHUNK_SIZE (4 MiB) and STREAM_CHUNK_OVERHEAD (17)

Tests are commented to serve as the canonical API documentation per the
README development workflow policy. Verified: 29 tests fail (red), 3
trivial constant tests pass; lint and fmt-check are green.

eslint.config.mjs is updated to honour the leading-underscore convention
for intentionally unused parameters (the stubs).
2026-05-09 12:43:52 -07:00

39 lines
1.3 KiB
TypeScript

/**
* Tests for `crypto.init()`.
*
* libsodium ships as WebAssembly. The bindings (`libsodium-wrappers-sumo`)
* load asynchronously: the runtime must `await sodium.ready` once before any
* crypto call is safe. quack hides that detail behind a single
* `init()` function.
*
* Every other test in `test/crypto/**` calls `init()` in `beforeAll`. New
* code that needs crypto should do the same. Calling it more than once is
* cheap and intentional; the second call returns the same already-resolved
* promise.
*/
import { beforeAll, describe, expect, it } from "vitest";
import { init } from "../../src/crypto/index.js";
describe("crypto.init", () => {
beforeAll(async () => {
await init();
});
it("resolves without throwing", async () => {
// The success criterion is simply that the promise resolves. If
// libsodium's WASM fails to load, `init()` rejects and this test
// fails.
await expect(init()).resolves.toBeUndefined();
});
it("is idempotent: repeated calls are safe", async () => {
// Code paths in this library may call `init()` defensively (e.g. a
// `Client` constructor that doesn't know whether the caller already
// initialised). Repeated calls must therefore be harmless.
await init();
await init();
await init();
});
});