UNPKG

@dabapps/create-webpack-config

Version:

A utility for creating webpack configs with common settings

531 lines (488 loc) 12.6 kB
// eslint-disable-next-line import/no-extraneous-dependencies const path = require('path'); const createWebpackConfig = require('../src'); const CWD = process.cwd(); jest.mock('webpack', () => ({ EnvironmentPlugin: jest.fn(), })); jest.mock('circular-dependency-plugin', () => jest.fn()); jest.mock('fork-ts-checker-webpack-plugin', () => jest.fn()); const { EnvironmentPlugin } = require('webpack'); describe('createWebpackConfig', () => { it('should be a function', () => { expect(typeof createWebpackConfig).toBe('function'); }); it('should return a webpack config object', () => { expect( typeof createWebpackConfig({ input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', }) ).toBe('object'); }); it('should error if invalid options provided', () => { const invalidOptions = /Invalid\sconfig\soptions/; const noInput = /No\s"input"/; const noKeys = /No\skeys\sin\s"input"/; const invalidInput = /Invalid\s"input"/; const noOutDir = /No\s"outDir"/; const invalidOutDir = /Invalid\s"outDir"/; const noTsconfig = /No\s"tsconfig"/; const invalidTsconfig = /Invalid\s"tsconfig"/; const invalidEnv = /Invalid\s"env"/; const invalidRawFileExtensions = /Invalid\s"rawFileExtensions"/; const invalidRootDir = /Invalid\s"rootDir"/; const invalidInclude = /Invalid\s"include"/; const optionsToErrors = [ { options: null, error: invalidOptions, }, { options: [], error: invalidOptions, }, { options: {}, error: noInput, }, { options: { input: '', }, error: invalidInput, }, { options: { input: null, }, error: invalidInput, }, { options: { input: [], }, error: invalidInput, }, { options: { input: 0, }, error: invalidInput, }, { options: { input: {}, }, error: noKeys, }, { options: { input: 'src/index.ts', }, error: noOutDir, }, { options: { input: 'src/index.ts', outDir: null, }, error: invalidOutDir, }, { options: { input: 'src/index.ts', outDir: {}, }, error: invalidOutDir, }, { options: { input: 'src/index.ts', outDir: [], }, error: invalidOutDir, }, { options: { input: 'src/index.ts', outDir: '', }, error: invalidOutDir, }, { options: { input: 'src/index.ts', outDir: 0, }, error: invalidOutDir, }, { options: { input: 'src/index.ts', outDir: 'dist', }, error: noTsconfig, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: null, }, error: invalidTsconfig, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: [], }, error: invalidTsconfig, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: {}, }, error: invalidTsconfig, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: '', }, error: invalidTsconfig, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', env: null, }, error: invalidEnv, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', env: [], }, error: invalidEnv, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', env: '', }, error: invalidEnv, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', rawFileExtensions: null, }, error: invalidRawFileExtensions, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', rawFileExtensions: {}, }, error: invalidRawFileExtensions, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', rawFileExtensions: '', }, error: invalidRawFileExtensions, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', rootDir: null, }, error: invalidRootDir, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', rootDir: '', }, error: invalidRootDir, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', rootDir: {}, }, error: invalidRootDir, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', rootDir: [], }, error: invalidRootDir, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', include: null, }, error: invalidInclude, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', include: {}, }, error: invalidInclude, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', include: '', }, error: invalidInclude, }, { options: { input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', include: [], }, error: invalidInclude, }, ]; optionsToErrors.forEach(({ options, error }) => { expect(() => createWebpackConfig(options)).toThrow(error); }); }); it('should bundle a single entry', () => { const config = createWebpackConfig({ input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', }); expect(config.entry).toEqual([ require.resolve('raf/polyfill'), path.resolve(CWD, 'src/index.ts'), ]); expect(config.output).toEqual({ filename: 'bundle.js', path: path.resolve(CWD, 'dist'), }); expect(config.resolve.alias).toEqual({ '^': path.resolve(CWD, 'src/'), }); expect( config.module.rules[config.module.rules.length - 1].include ).toEqual([path.resolve(CWD, 'src/')]); }); it('should bundle multiple entries', () => { const config = createWebpackConfig({ input: { frontend: 'src/index.ts', admin: 'src/admin.ts', }, outDir: 'dist', tsconfig: 'tsconfig.json', }); expect(config.entry).toEqual({ frontend: [ require.resolve('raf/polyfill'), path.resolve(CWD, 'src/index.ts'), ], admin: [ require.resolve('raf/polyfill'), path.resolve(CWD, 'src/admin.ts'), ], }); expect(config.output).toEqual({ filename: '[name]-bundle.js', path: path.resolve(CWD, 'dist'), }); expect(config.resolve.alias).toEqual({ '^': path.resolve(CWD, 'src/'), }); expect( config.module.rules[config.module.rules.length - 1].include ).toEqual([path.resolve(CWD, 'src/')]); }); it('should error if multiple entries are in different directories and no rootDir provided', () => { const unsureAboutAliases = () => createWebpackConfig({ input: { frontend: 'src/index.ts', admin: 'admin/index.js', }, outDir: 'dist', tsconfig: 'tsconfig.json', }); expect(unsureAboutAliases).toThrow(/rootDir/); }); it('should have multiple includes if entries are in different directories', () => { const config = createWebpackConfig({ input: { frontend: 'src/frontend/index.ts', admin: 'src/admin/index.ts', }, outDir: 'dist', tsconfig: 'tsconfig.json', rootDir: 'src', }); expect(config.resolve.alias).toEqual({ '^': path.resolve(CWD, 'src'), }); expect( config.module.rules[config.module.rules.length - 1].include ).toEqual([ path.resolve(CWD, 'src/frontend'), path.resolve(CWD, 'src/admin'), ]); }); it('should add include options to includes (single include)', () => { const config = createWebpackConfig({ input: { frontend: 'src/frontend/index.ts', admin: 'src/admin/index.ts', }, outDir: 'dist', tsconfig: 'tsconfig.json', rootDir: 'src', include: 'examples', }); expect(config.resolve.alias).toEqual({ '^': path.resolve(CWD, 'src'), }); expect( config.module.rules[config.module.rules.length - 1].include ).toEqual([ path.resolve(CWD, 'examples'), path.resolve(CWD, 'src/frontend'), path.resolve(CWD, 'src/admin'), ]); }); it('should add include options to includes (array of includes)', () => { const config = createWebpackConfig({ input: { frontend: 'src/frontend/index.ts', admin: 'src/admin/index.ts', }, outDir: 'dist', tsconfig: 'tsconfig.json', rootDir: 'src', include: ['examples', 'docs'], }); expect(config.resolve.alias).toEqual({ '^': path.resolve(CWD, 'src'), }); expect( config.module.rules[config.module.rules.length - 1].include ).toEqual([ path.resolve(CWD, 'examples'), path.resolve(CWD, 'docs'), path.resolve(CWD, 'src/frontend'), path.resolve(CWD, 'src/admin'), ]); }); it('should use rootDir if provided', () => { const config = createWebpackConfig({ input: { frontend: 'src/index.ts', admin: 'src/admin.ts', }, outDir: 'dist', tsconfig: 'tsconfig.json', rootDir: 'wat', }); expect(config.resolve.alias).toEqual({ '^': path.resolve(CWD, 'wat'), }); }); it('should create rules without raw files if no extensions provided', () => { const config1 = createWebpackConfig({ input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', }); const config2 = createWebpackConfig({ input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', rawFileExtensions: [], }); const babelLoader = require.resolve('babel-loader'); expect(config1.module.rules.length).toBe(2); expect( config1.module.rules.every(rule => rule.use[0].loader === babelLoader) ).toBe(true); expect(config2.module.rules.length).toBe(2); expect( config2.module.rules.every(rule => rule.use[0].loader === babelLoader) ).toBe(true); }); it('should create a regex for raw files', () => { const config = createWebpackConfig({ input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', rawFileExtensions: ['html', 'txt', 'xml', 'csv'], }); const rawLoaderRule = config.module.rules[0]; expect(typeof rawLoaderRule).toBe('object'); expect(rawLoaderRule.use).toBe(require.resolve('raw-loader')); expect(rawLoaderRule.test).toEqual(/\.(?:html|txt|xml|csv)$/); }); it('should work without environment variables', () => { createWebpackConfig({ input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', }); expect(EnvironmentPlugin).toHaveBeenCalledWith({}); }); it('should set default environment variables', () => { createWebpackConfig({ input: 'src/index.ts', outDir: 'dist', tsconfig: 'tsconfig.json', env: { NODE_ENV: 'production', }, }); expect(EnvironmentPlugin).toHaveBeenCalledWith({ NODE_ENV: 'production', }); }); });