@@ -2,13 +2,13 @@ import { expect, use } from "chai";
2
2
import { glob } from "glob" ;
3
3
import { join , normalize , relative } from "path" ;
4
4
import { readFileSync } from "fs" ;
5
- import fetch from "node-fetch" ;
6
5
import type { NextConfig } from "next" ;
7
6
import * as deepEqualUnordered from "deep-equal-in-any-order" ;
8
7
use ( deepEqualUnordered ) ;
9
8
10
9
import { getBuildId } from "../../src/frameworks/next/utils" ;
11
10
import { fileExistsSync } from "../../src/fsutils" ;
11
+ import { IS_WINDOWS } from "../../src/utils" ;
12
12
import { readFile } from "fs/promises" ;
13
13
14
14
const NEXT_OUTPUT_PATH = `${ __dirname } /.firebase/demo-nextjs` ;
@@ -21,6 +21,7 @@ const I18N_BASE = "";
21
21
const DEFAULT_LANG = "en" ;
22
22
const LOG_FILE = "firebase-debug.log" ;
23
23
const NEXT_SOURCE = `${ __dirname } /nextjs` ;
24
+ const PATH_SEPARATOR = IS_WINDOWS ? `\\\\` : `\/` ;
24
25
25
26
async function getFilesListFromDir ( dir : string ) : Promise < string [ ] > {
26
27
const files = await glob ( `${ dir } /**/*` , { nodir : true } ) ;
@@ -167,7 +168,7 @@ describe("webframeworks", function (this) {
167
168
i18n : {
168
169
root : "/" ,
169
170
} ,
170
- public : ".firebase/ demo-nextjs/ hosting" ,
171
+ public : join ( ".firebase" , " demo-nextjs" , " hosting") ,
171
172
webFramework : "next_ssr" ,
172
173
} ,
173
174
{
@@ -200,7 +201,7 @@ describe("webframeworks", function (this) {
200
201
i18n : {
201
202
root : "/" ,
202
203
} ,
203
- public : ".firebase/ demo-angular/ hosting" ,
204
+ public : join ( ".firebase" , " demo-angular" , " hosting") ,
204
205
webFramework : "angular_ssr" ,
205
206
} ,
206
207
] ,
@@ -212,11 +213,11 @@ describe("webframeworks", function (this) {
212
213
} ,
213
214
{
214
215
codebase : "firebase-frameworks-demo-nextjs" ,
215
- source : ".firebase/ demo-nextjs/ functions" ,
216
+ source : join ( ".firebase" , " demo-nextjs" , " functions") ,
216
217
} ,
217
218
{
218
219
codebase : "firebase-frameworks-demo-angular" ,
219
- source : ".firebase/ demo-angular/ functions" ,
220
+ source : join ( ".firebase" , " demo-angular" , " functions") ,
220
221
} ,
221
222
] ,
222
223
} ) ;
@@ -227,13 +228,23 @@ describe("webframeworks", function (this) {
227
228
describe ( "app directory" , ( ) => {
228
229
it ( "should have working static routes" , async ( ) => {
229
230
const apiStaticJSON = JSON . parse (
230
- readFileSync ( `${ NEXT_OUTPUT_PATH } /hosting/${ NEXT_BASE_PATH } /app/api/static` ) . toString ( ) ,
231
+ readFileSync (
232
+ join ( NEXT_OUTPUT_PATH , "hosting" , NEXT_BASE_PATH , "app" , "api" , "static" ) ,
233
+ ) . toString ( ) ,
231
234
) ;
232
235
const apiStaticResponse = await fetch ( `${ NEXTJS_HOST } /app/api/static` ) ;
236
+
237
+ const jsonResponse = await apiStaticResponse . json ( ) ;
238
+
233
239
expect ( apiStaticResponse . ok ) . to . be . true ;
234
- expect ( apiStaticResponse . headers . get ( "content-type" ) ) . to . eql ( "application/json" ) ;
235
- expect ( apiStaticResponse . headers . get ( "custom-header" ) ) . to . eql ( "custom-value" ) ;
236
- expect ( await apiStaticResponse . json ( ) ) . to . eql ( apiStaticJSON ) ;
240
+
241
+ // TODO(leoortizz|jamesdaniels): Figure out why custom headers aren't working with emulators on Windows
242
+ if ( ! IS_WINDOWS ) {
243
+ expect ( apiStaticResponse . headers . get ( "content-type" ) ) . to . eql ( "application/json" ) ;
244
+ expect ( apiStaticResponse . headers . get ( "custom-header" ) ) . to . eql ( "custom-value" ) ;
245
+ }
246
+
247
+ expect ( jsonResponse ) . to . eql ( apiStaticJSON ) ;
237
248
} ) ;
238
249
239
250
it ( "should have working SSG" , async ( ) => {
@@ -242,7 +253,7 @@ describe("webframeworks", function (this) {
242
253
const fooResponseText = await fooResponse . text ( ) ;
243
254
244
255
const fooHtml = readFileSync (
245
- ` ${ NEXT_OUTPUT_PATH } / hosting/ ${ NEXT_BASE_PATH } / app/ ssg.html` ,
256
+ join ( NEXT_OUTPUT_PATH , " hosting" , NEXT_BASE_PATH , " app" , " ssg.html" ) ,
246
257
) . toString ( ) ;
247
258
expect ( fooHtml ) . to . eql ( fooResponseText ) ;
248
259
} ) ;
@@ -331,42 +342,50 @@ describe("webframeworks", function (this) {
331
342
const EXPECTED_FILES = [ "" , "en" , "fr" ]
332
343
. flatMap ( ( locale ) => [
333
344
...( locale
334
- ? [
335
- `/${ NEXT_BASE_PATH } /_next/data/${ buildId } /${ locale } /pages/fallback/1.json` ,
336
- `/${ NEXT_BASE_PATH } /_next/data/${ buildId } /${ locale } /pages/fallback/2.json` ,
337
- ]
345
+ ? [ 1 , 2 ] . map ( ( num ) =>
346
+ join (
347
+ NEXT_BASE_PATH ,
348
+ "_next" ,
349
+ "data" ,
350
+ buildId ,
351
+ locale ,
352
+ "pages" ,
353
+ "fallback" ,
354
+ `${ num } .json` ,
355
+ ) ,
356
+ )
338
357
: [
339
- `/ ${ NEXT_BASE_PATH } / _next/ data/ ${ buildId } / pages/ ssg.json` ,
340
- `/ ${ NEXT_BASE_PATH } / _next/ static/ ${ buildId } / _buildManifest.js` ,
341
- `/ ${ NEXT_BASE_PATH } / _next/ static/ ${ buildId } / _ssgManifest.js` ,
342
- `/ ${ NEXT_BASE_PATH } / app/ api/ static` ,
343
- `/ ${ NEXT_BASE_PATH } / app/ image.html` ,
344
- `/ ${ NEXT_BASE_PATH } / app/ ssg.html` ,
345
- `/ ${ NEXT_BASE_PATH } / 404.html` ,
358
+ join ( NEXT_BASE_PATH , " _next" , " data" , buildId , " pages" , " ssg.json" ) ,
359
+ join ( NEXT_BASE_PATH , " _next" , " static" , buildId , " _buildManifest.js" ) ,
360
+ join ( NEXT_BASE_PATH , " _next" , " static" , buildId , " _ssgManifest.js" ) ,
361
+ join ( NEXT_BASE_PATH , " app" , " api" , " static" ) ,
362
+ join ( NEXT_BASE_PATH , " app" , " image.html" ) ,
363
+ join ( NEXT_BASE_PATH , " app" , " ssg.html" ) ,
364
+ join ( NEXT_BASE_PATH , " 404.html" ) ,
346
365
] ) ,
347
- `/ ${ I18N_BASE } / ${ locale } / ${ NEXT_BASE_PATH } / pages/ fallback/ 1.html` ,
348
- `/ ${ I18N_BASE } / ${ locale } / ${ NEXT_BASE_PATH } / pages/ fallback/ 2.html` ,
349
- `/ ${ I18N_BASE } / ${ locale } / ${ NEXT_BASE_PATH } / pages/ ssg.html` ,
366
+ join ( I18N_BASE , locale , NEXT_BASE_PATH , " pages" , " fallback" , " 1.html" ) ,
367
+ join ( I18N_BASE , locale , NEXT_BASE_PATH , " pages" , " fallback" , " 2.html" ) ,
368
+ join ( I18N_BASE , locale , NEXT_BASE_PATH , " pages" , " ssg.html" ) ,
350
369
// TODO(jamesdaniels) figure out why 404 isn't being translated
351
370
// `/${I18N_BASE}/${locale}/${NEXT_BASE_PATH}/404.html`,
352
- `/ ${ I18N_BASE } / ${ locale } / ${ NEXT_BASE_PATH } / 500.html` ,
353
- `/ ${ I18N_BASE } / ${ locale } / ${ NEXT_BASE_PATH } / index.html` ,
371
+ join ( I18N_BASE , locale , NEXT_BASE_PATH , " 500.html" ) ,
372
+ join ( I18N_BASE , locale , NEXT_BASE_PATH , " index.html" ) ,
354
373
] )
355
374
. map ( normalize )
356
375
. map ( ( it ) => ( it . startsWith ( "/" ) ? it . substring ( 1 ) : it ) ) ;
357
376
358
377
const EXPECTED_PATTERNS = [
359
- ` ${ NEXT_BASE_PATH } \/ _next\/ static\/ chunks\/ [^-]+-[^\ .]+\ .js`,
360
- ` ${ NEXT_BASE_PATH } \/ _next\/ static\/ chunks\/ app\/ layout-[^\ .]+\ .js`,
361
- ` ${ NEXT_BASE_PATH } \/ _next\/ static\/ chunks\/ main-[^\ .]+\ .js`,
362
- ` ${ NEXT_BASE_PATH } \/ _next\/ static\/ chunks\/ main-app-[^\ .]+\ .js`,
363
- ` ${ NEXT_BASE_PATH } \/ _next\/ static\/ chunks\/ pages\/ _app-[^\ .]+\ .js`,
364
- ` ${ NEXT_BASE_PATH } \/ _next\/ static\/ chunks\/ pages\/ _error-[^\ .]+\ .js`,
365
- ` ${ NEXT_BASE_PATH } \/ _next\/ static\/ chunks\/ pages\/ index-[^\ .]+\ .js`,
366
- ` ${ NEXT_BASE_PATH } \/ _next\/ static\/ chunks\/ polyfills-[^\ .]+\ .js`,
367
- ` ${ NEXT_BASE_PATH } \/ _next\/ static\/ chunks\/ webpack-[^\ .]+\ .js`,
368
- ` ${ NEXT_BASE_PATH } \/ _next\/ static\/ css\/[^\ .]+\ .css`,
369
- ] . map ( ( it ) => new RegExp ( it ) ) ;
378
+ [ NEXT_BASE_PATH , " _next" , " static" , " chunks" , ` [^-]+-[^.]+.js`] ,
379
+ [ NEXT_BASE_PATH , " _next" , " static" , " chunks" , " app" , ` layout-[^.]+.js`] ,
380
+ [ NEXT_BASE_PATH , " _next" , " static" , " chunks" , ` main-[^.]+.js`] ,
381
+ [ NEXT_BASE_PATH , " _next" , " static" , " chunks" , ` main-app-[^.]+.js`] ,
382
+ [ NEXT_BASE_PATH , " _next" , " static" , " chunks" , " pages" , ` _app-[^.]+.js`] ,
383
+ [ NEXT_BASE_PATH , " _next" , " static" , " chunks" , " pages" , ` _error-[^.]+.js`] ,
384
+ [ NEXT_BASE_PATH , " _next" , " static" , " chunks" , " pages" , ` index-[^.]+.js`] ,
385
+ [ NEXT_BASE_PATH , " _next" , " static" , " chunks" , ` polyfills-[^.]+.js`] ,
386
+ [ NEXT_BASE_PATH , " _next" , " static" , " chunks" , ` webpack-[^.]+.js`] ,
387
+ [ NEXT_BASE_PATH , " _next" , " static" , " css" , `[^ .]+.css`] ,
388
+ ] . map ( ( it ) => new RegExp ( it . filter ( Boolean ) . join ( PATH_SEPARATOR ) ) ) ;
370
389
371
390
const files = await getFilesListFromDir ( `${ NEXT_OUTPUT_PATH } /hosting` ) ;
372
391
const unmatchedFiles = files . filter (
@@ -435,25 +454,22 @@ describe("webframeworks", function (this) {
435
454
it ( "should have the expected static files to be deployed" , async ( ) => {
436
455
const EXPECTED_FILES = [ "" , "en" , "fr" , "es" ]
437
456
. flatMap ( ( locale ) => [
438
- `/ ${ I18N_BASE } / ${ locale } / ${ ANGULAR_BASE_PATH } / index.html` ,
439
- `/ ${ I18N_BASE } / ${ locale } / ${ ANGULAR_BASE_PATH } / 3rdpartylicenses.txt` ,
440
- `/ ${ I18N_BASE } / ${ locale } / ${ ANGULAR_BASE_PATH } / favicon.ico` ,
441
- `/ ${ I18N_BASE } / ${ locale } / ${ ANGULAR_BASE_PATH } / index.original.html` ,
442
- `/ ${ I18N_BASE } / ${ locale } / ${ ANGULAR_BASE_PATH } / 3rdpartylicenses.txt` ,
457
+ join ( I18N_BASE , locale , ANGULAR_BASE_PATH , " index.html" ) ,
458
+ join ( I18N_BASE , locale , ANGULAR_BASE_PATH , " 3rdpartylicenses.txt" ) ,
459
+ join ( I18N_BASE , locale , ANGULAR_BASE_PATH , " favicon.ico" ) ,
460
+ join ( I18N_BASE , locale , ANGULAR_BASE_PATH , " index.original.html" ) ,
461
+ join ( I18N_BASE , locale , ANGULAR_BASE_PATH , " 3rdpartylicenses.txt" ) ,
443
462
] )
444
- . map ( normalize )
445
- . map ( ( it ) => ( it . startsWith ( "/" ) ? it . substring ( 1 ) : it ) ) ;
463
+ . map ( normalize ) ;
446
464
447
465
const EXPECTED_PATTERNS = [ "" , "en" , "fr" , "es" ]
448
466
. flatMap ( ( locale ) => [
449
- `/ ${ I18N_BASE } / ${ locale } / ${ ANGULAR_BASE_PATH } / main\.[^\.]+\.js`,
450
- `/ ${ I18N_BASE } / ${ locale } / ${ ANGULAR_BASE_PATH } / polyfills\.[^\.]+\.js`,
451
- `/ ${ I18N_BASE } / ${ locale } / ${ ANGULAR_BASE_PATH } / runtime\.[^\.]+\.js`,
452
- `/ ${ I18N_BASE } / ${ locale } / ${ ANGULAR_BASE_PATH } / styles\.[^\.]+\.css`,
467
+ [ I18N_BASE , locale , ANGULAR_BASE_PATH , ` main\.[^\.]+\.js`] ,
468
+ [ I18N_BASE , locale , ANGULAR_BASE_PATH , ` polyfills\.[^\.]+\.js`] ,
469
+ [ I18N_BASE , locale , ANGULAR_BASE_PATH , ` runtime\.[^\.]+\.js`] ,
470
+ [ I18N_BASE , locale , ANGULAR_BASE_PATH , ` styles\.[^\.]+\.css`] ,
453
471
] )
454
- . map ( normalize )
455
- . map ( ( it ) => ( it . startsWith ( "/" ) ? it . substring ( 1 ) : it ) )
456
- . map ( ( it ) => new RegExp ( it . replace ( "/" , "\\/" ) ) ) ;
472
+ . map ( ( it ) => new RegExp ( it . filter ( Boolean ) . join ( PATH_SEPARATOR ) ) ) ;
457
473
458
474
const files = await getFilesListFromDir ( `${ ANGULAR_OUTPUT_PATH } /hosting` ) ;
459
475
const unmatchedFiles = files . filter (
0 commit comments