Replacing crypto.randomUUID() With Deterministic Seeds in Tests
One of the most common sources of flaky tests is the use of crypto.randomUUID() or similar random generators when creating records. The test passes locally, but the snapshot or database assertion fails in CI because a different identifier was generated.
The fix is surprisingly simple: generate the UUID from a stable seed instead of relying on randomness.
Pattern You Can Apply Today
Instead of calling crypto.randomUUID() directly, create a tiny helper that accepts a meaningful string. For a user you might use user-1, user-2, admin, guest, and so on. The helper hashes that string and returns the same UUID every time.
Where to Apply It
Apply the pattern in factories, fixtures, page objects, component stories, and anywhere an ID is needed during testing. Common places include:
Database seed files, Jest or Vitest setup files, Playwright page objects, API response stubs, Storybook stories, and snapshot tests.
Benefits You’ll Notice Immediately
Tests become idempotent, snapshots stop changing, database constraints never break because a foreign key changed, CI runs are green more often, and onboarding new developers is faster because they can run the exact same data locally.
FAQ
Do I have to change all tests at once?
No. Start with the most flaky ones and gradually replace as you touch the code.
Will this slow down my test suite?
No. SHA-256 in the browser is microseconds fast.
Can I keep random UUIDs in some places?
Yes. Use seeded only where stability matters; keep true randomness for security tests.
Making your identifiers deterministic is one of the highest-return refactors you can perform on a test suite.