Skip to content

Commit 7924e7b

Browse files
committed
add unit tests for next config overrides
1 parent e4c1966 commit 7924e7b

File tree

3 files changed

+211
-6
lines changed

3 files changed

+211
-6
lines changed

packages/@apphosting/adapter-nextjs/src/bin/build.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ if (!process.env.FRAMEWORK_VERSION) {
2222
}
2323

2424
const { distDir, configFileName } = await loadConfig(root, opts.projectDirectory);
25-
await overrideNextConfig(configFileName);
25+
await overrideNextConfig(root, configFileName);
2626
await runBuild();
2727

2828
const adapterMetadata = getAdapterMetadata();

packages/@apphosting/adapter-nextjs/src/overrides.spec.ts

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,209 @@ describe("route overrides", () => {
163163
fs.rmSync(tmpDir, { recursive: true, force: true });
164164
});
165165
});
166+
167+
describe("next config overrides", () => {
168+
let tmpDir: string;
169+
170+
beforeEach(() => {
171+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "test-overrides"));
172+
});
173+
174+
it("should set images.unoptimized to true - js normal config", async () => {
175+
const { overrideNextConfig } = await importOverrides;
176+
const originalConfig = `
177+
// @ts-check
178+
179+
/** @type {import('next').NextConfig} */
180+
const nextConfig = {
181+
/* config options here */
182+
}
183+
184+
module.exports = nextConfig
185+
`;
186+
187+
fs.writeFileSync(path.join(tmpDir, "next.config.js"), originalConfig);
188+
await overrideNextConfig(tmpDir, "next.config.js");
189+
190+
const updatedConfig = fs.readFileSync(path.join(tmpDir, "next.config.js"), "utf-8");
191+
192+
assert.equal(
193+
normalizeWhitespace(updatedConfig),
194+
normalizeWhitespace(`
195+
const originalConfig = require('./next.config.original.js');
196+
197+
// This file was automatically generated by Firebase App Hosting adapter
198+
const config = typeof originalConfig === 'function'
199+
? (...args) => {
200+
const resolvedConfig = originalConfig(...args);
201+
return {
202+
...resolvedConfig,
203+
images: {
204+
...(resolvedConfig.images || {}),
205+
unoptimized: true,
206+
},
207+
};
208+
}
209+
: {
210+
...originalConfig,
211+
images: {
212+
...(originalConfig.images || {}),
213+
unoptimized: true,
214+
},
215+
};
216+
217+
module.exports = config;
218+
`),
219+
);
220+
});
221+
222+
it("should set images.unoptimized to true - ECMAScript Modules", async () => {
223+
const { overrideNextConfig } = await importOverrides;
224+
const originalConfig = `
225+
// @ts-check
226+
227+
/**
228+
* @type {import('next').NextConfig}
229+
*/
230+
const nextConfig = {
231+
/* config options here */
232+
}
233+
234+
export default nextConfig
235+
`;
236+
237+
fs.writeFileSync(path.join(tmpDir, "next.config.mjs"), originalConfig);
238+
await overrideNextConfig(tmpDir, "next.config.mjs");
239+
240+
const updatedConfig = fs.readFileSync(path.join(tmpDir, "next.config.mjs"), "utf-8");
241+
assert.equal(
242+
normalizeWhitespace(updatedConfig),
243+
normalizeWhitespace(`
244+
import originalConfig from './next.config.original.mjs';
245+
246+
// This file was automatically generated by Firebase App Hosting adapter
247+
const config = typeof originalConfig === 'function'
248+
? (...args) => {
249+
const resolvedConfig = originalConfig(...args);
250+
return {
251+
...resolvedConfig,
252+
images: {
253+
...(resolvedConfig.images || {}),
254+
unoptimized: true,
255+
},
256+
};
257+
}
258+
: {
259+
...originalConfig,
260+
images: {
261+
...(originalConfig.images || {}),
262+
unoptimized: true,
263+
},
264+
};
265+
266+
export default config;
267+
`),
268+
);
269+
});
270+
271+
it("should set images.unoptimized to true - ECMAScript Function", async () => {
272+
const { overrideNextConfig } = await importOverrides;
273+
const originalConfig = `
274+
// @ts-check
275+
276+
export default (phase, { defaultConfig }) => {
277+
/**
278+
* @type {import('next').NextConfig}
279+
*/
280+
const nextConfig = {
281+
/* config options here */
282+
}
283+
return nextConfig
284+
}
285+
`;
286+
287+
fs.writeFileSync(path.join(tmpDir, "next.config.mjs"), originalConfig);
288+
await overrideNextConfig(tmpDir, "next.config.mjs");
289+
290+
const updatedConfig = fs.readFileSync(path.join(tmpDir, "next.config.mjs"), "utf-8");
291+
assert.equal(
292+
normalizeWhitespace(updatedConfig),
293+
normalizeWhitespace(`
294+
import originalConfig from './next.config.original.mjs';
295+
296+
// This file was automatically generated by Firebase App Hosting adapter
297+
const config = typeof originalConfig === 'function'
298+
? (...args) => {
299+
const resolvedConfig = originalConfig(...args);
300+
return {
301+
...resolvedConfig,
302+
images: {
303+
...(resolvedConfig.images || {}),
304+
unoptimized: true,
305+
},
306+
};
307+
}
308+
: {
309+
...originalConfig,
310+
images: {
311+
...(originalConfig.images || {}),
312+
unoptimized: true,
313+
},
314+
};
315+
316+
export default config;
317+
`),
318+
);
319+
});
320+
321+
it("should set images.unoptimized to true - TypeScript", async () => {
322+
const { overrideNextConfig } = await importOverrides;
323+
const originalConfig = `
324+
import type { NextConfig } from 'next'
325+
326+
const nextConfig: NextConfig = {
327+
/* config options here */
328+
}
329+
330+
export default nextConfig
331+
`;
332+
333+
fs.writeFileSync(path.join(tmpDir, "next.config.ts"), originalConfig);
334+
await overrideNextConfig(tmpDir, "next.config.ts");
335+
336+
const updatedConfig = fs.readFileSync(path.join(tmpDir, "next.config.ts"), "utf-8");
337+
assert.equal(
338+
normalizeWhitespace(updatedConfig),
339+
normalizeWhitespace(`
340+
import originalConfig from './next.config.original';
341+
342+
// This file was automatically generated by Firebase App Hosting adapter
343+
const config = typeof originalConfig === 'function'
344+
? (...args) => {
345+
const resolvedConfig = originalConfig(...args);
346+
return {
347+
...resolvedConfig,
348+
images: {
349+
...(resolvedConfig.images || {}),
350+
unoptimized: true,
351+
},
352+
};
353+
}
354+
: {
355+
...originalConfig,
356+
images: {
357+
...(originalConfig.images || {}),
358+
unoptimized: true,
359+
},
360+
};
361+
362+
module.exports = config;
363+
`),
364+
);
365+
});
366+
});
367+
368+
// Normalize whitespace for comparison
369+
function normalizeWhitespace(str: string) {
370+
return str.replace(/\s+/g, " ").trim();
371+
}

