Skip to content

feat: ship a Jest mock backed by node:crypto - #1076

Merged
boorad merged 2 commits into
margelo:mainfrom
AttayR:feat/jest-mock
Oct 5, 2026
Merged

boorad merged 2 commits into
margelo:mainfrom
AttayR:feat/jest-mock

Conversation

@AttayR

@AttayR AttayR commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Follows up on discussion #800, where adding mocks for Jest was suggested.

Problem

Jest runs in Node, where the native module doesn't exist, so any app test that imports react-native-quick-crypto (directly or through its own code) throws. Today every app has to hand-write stubs for the functions it uses.

Change

Ship a mock at react-native-quick-crypto/jest. Node already implements the crypto API this library brings to React Native, so the mock forwards to node:crypto instead of stubbing functions. Tests get real hashes, ciphertexts and signatures, and app code runs unchanged.

// jest.setup.js
jest.mock('react-native-quick-crypto', () =>
  require('react-native-quick-crypto/jest'),
);
  • Default and named exports both work; install() is a no-op (Node already has globalThis.crypto and Buffer).
  • APIs Node doesn't have (BLAKE3, ML-KEM, …) are undefined; the guide shows how to extend the mock for those.
  • jest is added to files so it's published. It's plain CommonJS because Jest doesn't transform node_modules by default.

Files

  • packages/react-native-quick-crypto/jest/index.js: the mock
  • packages/react-native-quick-crypto/test/jestMock.test.ts: default/named exports, SHA-256 vector, AES-256-GCM round trip, subtle.sign/verify (HMAC)
  • docs/content/docs/guides/testing-with-jest.mdx and meta.json: new guide
  • eslint.config.mjs: lets ESLint parse the CommonJS mock (allowDefaultProject plus a CommonJS override), since it sits outside tsconfig

Testing

  • jest: 19/19 (existing tests plus 4 new)
  • eslint "**/*.{js,ts,tsx}", prettier --check on the changed files, tsc --noEmit: clean
  • Checked the documented setup from a separate project that imports the package by name, with the real entry point replaced by one that throws. The tests pass through the mock, including subtle.verify resolving to true and argon2 being available (Node 24.7+).

I targeted main only. Happy to backport to 0.x if you want it there too.

Jest runs in Node, where the native module doesn't exist, so importing the
library in a test throws. Add react-native-quick-crypto/jest, which forwards
to node:crypto so tests get real results without hand-written stubs.

Includes a unit test, a 'Testing with Jest' guide, and an ESLint override for
the CommonJS mock file.
@vercel

vercel Bot commented Oct 4, 2026

Copy link
Copy Markdown

@AttayR is attempting to deploy a commit to the Margelo Team on Vercel.

A member of the Team first needs to authorize it.

@boorad

boorad commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

Thanks for this, @AttayR! Forwarding to node:crypto instead of stubbing each function is a good call.

I pushed a small follow-up commit (94d5a45) to your branch:

  • CryptoKey export: without it, app code doing x instanceof CryptoKey (with CryptoKey imported from the package) threw under the mock. It now comes from globalThis.CryptoKey, because Node doesn't put it on crypto.webcrypto. The HMAC test also checks the generated key against it.
  • Shorter header comment: it's one line now that points to the guide, which already covers usage.
  • Guide callout: it now also lists xsalsa20, randomUUIDv7, and the hkdfExtract/hkdfExpand helpers among the APIs the mock doesn't provide.

Jest passes 19/19, and ESLint and Prettier are clean. No need to backport to 0.x.

@boorad
boorad merged commit a27ab23 into margelo:main Oct 5, 2026
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants