-
Notifications
You must be signed in to change notification settings - Fork 530
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(router): don't write an existing URL (#4392)
* fix(router): don't write an existing URL Every write puts a history entry, we never want to write the same as what's already written to the URL. The history router didn't have tests yet, so I added just one for this case, as not to lose time writing tests for existing cases. Demonstration of the bug being fixed in user land: https://codesandbox.io/s/vigilant-mayer-u3lyd?file=/src/app.js:2097-2279 (note that this searchFunction is very similar to the default one in Shopify) * remove type creation in favor of Required * add more tests * add test for external write scenario * add inline snapshots to see the route values
- Loading branch information
Showing
2 changed files
with
156 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import historyRouter from '../history'; | ||
|
||
const wait = (ms = 0) => new Promise(res => setTimeout(res, ms)); | ||
|
||
describe('life cycle', () => { | ||
beforeEach(() => { | ||
window.history.pushState(null, '-- divider --', 'http://localhost/'); | ||
jest.restoreAllMocks(); | ||
}); | ||
|
||
it('does not write the same url twice', async () => { | ||
const pushState = jest.spyOn(window.history, 'pushState'); | ||
const router = historyRouter({ | ||
writeDelay: 0, | ||
}); | ||
|
||
router.write({ some: 'state' }); | ||
await wait(0); | ||
|
||
router.write({ some: 'state' }); | ||
await wait(0); | ||
|
||
router.write({ some: 'state' }); | ||
await wait(0); | ||
|
||
expect(pushState).toHaveBeenCalledTimes(1); | ||
expect(pushState.mock.calls).toMatchInlineSnapshot(` | ||
Array [ | ||
Array [ | ||
Object { | ||
"some": "state", | ||
}, | ||
"", | ||
"http://localhost/?some=state", | ||
], | ||
] | ||
`); | ||
}); | ||
|
||
it('does not write if already externally updated to desired URL', async () => { | ||
const pushState = jest.spyOn(window.history, 'pushState'); | ||
const router = historyRouter({ | ||
writeDelay: 0, | ||
}); | ||
|
||
const fakeState = { identifier: 'fake state' }; | ||
|
||
router.write({ some: 'state one' }); | ||
|
||
// external update before timeout passes | ||
window.history.pushState( | ||
fakeState, | ||
'', | ||
'http://localhost/?some=state%20two' | ||
); | ||
|
||
// this write isn't needed anymore | ||
router.write({ some: 'state two' }); | ||
await wait(0); | ||
|
||
expect(pushState).toHaveBeenCalledTimes(1); | ||
expect(pushState.mock.calls).toMatchInlineSnapshot(` | ||
Array [ | ||
Array [ | ||
Object { | ||
"identifier": "fake state", | ||
}, | ||
"", | ||
"http://localhost/?some=state%20two", | ||
], | ||
] | ||
`); | ||
|
||
// proves that InstantSearch' write did not happen | ||
expect(history.state).toBe(fakeState); | ||
}); | ||
|
||
it('does not write the same url title twice', async () => { | ||
const title = jest.spyOn(window.document, 'title', 'set'); | ||
const pushState = jest.spyOn(window.history, 'pushState'); | ||
|
||
const router = historyRouter({ | ||
writeDelay: 0, | ||
windowTitle: state => `My Site - ${state.some}`, | ||
}); | ||
|
||
expect(title).toHaveBeenCalledTimes(1); | ||
expect(window.document.title).toBe('My Site - undefined'); | ||
|
||
router.write({ some: 'state' }); | ||
await wait(0); | ||
|
||
router.write({ some: 'state' }); | ||
await wait(0); | ||
|
||
router.write({ some: 'state' }); | ||
await wait(0); | ||
|
||
expect(pushState).toHaveBeenCalledTimes(1); | ||
expect(pushState.mock.calls).toMatchInlineSnapshot(` | ||
Array [ | ||
Array [ | ||
Object { | ||
"some": "state", | ||
}, | ||
"My Site - state", | ||
"http://localhost/?some=state", | ||
], | ||
] | ||
`); | ||
|
||
expect(title).toHaveBeenCalledTimes(2); | ||
expect(window.document.title).toBe('My Site - state'); | ||
}); | ||
|
||
it('writes after timeout is done', async () => { | ||
const pushState = jest.spyOn(window.history, 'pushState'); | ||
|
||
const router = historyRouter({ | ||
writeDelay: 0, | ||
}); | ||
|
||
router.write({ some: 'state' }); | ||
router.write({ some: 'second' }); | ||
router.write({ some: 'third' }); | ||
await wait(0); | ||
|
||
expect(pushState).toHaveBeenCalledTimes(1); | ||
expect(pushState.mock.calls).toMatchInlineSnapshot(` | ||
Array [ | ||
Array [ | ||
Object { | ||
"some": "third", | ||
}, | ||
"", | ||
"http://localhost/?some=third", | ||
], | ||
] | ||
`); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters