Skip to content

Commit a0d1574

Browse files
committed
feat(routing): replace getLocation with getCurrentURL (#6477)
getCurrentURL is the alternative of getLocation in the history router. This is changed as it's possible to create a URL out of a string, but not a location. We also don't use any properties of the location that aren't also present in a URL. [FX-3191] BREAKING CHANGE: change from `getLocation` to `getCurrentURL`, and return a URL object. BREAKING CHANGE: createURL createURL now receives `currentURL` instead of `location` BREAKING CHANGE: parseURL createURL now receives `currentURL` instead of `location`
1 parent 0f90bbc commit a0d1574

File tree

13 files changed

+103
-119
lines changed

13 files changed

+103
-119
lines changed

examples/js/e-commerce-umd/src/routing.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ const router = window.instantsearch.routers.history<RouteState>({
8989
.join(' | ');
9090
},
9191

92-
createURL({ qsModule, routeState, location }): string {
93-
const { protocol, hostname, port = '', pathname, hash } = location;
92+
createURL({ qsModule, routeState, currentURL }): string {
93+
const { protocol, hostname, port = '', pathname, hash } = currentURL;
9494
const portWithPrefix = port === '' ? '' : `:${port}`;
95-
const urlParts = location.href.match(/^(.*?)\/search/);
95+
const urlParts = currentURL.href.match(/^(.*?)\/search/);
9696
const baseUrl =
9797
(urlParts && urlParts[0]) ||
9898
`${protocol}//${hostname}${portWithPrefix}${pathname}search`;
@@ -156,12 +156,14 @@ const router = window.instantsearch.routers.history<RouteState>({
156156
return `${baseUrl}/${categoryPath}${queryString}${hash}`;
157157
},
158158

159-
parseURL({ qsModule, location }): RouteState {
160-
const pathnameMatches = location.pathname.match(/search\/(.*?)\/?$/);
159+
parseURL({ qsModule, currentURL }): RouteState {
160+
const pathnameMatches = currentURL.pathname.match(/search\/(.*?)\/?$/);
161161
const category = getCategoryName(
162162
(pathnameMatches && pathnameMatches[1]) || ''
163163
);
164-
const queryParameters = qsModule.parse(location.search.slice(1));
164+
const queryParameters = qsModule.parse(currentURL.search, {
165+
ignoreQueryPrefix: true,
166+
});
165167
const {
166168
query = '',
167169
page = 1,

examples/js/e-commerce/src/routing.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ const router = historyRouter<RouteState>({
9191
.join(' | ');
9292
},
9393

94-
createURL({ qsModule, routeState, location }): string {
95-
const { protocol, hostname, port = '', pathname, hash } = location;
94+
createURL({ qsModule, routeState, currentURL }): string {
95+
const { protocol, hostname, port = '', pathname, hash } = currentURL;
9696
const portWithPrefix = port === '' ? '' : `:${port}`;
97-
const urlParts = location.href.match(/^(.*?)\/search/);
97+
const urlParts = currentURL.href.match(/^(.*?)\/search/);
9898
const baseUrl =
9999
(urlParts && urlParts[0]) ||
100100
`${protocol}//${hostname}${portWithPrefix}${pathname}search`;
@@ -158,12 +158,14 @@ const router = historyRouter<RouteState>({
158158
return `${baseUrl}/${categoryPath}${queryString}${hash}`;
159159
},
160160

161-
parseURL({ qsModule, location }): RouteState {
162-
const pathnameMatches = location.pathname.match(/search\/(.*?)\/?$/);
161+
parseURL({ qsModule, currentURL }): RouteState {
162+
const pathnameMatches = currentURL.pathname.match(/search\/(.*?)\/?$/);
163163
const category = getCategoryName(
164164
(pathnameMatches && pathnameMatches[1]) || ''
165165
);
166-
const queryParameters = qsModule.parse(location.search.slice(1));
166+
const queryParameters = qsModule.parse(currentURL.search, {
167+
ignoreQueryPrefix: true,
168+
});
167169
const {
168170
query = '',
169171
page = 1,

examples/react/e-commerce/routing.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,10 @@ const router = historyRouter<RouteState>({
8585
.join(' | ');
8686
},
8787

88-
createURL({ qsModule, routeState, location }): string {
89-
const { protocol, hostname, port = '', pathname, hash } = location;
88+
createURL({ qsModule, routeState, currentURL }): string {
89+
const { protocol, hostname, port = '', pathname, hash } = currentURL;
9090
const portWithPrefix = port === '' ? '' : `:${port}`;
91-
const urlParts = location.href.match(/^(.*?)\/search/);
91+
const urlParts = currentURL.href.match(/^(.*?)\/search/);
9292
const baseUrl =
9393
(urlParts && urlParts[0]) ||
9494
`${protocol}//${hostname}${portWithPrefix}${pathname}search`;
@@ -152,13 +152,15 @@ const router = historyRouter<RouteState>({
152152
return `${baseUrl}/${categoryPath}${queryString}${hash}`;
153153
},
154154

155-
parseURL({ qsModule, location }): RouteState {
156-
const pathnameMatches = location.pathname.match(/search\/(.*?)\/?$/);
155+
parseURL({ qsModule, currentURL }): RouteState {
156+
const pathnameMatches = currentURL.pathname.match(/search\/(.*?)\/?$/);
157157
const category = getCategoryName(
158158
(pathnameMatches && pathnameMatches[1]) || ''
159159
);
160160

161-
const queryParameters = qsModule.parse(location.search.slice(1));
161+
const queryParameters = qsModule.parse(currentURL.search, {
162+
ignoreQueryPrefix: true,
163+
});
162164
const {
163165
query = '',
164166
page = 1,

examples/react/ssr/src/App.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function Hit({ hit }) {
2121
return <Highlight hit={hit} attribute="name" />;
2222
}
2323

24-
function App({ serverState, location }) {
24+
function App({ serverState, currentURL }) {
2525
return (
2626
<InstantSearchSSRProvider {...serverState}>
2727
<InstantSearch
@@ -31,12 +31,12 @@ function App({ serverState, location }) {
3131
stateMapping: simple(),
3232
router: history({
3333
cleanUrlOnDispose: false,
34-
getLocation() {
34+
getCurrentURL() {
3535
if (typeof window === 'undefined') {
36-
return location;
36+
return currentURL;
3737
}
3838

39-
return window.location;
39+
return new URL(window.location.href);
4040
},
4141
}),
4242
}}

examples/react/ssr/src/server.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ const app = express();
1313
app.use('/assets', express.static(join(__dirname, 'assets')));
1414

1515
app.get('/', async (req, res) => {
16-
const location = new URL(
16+
const currentURL = new URL(
1717
`${req.protocol}://${req.get('host')}${req.originalUrl}`
1818
);
19-
const serverState = await getServerState(<App location={location} />, {
19+
const serverState = await getServerState(<App currentURL={currentURL} />, {
2020
renderToString,
2121
});
2222
requestsCache.clear();
2323
const html = renderToString(
24-
<App serverState={serverState} location={location} />
24+
<App serverState={serverState} currentURL={currentURL} />
2525
);
2626

2727
res.send(

examples/vue/e-commerce/src/routing.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ const router = historyRouter({
9696
.join(' | ');
9797
},
9898

99-
createURL({ qsModule, routeState, location }) {
100-
const { protocol, hostname, port = '', pathname, hash } = location;
99+
createURL({ qsModule, routeState, currentURL }) {
100+
const { protocol, hostname, port = '', pathname, hash } = currentURL;
101101
const portWithPrefix = port === '' ? '' : `:${port}`;
102-
const urlParts = location.href.match(/^(.*?)\/search/);
102+
const urlParts = currentURL.href.match(/^(.*?)\/search/);
103103
const baseUrl =
104104
(urlParts && urlParts[0]) ||
105105
`${protocol}//${hostname}${portWithPrefix}${pathname}search`;
@@ -163,12 +163,14 @@ const router = historyRouter({
163163
return `${baseUrl}/${categoryPath}${queryString}${hash}`;
164164
},
165165

166-
parseURL({ qsModule, location }) {
167-
const pathnameMatches = location.pathname.match(/search\/(.*?)\/?$/);
166+
parseURL({ qsModule, currentURL }) {
167+
const pathnameMatches = currentURL.pathname.match(/search\/(.*?)\/?$/);
168168
const category = getCategoryName(
169169
(pathnameMatches && pathnameMatches[1]) || ''
170170
);
171-
const queryParameters = qsModule.parse(location.search.slice(1));
171+
const queryParameters = qsModule.parse(currentURL.search, {
172+
ignoreQueryPrefix: true,
173+
});
172174
const {
173175
query = '',
174176
page = 1,

packages/instantsearch-core/src/__tests__/RoutingManager.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ describe('RoutingManager', () => {
580580
// In a next refactor, we can consider changing this test implementation.
581581
const parsedUrl = router.parseURL({
582582
qsModule: qs,
583-
location: window.location,
583+
currentURL: new URL(window.location.href),
584584
});
585585

586586
expect(parsedUrl.refinementList!.brand).toBeInstanceOf(Array);
@@ -627,7 +627,7 @@ describe('RoutingManager', () => {
627627
// In a next refactor, we can consider changing this test implementation.
628628
const parsedUrl = router.parseURL({
629629
qsModule: qs,
630-
location: window.location,
630+
currentURL: new URL(window.location.href),
631631
});
632632

633633
expect(parsedUrl.refinementList!.brand).toBeInstanceOf(Array);

packages/instantsearch-core/src/routing/__tests__/historyRouter.test.ts

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -80,50 +80,50 @@ describe('life cycle', () => {
8080
});
8181
});
8282

83-
describe('getLocation', () => {
84-
test('calls getLocation on windowTitle', () => {
85-
const getLocation = jest.fn(() => window.location);
83+
describe('getCurrentURL', () => {
84+
test('calls getCurrentURL on windowTitle', () => {
85+
const getCurrentURL = jest.fn(() => new URL(window.location.href));
8686

8787
historyRouter<UiState>({
8888
windowTitle() {
8989
return 'Search';
9090
},
91-
getLocation,
91+
getCurrentURL,
9292
cleanUrlOnDispose: true,
9393
});
9494

95-
expect(getLocation).toHaveBeenCalledTimes(1);
95+
expect(getCurrentURL).toHaveBeenCalledTimes(1);
9696
});
9797

98-
test('calls getLocation on read', () => {
99-
const getLocation = jest.fn(() => window.location);
98+
test('calls getCurrentURL on read', () => {
99+
const getCurrentURL = jest.fn(() => new URL(window.location.href));
100100
const router = historyRouter<UiState>({
101-
getLocation,
101+
getCurrentURL,
102102
cleanUrlOnDispose: true,
103103
});
104104

105-
expect(getLocation).toHaveBeenCalledTimes(0);
105+
expect(getCurrentURL).toHaveBeenCalledTimes(0);
106106

107107
router.write({ indexName: { query: 'query1' } });
108108
jest.runAllTimers();
109109

110-
expect(getLocation).toHaveBeenCalledTimes(1);
110+
expect(getCurrentURL).toHaveBeenCalledTimes(1);
111111

112112
router.read();
113113

114-
expect(getLocation).toHaveBeenCalledTimes(2);
114+
expect(getCurrentURL).toHaveBeenCalledTimes(2);
115115
});
116116

117-
test('calls getLocation on createURL', () => {
118-
const getLocation = jest.fn(() => window.location);
117+
test('calls getCurrentURL on createURL', () => {
118+
const getCurrentURL = jest.fn(() => new URL(window.location.href));
119119
const router = historyRouter<UiState>({
120-
getLocation,
120+
getCurrentURL,
121121
cleanUrlOnDispose: true,
122122
});
123123

124124
router.createURL({ indexName: { query: 'query1' } });
125125

126-
expect(getLocation).toHaveBeenCalledTimes(1);
126+
expect(getCurrentURL).toHaveBeenCalledTimes(1);
127127
});
128128
});
129129

@@ -188,25 +188,18 @@ describe('life cycle', () => {
188188
search.start();
189189
jest.runAllTimers();
190190
}).toThrowErrorMatchingInlineSnapshot(
191-
`"You need to provide \`getLocation\` to the \`history\` router in environments where \`window\` does not exist."`
191+
`"You need to provide \`getCurrentURL\` to the \`history\` router in environments where \`window\` does not exist."`
192192
);
193193
});
194194

195-
test('does not fail on environments without window with provided getLocation', () => {
195+
test('does not fail on environments without window with provided getCurrentURL', () => {
196196
// @ts-expect-error
197197
delete global.window;
198198

199199
expect(() => {
200200
const router = historyRouter<UiState>({
201-
getLocation() {
202-
return {
203-
protocol: '',
204-
hostname: '',
205-
port: '',
206-
pathname: '',
207-
hash: '',
208-
search: '',
209-
} as unknown as Location;
201+
getCurrentURL() {
202+
return new URL('http://localhost/');
210203
},
211204
cleanUrlOnDispose: true,
212205
});
@@ -224,21 +217,14 @@ describe('life cycle', () => {
224217
}).not.toThrow();
225218
});
226219

227-
test('does not fail when running the whole router lifecycle with getLocation', () => {
220+
test('does not fail when running the whole router lifecycle with getCurrentURL', () => {
228221
// @ts-expect-error
229222
delete global.window;
230223

231224
expect(() => {
232225
const router = historyRouter<UiState>({
233-
getLocation() {
234-
return {
235-
protocol: '',
236-
hostname: '',
237-
port: '',
238-
pathname: '',
239-
hash: '',
240-
search: '',
241-
} as unknown as Location;
226+
getCurrentURL() {
227+
return new URL('http://localhost/');
242228
},
243229
cleanUrlOnDispose: true,
244230
});

0 commit comments

Comments
 (0)