mochapack
Version:
mocha cli with webpack support
249 lines (223 loc) • 7.53 kB
text/typescript
import { join, resolve, sep, normalize } from 'path'
import { expect } from 'chai'
import { merge as _merge } from 'lodash'
import { SinonSandbox, createSandbox } from 'sinon'
import { ProgressPlugin, LoaderOptionsPlugin } from 'webpack'
import createWebpackConfig from '.'
import { CreateWebpackConfigOptions, MochapackWebpackConfigs } from './types'
import * as mochapackPlugins from '../../../webpack/plugin/buildProgressPlugin'
import { MOCHAPACK_NAME } from '../../../util/constants'
describe('createWebpackConfig', () => {
const fixturesDir = resolve(
__dirname,
'../../../..',
'test/fixture/createWebpackConfig'
)
const cwd = process.cwd()
const dummyProgressPlugin: ProgressPlugin = new ProgressPlugin()
let sandbox: SinonSandbox
let configOptions: CreateWebpackConfigOptions
let createdConfig: MochapackWebpackConfigs
let expectedTempPath: string
beforeEach(async () => {
sandbox = createSandbox()
sandbox.stub(Date, 'now').returns(12345)
sandbox
.stub(mochapackPlugins, 'buildProgressPlugin')
.returns(dummyProgressPlugin)
configOptions = {
cwd,
entries: ['test/fixture/createWebpackConfig/**.js'],
entryLoaderPath: 'path/to/entry/loader',
entryPath: 'path/to/entry',
includeLoaderPath: 'path/to/include/loader',
includes: ['hello.js', 'world.js'],
interactive: false,
webpackConfig: {}
}
expectedTempPath = join(cwd, '.tmp', MOCHAPACK_NAME, '12345')
createdConfig = await createWebpackConfig(configOptions)
})
afterEach(() => {
sandbox.restore()
})
it('builds the entry config using the provided options', () => {
expect(createdConfig.entryConfig.files).to.eql([
resolve(fixturesDir, 'fooBar.js'),
resolve(fixturesDir, 'helloWorld.js')
])
})
context('when an output path does not exist', () => {
it('uses a temporary path as the output path', () => {
expect(createdConfig.webpackConfig.output.path).to.eql(expectedTempPath)
})
it('adds a temporary path to the output path with a separator for the public path', () => {
expect(createdConfig.webpackConfig.output.publicPath).to.eql(
expectedTempPath + sep
)
})
})
context('when an output path exists', () => {
beforeEach(async () => {
configOptions = _merge({}, configOptions, {
webpackConfig: { output: { path: 'existing/path' } }
})
createdConfig = await createWebpackConfig(configOptions)
})
it('uses the existing output path', () => {
expect(createdConfig.webpackConfig.output.path).to.eql(
normalize('existing/path')
)
})
context('when a public path is not provided', () => {
it('is set to undefined', () => {
expect(createdConfig.webpackConfig.output.publicPath).to.be.undefined
})
})
context('when a public path is provided', () => {
beforeEach(async () => {
configOptions = _merge({}, configOptions, {
webpackConfig: {
output: {
path: 'existing/path',
publicPath: 'existing/public/path/'
}
}
})
createdConfig = await createWebpackConfig(configOptions)
})
it('uses the existing public path', () => {
expect(createdConfig.webpackConfig.output.publicPath).to.eql(
'existing/public/path/'
)
})
})
})
context('when no plugins are present in the provided webpack config', () => {
context('when interactive is false', () => {
it('sets the plugins to an empty array', () => {
expect(createdConfig.webpackConfig.plugins).to.eql([])
})
})
context('when interactive is true', () => {
it('includes the buildProgressPlugin in the plugins array', async () => {
configOptions = _merge({}, configOptions, {
interactive: true
})
createdConfig = await createWebpackConfig(configOptions)
expect(createdConfig.webpackConfig.plugins).to.include(
dummyProgressPlugin
)
})
})
})
context('when plugins are present in the provided webpack config', () => {
const dummyProvidedPlugin = new LoaderOptionsPlugin({})
beforeEach(async () => {
configOptions = _merge({}, configOptions, {
webpackConfig: {
plugins: [dummyProvidedPlugin]
}
})
createdConfig = await createWebpackConfig(configOptions)
})
context('when interactive is false', () => {
it('sets the plugins to provided plugins', () => {
expect(createdConfig.webpackConfig.plugins).to.eql([
dummyProvidedPlugin
])
})
})
context('when interactive is true', () => {
it('appends the buildProgressPlugin to the provided plugins', async () => {
configOptions = _merge({}, configOptions, {
interactive: true
})
createdConfig = await createWebpackConfig(configOptions)
expect(createdConfig.webpackConfig.plugins).to.eql([
dummyProvidedPlugin,
dummyProgressPlugin
])
})
})
})
context('when no other loader rules are present', () => {
it('sets loader rules to applicable rules for Mochapack', () => {
// Using stringify to avoid mismatch of EntryConfig object
expect(JSON.stringify(createdConfig.webpackConfig.module.rules)).to.eql(
JSON.stringify([
{
test: 'path/to/entry',
use: [
{
loader: 'path/to/include/loader',
options: {
include: ['hello.js', 'world.js']
}
},
{
loader: 'path/to/entry/loader',
options: {
entryConfig: {
files: [
resolve(fixturesDir, 'fooBar.js'),
resolve(fixturesDir, 'helloWorld.js')
]
}
}
}
]
}
])
)
})
})
context('when other loader rules are present', () => {
it('adds loader rules applicable to Mochapack to the beginning of the array', async () => {
configOptions = _merge({}, configOptions, {
webpackConfig: {
module: {
rules: [
{
test: 'some/test/rule',
use: [{ loader: 'my/special/loader' }]
}
]
}
}
})
createdConfig = await createWebpackConfig(configOptions)
// Using stringify to avoid mismatch of EntryConfig object
expect(JSON.stringify(createdConfig.webpackConfig.module.rules)).to.eql(
JSON.stringify([
{
test: 'path/to/entry',
use: [
{
loader: 'path/to/include/loader',
options: {
include: ['hello.js', 'world.js']
}
},
{
loader: 'path/to/entry/loader',
options: {
entryConfig: {
files: [
resolve(fixturesDir, 'fooBar.js'),
resolve(fixturesDir, 'helloWorld.js')
]
}
}
}
]
},
{
test: 'some/test/rule',
use: [{ loader: 'my/special/loader' }]
}
])
)
})
})
})