koa-classic-server 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/README.md +44 -120
  2. package/index.cjs +236 -21
  3. package/package.json +10 -5
  4. package/.github/workflows/npm-publish.yml +0 -98
  5. package/CLAUDE.md +0 -101
  6. package/__tests__/benchmark-results-baseline-v1.2.0.txt +0 -354
  7. package/__tests__/benchmark-results-optimized-v2.0.0.txt +0 -354
  8. package/__tests__/benchmark-results-v3.0.0.txt +0 -372
  9. package/__tests__/benchmark.js +0 -239
  10. package/__tests__/caching-headers.test.js +0 -556
  11. package/__tests__/compression-fixtures/data.json +0 -1
  12. package/__tests__/compression-fixtures/large.txt +0 -1
  13. package/__tests__/compression-fixtures/small.txt +0 -1
  14. package/__tests__/compression.test.js +0 -284
  15. package/__tests__/customTest/README.md +0 -6
  16. package/__tests__/customTest/loadConfig.util.js +0 -41
  17. package/__tests__/customTest/serversToLoad.util.js +0 -93
  18. package/__tests__/demo-regex-index.js +0 -140
  19. package/__tests__/deprecation-warnings.test.js +0 -105
  20. package/__tests__/directory-sorting-links.test.js +0 -135
  21. package/__tests__/dt-unknown.test.js +0 -635
  22. package/__tests__/ejs.test.js +0 -299
  23. package/__tests__/hidden-fixtures/.dot-dir/inside.txt +0 -1
  24. package/__tests__/hidden-fixtures/.env +0 -2
  25. package/__tests__/hidden-fixtures/.well-known/acme-challenge.txt +0 -1
  26. package/__tests__/hidden-fixtures/config/secrets/password.txt +0 -1
  27. package/__tests__/hidden-fixtures/data.key +0 -1
  28. package/__tests__/hidden-fixtures/file.secret +0 -1
  29. package/__tests__/hidden-fixtures/index.html +0 -1
  30. package/__tests__/hidden-fixtures/normal.txt +0 -1
  31. package/__tests__/hidden-fixtures/subdir/.env +0 -1
  32. package/__tests__/hidden-fixtures/subdir/regular.txt +0 -1
  33. package/__tests__/hidden-option.test.js +0 -407
  34. package/__tests__/hideExtension.test.js +0 -607
  35. package/__tests__/index-option.test.js +0 -449
  36. package/__tests__/index.test.js +0 -345
  37. package/__tests__/listing.test.js +0 -437
  38. package/__tests__/logger.test.js +0 -232
  39. package/__tests__/performance.test.js +0 -370
  40. package/__tests__/publicWwwTest/cartella/sottocartella/ciao.html +0 -11
  41. package/__tests__/publicWwwTest/cartella/sottocartella/provaEjs/testEjs.ejs +0 -11
  42. package/__tests__/publicWwwTest/cartella vuota con spazi nel nome/file con spazio nel nome .txt +0 -1
  43. package/__tests__/publicWwwTest/cartella vuota con spazi nel nome /file con spazio nel nome .txt +0 -1
  44. package/__tests__/publicWwwTest/ejs-templates/complex.ejs +0 -56
  45. package/__tests__/publicWwwTest/ejs-templates/index.ejs +0 -30
  46. package/__tests__/publicWwwTest/ejs-templates/simple.ejs +0 -13
  47. package/__tests__/publicWwwTest/ejs-templates/with-conditional.ejs +0 -28
  48. package/__tests__/publicWwwTest/ejs-templates/with-escaping.ejs +0 -26
  49. package/__tests__/publicWwwTest/ejs-templates/with-loop.ejs +0 -16
  50. package/__tests__/publicWwwTest/hideext-test/about/index.html +0 -1
  51. package/__tests__/publicWwwTest/hideext-test/about.EJS +0 -1
  52. package/__tests__/publicWwwTest/hideext-test/about.ejs +0 -2
  53. package/__tests__/publicWwwTest/hideext-test/blog/articolo.ejs +0 -2
  54. package/__tests__/publicWwwTest/hideext-test/conflict-test/pagina +0 -1
  55. package/__tests__/publicWwwTest/hideext-test/conflict-test/pagina.ejs +0 -1
  56. package/__tests__/publicWwwTest/hideext-test/file.ejs.bak +0 -1
  57. package/__tests__/publicWwwTest/hideext-test/index.ejs +0 -2
  58. package/__tests__/publicWwwTest/hideext-test/photo.txt +0 -1
  59. package/__tests__/publicWwwTest/hideext-test/sezione/index.ejs +0 -1
  60. package/__tests__/publicWwwTest/hideext-test/style.css +0 -1
  61. package/__tests__/publicWwwTest/ile_vuoto.txt +0 -0
  62. package/__tests__/publicWwwTest/index.html +0 -11
  63. package/__tests__/publicWwwTest/prova file .txt +0 -2
  64. package/__tests__/publicWwwTest/semplicetxt.txt +0 -1
  65. package/__tests__/publicWwwTest/test-page.html +0 -1
  66. package/__tests__/publicWwwTest/test.txt +0 -1
  67. package/__tests__/range-fixtures/sample.txt +0 -1
  68. package/__tests__/range.test.js +0 -223
  69. package/__tests__/security-headers.test.js +0 -165
  70. package/__tests__/security.test.js +0 -322
  71. package/__tests__/server-cache-fixtures/large.txt +0 -1
  72. package/__tests__/server-cache-fixtures/small.txt +0 -1
  73. package/__tests__/server-cache.test.js +0 -594
  74. package/__tests__/setup-benchmark.js +0 -178
  75. package/__tests__/symlink.test.js +0 -441
  76. package/__tests__/template-timeout.test.js +0 -321
  77. package/__tests__/test-regex-quick.js +0 -158
  78. package/__tests__/useOriginalUrl.test.js +0 -213
  79. package/docs/ACTION_PLAN.md +0 -293
  80. package/docs/BENCHMARKS.md +0 -317
  81. package/docs/CHANGELOG.md +0 -880
  82. package/docs/CODE_REVIEW.md +0 -300
  83. package/docs/DEBUG_REPORT.md +0 -593
  84. package/docs/DOCUMENTATION.md +0 -1864
  85. package/docs/EXAMPLES_INDEX_OPTION.md +0 -395
  86. package/docs/FLOW_DIAGRAM.md +0 -954
  87. package/docs/INDEX_OPTION_PRIORITY.md +0 -527
  88. package/docs/OPTIMIZATION_HTTP_CACHING.md +0 -689
  89. package/docs/OPTIMIZATION_ROADMAP_for_V3.md +0 -864
  90. package/docs/PERFORMANCE_ANALYSIS.md +0 -839
  91. package/docs/PERFORMANCE_COMPARISON.md +0 -388
  92. package/docs/noteExports.md +0 -148
  93. package/docs/security_improvement_for_V3.md +0 -421
  94. package/docs/template-engine/TEMPLATE_ENGINE_GUIDE.md +0 -1734
  95. package/docs/template-engine/esempi-incrementali.js +0 -192
  96. package/docs/template-engine/examples/esempio1-nessun-dato.ejs +0 -12
  97. package/docs/template-engine/examples/esempio2-una-variabile.ejs +0 -11
  98. package/docs/template-engine/examples/esempio3-piu-variabili.ejs +0 -15
  99. package/docs/template-engine/examples/esempio4-condizionale.ejs +0 -18
  100. package/docs/template-engine/examples/esempio5-loop.ejs +0 -18
  101. package/docs/template-engine/examples/index-esempi.html +0 -181
  102. package/docs/template-engine/examples/index.html +0 -40
  103. package/docs/template-engine/examples/test.ejs +0 -64
  104. package/eslint.config.mjs +0 -17
  105. package/jest.config.js +0 -18
