From c20216c1f683f58e75f59f1c24b503c5f9a720c6 Mon Sep 17 00:00:00 2001 From: sebastien Date: Fri, 6 Nov 2026 22:58:40 +0100 Subject: [PATCH 1/2] test(core): capture how `docusaurus serve` handles client redirect files of .html paths Co-Authored-By: Claude Opus 5.5 --- .../__fixtures__/build/legacy-false.html.html | 1 + .../serve/__tests__/requestHandler.test.ts | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/legacy-false.html.html diff --git a/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/legacy-false.html.html b/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/legacy-false.html.html new file mode 100644 index 000000000000..7d0432ba091f --- /dev/null +++ b/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/legacy-false.html.html @@ -0,0 +1 @@ +legacy-false.html.html diff --git a/packages/docusaurus/src/commands/serve/__tests__/requestHandler.test.ts b/packages/docusaurus/src/commands/serve/__tests__/requestHandler.test.ts index 73bc3ffc5bfc..a85298d2b5fc 100644 --- a/packages/docusaurus/src/commands/serve/__tests__/requestHandler.test.ts +++ b/packages/docusaurus/src/commands/serve/__tests__/requestHandler.test.ts @@ -64,6 +64,9 @@ const RequestPaths = [ '/missing.html', // A client redirect file, from /legacy.html '/legacy.html', + '/legacy.html/', + // A client redirect file with trailingSlash false, from /legacy-false.html + '/legacy-false.html', '/file?query=1', '/file/?query=1', @@ -152,6 +155,8 @@ describe('createServeRequestHandler', () => { /missing/ 404 404.html /missing.html 301 /missing → 404 404.html /legacy.html 301 /legacy → 404 404.html + /legacy.html/ 200 legacy.html/index.html + /legacy-false.html 301 /legacy-false → 404 404.html /file?query=1 200 file.html /file/?query=1 200 file.html /file.html?query=1 200 file.html @@ -213,6 +218,8 @@ describe('createServeRequestHandler', () => { /missing/ 404 404.html /missing.html 301 /missing → 301 /missing/ → 404 404.html /legacy.html 301 /legacy → 301 /legacy/ → 404 404.html + /legacy.html/ 200 legacy.html/index.html + /legacy-false.html 301 /legacy-false → 301 /legacy-false/ → 404 404.html /file?query=1 301 /file/?query=1 → 200 file.html /file/?query=1 200 file.html /file.html?query=1 200 file.html @@ -274,6 +281,8 @@ describe('createServeRequestHandler', () => { /missing/ 301 /missing → 404 404.html /missing.html 301 /missing → 404 404.html /legacy.html 301 /legacy → 404 404.html + /legacy.html/ 301 /legacy.html → 301 /legacy → 404 404.html + /legacy-false.html 301 /legacy-false → 404 404.html /file?query=1 200 file.html /file/?query=1 301 /file?query=1 → 200 file.html /file.html?query=1 200 file.html @@ -337,6 +346,8 @@ describe('createServeRequestHandler', () => { /base/missing/ 404 404.html /base/missing.html 301 /base/missing → 404 404.html /base/legacy.html 301 /base/legacy → 404 404.html + /base/legacy.html/ 200 legacy.html/index.html + /base/legacy-false.html 301 /base/legacy-false → 404 404.html /base/file?query=1 200 file.html /base/file/?query=1 200 file.html /base/file.html?query=1 200 file.html @@ -398,6 +409,8 @@ describe('createServeRequestHandler', () => { /base/missing/ 404 404.html /base/missing.html 301 /base/missing → 301 /base/missing/ → 404 404.html /base/legacy.html 301 /base/legacy → 301 /base/legacy/ → 404 404.html + /base/legacy.html/ 200 legacy.html/index.html + /base/legacy-false.html 301 /base/legacy-false → 301 /base/legacy-false/ → 404 404.html /base/file?query=1 301 /base/file/?query=1 → 200 file.html /base/file/?query=1 200 file.html /base/file.html?query=1 200 file.html @@ -459,6 +472,8 @@ describe('createServeRequestHandler', () => { /base/missing/ 301 /base/missing → 404 404.html /base/missing.html 301 /base/missing → 404 404.html /base/legacy.html 301 /base/legacy → 404 404.html + /base/legacy.html/ 301 /base/legacy.html → 301 /base/legacy → 404 404.html + /base/legacy-false.html 301 /base/legacy-false → 404 404.html /base/file?query=1 200 file.html /base/file/?query=1 301 /base/file?query=1 → 200 file.html /base/file.html?query=1 200 file.html @@ -815,6 +830,17 @@ describe('createServeRequestHandler', () => { ); }); + // TODO fix: serve the client redirect file, "200 legacy.html/index.html" + // plugin-client-redirects writes it for redirects from /legacy.html + it('serves no client redirect file of .html paths', async () => { + await expect( + serveRequest( + {baseUrl: '/base/', trailingSlash: undefined}, + '/base/legacy.html', + ), + ).resolves.toBe('301 /base/legacy → 404 404.html'); + }); + // Like the malformed percent-encodings it('answers 400 to null bytes', async () => { await expect( From 05fa68c6459983b64b92b412b74af4fafb37cadb Mon Sep 17 00:00:00 2001 From: sebastien Date: Fri, 6 Nov 2026 23:05:52 +0100 Subject: [PATCH 2/2] test(core): name the client redirect fixtures after their shape, request both forms Co-Authored-By: Claude Opus 5.5 --- .../__fixtures__/build/legacy-false.html.html | 1 - .../__fixtures__/build/legacy.html/index.html | 1 - .../build/redirect-file.html.html | 1 + .../build/redirect-folder.html/index.html | 1 + .../serve/__tests__/requestHandler.test.ts | 75 ++++++++++++------- 5 files changed, 49 insertions(+), 30 deletions(-) delete mode 100644 packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/legacy-false.html.html delete mode 100644 packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/legacy.html/index.html create mode 100644 packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/redirect-file.html.html create mode 100644 packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/redirect-folder.html/index.html diff --git a/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/legacy-false.html.html b/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/legacy-false.html.html deleted file mode 100644 index 7d0432ba091f..000000000000 --- a/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/legacy-false.html.html +++ /dev/null @@ -1 +0,0 @@ -legacy-false.html.html diff --git a/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/legacy.html/index.html b/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/legacy.html/index.html deleted file mode 100644 index 754720dc3169..000000000000 --- a/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/legacy.html/index.html +++ /dev/null @@ -1 +0,0 @@ -legacy.html/index.html diff --git a/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/redirect-file.html.html b/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/redirect-file.html.html new file mode 100644 index 000000000000..931c060a761c --- /dev/null +++ b/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/redirect-file.html.html @@ -0,0 +1 @@ +redirect-file.html.html diff --git a/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/redirect-folder.html/index.html b/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/redirect-folder.html/index.html new file mode 100644 index 000000000000..fc89b9b924fe --- /dev/null +++ b/packages/docusaurus/src/commands/serve/__tests__/__fixtures__/build/redirect-folder.html/index.html @@ -0,0 +1 @@ +redirect-folder.html/index.html diff --git a/packages/docusaurus/src/commands/serve/__tests__/requestHandler.test.ts b/packages/docusaurus/src/commands/serve/__tests__/requestHandler.test.ts index a85298d2b5fc..0c8b5056066a 100644 --- a/packages/docusaurus/src/commands/serve/__tests__/requestHandler.test.ts +++ b/packages/docusaurus/src/commands/serve/__tests__/requestHandler.test.ts @@ -62,11 +62,12 @@ const RequestPaths = [ '/missing', '/missing/', '/missing.html', - // A client redirect file, from /legacy.html - '/legacy.html', - '/legacy.html/', - // A client redirect file with trailingSlash false, from /legacy-false.html - '/legacy-false.html', + // Client redirect files, for redirects from a .html path + // plugin-client-redirects writes a folder, or a file with trailingSlash false + '/redirect-folder.html', + '/redirect-folder.html/', + '/redirect-file.html', + '/redirect-file.html/', '/file?query=1', '/file/?query=1', @@ -154,9 +155,10 @@ describe('createServeRequestHandler', () => { /missing 404 404.html /missing/ 404 404.html /missing.html 301 /missing → 404 404.html - /legacy.html 301 /legacy → 404 404.html - /legacy.html/ 200 legacy.html/index.html - /legacy-false.html 301 /legacy-false → 404 404.html + /redirect-folder.html 301 /redirect-folder → 404 404.html + /redirect-folder.html/ 200 redirect-folder.html/index.html + /redirect-file.html 301 /redirect-file → 404 404.html + /redirect-file.html/ 200 redirect-file.html.html /file?query=1 200 file.html /file/?query=1 200 file.html /file.html?query=1 200 file.html @@ -217,9 +219,10 @@ describe('createServeRequestHandler', () => { /missing 301 /missing/ → 404 404.html /missing/ 404 404.html /missing.html 301 /missing → 301 /missing/ → 404 404.html - /legacy.html 301 /legacy → 301 /legacy/ → 404 404.html - /legacy.html/ 200 legacy.html/index.html - /legacy-false.html 301 /legacy-false → 301 /legacy-false/ → 404 404.html + /redirect-folder.html 301 /redirect-folder → 301 /redirect-folder/ → 404 404.html + /redirect-folder.html/ 200 redirect-folder.html/index.html + /redirect-file.html 301 /redirect-file → 301 /redirect-file/ → 404 404.html + /redirect-file.html/ 200 redirect-file.html.html /file?query=1 301 /file/?query=1 → 200 file.html /file/?query=1 200 file.html /file.html?query=1 200 file.html @@ -280,9 +283,10 @@ describe('createServeRequestHandler', () => { /missing 404 404.html /missing/ 301 /missing → 404 404.html /missing.html 301 /missing → 404 404.html - /legacy.html 301 /legacy → 404 404.html - /legacy.html/ 301 /legacy.html → 301 /legacy → 404 404.html - /legacy-false.html 301 /legacy-false → 404 404.html + /redirect-folder.html 301 /redirect-folder → 404 404.html + /redirect-folder.html/ 301 /redirect-folder.html → 301 /redirect-folder → 404 404.html + /redirect-file.html 301 /redirect-file → 404 404.html + /redirect-file.html/ 301 /redirect-file.html → 301 /redirect-file → 404 404.html /file?query=1 200 file.html /file/?query=1 301 /file?query=1 → 200 file.html /file.html?query=1 200 file.html @@ -345,9 +349,10 @@ describe('createServeRequestHandler', () => { /base/missing 404 404.html /base/missing/ 404 404.html /base/missing.html 301 /base/missing → 404 404.html - /base/legacy.html 301 /base/legacy → 404 404.html - /base/legacy.html/ 200 legacy.html/index.html - /base/legacy-false.html 301 /base/legacy-false → 404 404.html + /base/redirect-folder.html 301 /base/redirect-folder → 404 404.html + /base/redirect-folder.html/ 200 redirect-folder.html/index.html + /base/redirect-file.html 301 /base/redirect-file → 404 404.html + /base/redirect-file.html/ 200 redirect-file.html.html /base/file?query=1 200 file.html /base/file/?query=1 200 file.html /base/file.html?query=1 200 file.html @@ -408,9 +413,10 @@ describe('createServeRequestHandler', () => { /base/missing 301 /base/missing/ → 404 404.html /base/missing/ 404 404.html /base/missing.html 301 /base/missing → 301 /base/missing/ → 404 404.html - /base/legacy.html 301 /base/legacy → 301 /base/legacy/ → 404 404.html - /base/legacy.html/ 200 legacy.html/index.html - /base/legacy-false.html 301 /base/legacy-false → 301 /base/legacy-false/ → 404 404.html + /base/redirect-folder.html 301 /base/redirect-folder → 301 /base/redirect-folder/ → 404 404.html + /base/redirect-folder.html/ 200 redirect-folder.html/index.html + /base/redirect-file.html 301 /base/redirect-file → 301 /base/redirect-file/ → 404 404.html + /base/redirect-file.html/ 200 redirect-file.html.html /base/file?query=1 301 /base/file/?query=1 → 200 file.html /base/file/?query=1 200 file.html /base/file.html?query=1 200 file.html @@ -471,9 +477,10 @@ describe('createServeRequestHandler', () => { /base/missing 404 404.html /base/missing/ 301 /base/missing → 404 404.html /base/missing.html 301 /base/missing → 404 404.html - /base/legacy.html 301 /base/legacy → 404 404.html - /base/legacy.html/ 301 /base/legacy.html → 301 /base/legacy → 404 404.html - /base/legacy-false.html 301 /base/legacy-false → 404 404.html + /base/redirect-folder.html 301 /base/redirect-folder → 404 404.html + /base/redirect-folder.html/ 301 /base/redirect-folder.html → 301 /base/redirect-folder → 404 404.html + /base/redirect-file.html 301 /base/redirect-file → 404 404.html + /base/redirect-file.html/ 301 /base/redirect-file.html → 301 /base/redirect-file → 404 404.html /base/file?query=1 200 file.html /base/file/?query=1 301 /base/file?query=1 → 200 file.html /base/file.html?query=1 200 file.html @@ -830,15 +837,27 @@ describe('createServeRequestHandler', () => { ); }); - // TODO fix: serve the client redirect file, "200 legacy.html/index.html" - // plugin-client-redirects writes it for redirects from /legacy.html - it('serves no client redirect file of .html paths', async () => { + // TODO fix: "200 redirect-folder.html/index.html" + // plugin-client-redirects writes it for redirects from /redirect-folder.html + it('serves no client redirect folder of .html paths', async () => { await expect( serveRequest( {baseUrl: '/base/', trailingSlash: undefined}, - '/base/legacy.html', + '/base/redirect-folder.html', + ), + ).resolves.toBe('301 /base/redirect-folder → 404 404.html'); + }); + + // TODO fix: "200 redirect-file.html.html" + // plugin-client-redirects writes it for redirects from /redirect-file.html, + // with trailingSlash false + it('serves no client redirect file of .html paths', async () => { + await expect( + serveRequest( + {baseUrl: '/base/', trailingSlash: false}, + '/base/redirect-file.html', ), - ).resolves.toBe('301 /base/legacy → 404 404.html'); + ).resolves.toBe('301 /base/redirect-file → 404 404.html'); }); // Like the malformed percent-encodings