packages/@apphosting/adapter-nextjs/src/overrides.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ import {
99
import { join } from "path";
1010
import { readFileSync } from "fs";
1111

12-
export async function overrideNextConfig(nextConfigFileName: string) {
12+
export async function overrideNextConfig(projectRoot: string, nextConfigFileName: string) {
1313
// Check if the file exists in the current working directory
14-
const cwd = process.cwd();
15-
const configPath = join(cwd, nextConfigFileName);
14+
const configPath = join(projectRoot, nextConfigFileName);
1615

1716
if (!(await exists(configPath))) {
1817
console.log(`No Next.js config file found at ${configPath}`);
@@ -27,7 +26,7 @@ export async function overrideNextConfig(nextConfigFileName: string) {
2726
// Rename the original config file
2827
try {
2928
const originalContent = readFileSync(configPath, "utf-8");
30-
await writeFile(join(cwd, originalConfigName), originalContent);
29+
await writeFile(join(projectRoot, originalConfigName), originalContent);
3130

3231
// Create a new config file with the appropriate import
3332
let importStatement;
@@ -68,7 +67,7 @@ ${fileExtension === "mjs" ? "export default config;" : "module.exports = config;
6867
`;
6968

7069
// Write the new config file
71-
await writeFile(join(cwd, newConfigName), newConfigContent);
70+
await writeFile(join(projectRoot, newConfigName), newConfigContent);
7271
console.log(`Successfully created ${newConfigName} with Firebase App Hosting overrides`);
7372
} catch (error) {
7473
console.error(`Error overriding Next.js config: ${error}`);

0 commit comments

Comments
 (0)