@@ -1,449 +0,0 @@
1
- /**
2
- * Enhanced Index Option Tests
3
- *
4
- * Tests for the index option that supports:
5
- * - Array of strings
6
- * - Array of RegExp
7
- * - Mixed array (strings + RegExp)
8
- * - Priority handling (first match wins)
9
- *
10
- * v3.0.0: string format removed — passing a non-empty string throws an Error.
11
- */
12
-
13
- const Koa = require('koa');
14
- const supertest = require('supertest');
15
- const koaClassicServer = require('../index.cjs');
16
- const path = require('path');
17
- const fs = require('fs');
18
-
19
- describe('Enhanced Index Option Tests', () => {
20
- let app;
21
- let server;
22
- let tempDir;
23
-
24
- beforeEach(() => {
25
- // Create temporary test directory
26
- tempDir = path.join(__dirname, 'temp-index-test');
27
- if (!fs.existsSync(tempDir)) {
28
- fs.mkdirSync(tempDir, { recursive: true });
29
- }
30
- });
31
-
32
- afterEach(() => {
33
- // Cleanup
34
- if (server) {
35
- server.close();
36
- }
37
- // Remove temp directory
38
- if (fs.existsSync(tempDir)) {
39
- fs.rmSync(tempDir, { recursive: true, force: true });
40
- }
41
- });
42
-
43
- describe('String index — removed in v3.0.0', () => {
44
- test('Non-empty string should throw an Error', () => {
45
- expect(() => {
46
- new Koa().use(koaClassicServer(tempDir, { index: 'index.html' }));
47
- }).toThrow('"index" option no longer accepts a string in v3.0.0');
48
- });
49
-
50
- test('Throw message should include migration hint', () => {
51
- expect(() => {
52
- new Koa().use(koaClassicServer(tempDir, { index: 'default.htm' }));
53
- }).toThrow('index: ["default.htm"]');
54
- });
55
-
56
- test('Empty string should show directory listing (no throw)', async () => {
57
- fs.writeFileSync(path.join(tempDir, 'test.txt'), 'test');
58
-
59
- app = new Koa();
60
- app.use(koaClassicServer(tempDir, { index: '' }));
61
- server = app.listen();
62
-
63
- const res = await supertest(server).get('/');
64
- expect(res.status).toBe(200);
65
- expect(res.text).toContain('Index of');
66
- expect(res.text).toContain('test.txt');
67
- });
68
- });
69
-
70
- describe('Array of Strings - Priority order', () => {
71
- test('Priority order - index1.html searched before index2.html', async () => {
72
- // Create both files with distinctive content
73
- fs.writeFileSync(path.join(tempDir, 'index1.html'), '<h1>FILE 1 - FIRST PRIORITY</h1>');
74
- fs.writeFileSync(path.join(tempDir, 'index2.html'), '<h1>FILE 2 - SECOND PRIORITY</h1>');
75
- fs.writeFileSync(path.join(tempDir, 'index3.html'), '<h1>FILE 3 - THIRD PRIORITY</h1>');
76
-
77
- app = new Koa();
78
- app.use(koaClassicServer(tempDir, {
79
- index: ['index1.html', 'index2.html', 'index3.html']
80
- }));
81
- server = app.listen();
82
-
83
- const res = await supertest(server).get('/');
84
- expect(res.status).toBe(200);
85
- // Must serve index1.html (first in array)
86
- expect(res.text).toContain('FILE 1 - FIRST PRIORITY');
87
- // Must NOT serve index2.html or index3.html
88
- expect(res.text).not.toContain('FILE 2');
89
- expect(res.text).not.toContain('FILE 3');
90
- });
91
-
92
- test('Priority order - index2.html served when index1.html missing', async () => {
93
- // Only create index2.html and index3.html (index1.html missing)
94
- fs.writeFileSync(path.join(tempDir, 'index2.html'), '<h1>FILE 2 - NOW FIRST AVAILABLE</h1>');
95
- fs.writeFileSync(path.join(tempDir, 'index3.html'), '<h1>FILE 3 - STILL THIRD</h1>');
96
-
97
- app = new Koa();
98
- app.use(koaClassicServer(tempDir, {
99
- index: ['index1.html', 'index2.html', 'index3.html']
100
- }));
101
- server = app.listen();
102
-
103
- const res = await supertest(server).get('/');
104
- expect(res.status).toBe(200);
105
- // Must serve index2.html (first available in array)
106
- expect(res.text).toContain('FILE 2 - NOW FIRST AVAILABLE');
107
- // Must NOT serve index3.html
108
- expect(res.text).not.toContain('FILE 3');
109
- });
110
-
111
- test('First match wins - index.html over index.htm', async () => {
112
- fs.writeFileSync(path.join(tempDir, 'index.html'), '<h1>This is HTML version</h1>');
113
- fs.writeFileSync(path.join(tempDir, 'index.htm'), '<h1>This is HTM version</h1>');
114
-
115
- app = new Koa();
116
- app.use(koaClassicServer(tempDir, {
117
- index: ['index.html', 'index.htm']
118
- }));
119
- server = app.listen();
120
-
121
- const res = await supertest(server).get('/');
122
- expect(res.status).toBe(200);
123
- expect(res.text).toContain('This is HTML version');
124
- expect(res.text).not.toContain('This is HTM version');
125
- });
126
-
127
- test('First match wins - index.htm when index.html missing', async () => {
128
- fs.writeFileSync(path.join(tempDir, 'index.htm'), '<h1>HTM</h1>');
129
- fs.writeFileSync(path.join(tempDir, 'default.html'), '<h1>Default</h1>');
130
-
131
- app = new Koa();
132
- app.use(koaClassicServer(tempDir, {
133
- index: ['index.html', 'index.htm', 'default.html']
134
- }));
135
- server = app.listen();
136
-
137
- const res = await supertest(server).get('/');
138
- expect(res.status).toBe(200);
139
- expect(res.text).toContain('HTM');
140
- expect(res.text).not.toContain('Default');
141
- });
142
-
143
- test('Falls back to directory listing when no match', async () => {
144
- fs.writeFileSync(path.join(tempDir, 'other.html'), '<h1>Other</h1>');
145
-
146
- app = new Koa();
147
- app.use(koaClassicServer(tempDir, {
148
- index: ['index.html', 'index.htm']
149
- }));
150
- server = app.listen();
151
-
152
- const res = await supertest(server).get('/');
153
- expect(res.status).toBe(200);
154
- expect(res.text).toContain('Index of');
155
- expect(res.text).toContain('other.html');
156
- });
157
- });
158
-
159
- describe('Array of RegExp - Case insensitive matching', () => {
160
- test('Priority order - First RegExp pattern searched before second', async () => {
161
- // Create files that match different patterns
162
- fs.writeFileSync(path.join(tempDir, 'index1.html'), '<h1>PATTERN 1 MATCH</h1>');
163
- fs.writeFileSync(path.join(tempDir, 'index2.html'), '<h1>PATTERN 2 MATCH</h1>');
164
- fs.writeFileSync(path.join(tempDir, 'index3.html'), '<h1>PATTERN 3 MATCH</h1>');
165
-
166
- app = new Koa();
167
- app.use(koaClassicServer(tempDir, {
168
- index: [
169
- /index1\.html/i, // First pattern - should match index1.html
170
- /index2\.html/i, // Second pattern - should be skipped
171
- /index3\.html/i // Third pattern - should be skipped
172
- ]
173
- }));
174
- server = app.listen();
175
-
176
- const res = await supertest(server).get('/');
177
- expect(res.status).toBe(200);
178
- // Must serve index1.html (first RegExp match)
179
- expect(res.text).toContain('PATTERN 1 MATCH');
180
- // Must NOT serve index2.html or index3.html
181
- expect(res.text).not.toContain('PATTERN 2');
182
- expect(res.text).not.toContain('PATTERN 3');
183
- });
184
-
185
- test('Priority order - Second RegExp when first does not match', async () => {
186
- // index1.html does NOT exist, so first pattern won't match
187
- fs.writeFileSync(path.join(tempDir, 'index2.html'), '<h1>PATTERN 2 NOW FIRST</h1>');
188
- fs.writeFileSync(path.join(tempDir, 'index3.html'), '<h1>PATTERN 3 STILL THIRD</h1>');
189
-
190
- app = new Koa();
191
- app.use(koaClassicServer(tempDir, {
192
- index: [
193
- /index1\.html/i, // First pattern - no match (file doesn't exist)
194
- /index2\.html/i, // Second pattern - should match
195
- /index3\.html/i // Third pattern - should be skipped
196
- ]
197
- }));
198
- server = app.listen();
199
-
200
- const res = await supertest(server).get('/');
201
- expect(res.status).toBe(200);
202
- // Must serve index2.html (first available match)
203
- expect(res.text).toContain('PATTERN 2 NOW FIRST');
204
- // Must NOT serve index3.html
205
- expect(res.text).not.toContain('PATTERN 3');
206
- });
207
-
208
- test('Priority order - Broader pattern searched before narrower pattern', async () => {
209
- // Create multiple files
210
- fs.writeFileSync(path.join(tempDir, 'index.html'), '<h1>HTML FILE</h1>');
211
- fs.writeFileSync(path.join(tempDir, 'index.htm'), '<h1>HTM FILE</h1>');
212
- fs.writeFileSync(path.join(tempDir, 'default.html'), '<h1>DEFAULT FILE</h1>');
213
-
214
- app = new Koa();
215
- app.use(koaClassicServer(tempDir, {
216
- index: [
217
- /index\.(html|htm)/i, // Broader pattern first - matches both .html and .htm
218
- /default\.html/i // Narrower pattern second - should be skipped
219
- ]
220
- }));
221
- server = app.listen();
222
-
223
- const res = await supertest(server).get('/');
224
- expect(res.status).toBe(200);
225
- // Must serve one of: index.html or index.htm (first pattern match)
226
- expect(res.text).toMatch(/HTML FILE|HTM FILE/);
227
- // Must NOT serve default.html
228
- expect(res.text).not.toContain('DEFAULT FILE');
229
- });
230
-
231
- test('RegExp case-insensitive: /index\\.html/i matches INDEX.HTML', async () => {
232
- fs.writeFileSync(path.join(tempDir, 'INDEX.HTML'), '<h1>UPPERCASE INDEX</h1>');
233
-
234
- app = new Koa();
235
- app.use(koaClassicServer(tempDir, {
236
- index: [/index\.html/i]
237
- }));
238
- server = app.listen();
239
-
240
- const res = await supertest(server).get('/');
241
- expect(res.status).toBe(200);
242
- expect(res.text).toContain('UPPERCASE INDEX');
243
- });
244
-
245
- test('RegExp case-insensitive: matches index.HTML, Index.html, INDEX.html', async () => {
246
- fs.writeFileSync(path.join(tempDir, 'Index.Html'), '<h1>Mixed Case Index</h1>');
247
-
248
- app = new Koa();
249
- app.use(koaClassicServer(tempDir, {
250
- index: [/index\.html/i]
251
- }));
252
- server = app.listen();
253
-
254
- const res = await supertest(server).get('/');
255
- expect(res.status).toBe(200);
256
- expect(res.text).toContain('Mixed Case Index');
257
- });
258
-
259
- test('RegExp pattern: /index\\.(html|htm)/i matches both extensions', async () => {
260
- fs.writeFileSync(path.join(tempDir, 'index.HTM'), '<h1>HTM</h1>');
261
-
262
- app = new Koa();
263
- app.use(koaClassicServer(tempDir, {
264
- index: [/index\.(html|htm)/i]
265
- }));
266
- server = app.listen();
267
-
268
- const res = await supertest(server).get('/');
269
- expect(res.status).toBe(200);
270
- expect(res.text).toContain('HTM');
271
- });
272
-
273
- test('RegExp pattern: /index\\.ejs/i matches INDEX.EJS', async () => {
274
- fs.writeFileSync(path.join(tempDir, 'INDEX.EJS'), 'EJS content');
275
-
276
- app = new Koa();
277
- app.use(koaClassicServer(tempDir, {
278
- index: [/index\.ejs/i]
279
- }));
280
- server = app.listen();
281
-
282
- const res = await supertest(server).get('/');
283
- expect(res.status).toBe(200);
284
- const body = res.text !== undefined ? res.text : res.body.toString('utf8');
285
- expect(body).toContain('EJS content');
286
- });
287
- });
288
-
289
- describe('Mixed Array - Strings + RegExp', () => {
290
- test('Priority: String before RegExp', async () => {
291
- fs.writeFileSync(path.join(tempDir, 'index.html'), '<h1>HTML Exact</h1>');
292
- fs.writeFileSync(path.join(tempDir, 'INDEX.HTML'), '<h1>HTML Uppercase</h1>');
293
-
294
- app = new Koa();
295
- app.use(koaClassicServer(tempDir, {
296
- index: ['index.html', /INDEX\.HTML/]
297
- }));
298
- server = app.listen();
299
-
300
- const res = await supertest(server).get('/');
301
- expect(res.status).toBe(200);
302
- expect(res.text).toContain('HTML Exact');
303
- });
304
-
305
- test('Falls back to RegExp when string doesn\'t match', async () => {
306
- fs.writeFileSync(path.join(tempDir, 'INDEX.HTML'), '<h1>HTML Uppercase</h1>');
307
-
308
- app = new Koa();
309
- app.use(koaClassicServer(tempDir, {
310
- index: ['index.html', /INDEX\.HTML/i]
311
- }));
312
- server = app.listen();
313
-
314
- const res = await supertest(server).get('/');
315
- expect(res.status).toBe(200);
316
- expect(res.text).toContain('HTML Uppercase');
317
- });
318
-
319
- test('Complex example: Mixed priorities', async () => {
320
- fs.writeFileSync(path.join(tempDir, 'default.html'), '<h1>Default</h1>');
321
- fs.writeFileSync(path.join(tempDir, 'INDEX.HTML'), '<h1>Uppercase Index</h1>');
322
-
323
- app = new Koa();
324
- app.use(koaClassicServer(tempDir, {
325
- index: [
326
- 'index.html', // 1. Exact match (case-sensitive)
327
- /index\.htm/i, // 2. Case-insensitive index.htm(l)
328
- 'default.html' // 3. default.html
329
- ]
330
- }));
331
- server = app.listen();
332
-
333
- const res = await supertest(server).get('/');
334
- expect(res.status).toBe(200);
335
- // Should match #2 (INDEX.HTML via regex)
336
- expect(res.text).toContain('Uppercase Index');
337
- });
338
- });
339
-
340
- describe('Real-world use cases', () => {
341
- test('Apache-like: index.html, index.htm, index.php', async () => {
342
- fs.writeFileSync(path.join(tempDir, 'index.htm'), '<h1>HTM</h1>');
343
-
344
- app = new Koa();
345
- app.use(koaClassicServer(tempDir, {
346
- index: ['index.html', 'index.htm', 'index.php']
347
- }));
348
- server = app.listen();
349
-
350
- const res = await supertest(server).get('/');
351
- expect(res.status).toBe(200);
352
- expect(res.text).toContain('HTM');
353
- });
354
-
355
- test('Template engines: index.ejs, index.pug, index.html', async () => {
356
- fs.writeFileSync(path.join(tempDir, 'index.pug'), 'pug content');
357
-
358
- app = new Koa();
359
- app.use(koaClassicServer(tempDir, {
360
- index: ['index.ejs', 'index.pug', 'index.html']
361
- }));
362
- server = app.listen();
363
-
364
- const res = await supertest(server).get('/');
365
- expect(res.status).toBe(200);
366
- const body = res.text !== undefined ? res.text : res.body.toString('utf8');
367
- expect(body).toContain('pug content');
368
- });
369
-
370
- test('Case-insensitive filesystem (Windows-like): matches any case', async () => {
371
- fs.writeFileSync(path.join(tempDir, 'InDeX.HtMl'), '<h1>Mixed Case</h1>');
372
-
373
- app = new Koa();
374
- app.use(koaClassicServer(tempDir, {
375
- index: [/index\.html/i]
376
- }));
377
- server = app.listen();
378
-
379
- const res = await supertest(server).get('/');
380
- expect(res.status).toBe(200);
381
- expect(res.text).toContain('Mixed Case');
382
- });
383
- });
384
-
385
- describe('Edge cases', () => {
386
- test('Empty array shows directory listing', async () => {
387
- fs.writeFileSync(path.join(tempDir, 'test.txt'), 'test');
388
-
389
- app = new Koa();
390
- app.use(koaClassicServer(tempDir, { index: [] }));
391
- server = app.listen();
392
-
393
- const res = await supertest(server).get('/');
394
- expect(res.status).toBe(200);
395
- expect(res.text).toContain('Index of');
396
- });
397
-
398
- test('Invalid array elements are filtered out', async () => {
399
- fs.writeFileSync(path.join(tempDir, 'test.txt'), 'test');
400
-
401
- app = new Koa();
402
- app.use(koaClassicServer(tempDir, {
403
- index: ['index.html', 123, null, /notfound/] // Invalid: 123, null; /notfound/ won't match
404
- }));
405
- server = app.listen();
406
-
407
- const res = await supertest(server).get('/');
408
- expect(res.status).toBe(200);
409
- // Should show directory listing (no valid match)
410
- expect(res.text).toContain('Index of');
411
- });
412
-
413
- test('RegExp matches first file when multiple match', async () => {
414
- fs.writeFileSync(path.join(tempDir, 'index.html'), '<h1>HTML</h1>');
415
- fs.writeFileSync(path.join(tempDir, 'index.htm'), '<h1>HTM</h1>');
416
-
417
- app = new Koa();
418
- app.use(koaClassicServer(tempDir, {
419
- index: [/index\.(html|htm)/]
420
- }));
421
- server = app.listen();
422
-
423
- const res = await supertest(server).get('/');
424
- expect(res.status).toBe(200);
425
- // Should match one of them (order depends on readdir)
426
- expect(res.text).toMatch(/HTML|HTM/);
427
- });
428
- });
429
-
430
- describe('Integration with existing index.html tests', () => {
431
- test('Works with array index option for typical setup', async () => {
432
- // Create typical index.html setup
433
- fs.writeFileSync(path.join(tempDir, 'index.html'), '<!DOCTYPE html><html><body><h1>Welcome</h1></body></html>');
434
- fs.writeFileSync(path.join(tempDir, 'other.txt'), 'other file');
435
-
436
- app = new Koa();
437
- app.use(koaClassicServer(tempDir, {
438
- index: ['index.html', 'index.htm', 'default.html']
439
- }));
440
- server = app.listen();
441
-
442
- const res = await supertest(server).get('/');
443
- expect(res.status).toBe(200);
444
- // Should find index.html
445
- expect(res.text).toContain('Welcome');
446
- expect(res.text).toContain('<!DOCTYPE html>');
447
- });
448
- });
449
- });