diff --git a/aio/firebase.json b/aio/firebase.json index c801f78c58..5700ee5f5f 100644 --- a/aio/firebase.json +++ b/aio/firebase.json @@ -104,7 +104,12 @@ {"type": 301, "source": "/guide/ngmodule", "destination": "/guide/ngmodules"}, {"type": 301, "source": "/guide/learning-angular*", "destination": "/guide/quickstart"}, {"type": 301, "source": "/testing", "destination": "/guide/testing"}, - {"type": 301, "source": "/testing/**", "destination": "/guide/testing"} + {"type": 301, "source": "/testing/**", "destination": "/guide/testing"}, + + // Strip off the `.html` extension, because Firebase will not do this automatically any more + // (unless the new URL points to an existing file, which is not necessarily the case here). + {"type": 301, "source": "/:somePath*/:file.html", "destination": "/:somePath*/:file"}, + {"type": 301, "source": "/:topLevelFile.html", "destination": "/:topLevelFile"} ], "rewrites": [ { diff --git a/aio/tests/deployment/e2e/redirection.e2e-spec.ts b/aio/tests/deployment/e2e/redirection.e2e-spec.ts index 8b63311d97..481b92419a 100644 --- a/aio/tests/deployment/e2e/redirection.e2e-spec.ts +++ b/aio/tests/deployment/e2e/redirection.e2e-spec.ts @@ -13,11 +13,11 @@ describe(browser.baseUrl, () => { afterEach(() => browser.waitForAngularEnabled(true)); describe('(with sitemap URLs)', () => { - page.sitemapUrls.forEach((url, i) => { - it(`should not redirect '${url}' (${i + 1}/${page.sitemapUrls.length})`, async () => { - await page.goTo(url); + page.sitemapUrls.forEach((path, i) => { + it(`should not redirect '${path}' (${i + 1}/${page.sitemapUrls.length})`, async () => { + await page.goTo(path); - const expectedUrl = stripTrailingSlash(page.baseUrl + url); + const expectedUrl = stripTrailingSlash(page.baseUrl + path); const actualUrl = await getCurrentUrl(); expect(actualUrl).toBe(expectedUrl); @@ -38,14 +38,28 @@ describe(browser.baseUrl, () => { }); }); + describe('(with `.html` URLs)', () => { + ['/path/to/file.html', '/top-level-file.html'].forEach(fromPath => { + const toPath = fromPath.replace(/\.html$/, ''); + it(`should redirect '${fromPath}' to '${toPath}'`, async () => { + await page.goTo(fromPath); + + const expectedUrl = page.baseUrl + toPath; + const actualUrl = await getCurrentUrl(); + + expect(actualUrl).toBe(expectedUrl); + }); + }); + }); + describe('(with unknown URLs)', () => { - const unknownPageUrl = '/unknown/page'; - const unknownResourceUrl = '/unknown/resource.ext'; + const unknownPagePath = '/unknown/page'; + const unknownResourcePath = '/unknown/resource.ext'; it('should serve `index.html` for unknown pages', async () => { const aioShell = element(by.css('aio-shell')); const heading = aioShell.element(by.css('h1')); - await page.goTo(unknownPageUrl); + await page.goTo(unknownPagePath); expect(aioShell.isPresent()).toBe(true); expect(heading.getText()).toMatch(/page not found/i); @@ -54,7 +68,7 @@ describe(browser.baseUrl, () => { it('should serve a custom 404 page for unknown resources', async () => { const aioShell = element(by.css('aio-shell')); const heading = aioShell.element(by.css('h1')); - await page.goTo(unknownResourceUrl); + await page.goTo(unknownResourcePath); expect(aioShell.isPresent()).toBe(true); expect(heading.getText()).toMatch(/resource not found/i); @@ -62,7 +76,7 @@ describe(browser.baseUrl, () => { it('should include a link to the home page in custom 404 page', async () => { const homeNavLink = element(by.css('.nav-link.home')); - await page.goTo(unknownResourceUrl); + await page.goTo(unknownResourcePath); expect(homeNavLink.isPresent()).toBe(true);