diff --git a/packages/liveblocks-core/src/crdts/__tests__/liveblocks-helpers.test.ts b/packages/liveblocks-core/src/crdts/__tests__/liveblocks-helpers.test.ts index 08492cb09a..da6f4225c9 100644 --- a/packages/liveblocks-core/src/crdts/__tests__/liveblocks-helpers.test.ts +++ b/packages/liveblocks-core/src/crdts/__tests__/liveblocks-helpers.test.ts @@ -1,3 +1,4 @@ +import fc from "fast-check"; import { describe, expect, test } from "vitest"; import { @@ -7,10 +8,11 @@ import { SECOND_POSITION, THIRD_POSITION, } from "../../__tests__/_MockWebSocketServer.setup"; +import { stableStringify } from "../../lib/stringify"; import { OpCode } from "../../protocol/Op"; import type { NodeMap } from "../../protocol/StorageNode"; import { CrdtType } from "../../protocol/StorageNode"; -import { getTreesDiffOperations } from "../liveblocks-helpers"; +import { getTreesDiffOperations, isJsonEq } from "../liveblocks-helpers"; import { LiveList } from "../LiveList"; import { LiveMap } from "../LiveMap"; import { LiveObject } from "../LiveObject"; @@ -440,3 +442,23 @@ describe("toPlainLson", () => { expect(toPlainLson(mockLsonObject)).toEqual(plainLsonValue); }); }); + +describe("isJsonEq", () => { + test("[property] true iff the stable stringifications match", () => { + fc.assert( + fc.property(fc.jsonValue(), fc.jsonValue(), (j1, j2) => { + expect(isJsonEq(j1, j2)).toBe( + stableStringify(j1) === stableStringify(j2) + ); + }) + ); + }); + + test("[property] reflexive: a value always equals (a clone of) itself", () => { + fc.assert( + fc.property(fc.jsonValue(), (j) => { + expect(isJsonEq(j, structuredClone(j))).toBe(true); + }) + ); + }); +}); diff --git a/packages/liveblocks-core/src/crdts/liveblocks-helpers.ts b/packages/liveblocks-core/src/crdts/liveblocks-helpers.ts index a9a7280cf4..156048d6c0 100644 --- a/packages/liveblocks-core/src/crdts/liveblocks-helpers.ts +++ b/packages/liveblocks-core/src/crdts/liveblocks-helpers.ts @@ -201,7 +201,7 @@ export function dumpPool(pool: ManagedPool): string { * and nested arrays/objects are compared by traversal (key-by-key, so key order * is irrelevant). */ -function isJsonEq(a: Json | undefined, b: Json | undefined): boolean { +export function isJsonEq(a: Json | undefined, b: Json | undefined): boolean { if (a === b) { return true; }