11import { join , sep } from 'node:path' ;
2- import {
3- makeFileStructure ,
4- makeTestTempDir ,
5- type FilesDefinition ,
6- } from '../../test-helpers/makeFileStructure.mts' ;
2+ import { type FilesDefinition } from '../../test-helpers/makeFileStructure.mts' ;
73import { Negotiator } from '../request/Negotiator.mts' ;
8- import { FileFinder , type FileFinderCore , type FileFinderOptions } from './FileFinder.mts' ;
4+ import type { FileFinder , FileFinderOptions } from './FileFinder.mts' ;
5+ import type { TypedParameters } from 'lean-test' ;
96import 'lean-test' ;
107
11- function fileFinderTestSuite ( isPrecomputed : boolean ) {
12- it ( 'resolves files within a directory' , async ( { getTyped } ) => {
13- const fileFinder = await initialise ( getTyped ( TEST_DIR ) , {
8+ export function fileFinderTestSuite (
9+ initialise : (
10+ ctx : TypedParameters ,
11+ structure : FilesDefinition ,
12+ options ?: FileFinderOptions ,
13+ relativePath ?: string [ ] ,
14+ ) => Promise < FileFinder > ,
15+ getRootDir : ( ctx : TypedParameters ) => string ,
16+ ) {
17+ it ( 'resolves files within a directory' , async ( ctx ) => {
18+ const fileFinder = await initialise ( ctx , {
1419 'one.txt' : 'Content' ,
1520 'two.txt' : 'Other' ,
1621 sub : { 'three.txt' : 'Nested Content' } ,
@@ -23,8 +28,8 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
2328 expect ( one ! . headers [ 'content-language' ] ) . isUndefined ( ) ;
2429 expect ( one ! . headers [ 'content-language' ] ) . isUndefined ( ) ;
2530 expect ( one ! . headers [ 'vary' ] ) . isUndefined ( ) ;
26- expect ( one ! . canonicalPath ) . endsWith ( sep + 'one.txt' ) ;
27- expect ( one ! . negotiatedPath ) . endsWith ( sep + 'one.txt' ) ;
31+ expect ( one ! . canonicalFilename ) . equals ( 'one.txt' ) ;
32+ expect ( one ! . filesystemPath ) . endsWith ( sep + 'one.txt' ) ;
2833 expect ( one ! . stats . size ) . equals ( 7 ) ;
2934 } finally {
3035 one ?. handle . close ( ) ;
@@ -33,8 +38,8 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
3338 const three = await fileFinder . find ( [ 'sub' , 'three.txt' ] ) ;
3439 expect ( three ) . isTruthy ( ) ;
3540 try {
36- expect ( three ! . canonicalPath ) . endsWith ( sep + join ( 'sub' , ' three.txt') ) ;
37- expect ( three ! . negotiatedPath ) . endsWith ( sep + join ( 'sub' , 'three.txt' ) ) ;
41+ expect ( three ! . canonicalFilename ) . equals ( ' three.txt') ;
42+ expect ( three ! . filesystemPath ) . endsWith ( sep + join ( 'sub' , 'three.txt' ) ) ;
3843 expect ( three ! . stats . size ) . equals ( 14 ) ;
3944 } finally {
4045 three ?. handle . close ( ) ;
@@ -43,8 +48,8 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
4348 expect ( await fileExists ( fileFinder , [ 'three.txt' ] ) ) . isFalse ( ) ;
4449 } ) ;
4550
46- it ( 'serves index files if a directory is requested' , async ( { getTyped } ) => {
47- const fileFinder = await initialise ( getTyped ( TEST_DIR ) , {
51+ it ( 'serves index files if a directory is requested' , async ( ctx ) => {
52+ const fileFinder = await initialise ( ctx , {
4853 sub1 : {
4954 'index.htm' : 'Index Content' ,
5055 'foo.htm' : 'Other Content' ,
@@ -55,8 +60,8 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
5560 const index = await fileFinder . find ( [ 'sub1' ] ) ;
5661 expect ( index ) . isTruthy ( ) ;
5762 try {
58- expect ( index ! . canonicalPath ) . endsWith ( sep + join ( 'sub1' , ' index.htm') ) ;
59- expect ( index ! . negotiatedPath ) . endsWith ( sep + join ( 'sub1' , 'index.htm' ) ) ;
63+ expect ( index ! . canonicalFilename ) . equals ( ' index.htm') ;
64+ expect ( index ! . filesystemPath ) . endsWith ( sep + join ( 'sub1' , 'index.htm' ) ) ;
6065 expect ( index ! . stats . size ) . equals ( 13 ) ;
6166 } finally {
6267 index ?. handle . close ( ) ;
@@ -69,16 +74,16 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
6974 expect ( await fileExists ( fileFinder , [ 'sub2' ] ) ) . isFalse ( ) ;
7075 } ) ;
7176
72- it ( 'serves the root index file if the root is requested' , async ( { getTyped } ) => {
73- const fileFinder = await initialise ( getTyped ( TEST_DIR ) , {
77+ it ( 'serves the root index file if the root is requested' , async ( ctx ) => {
78+ const fileFinder = await initialise ( ctx , {
7479 'index.htm' : 'Index Content' ,
7580 } ) ;
7681
7782 const index = await fileFinder . find ( [ ] ) ;
7883 expect ( index ) . isTruthy ( ) ;
7984 try {
80- expect ( index ! . canonicalPath ) . endsWith ( sep + join ( 'index.htm' ) ) ;
81- expect ( index ! . negotiatedPath ) . endsWith ( sep + join ( 'index.htm' ) ) ;
85+ expect ( index ! . canonicalFilename ) . equals ( 'index.htm' ) ;
86+ expect ( index ! . filesystemPath ) . endsWith ( sep + join ( 'index.htm' ) ) ;
8287 expect ( index ! . stats . size ) . equals ( 13 ) ;
8388 } finally {
8489 index ?. handle . close ( ) ;
@@ -88,18 +93,18 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
8893 expect ( await fileExists ( fileFinder , [ 'index.htm' ] ) ) . isFalse ( ) ;
8994 } ) ;
9095
91- it ( 'uses configured index files' , async ( { getTyped } ) => {
96+ it ( 'uses configured index files' , async ( ctx ) => {
9297 const fileFinder = await initialise (
93- getTyped ( TEST_DIR ) ,
98+ ctx ,
9499 { sub : { 'index.htm' : 'Index Content' , 'custom.thing' : 'Custom Content' } } ,
95100 { indexFiles : [ 'custom.thing' ] } ,
96101 ) ;
97102
98103 const index = await fileFinder . find ( [ 'sub' ] ) ;
99104 expect ( index ) . isTruthy ( ) ;
100105 try {
101- expect ( index ! . canonicalPath ) . endsWith ( sep + join ( 'sub' , ' custom.thing') ) ;
102- expect ( index ! . negotiatedPath ) . endsWith ( sep + join ( 'sub' , 'custom.thing' ) ) ;
106+ expect ( index ! . canonicalFilename ) . equals ( ' custom.thing') ;
107+ expect ( index ! . filesystemPath ) . endsWith ( sep + join ( 'sub' , 'custom.thing' ) ) ;
103108 expect ( index ! . stats . size ) . equals ( 14 ) ;
104109 } finally {
105110 index ?. handle . close ( ) ;
@@ -109,27 +114,27 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
109114 expect ( await fileExists ( fileFinder , [ 'sub' , 'custom.thing' ] ) ) . isFalse ( ) ;
110115 } ) ;
111116
112- it ( 'prioritises index files by their configured order' , async ( { getTyped } ) => {
117+ it ( 'prioritises index files by their configured order' , async ( ctx ) => {
113118 const fileFinder = await initialise (
114- getTyped ( TEST_DIR ) ,
119+ ctx ,
115120 { a : 'nope' , m : 'yep' , z : 'nope' } ,
116121 { indexFiles : [ 'm' , 'a' , 'z' ] } ,
117122 ) ;
118123
119124 const index = await fileFinder . find ( [ ] ) ;
120125 expect ( index ) . isTruthy ( ) ;
121126 try {
122- expect ( index ! . canonicalPath ) . endsWith ( sep + 'm' ) ;
123- expect ( index ! . negotiatedPath ) . endsWith ( sep + 'm' ) ;
127+ expect ( index ! . canonicalFilename ) . equals ( 'm' ) ;
128+ expect ( index ! . filesystemPath ) . endsWith ( sep + 'm' ) ;
124129 expect ( index ! . stats . size ) . equals ( 3 ) ;
125130 } finally {
126131 index ?. handle . close ( ) ;
127132 }
128133 } ) ;
129134
130- it ( 'uses configured suffixes if the requested file does not exist' , async ( { getTyped } ) => {
135+ it ( 'uses configured suffixes if the requested file does not exist' , async ( ctx ) => {
131136 const fileFinder = await initialise (
132- getTyped ( TEST_DIR ) ,
137+ ctx ,
133138 {
134139 'file.foo' : 'Foo' ,
135140 'other.bar' : 'Bar' ,
@@ -144,8 +149,8 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
144149 const f1 = await fileFinder . find ( [ 'file' ] ) ;
145150 expect ( f1 ) . isTruthy ( ) ;
146151 try {
147- expect ( f1 ! . canonicalPath ) . endsWith ( sep + 'file.foo' ) ;
148- expect ( f1 ! . negotiatedPath ) . endsWith ( sep + 'file.foo' ) ;
152+ expect ( f1 ! . canonicalFilename ) . equals ( 'file.foo' ) ;
153+ expect ( f1 ! . filesystemPath ) . endsWith ( sep + 'file.foo' ) ;
149154 expect ( f1 ! . stats . size ) . equals ( 3 ) ;
150155 } finally {
151156 f1 ?. handle . close ( ) ;
@@ -154,8 +159,8 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
154159 const f2 = await fileFinder . find ( [ 'other' ] ) ;
155160 expect ( f2 ) . isTruthy ( ) ;
156161 try {
157- expect ( f2 ! . canonicalPath ) . endsWith ( sep + 'other.bar' ) ;
158- expect ( f2 ! . negotiatedPath ) . endsWith ( sep + 'other.bar' ) ;
162+ expect ( f2 ! . canonicalFilename ) . equals ( 'other.bar' ) ;
163+ expect ( f2 ! . filesystemPath ) . endsWith ( sep + 'other.bar' ) ;
159164 expect ( f2 ! . stats . size ) . equals ( 3 ) ;
160165 } finally {
161166 f2 ?. handle . close ( ) ;
@@ -164,8 +169,8 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
164169 const f3 = await fileFinder . find ( [ 'raw' ] ) ;
165170 expect ( f3 ) . isTruthy ( ) ;
166171 try {
167- expect ( f3 ! . canonicalPath ) . endsWith ( sep + 'raw' ) ;
168- expect ( f3 ! . negotiatedPath ) . endsWith ( sep + 'raw' ) ;
172+ expect ( f3 ! . canonicalFilename ) . equals ( 'raw' ) ;
173+ expect ( f3 ! . filesystemPath ) . endsWith ( sep + 'raw' ) ;
169174 expect ( f3 ! . stats . size ) . equals ( 6 ) ;
170175 } finally {
171176 f3 ?. handle . close ( ) ;
@@ -177,34 +182,34 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
177182 expect ( await fileExists ( fileFinder , [ 'sub' , 'custom.thing' ] ) ) . isFalse ( ) ;
178183 } ) ;
179184
180- it ( 'prioritises suffixes by their configured order' , async ( { getTyped } ) => {
185+ it ( 'prioritises suffixes by their configured order' , async ( ctx ) => {
181186 const fileFinder = await initialise (
182- getTyped ( TEST_DIR ) ,
187+ ctx ,
183188 { aa : 'nope' , am : 'yep' , az : 'nope' } ,
184189 { implicitSuffixes : [ 'm' , 'a' , 'z' ] } ,
185190 ) ;
186191
187192 const index = await fileFinder . find ( [ 'a' ] ) ;
188193 expect ( index ) . isTruthy ( ) ;
189194 try {
190- expect ( index ! . canonicalPath ) . endsWith ( sep + 'am' ) ;
191- expect ( index ! . negotiatedPath ) . endsWith ( sep + 'am' ) ;
195+ expect ( index ! . canonicalFilename ) . equals ( 'am' ) ;
196+ expect ( index ! . filesystemPath ) . endsWith ( sep + 'am' ) ;
192197 expect ( index ! . stats . size ) . equals ( 3 ) ;
193198 } finally {
194199 index ?. handle . close ( ) ;
195200 }
196201 } ) ;
197202
198- it ( 'does not allow access to files outside the directory' , async ( props ) => {
199- const dir = props . getTyped ( TEST_DIR ) ;
203+ it ( 'does not allow access to files outside the directory' , async ( ctx ) => {
204+ const dir = getRootDir ( ctx ) ;
200205 const fileFinder = await initialise (
201- dir ,
206+ ctx ,
202207 {
203208 'one.txt' : 'Blocked Content' ,
204209 sub : { 'ok.txt' : 'Permitted Content' } ,
205210 } ,
206211 { } ,
207- 'sub' ,
212+ [ 'sub' ] ,
208213 ) ;
209214
210215 expect ( await fileExists ( fileFinder , [ 'one.txt' ] ) ) . isFalse ( ) ;
@@ -221,9 +226,11 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
221226 }
222227 } ) ;
223228
224- it ( 'does not disclose the root path' , async ( props ) => {
225- const dir = props . getTyped ( TEST_DIR ) ;
226- const fileFinder = await initialise ( dir , { sub : { 'ok.txt' : 'Permitted Content' } } , { } , 'sub' ) ;
229+ it ( 'does not disclose the root path' , async ( ctx ) => {
230+ const dir = getRootDir ( ctx ) ;
231+ const fileFinder = await initialise ( ctx , { sub : { 'ok.txt' : 'Permitted Content' } } , { } , [
232+ 'sub' ,
233+ ] ) ;
227234
228235 expect ( await fileExists ( fileFinder , [ '..' , 'sub' , 'ok.txt' ] ) ) . isFalse ( ) ;
229236 expect ( await fileExists ( fileFinder , [ '../sub/ok.txt' ] ) ) . isFalse ( ) ;
@@ -233,8 +240,8 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
233240 expect ( await fileExists ( fileFinder , [ join ( dir , 'sub' , 'ok.txt' ) ] ) ) . isFalse ( ) ;
234241 } ) ;
235242
236- it ( 'does not allow access to special files by default' , async ( { getTyped } ) => {
237- const fileFinder = await initialise ( getTyped ( TEST_DIR ) , {
243+ it ( 'does not allow access to special files by default' , async ( ctx ) => {
244+ const fileFinder = await initialise ( ctx , {
238245 '.dot' : 'Blocked Content' ,
239246 '~tilde' : 'Blocked Content' ,
240247 'tilde~' : 'Blocked Content' ,
@@ -256,8 +263,8 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
256263 }
257264 } ) ;
258265
259- it ( 'is case sensitive by default' , async ( { getTyped } ) => {
260- const fileFinder = await initialise ( getTyped ( TEST_DIR ) , {
266+ it ( 'is case sensitive by default' , async ( ctx ) => {
267+ const fileFinder = await initialise ( ctx , {
261268 'one.txt' : 'Content' ,
262269 'TWO.txt' : 'Other' ,
263270 Sub : { 'three.txt' : 'Nested Content' } ,
@@ -270,9 +277,9 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
270277 expect ( await fileExists ( fileFinder , [ 'Sub' , 'three.txt' ] ) ) . isTrue ( ) ;
271278 } ) ;
272279
273- it ( 'forces all paths lowercase if configured' , async ( { getTyped } ) => {
280+ it ( 'forces all paths lowercase if configured' , async ( ctx ) => {
274281 const fileFinder = await initialise (
275- getTyped ( TEST_DIR ) ,
282+ ctx ,
276283 {
277284 'one.txt' : 'Content' ,
278285 sub : { 'two.txt' : 'Nested Content' } ,
@@ -286,9 +293,9 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
286293 expect ( await fileExists ( fileFinder , [ 'Sub' , 'two.TXT' ] ) ) . isTrue ( ) ;
287294 } ) ;
288295
289- it ( 'returns specific file variants if negotiated' , async ( { getTyped } ) => {
296+ it ( 'returns specific file variants if negotiated' , async ( ctx ) => {
290297 const fileFinder = await initialise (
291- getTyped ( TEST_DIR ) ,
298+ ctx ,
292299 {
293300 'one.txt' : 'Content' ,
294301 'one.txt.gz' : 'Compressed Content' ,
@@ -308,8 +315,8 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
308315 expect ( withGzip ! . headers [ 'content-language' ] ) . isUndefined ( ) ;
309316 expect ( withGzip ! . headers [ 'content-encoding' ] ) . equals ( 'gzip' ) ;
310317 expect ( withGzip ! . headers [ 'vary' ] ) . equals ( 'accept-encoding' ) ;
311- expect ( withGzip ! . canonicalPath ) . endsWith ( sep + 'one.txt' ) ;
312- expect ( withGzip ! . negotiatedPath ) . endsWith ( sep + 'one.txt.gz' ) ;
318+ expect ( withGzip ! . canonicalFilename ) . equals ( 'one.txt' ) ;
319+ expect ( withGzip ! . filesystemPath ) . endsWith ( sep + 'one.txt.gz' ) ;
313320 expect ( withGzip ! . stats . size ) . equals ( 18 ) ;
314321 } finally {
315322 withGzip ?. handle . close ( ) ;
@@ -322,8 +329,8 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
322329 expect ( withoutGzip ! . headers [ 'content-language' ] ) . isUndefined ( ) ;
323330 expect ( withoutGzip ! . headers [ 'content-encoding' ] ) . isUndefined ( ) ;
324331 expect ( withoutGzip ! . headers [ 'vary' ] ) . equals ( 'accept-encoding' ) ;
325- expect ( withoutGzip ! . canonicalPath ) . endsWith ( sep + 'one.txt' ) ;
326- expect ( withoutGzip ! . negotiatedPath ) . endsWith ( sep + 'one.txt' ) ;
332+ expect ( withoutGzip ! . canonicalFilename ) . equals ( 'one.txt' ) ;
333+ expect ( withoutGzip ! . filesystemPath ) . endsWith ( sep + 'one.txt' ) ;
327334 expect ( withoutGzip ! . stats . size ) . equals ( 7 ) ;
328335 } finally {
329336 withoutGzip ?. handle . close ( ) ;
@@ -336,52 +343,16 @@ function fileFinderTestSuite(isPrecomputed: boolean) {
336343 expect ( noGzip ! . headers [ 'content-language' ] ) . isUndefined ( ) ;
337344 expect ( noGzip ! . headers [ 'content-encoding' ] ) . isUndefined ( ) ;
338345 expect ( noGzip ! . headers [ 'vary' ] ) . equals ( 'accept-encoding' ) ;
339- expect ( noGzip ! . canonicalPath ) . endsWith ( sep + 'two.txt' ) ;
340- expect ( noGzip ! . negotiatedPath ) . endsWith ( sep + 'two.txt' ) ;
346+ expect ( noGzip ! . canonicalFilename ) . equals ( 'two.txt' ) ;
347+ expect ( noGzip ! . filesystemPath ) . endsWith ( sep + 'two.txt' ) ;
341348 expect ( noGzip ! . stats . size ) . equals ( 7 ) ;
342349 } finally {
343350 noGzip ?. handle . close ( ) ;
344351 }
345352 } ) ;
346-
347- describe ( 'debugAllPaths' , ( ) => {
348- it ( 'returns a set of all recognised paths' , async ( { getTyped } ) => {
349- const fileFinder = await initialise ( getTyped ( TEST_DIR ) , {
350- 'foo.txt' : 'Hello' ,
351- sub1 : {
352- 'index.htm' : 'Index Content' ,
353- 'foo.htm' : 'Other Content' ,
354- } ,
355- sub2 : { 'nope.htm' : 'Nested Content' } ,
356- } ) ;
357-
358- const paths = await fileFinder . debugAllPaths ( ) ;
359- expect ( paths ) . equals ( new Set ( [ 'foo.txt' , 'sub1' , 'sub1/foo.htm' , 'sub2/nope.htm' ] ) ) ;
360- } ) ;
361- } ) ;
362-
363- const TEST_DIR = makeTestTempDir ( 'ff-' ) ;
364-
365- async function initialise (
366- dir : string ,
367- structure : FilesDefinition ,
368- options : FileFinderOptions = { } ,
369- relativePath = '' ,
370- ) {
371- await makeFileStructure ( dir , structure ) ;
372- const fileFinder = await FileFinder . build ( join ( dir , relativePath ) , options ) ;
373- if ( isPrecomputed ) {
374- return fileFinder . precompute ( ) ;
375- } else {
376- return fileFinder ;
377- }
378- }
379353}
380354
381- describe ( 'FileFinder (Dynamic)' , ( ) => fileFinderTestSuite ( false ) ) ;
382- describe ( 'FileFinder (Precomputed)' , ( ) => fileFinderTestSuite ( true ) ) ;
383-
384- async function fileExists ( fileFinder : FileFinderCore , path : string [ ] ) {
355+ async function fileExists ( fileFinder : FileFinder , path : string [ ] ) {
385356 const file = await fileFinder . find ( path ) ;
386357 const exists = Boolean ( file ) ;
387358 file ?. handle . close ( ) ;
0 commit comments