test(mobile): pin replay paging-metadata and base-snapshot authority

Two more branches of the replay logic were unpinned. Adopting a replay's
`beforeOffset` when it starts partway into paged-in history would make the
next loadEarlier re-fetch on-screen rows and prepend duplicates; treating a
post-replacement snapshot as a replay would retain a row the authoritative
window dropped. Both mutants now fail exactly one test.
This commit is contained in:
Brennan Benson
2026-08-04 02:53:55 -07:00
parent 45a40dc485
commit c502643bc1
@@ -103,6 +103,27 @@ describe('applyMobileNativeChatStreamFrame', () => {
})
})
it('ignores replay paging metadata that describes a row other than our oldest', () => {
const merger = createNativeChatMerger()
replaceList(merger, ['p1', 'p2', 'a', 'b'].map(message))
// `beforeOffset` here points before 'a', not before 'p1'. Adopting it would
// make the next loadEarlier re-fetch 'p1'/'p2' and prepend them twice.
expect(
applyMobileNativeChatStreamFrame({
merger,
frame: {
type: 'snapshot',
messages: [message('a'), message('b')],
hasMore: true,
beforeOffset: 500
},
limit: 100,
replaceSnapshot: false
})
).toEqual({ kind: 'messages', messages: ['p1', 'p2', 'a', 'b'].map(message) })
})
it('replaces the window when a reconnect replay is disjoint from history', () => {
const merger = createNativeChatMerger()
replaceList(merger, [message('old-1'), message('old-2')])
@@ -249,6 +270,33 @@ describe('applyMobileNativeChatStreamFrame', () => {
})
})
it('still treats the base snapshot as authoritative after a replacement frame', () => {
const merger = createNativeChatMerger()
replaceList(merger, ['a', 'b'].map(message))
// A replacement is not this subscription's base snapshot, so the first real
// snapshot still replaces — merging would keep 'a', which it does not carry.
expect(
applyMobileNativeChatStreamFrame({
merger,
frame: {
type: 'snapshot',
messages: [message('b'), message('c')],
hasMore: true,
beforeOffset: 77
},
limit: 100,
replaceSnapshot: true
})
).toEqual({
kind: 'messages',
messages: [message('b'), message('c')],
hasMore: true,
beforeOffset: 77,
windowReplaced: true
})
})
it('surfaces snapshot errors and ignores unrelated frames', () => {
const merger = createNativeChatMerger()
expect(