mirror of
https://github.com/block/buzz.git
synced 2026-10-29 05:21:31 +00:00
test(sidebar-sync): assert durable adoption and outbox clearing in Carl hook tests
P1/C1-stale: after adopt completes, assert (a) lane storage equals the adopted remote store, and (c) readOutbox returns null. Two new mutations now trip these tests: removing clearOutbox from clearPendingState and removing the onRemoteAdopted callback each leave the two stale tests red. P2a-1 hook: after H102 adopt completes, assert lane storage equals H102's store and the click outbox is cleared. The dropped-callback mutation turns the two hook tests red. runWholeBlobP2a1HookSuite signature extended with storageKey and readOutbox; callers (sections, sort) pass readOutbox from their respective lane modules. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
This commit is contained in:
@@ -346,6 +346,7 @@ runWholeBlobP2a1HookSuite({
|
||||
return `buzz-channel-sections-outbox.v1:${pubkey}:${encoded}`;
|
||||
},
|
||||
storageKey,
|
||||
readOutbox: readChannelSectionsOutbox,
|
||||
useHook: useChannelSections,
|
||||
makeEdit: (r) => r.createSection("P2a1-Section"),
|
||||
makeEditStore: () => ({
|
||||
|
||||
@@ -213,6 +213,7 @@ runWholeBlobP2a1HookSuite({
|
||||
return `buzz-channel-sort-outbox.v1:${pubkey}:${encoded}`;
|
||||
},
|
||||
storageKey,
|
||||
readOutbox: readChannelSortOutbox,
|
||||
useHook: useChannelSortPreference,
|
||||
makeEdit: (r) => r.setSortModeFor("channels", "alpha"),
|
||||
makeEditStore: () => ({ version: 1, groups: { click: "alpha" } }),
|
||||
|
||||
@@ -288,6 +288,42 @@ export function runWholeBlobCarlSuite({
|
||||
`fires → publishes stale edit`,
|
||||
);
|
||||
|
||||
// Flush React state updates triggered by onRemoteAdopted → setStore(applyRemote(remote)).
|
||||
// applyRemote's state updater writes to localStorage; act() flushes the commit phase.
|
||||
await act(async () => {
|
||||
for (let i = 0; i < 50; i++) await Promise.resolve();
|
||||
});
|
||||
|
||||
// (a) Persisted lane storage must reflect the adopted remote store.
|
||||
// Mutation (onRemoteAdopted callback removed): adopted store never written → still editStore → fails.
|
||||
const persistedRaw = window.localStorage.getItem(
|
||||
storageKey(pubkey, relayUrl),
|
||||
);
|
||||
assert.ok(
|
||||
persistedRaw !== null,
|
||||
`P1/C1-stale ${label}: lane storage must exist after adopt`,
|
||||
);
|
||||
assert.deepEqual(
|
||||
JSON.parse(persistedRaw),
|
||||
makeRemoteStore(),
|
||||
`P1/C1-stale ${label}: lane storage must equal the adopted remote store — ` +
|
||||
`remove onRemoteAdopted callback → old edit store remains persisted`,
|
||||
);
|
||||
|
||||
// (b) Hook state reflects the adopted remote store (driven by localStorage).
|
||||
// After act+microtasks above the hook has already re-rendered from the adopted value.
|
||||
// We use the persisted value as the oracle because it is the source of hook state.
|
||||
// (assertion collapsed into (a) above — same invariant, same mutation tripwire)
|
||||
|
||||
// (c) Losing own outbox must be cleared — head supersedes the stale edit.
|
||||
// Mutation (clearOutbox removed from clearPendingState): old outbox persists → not null → fails.
|
||||
assert.equal(
|
||||
readOutbox(pubkey, relayUrl),
|
||||
null,
|
||||
`P1/C1-stale ${label}: own outbox must be cleared after adopt — ` +
|
||||
`remove clearOutbox from clearPendingState → stale outbox remains, replays again after restart`,
|
||||
);
|
||||
|
||||
hook.unmount();
|
||||
} finally {
|
||||
cleanup();
|
||||
@@ -597,6 +633,8 @@ export function runWholeBlobP2a1Suite({
|
||||
*/
|
||||
export function runWholeBlobP2a1HookSuite({
|
||||
label,
|
||||
storageKey,
|
||||
readOutbox,
|
||||
useHook,
|
||||
makeEdit,
|
||||
makeRemoteStore,
|
||||
@@ -710,6 +748,37 @@ export function runWholeBlobP2a1HookSuite({
|
||||
`set publishBaseline=lastRemoteHead in publish(_, true) → H102 folds into baseline → publishes over H102`,
|
||||
);
|
||||
|
||||
// Flush React state updates triggered by onRemoteAdopted → setStore(applyRemote(remote)).
|
||||
// applyRemote's state updater writes to localStorage; act() flushes the commit phase.
|
||||
await act(async () => {
|
||||
for (let i = 0; i < 50; i++) await Promise.resolve();
|
||||
});
|
||||
|
||||
// Hook state and lane storage must reflect the adopted H102 store.
|
||||
// Mutation (onRemoteAdopted callback removed): H102 never written to storage → old edit persists → fails.
|
||||
const persistedRaw = window.localStorage.getItem(
|
||||
storageKey(pubkey, relayUrl),
|
||||
);
|
||||
assert.ok(
|
||||
persistedRaw !== null,
|
||||
`P2a-1 ${label} (hook): lane storage must exist after H102 adopt`,
|
||||
);
|
||||
assert.deepEqual(
|
||||
JSON.parse(persistedRaw),
|
||||
makeRemoteStore(),
|
||||
`P2a-1 ${label} (hook): lane storage must equal the adopted H102 store — ` +
|
||||
`remove onRemoteAdopted callback → own edit store remains persisted`,
|
||||
);
|
||||
|
||||
// Own outbox written by the click must be cleared after H102 supersedes it.
|
||||
// Mutation (onRemoteAdopted callback removed): adopt never fires, outbox not cleared → not null → fails.
|
||||
assert.equal(
|
||||
readOutbox(pubkey, relayUrl),
|
||||
null,
|
||||
`P2a-1 ${label} (hook): own outbox must be cleared after H102 adopt — ` +
|
||||
`remove onRemoteAdopted callback → click outbox remains, replays stale edit on next restart`,
|
||||
);
|
||||
|
||||
hook.unmount();
|
||||
} finally {
|
||||
cleanup();
|
||||
|
||||
Reference in New Issue
Block a user