Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ref(nextjs): Small improvements to config tests #3938

Merged
merged 6 commits into from Aug 31, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/nextjs/src/config/index.ts
Expand Up @@ -15,7 +15,7 @@ export function withSentryConfig(
// If the user has passed us a function, we need to return a function, so that we have access to `phase` and
// `defaults` in order to pass them along to the user's function
if (typeof userNextConfig === 'function') {
return function(phase: string, defaults: { defaultConfig: { [key: string]: unknown } }): NextConfigObject {
return function(phase: string, defaults: { defaultConfig: NextConfigObject }): NextConfigObject {
const materializedUserNextConfig = userNextConfig(phase, defaults);
return {
...materializedUserNextConfig,
Expand Down
58 changes: 32 additions & 26 deletions packages/nextjs/test/config.test.ts
Expand Up @@ -33,7 +33,7 @@ const mockExistsSync = (path: fs.PathLike) => {
const exitsSync = jest.spyOn(fs, 'existsSync').mockImplementation(mockExistsSync);

/** Mocks of the arguments passed to `withSentryConfig` */
const userNextConfig = {
const userNextConfig: Partial<NextConfigObject> = {
publicRuntimeConfig: { location: 'dogpark', activities: ['fetch', 'chasing', 'digging'] },
webpack: (config: WebpackConfigObject, _options: BuildContext) => ({
...config,
Expand All @@ -51,7 +51,9 @@ process.env.SENTRY_RELEASE = 'doGsaREgReaT';

/** Mocks of the arguments passed to the result of `withSentryConfig` (when it's a function). */
const runtimePhase = 'ball-fetching';
const defaultNextConfig = { nappingHoursPerDay: 20, oversizeFeet: true, shouldChaseTail: true };
// `defaultConfig` is the defaults for all nextjs options (we don't use these at all in the tests, so for our purposes
// here the values don't matter)
const defaultsObject = { defaultConfig: {} };

/** mocks of the arguments passed to `nextConfig.webpack` */
const serverWebpackConfig = {
Expand Down Expand Up @@ -84,15 +86,21 @@ const clientWebpackConfig = {
context: '/Users/Maisey/projects/squirrelChasingSimulator',
};

const baseBuildContext = {
dev: false,
buildId: 'sItStAyLiEdOwN',
dir: '/Users/Maisey/projects/squirrelChasingSimulator',
config: { target: 'server' as const },
webpack: { version: '5.4.15' },
};
const serverBuildContext = { isServer: true, ...baseBuildContext };
const clientBuildContext = { isServer: false, ...baseBuildContext };
// In real life, next will copy the `userNextConfig` into the `buildContext`. Since we're providing mocks for both of
// those, we need to mimic that behavior, and since `userNextConfig` can vary per test, we need to have the option do it
// dynamically.
function getBuildContext(buildTarget: 'server' | 'client', userNextConfig: Partial<NextConfigObject>): BuildContext {
return {
dev: false,
buildId: 'sItStAyLiEdOwN',
dir: '/Users/Maisey/projects/squirrelChasingSimulator',
config: { target: 'server', ...userNextConfig },
webpack: { version: '5.4.15' },
isServer: buildTarget === 'server',
};
}
const serverBuildContext = getBuildContext('server', userNextConfig);
const clientBuildContext = getBuildContext('client', userNextConfig);

/**
* Derive the final values of all next config options, by first applying `withSentryConfig` and then, if it returns a
Expand All @@ -114,9 +122,7 @@ function materializeFinalNextConfig(
if (typeof sentrifiedConfig === 'function') {
// for some reason TS won't recognize that `finalConfigValues` is now a NextConfigObject, which is why the cast
// below is necessary
finalConfigValues = sentrifiedConfig(runtimePhase, {
defaultConfig: defaultNextConfig,
});
finalConfigValues = sentrifiedConfig(runtimePhase, defaultsObject);
}

return finalConfigValues as NextConfigObject;
Expand Down Expand Up @@ -145,11 +151,7 @@ async function materializeFinalWebpackConfig(options: {

// if the user's next config is a function, run it so we have access to the values
const materializedUserNextConfig =
typeof userNextConfig === 'function'
? userNextConfig('phase-production-build', {
defaultConfig: {},
})
: userNextConfig;
typeof userNextConfig === 'function' ? userNextConfig('phase-production-build', defaultsObject) : userNextConfig;

// get the webpack config function we'd normally pass back to next
const webpackConfigFunction = constructWebpackConfigFunction(
Expand Down Expand Up @@ -211,9 +213,7 @@ describe('withSentryConfig', () => {

materializeFinalNextConfig(userNextConfigFunction);

expect(userNextConfigFunction).toHaveBeenCalledWith(runtimePhase, {
defaultConfig: defaultNextConfig,
});
expect(userNextConfigFunction).toHaveBeenCalledWith(runtimePhase, defaultsObject);
});
});

Expand Down Expand Up @@ -243,7 +243,7 @@ describe('webpack config', () => {

// Run the user's webpack config function, so we can check the results against ours. Delete `entry` because we'll
// test it separately, and besides, it's one that we *should* be overwriting.
const materializedUserWebpackConfig = userNextConfig.webpack(serverWebpackConfig, serverBuildContext);
const materializedUserWebpackConfig = userNextConfig.webpack!(serverWebpackConfig, serverBuildContext);
// @ts-ignore `entry` may be required in real life, but we don't need it for our tests
delete materializedUserWebpackConfig.entry;

Expand Down Expand Up @@ -377,10 +377,13 @@ describe('Sentry webpack plugin config', () => {
});

it('has the correct value when building serverless server bundles', async () => {
const userNextConfigServerless = { ...userNextConfig };
userNextConfigServerless.target = 'experimental-serverless-trace';

const finalWebpackConfig = await materializeFinalWebpackConfig({
userNextConfig,
userNextConfig: userNextConfigServerless,
incomingWebpackConfig: serverWebpackConfig,
incomingWebpackBuildContext: { ...serverBuildContext, config: { target: 'experimental-serverless-trace' } },
incomingWebpackBuildContext: getBuildContext('server', userNextConfigServerless),
});

const sentryWebpackPlugin = finalWebpackConfig.plugins?.[0] as SentryWebpackPluginType;
Expand All @@ -391,10 +394,13 @@ describe('Sentry webpack plugin config', () => {
});

it('has the correct value when building serverful server bundles using webpack 4', async () => {
const serverBuildContextWebpack4 = getBuildContext('server', userNextConfig);
serverBuildContextWebpack4.webpack.version = '4.15.13';

const finalWebpackConfig = await materializeFinalWebpackConfig({
userNextConfig,
incomingWebpackConfig: serverWebpackConfig,
incomingWebpackBuildContext: { ...serverBuildContext, webpack: { version: '4.15.13' } },
incomingWebpackBuildContext: serverBuildContextWebpack4,
});

const sentryWebpackPlugin = finalWebpackConfig.plugins?.[0] as SentryWebpackPluginType;
Expand Down