@@ -190,4 +190,162 @@ describe("mdnHandler", () => {
190190 strictEqual ( res . statusCode , 200 ) ;
191191 } ) ;
192192 } ) ;
193+
194+ describe ( "missing locale (canonical-aware fallback)" , ( ) => {
195+ it ( "redirects /about to /en-US/about (issue #279)" , async ( ) => {
196+ const req = createRequest ( {
197+ method : "GET" ,
198+ url : "/about" ,
199+ hostname : "localhost" ,
200+ headers : { host : "localhost" } ,
201+ } ) ;
202+ const res = createResponse ( ) ;
203+ mdnHandler ( req , res ) ;
204+
205+ strictEqual ( res . statusCode , 302 ) ;
206+ strictEqual ( res . _getRedirectUrl ( ) , "/en-US/about" ) ;
207+ } ) ;
208+
209+ it ( "redirects /community to /en-US/community" , async ( ) => {
210+ const req = createRequest ( {
211+ method : "GET" ,
212+ url : "/community" ,
213+ hostname : "localhost" ,
214+ headers : { host : "localhost" } ,
215+ } ) ;
216+ const res = createResponse ( ) ;
217+ mdnHandler ( req , res ) ;
218+
219+ strictEqual ( res . statusCode , 302 ) ;
220+ strictEqual ( res . _getRedirectUrl ( ) , "/en-US/community" ) ;
221+ } ) ;
222+
223+ it ( "redirects /advertising to /en-US/advertising" , async ( ) => {
224+ const req = createRequest ( {
225+ method : "GET" ,
226+ url : "/advertising" ,
227+ hostname : "localhost" ,
228+ headers : { host : "localhost" } ,
229+ } ) ;
230+ const res = createResponse ( ) ;
231+ mdnHandler ( req , res ) ;
232+
233+ strictEqual ( res . statusCode , 302 ) ;
234+ strictEqual ( res . _getRedirectUrl ( ) , "/en-US/advertising" ) ;
235+ } ) ;
236+
237+ it ( "preserves query string when inserting locale" , async ( ) => {
238+ const req = createRequest ( {
239+ method : "GET" ,
240+ url : "/about?foo=bar" ,
241+ hostname : "localhost" ,
242+ headers : { host : "localhost" } ,
243+ } ) ;
244+ const res = createResponse ( ) ;
245+ mdnHandler ( req , res ) ;
246+
247+ strictEqual ( res . statusCode , 302 ) ;
248+ strictEqual ( res . _getRedirectUrl ( ) , "/en-US/about?foo=bar" ) ;
249+ } ) ;
250+
251+ it ( "uses Accept-Language to pick best locale when multiple are available" , async ( ) => {
252+ const req = createRequest ( {
253+ method : "GET" ,
254+ url : "/docs/Web" ,
255+ hostname : "localhost" ,
256+ headers : { host : "localhost" , "accept-language" : "fr" } ,
257+ } ) ;
258+ const res = createResponse ( ) ;
259+ mdnHandler ( req , res ) ;
260+
261+ strictEqual ( res . statusCode , 302 ) ;
262+ strictEqual ( res . _getRedirectUrl ( ) , "/fr/docs/Web" ) ;
263+ } ) ;
264+
265+ it ( "falls back to en-US when preferredlocale has no translation" , async ( ) => {
266+ const req = createRequest ( {
267+ method : "GET" ,
268+ url : "/about" ,
269+ hostname : "localhost" ,
270+ headers : { host : "localhost" } ,
271+ cookies : { preferredlocale : "de" } ,
272+ } ) ;
273+ const res = createResponse ( ) ;
274+ mdnHandler ( req , res ) ;
275+
276+ strictEqual ( res . statusCode , 302 ) ;
277+ strictEqual ( res . _getRedirectUrl ( ) , "/en-US/about" ) ;
278+ } ) ;
279+ } ) ;
280+
281+ describe ( "locale fallback to en-US" , ( ) => {
282+ it ( "redirects /de/about to /en-US/about when de translation is missing" , async ( ) => {
283+ const req = createRequest ( {
284+ method : "GET" ,
285+ url : "/de/about" ,
286+ hostname : "localhost" ,
287+ headers : { host : "localhost" } ,
288+ } ) ;
289+ const res = createResponse ( ) ;
290+ mdnHandler ( req , res ) ;
291+
292+ strictEqual ( res . statusCode , 302 ) ;
293+ strictEqual ( res . _getRedirectUrl ( ) , "/en-US/about" ) ;
294+ } ) ;
295+
296+ it ( "does not fall back from en-US to itself for missing pages" , async ( ) => {
297+ const req = createRequest ( {
298+ method : "GET" ,
299+ url : "/en-US/non-existent-page" ,
300+ hostname : "localhost" ,
301+ headers : { host : "localhost" } ,
302+ } ) ;
303+ const res = createResponse ( ) ;
304+ mdnHandler ( req , res ) ;
305+
306+ strictEqual ( res . statusCode , 200 ) ;
307+ } ) ;
308+
309+ it ( "does not redirect when neither current locale nor en-US has the page" , async ( ) => {
310+ const req = createRequest ( {
311+ method : "GET" ,
312+ url : "/de/non-existent-page" ,
313+ hostname : "localhost" ,
314+ headers : { host : "localhost" } ,
315+ } ) ;
316+ const res = createResponse ( ) ;
317+ mdnHandler ( req , res ) ;
318+
319+ strictEqual ( res . statusCode , 200 ) ;
320+ } ) ;
321+ } ) ;
322+
323+ describe ( "unsupported locale recovery" , ( ) => {
324+ it ( "redirects /xy/about to /en-US/about (treats xy as bogus locale)" , async ( ) => {
325+ const req = createRequest ( {
326+ method : "GET" ,
327+ url : "/xy/about" ,
328+ hostname : "localhost" ,
329+ headers : { host : "localhost" } ,
330+ } ) ;
331+ const res = createResponse ( ) ;
332+ mdnHandler ( req , res ) ;
333+
334+ strictEqual ( res . statusCode , 302 ) ;
335+ strictEqual ( res . _getRedirectUrl ( ) , "/en-US/about" ) ;
336+ } ) ;
337+
338+ it ( "does not redirect /xy/non-existent (no canonical match in either form)" , async ( ) => {
339+ const req = createRequest ( {
340+ method : "GET" ,
341+ url : "/xy/non-existent" ,
342+ hostname : "localhost" ,
343+ headers : { host : "localhost" } ,
344+ } ) ;
345+ const res = createResponse ( ) ;
346+ mdnHandler ( req , res ) ;
347+
348+ strictEqual ( res . statusCode , 200 ) ;
349+ } ) ;
350+ } ) ;
193351} ) ;
0 commit comments