Skip to content
Prev Previous commit
Next Next commit
some more tests
  • Loading branch information
chargome committed Oct 6, 2025
commit 2b525823075ef1bc3669e1495623baa00489050e
276 changes: 275 additions & 1 deletion packages/nextjs/test/config/withSentryConfig.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { afterEach, describe, expect, it, vi } from 'vitest';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import * as util from '../../src/config/util';
import { DEFAULT_SERVER_EXTERNAL_PACKAGES } from '../../src/config/withSentryConfig';
import { defaultRuntimePhase, defaultsObject, exportedNextConfig, userNextConfig } from './fixtures';
Expand Down Expand Up @@ -269,6 +269,280 @@ describe('withSentryConfig', () => {
});
});

describe('bundler detection with version-based defaults', () => {
const originalTurbopack = process.env.TURBOPACK;
const originalArgv = process.argv;

beforeEach(() => {
process.argv = [...originalArgv];
delete process.env.TURBOPACK;
});

afterEach(() => {
vi.restoreAllMocks();
process.env.TURBOPACK = originalTurbopack;
process.argv = originalArgv;
});

describe('Next.js 16+ defaults to turbopack', () => {
it('uses turbopack config by default for Next.js 16.0.0', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('16.0.0');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeDefined();
expect(finalConfig.webpack).toBe(exportedNextConfig.webpack);
});

it('uses turbopack config by default for Next.js 17.0.0', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('17.0.0');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeDefined();
expect(finalConfig.webpack).toBe(exportedNextConfig.webpack);
});

it('uses webpack when --webpack flag is present on Next.js 16.0.0', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('16.0.0');
process.argv.push('--webpack');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeUndefined();
expect(finalConfig.webpack).toBeInstanceOf(Function);
});

it('prioritizes TURBOPACK env var over --webpack flag', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('16.0.0');
process.env.TURBOPACK = '1';
process.argv.push('--webpack');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeDefined();
expect(finalConfig.webpack).toBe(exportedNextConfig.webpack);
});
});

describe('Next.js 15.6.0-canary.38+ defaults to turbopack', () => {
it('uses turbopack config by default for 15.6.0-canary.38', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.6.0-canary.38');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeDefined();
expect(finalConfig.webpack).toBe(exportedNextConfig.webpack);
});

it('uses turbopack config by default for 15.6.0-canary.50', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.6.0-canary.50');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeDefined();
expect(finalConfig.webpack).toBe(exportedNextConfig.webpack);
});

it('uses turbopack config by default for 15.7.0-canary.1', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.7.0-canary.1');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeDefined();
expect(finalConfig.webpack).toBe(exportedNextConfig.webpack);
});

it('uses webpack when --webpack flag is present on 15.6.0-canary.38', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.6.0-canary.38');
process.argv.push('--webpack');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeUndefined();
expect(finalConfig.webpack).toBeInstanceOf(Function);
});

it('uses webpack when --webpack flag is present on 15.7.0-canary.1', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.7.0-canary.1');
process.argv.push('--webpack');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeUndefined();
expect(finalConfig.webpack).toBeInstanceOf(Function);
});
});

describe('Next.js 15.6.0-canary.37 and below defaults to webpack', () => {
it('uses webpack config by default for 15.6.0-canary.37', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.6.0-canary.37');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeUndefined();
expect(finalConfig.webpack).toBeInstanceOf(Function);
});

it('uses webpack config by default for 15.6.0-canary.1', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.6.0-canary.1');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeUndefined();
expect(finalConfig.webpack).toBeInstanceOf(Function);
});

it('uses turbopack when TURBOPACK env var is set on 15.6.0-canary.37', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.6.0-canary.37');
process.env.TURBOPACK = '1';

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeDefined();
expect(finalConfig.webpack).toBe(exportedNextConfig.webpack);
});
});

describe('Next.js 15.6.x stable releases default to webpack', () => {
it('uses webpack config by default for 15.6.0 stable', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.6.0');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeUndefined();
expect(finalConfig.webpack).toBeInstanceOf(Function);
});

it('uses webpack config by default for 15.6.1 stable', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.6.1');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeUndefined();
expect(finalConfig.webpack).toBeInstanceOf(Function);
});

it('uses webpack config by default for 15.7.0 stable', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.7.0');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeUndefined();
expect(finalConfig.webpack).toBeInstanceOf(Function);
});

it('uses turbopack when explicitly requested via env var on 15.6.0 stable', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.6.0');
process.env.TURBOPACK = '1';

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeDefined();
expect(finalConfig.webpack).toBe(exportedNextConfig.webpack);
});
});

describe('older Next.js versions default to webpack', () => {
it.each([['15.5.0'], ['15.0.0'], ['14.2.0'], ['13.5.0']])(
'uses webpack config by default for Next.js %s',
version => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue(version);

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeUndefined();
expect(finalConfig.webpack).toBeInstanceOf(Function);
},
);

it.each([['15.5.0-canary.100'], ['15.0.0-canary.1'], ['14.2.0-canary.50']])(
'uses webpack config by default for Next.js %s canary',
version => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue(version);

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeUndefined();
expect(finalConfig.webpack).toBeInstanceOf(Function);
},
);
});

describe('warnings are shown for unsupported turbopack usage', () => {
let consoleWarnSpy: ReturnType<typeof vi.spyOn>;

beforeEach(() => {
consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
});

it('warns when using turbopack on unsupported version', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.0.0');
vi.spyOn(util, 'supportsProductionCompileHook').mockReturnValue(false);
process.env.TURBOPACK = '1';

materializeFinalNextConfig(exportedNextConfig);

expect(consoleWarnSpy).toHaveBeenCalledWith(
expect.stringContaining('WARNING: You are using the Sentry SDK with Turbopack'),
);
expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining('15.0.0'));
});

it('does not warn when using turbopack on supported version', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('16.0.0');
vi.spyOn(util, 'supportsProductionCompileHook').mockReturnValue(true);
process.env.TURBOPACK = '1';

materializeFinalNextConfig(exportedNextConfig);

expect(consoleWarnSpy).not.toHaveBeenCalled();
});

it('does not warn when using webpack', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('15.0.0');
vi.spyOn(util, 'supportsProductionCompileHook').mockReturnValue(false);

materializeFinalNextConfig(exportedNextConfig);

expect(consoleWarnSpy).not.toHaveBeenCalled();
});
});

describe('edge cases', () => {
it('defaults to webpack when Next.js version cannot be determined', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue(undefined);

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeUndefined();
expect(finalConfig.webpack).toBeInstanceOf(Function);
});

it('uses turbopack when TURBOPACK env var is set even when version is undefined', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue(undefined);
process.env.TURBOPACK = '1';

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

// Note: turbopack config won't be added when version is undefined because
// isTurbopackSupported will be false, but webpack config should still be skipped
expect(finalConfig.webpack).toBe(exportedNextConfig.webpack);
// Turbopack config is only added when both isTurbopack AND isTurbopackSupported are true
expect(finalConfig.turbopack).toBeUndefined();
});

it('handles malformed version strings gracefully', () => {
vi.spyOn(util, 'getNextjsVersion').mockReturnValue('not.a.version');

const finalConfig = materializeFinalNextConfig(exportedNextConfig);

expect(finalConfig.turbopack).toBeUndefined();
expect(finalConfig.webpack).toBeInstanceOf(Function);
});
});
});

describe('turbopack sourcemap configuration', () => {
const originalTurbopack = process.env.TURBOPACK;

Expand Down