11import { describe , test , expect , vi , beforeEach } from 'vitest'
22import type { Response , NextFunction } from 'express'
3- import type { ExtendedRequest } from '@/types'
3+ import type { ExtendedRequest , Page , ResolvedArticle } from '@/types'
44import findPage from '@/frame/lib/find-page'
55import resolveRecommended from '../middleware/resolve-recommended'
66
@@ -17,23 +17,38 @@ vi.mock('@/content-render/index', () => ({
1717describe ( 'resolveRecommended middleware' , ( ) => {
1818 const mockFindPage = vi . mocked ( findPage )
1919
20- const createMockRequest = ( pageData : any = { } , contextData : any = { } ) : ExtendedRequest =>
21- ( {
22- context : {
23- page : pageData ,
24- pages : {
20+ type TestPage = Partial < Page > & {
21+ rawRecommended ?: string [ ]
22+ spotlight ?: Array < { article : string } >
23+ }
24+
25+ const createMockRequest = (
26+ pageData : TestPage = { } ,
27+ contextData : Partial < ExtendedRequest [ 'context' ] > & { pages ?: Record < string , Page > } = { } ,
28+ ) : ExtendedRequest => {
29+ const { pages : pagesOverride , ...restContext } = contextData
30+ const hasPagesOverride = Object . prototype . hasOwnProperty . call ( contextData , 'pages' )
31+ const pages = hasPagesOverride
32+ ? pagesOverride
33+ : ( {
2534 '/test-article' : {
2635 title : 'Test Article' ,
2736 intro : 'Test intro' ,
2837 relativePath : 'test/article.md' ,
29- } ,
30- } ,
38+ } as unknown as Page ,
39+ } as Record < string , Page > )
40+
41+ return {
42+ context : {
43+ page : pageData as Page ,
44+ pages,
3145 redirects : { } ,
3246 currentVersion : 'free-pro-team@latest' ,
3347 currentLanguage : 'en' ,
34- ...contextData ,
48+ ...restContext ,
3549 } ,
36- } ) as ExtendedRequest
50+ } as unknown as ExtendedRequest
51+ }
3752
3853 const mockRes = { } as Response
3954 const mockNext = vi . fn ( ) as NextFunction
@@ -86,7 +101,7 @@ describe('resolveRecommended middleware', () => {
86101 applicableVersions : [ 'free-pro-team@latest' ] ,
87102 }
88103
89- mockFindPage . mockReturnValue ( testPage as any )
104+ mockFindPage . mockReturnValue ( testPage as unknown as Page )
90105
91106 const req = createMockRequest ( { rawRecommended : [ '/copilot/tutorials/article' ] } )
92107
@@ -97,7 +112,7 @@ describe('resolveRecommended middleware', () => {
97112 req . context ! . pages ,
98113 req . context ! . redirects ,
99114 )
100- expect ( ( req . context ! . page as any ) . recommended ) . toEqual ( [
115+ expect ( ( req . context ! . page as Page & { recommended ?: ResolvedArticle [ ] } ) . recommended ) . toEqual ( [
101116 {
102117 title : 'Test Article' ,
103118 intro : '<p>Test intro</p>' ,
@@ -116,7 +131,7 @@ describe('resolveRecommended middleware', () => {
116131 applicableVersions : [ 'free-pro-team@latest' ] ,
117132 }
118133
119- mockFindPage . mockReturnValueOnce ( testPage as any )
134+ mockFindPage . mockReturnValueOnce ( testPage as unknown as Page )
120135
121136 const req = createMockRequest ( {
122137 rawRecommended : [ '/copilot/tutorials/article' ] ,
@@ -131,7 +146,7 @@ describe('resolveRecommended middleware', () => {
131146 req . context ! . pages ,
132147 req . context ! . redirects ,
133148 )
134- expect ( ( req . context ! . page as any ) . recommended ) . toEqual ( [
149+ expect ( ( req . context ! . page as Page & { recommended ?: ResolvedArticle [ ] } ) . recommended ) . toEqual ( [
135150 {
136151 title : 'Test Article' ,
137152 intro : '<p>Test intro</p>' ,
@@ -154,7 +169,9 @@ describe('resolveRecommended middleware', () => {
154169 req . context ! . pages ,
155170 req . context ! . redirects ,
156171 )
157- expect ( ( req . context ! . page as any ) . recommended ) . toEqual ( [ ] )
172+ expect ( ( req . context ! . page as Page & { recommended ?: ResolvedArticle [ ] } ) . recommended ) . toEqual (
173+ [ ] ,
174+ )
158175 expect ( mockNext ) . toHaveBeenCalled ( )
159176 } )
160177
@@ -163,11 +180,13 @@ describe('resolveRecommended middleware', () => {
163180 throw new Error ( 'Test error' )
164181 } )
165182
166- const req = createMockRequest ( { rawRecommended : [ '/error-article' ] } )
183+ const req = createMockRequest ( { rawRecommended : [ '/error-article' ] as string [ ] } )
167184
168185 await resolveRecommended ( req , mockRes , mockNext )
169186
170- expect ( ( req . context ! . page as any ) . recommended ) . toEqual ( [ ] )
187+ expect ( ( req . context ! . page as Page & { recommended ?: ResolvedArticle [ ] } ) . recommended ) . toEqual (
188+ [ ] ,
189+ )
171190 expect ( mockNext ) . toHaveBeenCalled ( )
172191 } )
173192
@@ -179,13 +198,13 @@ describe('resolveRecommended middleware', () => {
179198 applicableVersions : [ 'free-pro-team@latest' ] ,
180199 }
181200
182- mockFindPage . mockReturnValueOnce ( testPage as any ) . mockReturnValueOnce ( undefined )
201+ mockFindPage . mockReturnValueOnce ( testPage as unknown as Page ) . mockReturnValueOnce ( undefined )
183202
184203 const req = createMockRequest ( { rawRecommended : [ '/valid-article' , '/invalid-article' ] } )
185204
186205 await resolveRecommended ( req , mockRes , mockNext )
187206
188- expect ( ( req . context ! . page as any ) . recommended ) . toEqual ( [
207+ expect ( ( req . context ! . page as Page & { recommended ?: ResolvedArticle [ ] } ) . recommended ) . toEqual ( [
189208 {
190209 title : 'Valid Article' ,
191210 intro : '<p>Valid intro</p>' ,
@@ -205,7 +224,7 @@ describe('resolveRecommended middleware', () => {
205224 }
206225
207226 // Mock findPage to fail on first call (content-relative) and succeed on second (page-relative)
208- mockFindPage . mockReturnValueOnce ( undefined ) . mockReturnValueOnce ( testPage as any )
227+ mockFindPage . mockReturnValueOnce ( undefined ) . mockReturnValueOnce ( testPage as unknown as Page )
209228
210229 const req = createMockRequest ( {
211230 rawRecommended : [ 'relative-article' ] ,
@@ -225,7 +244,7 @@ describe('resolveRecommended middleware', () => {
225244 req . context ! . pages ,
226245 req . context ! . redirects ,
227246 )
228- expect ( ( req . context ! . page as any ) . recommended ) . toEqual ( [
247+ expect ( ( req . context ! . page as Page & { recommended ?: ResolvedArticle [ ] } ) . recommended ) . toEqual ( [
229248 {
230249 title : 'Relative Article' ,
231250 intro : '<p>Relative intro</p>' ,
@@ -244,7 +263,7 @@ describe('resolveRecommended middleware', () => {
244263 applicableVersions : [ 'free-pro-team@latest' ] ,
245264 }
246265
247- mockFindPage . mockReturnValue ( testPage as any )
266+ mockFindPage . mockReturnValue ( testPage as unknown as Page )
248267
249268 const req = createMockRequest ( { rawRecommended : [ '/copilot/tutorials/tutorial-page' ] } )
250269
@@ -258,7 +277,7 @@ describe('resolveRecommended middleware', () => {
258277
259278 // Verify that the href is a clean path without language/version, that gets
260279 // added on the React side.
261- expect ( ( req . context ! . page as any ) . recommended ) . toEqual ( [
280+ expect ( ( req . context ! . page as Page & { recommended ?: ResolvedArticle [ ] } ) . recommended ) . toEqual ( [
262281 {
263282 title : 'Tutorial Page' ,
264283 intro : '<p>Tutorial intro</p>' ,
@@ -278,7 +297,7 @@ describe('resolveRecommended middleware', () => {
278297 applicableVersions : [ 'free-pro-team@latest' ] , // Not available in ghec
279298 }
280299
281- mockFindPage . mockReturnValue ( fptOnlyPage as any )
300+ mockFindPage . mockReturnValue ( fptOnlyPage as unknown as Page )
282301
283302 // Create a request context where we're viewing the GHEC version
284303 const req = createMockRequest (
@@ -292,7 +311,9 @@ describe('resolveRecommended middleware', () => {
292311 await resolveRecommended ( req , mockRes , mockNext )
293312
294313 // The recommended array should be empty since the article isn't available in enterprise-cloud
295- expect ( ( req . context ! . page as any ) . recommended ) . toEqual ( [ ] )
314+ expect ( ( req . context ! . page as Page & { recommended ?: ResolvedArticle [ ] } ) . recommended ) . toEqual (
315+ [ ] ,
316+ )
296317 expect ( mockNext ) . toHaveBeenCalled ( )
297318 } )
298319} )
0 commit comments