browser-navigation.client.spec.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import { describe, expect, it } from 'vitest'
  2. import type { BrowserTarget } from '../src/client/browser/url.ts'
  3. import { BrowserNavigation, MAX_BROWSER_HISTORY } from '../src/client/browser/BrowserNavigation.ts'
  4. const httpsTarget = (index: number): BrowserTarget => ({
  5. kind: 'https', url: `https://example.test/${index}`, title: `page ${index}`,
  6. })
  7. describe('BrowserNavigation', () => {
  8. it('owns bounded history, branch replacement, and reload revisions', () => {
  9. const navigation = new BrowserNavigation()
  10. expect(BrowserNavigation.current(navigation.snapshot)).toBeUndefined()
  11. expect(navigation.back()).toBeUndefined()
  12. expect(navigation.forward()).toBeUndefined()
  13. expect(navigation.reload()).toBeUndefined()
  14. for (let index = 0; index <= MAX_BROWSER_HISTORY; index++) navigation.navigate(httpsTarget(index))
  15. expect(navigation.snapshot.entries).toHaveLength(MAX_BROWSER_HISTORY)
  16. expect(navigation.snapshot.entries[0]?.url).toBe('https://example.test/1')
  17. expect(navigation.canGoBack).toBe(true)
  18. expect(navigation.canGoForward).toBe(false)
  19. const back = navigation.back()
  20. expect(back?.target.url).toBe('https://example.test/99')
  21. expect(navigation.canGoForward).toBe(true)
  22. navigation.navigate(httpsTarget(200))
  23. expect(navigation.snapshot.entries.at(-1)?.url).toBe('https://example.test/200')
  24. expect(navigation.snapshot.entries.some(entry => entry.url === 'https://example.test/100')).toBe(false)
  25. const beforeReload = navigation.snapshot.request!.revision
  26. navigation.reload()
  27. expect(navigation.snapshot.request?.revision).toBe(beforeReload + 1)
  28. })
  29. it('classifies only the first current frame load as known', () => {
  30. const navigation = new BrowserNavigation()
  31. navigation.navigate(httpsTarget(1))
  32. const revision = navigation.snapshot.request!.revision
  33. navigation.frameLoaded(revision - 1)
  34. expect(navigation.snapshot.navigation).toEqual({ status: 'loading', revision })
  35. navigation.frameLoaded(revision)
  36. expect(navigation.snapshot.navigation).toEqual({ status: 'known', revision })
  37. navigation.frameLoaded(revision)
  38. expect(navigation.snapshot.navigation).toEqual({ status: 'unknown', revision })
  39. navigation.frameLoaded(revision)
  40. expect(navigation.snapshot.navigation).toEqual({ status: 'unknown', revision })
  41. expect(navigation.back()).toBeUndefined()
  42. expect(navigation.forward()).toBeUndefined()
  43. const reload = navigation.reload()!
  44. expect(navigation.snapshot.navigation).toEqual({ status: 'loading', revision: reload.revision })
  45. })
  46. it('leaves address failures outside navigation', () => {
  47. const navigation = new BrowserNavigation()
  48. navigation.frameLoaded(1)
  49. navigation.navigate(httpsTarget(1))
  50. const revision = navigation.snapshot.request!.revision
  51. expect(navigation.snapshot.failure).toBeUndefined()
  52. navigation.frameLoaded(revision)
  53. expect(navigation.snapshot.navigation).toEqual({ status: 'known', revision })
  54. navigation.addressFailed('invalid')
  55. expect(navigation.snapshot).toMatchObject({
  56. navigation: { status: 'known', revision },
  57. failure: { kind: 'address', reason: 'invalid' },
  58. })
  59. })
  60. })