diff --git a/packages/history/src/index.ts b/packages/history/src/index.ts index 3178cb90bb..0e1f78fdc4 100644 --- a/packages/history/src/index.ts +++ b/packages/history/src/index.ts @@ -101,7 +101,7 @@ export function createHistory(opts: { getLength: () => number pushState: (path: string, state: any) => void replaceState: (path: string, state: any) => void - go: (n: number) => void + go: (n: number, ignoreBlocker: boolean) => void back: (ignoreBlocker: boolean) => void forward: (ignoreBlocker: boolean) => void createHref: (path: string) => string @@ -204,7 +204,7 @@ export function createHistory(opts: { go: (index, navigateOpts) => { tryNavigation({ task: () => { - opts.go(index) + opts.go(index, navigateOpts?.ignoreBlocker ?? false) handleIndexChange({ type: 'GO', index }) }, navigateOpts, @@ -500,7 +500,8 @@ export function createBrowserHistory(opts?: { ignoreNextBeforeUnload = true win.history.forward() }, - go: (n) => { + go: (n, ignoreBlocker) => { + if (ignoreBlocker) skipBlockerNextPop = true nextPopIsGo = true win.history.go(n) }, diff --git a/packages/history/tests/ignoreBlocker.test.ts b/packages/history/tests/ignoreBlocker.test.ts new file mode 100644 index 0000000000..3e49328fc7 --- /dev/null +++ b/packages/history/tests/ignoreBlocker.test.ts @@ -0,0 +1,97 @@ +import { describe, expect, test, vi } from 'vitest' +import { createBrowserHistory } from '../src' + +describe('ignoreBlocker functionality', () => { + test('go method should respect ignoreBlocker option', () => { + const mockWindow = { + history: { + pushState: vi.fn(), + replaceState: vi.fn(), + go: vi.fn(), + back: vi.fn(), + forward: vi.fn(), + length: 3, + state: { __TSR_index: 2 }, + }, + location: { + pathname: '/a', + search: '', + hash: '', + }, + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + } + + const history = createBrowserHistory({ window: mockWindow }) + const blocker = vi.fn(() => true) + + const unblock = history.block({ blockerFn: blocker }) + + history.go(-2, { ignoreBlocker: true }) + expect(mockWindow.history.go).toHaveBeenCalledWith(-2) + + unblock() + }) + + test('back method should respect ignoreBlocker option', () => { + const mockWindow = { + history: { + pushState: vi.fn(), + replaceState: vi.fn(), + go: vi.fn(), + back: vi.fn(), + forward: vi.fn(), + length: 3, + state: { __TSR_index: 2 }, + }, + location: { + pathname: '/a', + search: '', + hash: '', + }, + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + } + + const history = createBrowserHistory({ window: mockWindow }) + const blocker = vi.fn(() => true) + + const unblock = history.block({ blockerFn: blocker }) + + history.back({ ignoreBlocker: true }) + expect(mockWindow.history.back).toHaveBeenCalled() + + unblock() + }) + + test('forward method should respect ignoreBlocker option', () => { + const mockWindow = { + history: { + pushState: vi.fn(), + replaceState: vi.fn(), + go: vi.fn(), + back: vi.fn(), + forward: vi.fn(), + length: 3, + state: { __TSR_index: 2 }, + }, + location: { + pathname: '/a', + search: '', + hash: '', + }, + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + } + + const history = createBrowserHistory({ window: mockWindow }) + const blocker = vi.fn(() => true) + + const unblock = history.block({ blockerFn: blocker }) + + history.forward({ ignoreBlocker: true }) + expect(mockWindow.history.forward).toHaveBeenCalled() + + unblock() + }) +})