diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 3b505ee34f..bdc447e6b2 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -2197,11 +2197,11 @@ export namespace Components { "navChanged": (direction: RouterDirection) => Promise; "printDebug": () => Promise; /** - * Navigate to the specified URL. - * @param url The url to navigate to. + * Navigate to the specified path. + * @param path The path to navigate to. * @param direction The direction of the animation. Defaults to `"forward"`. */ - "push": (url: string, direction?: RouterDirection, animation?: AnimationBuilder | undefined) => Promise; + "push": (path: string, direction?: RouterDirection, animation?: AnimationBuilder | undefined) => Promise; /** * The root path to use when matching URLs. By default, this is set to "/", but you can specify an alternate prefix for all URL paths. */ diff --git a/core/src/components/router/readme.md b/core/src/components/router/readme.md index 3da084df83..16686c89a2 100644 --- a/core/src/components/router/readme.md +++ b/core/src/components/router/readme.md @@ -100,9 +100,9 @@ Type: `Promise` -### `push(url: string, direction?: RouterDirection, animation?: AnimationBuilder | undefined) => Promise` +### `push(path: string, direction?: RouterDirection, animation?: AnimationBuilder | undefined) => Promise` -Navigate to the specified URL. +Navigate to the specified path. #### Returns diff --git a/core/src/components/router/router.tsx b/core/src/components/router/router.tsx index 978c699d4d..db51b8e64a 100644 --- a/core/src/components/router/router.tsx +++ b/core/src/components/router/router.tsx @@ -117,18 +117,21 @@ export class Router implements ComponentInterface { } /** - * Navigate to the specified URL. + * Navigate to the specified path. * - * @param url The url to navigate to. + * @param path The path to navigate to. * @param direction The direction of the animation. Defaults to `"forward"`. */ @Method() - async push(url: string, direction: RouterDirection = 'forward', animation?: AnimationBuilder) { - if (url.startsWith('.')) { - url = (new URL(url, window.location.href)).pathname; + async push(path: string, direction: RouterDirection = 'forward', animation?: AnimationBuilder) { + if (path.startsWith('.')) { + const currentPath = this.previousPath ?? '/'; + // Convert currentPath to an URL by pre-pending a protocol and a host to resolve the relative path. + const url = new URL(path, `https://host/${currentPath}`); + path = url.pathname + url.search; } - let parsedPath = parsePath(url); + let parsedPath = parsePath(path); const canProceed = await this.runGuards(parsedPath.segments); if (canProceed !== true) { diff --git a/core/src/components/router/test/basic/index.html b/core/src/components/router/test/basic/index.html index 635166f8af..6c131983ed 100644 --- a/core/src/components/router/test/basic/index.html +++ b/core/src/components/router/test/basic/index.html @@ -57,6 +57,8 @@

Go to page 3 (hello)

Go to page 2

Go to page 1

+ Page 3 (relative) + Page 3 (absolute) `; } } diff --git a/core/src/components/router/test/basic/router-push.e2e.ts b/core/src/components/router/test/basic/router-push.e2e.ts new file mode 100644 index 0000000000..df6b3666c0 --- /dev/null +++ b/core/src/components/router/test/basic/router-push.e2e.ts @@ -0,0 +1,29 @@ +import { newE2EPage } from '@stencil/core/testing'; + +test('push should support relative path', async () => { + const page = await newE2EPage({ + url: '/src/components/router/test/basic#/two/three/hola?ionic:_testing=true' + }); + await page.waitForChanges(); + + const backButton = await page.$('#btn-rel'); + await backButton.click(); + await page.waitForChanges(); + + const url = await page.url(); + expect(url).toContain('#/two/three/relative?param=1'); +}); + +test('push should support absolute path', async () => { + const page = await newE2EPage({ + url: '/src/components/router/test/basic#/two/three/hola?ionic:_testing=true' + }); + await page.waitForChanges(); + + const backButton = await page.$('#btn-abs'); + await backButton.click(); + await page.waitForChanges(); + + const url = await page.url(); + expect(url).toContain('#/two/three/absolute'); +}); \ No newline at end of file