import { isStuckToBottom, resolveAutoScrollBehavior } from './auto-scroll.rules'; describe('resolveAutoScrollBehavior', () => { const base = { newMessages: true, forceLocalSend: false, distanceFromBottom: 0, withinInitialGrace: false }; it('does nothing when no new messages arrived', () => { expect(resolveAutoScrollBehavior({ ...base, newMessages: false })).toBe('none'); }); it('jumps instantly for the local user own send regardless of grace', () => { expect(resolveAutoScrollBehavior({ ...base, forceLocalSend: true })).toBe('instant'); expect(resolveAutoScrollBehavior({ ...base, forceLocalSend: true, withinInitialGrace: true })).toBe('instant'); }); it('jumps instantly when near bottom while settling after a channel switch', () => { expect(resolveAutoScrollBehavior({ ...base, distanceFromBottom: 40, withinInitialGrace: true })).toBe('instant'); }); it('animates smoothly for live messages once settled and near bottom', () => { expect(resolveAutoScrollBehavior({ ...base, distanceFromBottom: 40, withinInitialGrace: false })).toBe('smooth'); }); it('shows the indicator (no scroll) when far from the bottom', () => { expect(resolveAutoScrollBehavior({ ...base, distanceFromBottom: 800 })).toBe('none'); expect(resolveAutoScrollBehavior({ ...base, distanceFromBottom: 800, withinInitialGrace: true })).toBe('none'); }); it('honours a custom sticky threshold', () => { expect(resolveAutoScrollBehavior({ ...base, distanceFromBottom: 150, stickyThreshold: 100 })).toBe('none'); expect(resolveAutoScrollBehavior({ ...base, distanceFromBottom: 80, stickyThreshold: 100 })).toBe('smooth'); }); }); describe('isStuckToBottom', () => { it('is stuck when exactly at the bottom', () => { expect(isStuckToBottom(0)).toBe(true); }); it('is stuck within the default sticky threshold', () => { expect(isStuckToBottom(300)).toBe(true); expect(isStuckToBottom(299)).toBe(true); }); it('is not stuck once past the default threshold', () => { expect(isStuckToBottom(301)).toBe(false); expect(isStuckToBottom(2000)).toBe(false); }); it('honours a custom threshold', () => { expect(isStuckToBottom(80, 100)).toBe(true); expect(isStuckToBottom(150, 100)).toBe(false); }); it('treats negative overscroll distances as stuck', () => { expect(isStuckToBottom(-20)).toBe(true); }); });