1+ import * as fs from 'fs' ;
2+ import * as os from 'os' ;
3+ import * as path from 'path' ;
4+ import * as rimraf from 'rimraf' ;
5+
16import { withSentryConfig } from '../src/config' ;
27import {
38 BuildContext ,
@@ -7,12 +12,24 @@ import {
712 SentryWebpackPluginOptions ,
813 WebpackConfigObject ,
914} from '../src/config/types' ;
10- import {
11- CLIENT_SDK_CONFIG_FILE ,
12- constructWebpackConfigFunction ,
13- SentryWebpackPlugin ,
14- SERVER_SDK_CONFIG_FILE ,
15- } from '../src/config/webpack' ;
15+ import { constructWebpackConfigFunction , getUserConfigFile , SentryWebpackPlugin } from '../src/config/webpack' ;
16+
17+ const SERVER_SDK_CONFIG_FILE = 'sentry.server.config.js' ;
18+ const CLIENT_SDK_CONFIG_FILE = 'sentry.client.config.js' ;
19+
20+ // We use `fs.existsSync()` in `getUserConfigFile()`. When we're not testing `getUserConfigFile()` specifically, all we
21+ // need is for it to give us any valid answer, so make it always find what it's looking for. Since this is a core node
22+ // built-in, though, which jest itself uses, otherwise let it do the normal thing. Storing the real version of the
23+ // function also lets us restore the original when we do want to test `getUserConfigFile()`.
24+ const realExistsSync = jest . requireActual ( 'fs' ) . existsSync ;
25+ const mockExistsSync = ( path : fs . PathLike ) => {
26+ if ( ( path as string ) . endsWith ( SERVER_SDK_CONFIG_FILE ) || ( path as string ) . endsWith ( CLIENT_SDK_CONFIG_FILE ) ) {
27+ return true ;
28+ }
29+
30+ return realExistsSync ( path ) ;
31+ } ;
32+ const exitsSync = jest . spyOn ( fs , 'existsSync' ) . mockImplementation ( mockExistsSync ) ;
1633
1734/** Mocks of the arguments passed to `withSentryConfig` */
1835const userNextConfig = {
@@ -63,8 +80,13 @@ const clientWebpackConfig = {
6380 target : 'web' ,
6481 context : '/Users/Maisey/projects/squirrelChasingSimulator' ,
6582} ;
66- const serverBuildContext = { isServer : true , dev : false , buildId : 'doGsaREgReaT' } ;
67- const clientBuildContext = { isServer : false , dev : false , buildId : 'doGsaREgReaT' } ;
83+ const baseBuildContext = {
84+ dev : false ,
85+ buildId : 'doGsaREgReaT' ,
86+ dir : '/Users/Maisey/projects/squirrelChasingSimulator' ,
87+ } ;
88+ const serverBuildContext = { isServer : true , ...baseBuildContext } ;
89+ const clientBuildContext = { isServer : false , ...baseBuildContext } ;
6890
6991/**
7092 * Derive the final values of all next config options, by first applying `withSentryConfig` and then, if it returns a
@@ -223,6 +245,9 @@ describe('webpack config', () => {
223245 } ) ;
224246
225247 describe ( 'webpack `entry` property config' , ( ) => {
248+ const serverConfigFilePath = `./${ SERVER_SDK_CONFIG_FILE } ` ;
249+ const clientConfigFilePath = `./${ CLIENT_SDK_CONFIG_FILE } ` ;
250+
226251 it ( 'handles various entrypoint shapes' , async ( ) => {
227252 const finalWebpackConfig = await materializeFinalWebpackConfig ( {
228253 userNextConfig,
@@ -234,23 +259,23 @@ describe('webpack config', () => {
234259 expect . objectContaining ( {
235260 // original entry point value is a string
236261 // (was 'private-next-pages/api/dogs/[name].js')
237- 'pages/api/dogs/[name]' : [ SERVER_SDK_CONFIG_FILE , 'private-next-pages/api/dogs/[name].js' ] ,
262+ 'pages/api/dogs/[name]' : [ serverConfigFilePath , 'private-next-pages/api/dogs/[name].js' ] ,
238263
239264 // original entry point value is a string array
240265 // (was ['./node_modules/smellOVision/index.js', 'private-next-pages/_app.js'])
241- 'pages/_app' : [ SERVER_SDK_CONFIG_FILE , './node_modules/smellOVision/index.js' , 'private-next-pages/_app.js' ] ,
266+ 'pages/_app' : [ serverConfigFilePath , './node_modules/smellOVision/index.js' , 'private-next-pages/_app.js' ] ,
242267
243268 // original entry point value is an object containing a string `import` value
244269 // (`import` was 'private-next-pages/api/simulator/dogStats/[name].js')
245270 'pages/api/simulator/dogStats/[name]' : {
246- import : [ SERVER_SDK_CONFIG_FILE , 'private-next-pages/api/simulator/dogStats/[name].js' ] ,
271+ import : [ serverConfigFilePath , 'private-next-pages/api/simulator/dogStats/[name].js' ] ,
247272 } ,
248273
249274 // original entry point value is an object containing a string array `import` value
250275 // (`import` was ['./node_modules/dogPoints/converter.js', 'private-next-pages/api/simulator/leaderboard.js'])
251276 'pages/api/simulator/leaderboard' : {
252277 import : [
253- SERVER_SDK_CONFIG_FILE ,
278+ serverConfigFilePath ,
254279 './node_modules/dogPoints/converter.js' ,
255280 'private-next-pages/api/simulator/leaderboard.js' ,
256281 ] ,
@@ -259,7 +284,7 @@ describe('webpack config', () => {
259284 // original entry point value is an object containg properties besides `import`
260285 // (`dependOn` remains untouched)
261286 'pages/api/tricks/[trickName]' : {
262- import : [ SERVER_SDK_CONFIG_FILE , 'private-next-pages/api/tricks/[trickName].js' ] ,
287+ import : [ serverConfigFilePath , 'private-next-pages/api/tricks/[trickName].js' ] ,
263288 dependOn : 'treats' ,
264289 } ,
265290 } ) ,
@@ -278,7 +303,7 @@ describe('webpack config', () => {
278303 // no injected file
279304 main : './src/index.ts' ,
280305 // was 'next-client-pages-loader?page=%2F_app'
281- 'pages/_app' : [ CLIENT_SDK_CONFIG_FILE , 'next-client-pages-loader?page=%2F_app' ] ,
306+ 'pages/_app' : [ clientConfigFilePath , 'next-client-pages-loader?page=%2F_app' ] ,
282307 } ) ,
283308 ) ;
284309 } ) ;
@@ -340,4 +365,50 @@ describe('Sentry webpack plugin config', () => {
340365
341366 expect ( finalWebpackConfig ?. devtool ) . not . toEqual ( 'source-map' ) ;
342367 } ) ;
368+
369+ describe ( 'getUserConfigFile' , ( ) => {
370+ let tempDir : string ;
371+
372+ beforeAll ( ( ) => {
373+ exitsSync . mockImplementation ( realExistsSync ) ;
374+ } ) ;
375+
376+ beforeEach ( ( ) => {
377+ const tempDirPathPrefix = path . join ( os . tmpdir ( ) , 'sentry-nextjs-test-' ) ;
378+ tempDir = fs . mkdtempSync ( tempDirPathPrefix ) ;
379+ } ) ;
380+
381+ afterEach ( ( ) => {
382+ rimraf . sync ( tempDir ) ;
383+ } ) ;
384+
385+ afterAll ( ( ) => {
386+ exitsSync . mockImplementation ( mockExistsSync ) ;
387+ } ) ;
388+
389+ it ( 'successfully finds js files' , ( ) => {
390+ fs . writeFileSync ( path . resolve ( tempDir , 'sentry.server.config.js' ) , 'Dogs are great!' ) ;
391+ fs . writeFileSync ( path . resolve ( tempDir , 'sentry.client.config.js' ) , 'Squirrel!' ) ;
392+
393+ expect ( getUserConfigFile ( tempDir , 'server' ) ) . toEqual ( 'sentry.server.config.js' ) ;
394+ expect ( getUserConfigFile ( tempDir , 'client' ) ) . toEqual ( 'sentry.client.config.js' ) ;
395+ } ) ;
396+
397+ it ( 'successfully finds ts files' , ( ) => {
398+ fs . writeFileSync ( path . resolve ( tempDir , 'sentry.server.config.ts' ) , 'Sit. Stay. Lie Down.' ) ;
399+ fs . writeFileSync ( path . resolve ( tempDir , 'sentry.client.config.ts' ) , 'Good dog!' ) ;
400+
401+ expect ( getUserConfigFile ( tempDir , 'server' ) ) . toEqual ( 'sentry.server.config.ts' ) ;
402+ expect ( getUserConfigFile ( tempDir , 'client' ) ) . toEqual ( 'sentry.client.config.ts' ) ;
403+ } ) ;
404+
405+ it ( 'errors when files are missing' , ( ) => {
406+ expect ( ( ) => getUserConfigFile ( tempDir , 'server' ) ) . toThrowError (
407+ `Cannot find 'sentry.server.config.ts' or 'sentry.server.config.js' in '${ tempDir } '` ,
408+ ) ;
409+ expect ( ( ) => getUserConfigFile ( tempDir , 'client' ) ) . toThrowError (
410+ `Cannot find 'sentry.client.config.ts' or 'sentry.client.config.js' in '${ tempDir } '` ,
411+ ) ;
412+ } ) ;
413+ } ) ;
343414} ) ;
0 commit comments