@@ -8,6 +8,7 @@ const GHES = `enterprise-server@${latest}`
88
99// pages stands in for req.context.pages, keyed by full versioned permalink.
1010// /actions/versioned exists in all three versions; /actions/fpt-only exists only unversioned.
11+ // /actions/no-fpt has no Free/Pro/Team version, like much of /admin.
1112const pages = Object . fromEntries (
1213 [
1314 '/en/actions/versioned' ,
@@ -16,6 +17,8 @@ const pages = Object.fromEntries(
1617 '/en/actions/fpt-only' ,
1718 '/en/actions/ghec-only' ,
1819 `/en/${ GHEC } /actions/ghec-only` ,
20+ `/en/${ GHEC } /actions/no-fpt` ,
21+ `/en/${ GHES } /actions/no-fpt` ,
1922 '/ja/actions/versioned' ,
2023 `/ja/${ GHEC } /actions/versioned` ,
2124 '/en' ,
@@ -126,6 +129,36 @@ describe('getVersionPreference', () => {
126129 ) . toEqual ( { vary : true , redirectTo : `/en/${ GHEC } /actions/versioned.md` } )
127130 } )
128131
132+ // Versionless URLs for articles without Free/Pro/Team resolve to their first version.
133+ // The cookie still overrides that default because the reader named no version.
134+ test ( 'overrides the first-version fallback for articles without Free/Pro/Team' , ( ) => {
135+ expect (
136+ getVersionPreference ( '/en/actions/no-fpt' , `/en/${ GHEC } /actions/no-fpt` , GHES , pages ) ,
137+ ) . toEqual ( { vary : true , redirectTo : `/en/${ GHES } /actions/no-fpt` } )
138+ } )
139+
140+ test ( 'varies on the first-version fallback without a cookie' , ( ) => {
141+ expect (
142+ getVersionPreference ( '/en/actions/no-fpt' , `/en/${ GHEC } /actions/no-fpt` , undefined , pages ) ,
143+ ) . toEqual ( { vary : true } )
144+ } )
145+
146+ test ( 'leaves an explicitly versioned URL alone when the target is versioned too' , ( ) => {
147+ const path = `/en/${ GHEC } /actions/no-fpt`
148+ expect ( getVersionPreference ( path , path , GHES , pages ) ) . toEqual ( { vary : false } )
149+ } )
150+
151+ test ( 'leaves a deprecated version target alone' , ( ) => {
152+ expect (
153+ getVersionPreference (
154+ '/en/actions/no-fpt' ,
155+ '/en/enterprise-server@3.0/actions/no-fpt' ,
156+ GHES ,
157+ pages ,
158+ ) ,
159+ ) . toEqual ( { vary : false } )
160+ } )
161+
129162 test ( 'redirects a language homepage to the preferred version' , ( ) => {
130163 expect ( getVersionPreference ( '/en' , '/en' , GHEC , pages ) ) . toEqual ( {
131164 vary : true ,
@@ -160,7 +193,7 @@ describe('getVersionPreference', () => {
160193 } )
161194 } )
162195
163- // Versioned redirect targets short-circuit on pathNamesAVersion , so they cannot bounce back .
196+ // The follow-up request names a version , so it short-circuits on pathNamesAVersion .
164197 test ( 'cannot loop' , ( ) => {
165198 const first = getVersionPreference (
166199 '/en/actions/versioned' ,
0 commit comments