import path from 'path';
import fs from 'fs';
import {
compile,
getCompiler,
getErrors,
getExecutedCode,
getModuleSource,
getWarnings,
} from './helpers/index';
const testCasesPath = path.join(__dirname, 'fixtures/modules/tests-cases');
const testCases = fs.readdirSync(testCasesPath);
jest.setTimeout(60000);
describe('"modules" option', () => {
[
true,
false,
'local',
'global',
{ mode: 'local' },
{ mode: 'global' },
].forEach((modulesValue) => {
testCases.forEach((name) => {
it(`should work with case \`${name}\` (\`modules\` value is \`${
modulesValue.mode
? `object with mode ${modulesValue.mode}`
: modulesValue
})\``, async () => {
const pathToTest = `./modules/tests-cases/${name}/source.js`;
const moduleId = `./modules/tests-cases/${name}/source.css`;
const compiler = getCompiler(pathToTest, {
modules: modulesValue.mode
? { mode: modulesValue.mode, localIdentName: '_[local]' }
: modulesValue,
});
const stats = await compile(compiler);
expect(getModuleSource(moduleId, stats)).toMatchSnapshot('module');
expect(
getExecutedCode('main.bundle.js', compiler, stats)
).toMatchSnapshot('result');
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
});
});
it('should work and support "pure" mode', async () => {
const compiler = getCompiler('./modules/pure/pure.js', { modules: 'pure' });
const stats = await compile(compiler);
expect(getModuleSource('./modules/pure/pure.css', stats)).toMatchSnapshot(
'module'
);
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and support "pure" mode #2', async () => {
const compiler = getCompiler('./modules/pure/pure.js', {
modules: { mode: 'pure' },
});
const stats = await compile(compiler);
expect(getModuleSource('./modules/pure/pure.css', stats)).toMatchSnapshot(
'module'
);
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with the "[local]" placeholder for the "localIdentName" option', async () => {
const compiler = getCompiler('./modules/localIdentName/localIdentName.js', {
modules: { localIdentName: '[local]' },
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localIdentName/localIdentName.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and respect the "localIdentName" option', async () => {
const compiler = getCompiler('./modules/localIdentName/localIdentName.js', {
modules: {
localIdentName: '[name]--[local]--[hash:base64:5]',
localIdentContext: path.resolve(__dirname),
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localIdentName/localIdentName.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and respect the "context" option', async () => {
const compiler = getCompiler('./modules/localIdentName/localIdentName.js', {
modules: {
localIdentName: '[hash:base64:8]',
localIdentContext: path.resolve(__dirname),
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localIdentName/localIdentName.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and respect the "path" placeholder', async () => {
const compiler = getCompiler('./modules/localIdentName/localIdentName.js', {
modules: {
localIdentName: '[path][name]__[local]',
localIdentContext: path.resolve(__dirname),
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localIdentName/localIdentName.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and respect the "hashPrefix" option', async () => {
const compiler = getCompiler('./modules/localIdentName/localIdentName.js', {
modules: {
localIdentName: '[local]--[hash]',
localIdentHashPrefix: 'x',
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localIdentName/localIdentName.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and prefix leading hyphen when digit is first', async () => {
const compiler = getCompiler('./modules/localIdentName/localIdentName.js', {
modules: { localIdentName: '-1[local]' },
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localIdentName/localIdentName.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should should work with two leading hyphens', async () => {
const compiler = getCompiler('./modules/localIdentName/localIdentName.js', {
modules: { localIdentName: '--[local]' },
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localIdentName/localIdentName.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should should work with two leading underscore', async () => {
const compiler = getCompiler('./modules/localIdentName/localIdentName.js', {
modules: { localIdentName: '__[local]' },
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localIdentName/localIdentName.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and correctly replace escaped symbols', async () => {
const compiler = getCompiler('./modules/localIdentName/localIdentName.js', {
modules: { localIdentName: '[local]--[hash:base64:4]' },
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localIdentName/localIdentName.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and respect the "getLocalIdent" option', async () => {
expect.assertions(382);
const compiler = getCompiler('./modules/localIdentName/localIdentName.js', {
modules: {
localIdentRegExp: 'regExp',
localIdentContext: 'context',
localIdentHashPrefix: 'hash',
getLocalIdent(loaderContext, localIdentName, localName, options) {
expect(loaderContext).toBeDefined();
expect(typeof localIdentName).toBe('string');
expect(typeof localName).toBe('string');
expect(options).toBeDefined();
expect(options.regExp).toBe('regExp');
expect(options.context).toBe('context');
expect(options.hashPrefix).toBe('hash');
return 'foo';
},
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localIdentName/localIdentName.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and has "undefined" context if no context was given', async () => {
expect.assertions(58);
const compiler = getCompiler('./modules/localIdentName/localIdentName.js', {
modules: {
getLocalIdent(loaderContext, localIdentName, localName, options) {
expect(options.context).toBeDefined();
return 'foo';
},
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localIdentName/localIdentName.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should support resolving in composes', async () => {
const compiler = getCompiler('./modules/composes/composes.js', {
modules: true,
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/composes/composes.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should resolve absolute path in composes', async () => {
const fileDirectory = path.resolve(
__dirname,
'fixtures',
'modules',
'composes'
);
const file = path.resolve(fileDirectory, 'composes-absolute.css');
const absolutePath = path.resolve(fileDirectory, 'imported-simple.css');
fs.writeFileSync(
file,
`.simple { color: red; composes: imported-simple from '${absolutePath}'; }`
);
const compiler = getCompiler('./modules/composes/composes-absolute.js', {
modules: true,
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/composes/composes-absolute.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should support resolving in composes preprocessor files with extensions', async () => {
const compiler = getCompiler(
'./modules/composes/composes-preprocessors.js',
{
modules: {
mode: 'local',
exportGlobals: true,
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource('./modules/composes/composes-preprocessors.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('issue #286', async () => {
const compiler = getCompiler(
'./modules/issue-286/source.js',
{},
{
module: {
rules: [
{
test: /source\.css$/,
loader: path.resolve(__dirname, '../src'),
options: {
importLoaders: false,
modules: {
localIdentName: 'b--[local]',
},
},
},
{
test: /dep\.css$/,
loader: path.resolve(__dirname, '../src'),
options: {
importLoaders: false,
modules: {
localIdentName: 'a--[local]',
},
},
},
],
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource('./modules/issue-286/source.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('issue #636', async () => {
const compiler = getCompiler(
'./modules/issue-636/source.js',
{},
{
module: {
rules: [
{
test: /\.s[ca]ss$/i,
use: [
{
loader: path.resolve(__dirname, '../src'),
options: {
modules: {
localIdentName: '[local]',
getLocalIdent: (context, localIdentName, localName) =>
`prefix-${localName}`,
},
importLoaders: 1,
},
},
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
},
},
],
},
],
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource('./modules/issue-636/source.scss', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('issue #861', async () => {
const compiler = getCompiler(
'./modules/issue-861/resolving-from-node_modules.js',
{
modules: true,
}
);
const stats = await compile(compiler);
expect(
getModuleSource(
'./modules/issue-861/resolving-from-node_modules.css',
stats
)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('issue #966', async () => {
const compiler = getCompiler('./modules/issue-966/button.js', {
modules: {
getLocalIdent: (ctx, localIdentName, localName) => `${localName}.hey`,
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/issue-966/button.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it("issue #966 - values in selectors aren't escaped properly", async () => {
const compiler = getCompiler('./modules/issue-966/issue-966.js', {
modules: {
getLocalIdent: (loaderContext, localIdentName, localName) => {
if (localName === 'foo-class') {
return `7-${localName}`;
}
if (localName === 'bar-class') {
return `>-${localName}`;
}
if (localName === 'baz-class') {
return `\u0000-${localName}`;
}
if (localName === 'fooBaz-class') {
return `${localName}.continuation`;
}
return null;
},
localIdentName: '[local]',
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/issue-966/issue-966.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('issue #967', async () => {
const compiler = getCompiler('./modules/issue-967/path-placeholder.js', {
modules: {
mode: 'local',
localIdentName:
'[path][name]__[local]__/-sep-?-sep-<-sep->-sep-\\\\-sep-:-sep-*-sep-|-sep-"-sep-:',
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/issue-967/path-placeholder.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('issue #980', async () => {
const compiler = getCompiler(
'./modules/issue-980/file.with.many.dots.in.name.js',
{
modules: {
localIdentName: '[name]_[local]_[hash:base64:5]',
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource(
'./modules/issue-980/file.with.many.dots.in.name.css',
stats
)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('issue #995', async () => {
const compiler = getCompiler('./modules/issue-995/issue-995.js', {
modules: {
mode: 'global',
localIdentName: '😀',
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/issue-995/issue-995.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should avoid unnecessary "require"', async () => {
const compiler = getCompiler('./modules/composes/composes-duplicate.js', {
modules: true,
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/composes/composes-duplicate.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should keep order', async () => {
const compiler = getCompiler('./modules/order/index.js', { modules: true });
const stats = await compile(compiler);
expect(getModuleSource('./modules/order/index.css', stats)).toMatchSnapshot(
'module'
);
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should dedupe same modules in one module (issue #1037)', async () => {
const compiler = getCompiler('./modules/dedupe/source.js', {
modules: true,
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/dedupe/source.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('issue #1063', async () => {
const compiler = getCompiler('./modules/issue-1063/issue-1063.js', {
modules: {
mode: (resourcePath) => {
if (/pure.css$/i.test(resourcePath)) {
return 'pure';
}
if (/global.css$/i.test(resourcePath)) {
return 'global';
}
return 'local';
},
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/issue-1063/local.css', stats)
).toMatchSnapshot('module with the `local` mode');
expect(
getModuleSource('./modules/issue-1063/global.css', stats)
).toMatchSnapshot('module with the `global` mode');
expect(
getModuleSource('./modules/issue-1063/pure.css', stats)
).toMatchSnapshot('module with the `pure` mode');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('issue #1063 throw error', async () => {
const compiler = getCompiler('./modules/issue-1063/issue-1063.js', {
modules: {
mode: () => {
return 'not local, global or pure';
},
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/issue-1063/local.css', stats)
).toMatchSnapshot('module');
expect(
getModuleSource('./modules/issue-1063/global.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('issue #1191 - fallback to default getLocalIdent', async () => {
const compiler = getCompiler('./modules/issue-1191/issue-1191.js', {
modules: {
getLocalIdent: (ctx, localIdentName, localName) =>
ctx.resourcePath.includes('custom') ? `custom-${localName}` : null,
localIdentName: '[local]',
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/issue-1191/issue-1191.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with the `exportGlobals` option (the `mode` option is `global`)', async () => {
const compiler = getCompiler(
'./modules/exportGlobals-global/exportGlobals.js',
{
modules: {
mode: 'local',
exportGlobals: true,
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource('./modules/exportGlobals-global/exportGlobals.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with the `exportGlobals` option (the `mode` option is `local`)', async () => {
const compiler = getCompiler(
'./modules/exportGlobals-local/exportGlobals.js',
{
modules: {
mode: 'global',
exportGlobals: true,
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource('./modules/exportGlobals-local/exportGlobals.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with the `exportGlobals` option (the `mode` option is `pure`)', async () => {
const compiler = getCompiler(
'./modules/exportGlobals-pure/exportGlobals.js',
{
modules: {
mode: 'pure',
exportGlobals: true,
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource('./modules/exportGlobals-pure/exportGlobals.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with the "auto" by default', async () => {
const compiler = getCompiler('./modules/mode/modules.js');
const stats = await compile(compiler);
expect(
getModuleSource('./modules/mode/relative.module.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with the "auto" by default with "modules" filename', async () => {
const compiler = getCompiler('./modules/mode/modules-2.js');
const stats = await compile(compiler);
expect(
getModuleSource('./modules/mode/relative.modules.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with the "auto" by default for icss', async () => {
const compiler = getCompiler('./modules/mode/icss/icss.js');
const stats = await compile(compiler);
expect(
getModuleSource('./modules/mode/icss/relative.icss.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with the "auto" when it is "false"', async () => {
const compiler = getCompiler('./modules/mode/modules.js', {
modules: {
auto: false,
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/mode/relative.module.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with the "auto" when it is "true"', async () => {
const compiler = getCompiler('./modules/mode/modules.js', {
modules: {
auto: true,
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/mode/relative.module.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with a modules.auto RegExp that returns "true"', async () => {
const compiler = getCompiler('./modules/mode/modules.js', {
modules: {
auto: /relative\.module\.css$/,
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/mode/relative.module.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with a modules.auto RegExp that returns "false"', async () => {
const compiler = getCompiler('./modules/mode/modules.js', {
modules: {
auto: /will no pass/,
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/mode/relative.module.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with a modules.auto Function that returns "true"', async () => {
const compiler = getCompiler('./modules/mode/modules.js', {
modules: {
auto: (relativePath) => relativePath.endsWith('module.css'),
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/mode/relative.module.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with a modules.auto Function that returns "false"', async () => {
const compiler = getCompiler('./modules/mode/modules.js', {
modules: {
auto: (relativePath) => relativePath.endsWith('will no pass'),
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/mode/relative.module.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should resolve package from node_modules with and without tilde', async () => {
const compiler = getCompiler('./modules/issue-914/source.js', {
modules: true,
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/issue-914/source.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should throw an error on unresolved import', async () => {
const compiler = getCompiler('./modules/unresolved/source.js', {
modules: true,
});
const stats = await compile(compiler);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats, true)).toMatchSnapshot('errors');
});
it('should work and respect the "localConvention" option with the "asIs" value', async () => {
const compiler = getCompiler(
'./modules/localsConvention/localsConvention.js',
{
modules: {
mode: 'local',
exportLocalsConvention: 'asIs',
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localsConvention/localsConvention.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and respect the "localConvention" option with the "camelCase" value', async () => {
const compiler = getCompiler(
'./modules/localsConvention/localsConvention.js',
{
modules: {
mode: 'local',
exportLocalsConvention: 'camelCase',
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localsConvention/localsConvention.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and respect the "localConvention" option with the "camelCaseOnly" value', async () => {
const compiler = getCompiler(
'./modules/localsConvention/localsConvention.js',
{
modules: {
mode: 'local',
exportLocalsConvention: 'camelCaseOnly',
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localsConvention/localsConvention.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and respect the "localConvention" option with the "dashes" value', async () => {
const compiler = getCompiler(
'./modules/localsConvention/localsConvention.js',
{
modules: {
mode: 'local',
exportLocalsConvention: 'dashes',
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localsConvention/localsConvention.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and respect the "localConvention" option with the "dashesOnly" value', async () => {
const compiler = getCompiler(
'./modules/localsConvention/localsConvention.js',
{
modules: {
mode: 'local',
exportLocalsConvention: 'dashesOnly',
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource('./modules/localsConvention/localsConvention.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work and respect the "exportOnlyLocals" option', async () => {
const compiler = getCompiler('./modules/composes/composes.js', {
modules: {
mode: 'local',
localIdentName: '_[local]',
exportOnlyLocals: true,
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/composes/composes.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with "exportOnlyLocals" and "esModule" with "true" value options', async () => {
const compiler = getCompiler('./modules/composes/composes.js', {
modules: {
mode: 'local',
localIdentName: '_[local]',
exportOnlyLocals: true,
},
esModule: true,
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/composes/composes.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with "exportOnlyLocals" and "esModule" with "false" value options', async () => {
const compiler = getCompiler('./modules/composes/composes.js', {
modules: {
mode: 'local',
localIdentName: '_[local]',
exportOnlyLocals: true,
},
esModule: false,
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/composes/composes.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with an empty object value', async () => {
const compiler = getCompiler('./modules/pure/pure.js', { modules: {} });
const stats = await compile(compiler);
expect(getModuleSource('./modules/pure/pure.css', stats)).toMatchSnapshot(
'module'
);
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with the "namedExport" option', async () => {
const compiler = getCompiler('./modules/namedExport/base/index.js', {
modules: {
namedExport: true,
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/namedExport/base/index.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with the "namedExport" option with nested import', async () => {
const compiler = getCompiler('./modules/namedExport/nested/index.js', {
esModule: true,
modules: {
namedExport: true,
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/namedExport/nested/index.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work js template with "namedExport" option', async () => {
const compiler = getCompiler('./modules/namedExport/template/index.js', {
esModule: true,
modules: {
localIdentName: '[local]',
namedExport: true,
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/namedExport/template/index.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work when the "namedExport" is enabled and the "exportLocalsConvention" options has "dashesOnly" value', async () => {
const compiler = getCompiler('./modules/namedExport/dashesOnly/index.js', {
modules: {
localIdentName: '[local]',
namedExport: true,
exportLocalsConvention: 'dashesOnly',
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/namedExport/dashesOnly/index.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats, true)).toMatchSnapshot('errors');
});
it('should work with composes when the "namedExport" is enabled and "exportLocalsConvention" options has "dashesOnly" value', async () => {
const compiler = getCompiler('./modules/namedExport/composes/composes.js', {
modules: {
localIdentName: '_[local]',
namedExport: true,
exportLocalsConvention: 'dashesOnly',
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/namedExport/composes/composes.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should throw error with composes when the "namedExport" is enabled and "exportLocalsConvention" options has invalid value', async () => {
const compiler = getCompiler('./modules/namedExport/composes/composes.js', {
modules: {
localIdentName: '_[local]',
namedExport: true,
exportLocalsConvention: 'dashes',
},
});
const stats = await compile(compiler);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats, true)).toMatchSnapshot('errors');
});
it('should throw an error when the "namedExport" option is "true", but the "esModule" is "false"', async () => {
const compiler = getCompiler('./modules/namedExport/base/index.js', {
esModule: false,
modules: {
namedExport: true,
},
});
const stats = await compile(compiler);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats, true)).toMatchSnapshot('errors');
});
it('should throw an error when the "namedExport" is enabled and the "exportLocalsConvention" options has not "camelCaseOnly" value', async () => {
const compiler = getCompiler('./modules/namedExport/broken/index.js', {
esModule: true,
modules: {
namedExport: true,
exportLocalsConvention: 'dashes',
},
});
const stats = await compile(compiler);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats, true)).toMatchSnapshot('errors');
});
it('should throw an error when class has unsupported name (JavaScript reserved words)', async () => {
const compiler = getCompiler('./modules/namedExport/broken/index.js', {
esModule: true,
modules: {
namedExport: true,
},
});
const stats = await compile(compiler);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats, true)).toMatchSnapshot('errors');
});
it('should work with "exportOnlyLocals" and "namedExport" option', async () => {
const compiler = getCompiler('./modules/composes/composes-named.js', {
modules: {
mode: 'local',
localIdentName: '_[local]',
namedExport: true,
exportOnlyLocals: true,
},
esModule: true,
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/composes/composes.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with "url" and "namedExport"', async () => {
const compiler = getCompiler('./modules/url/source.js', {
modules: {
namedExport: true,
},
});
const stats = await compile(compiler);
expect(getModuleSource('./modules/url/source.css', stats)).toMatchSnapshot(
'module'
);
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should work with "url"', async () => {
const compiler = getCompiler('./modules/url/source.js', {
modules: true,
});
const stats = await compile(compiler);
expect(getModuleSource('./modules/url/source.css', stats)).toMatchSnapshot(
'module'
);
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
const icssTestCasesPath = path.join(
__dirname,
'fixtures/modules/icss/tests-cases'
);
const icssTestCases = fs.readdirSync(icssTestCasesPath);
icssTestCases.forEach((name) => {
it(`show work with the "compileType" option, case "${name}"`, async () => {
const compiler = getCompiler(
`./modules/icss/tests-cases/${name}/source.js`,
{
modules: {
compileType: 'icss',
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource(`./modules/icss/tests-cases/${name}/source.css`, stats)
).toMatchSnapshot('module');
expect(
getExecutedCode('main.bundle.js', compiler, stats)
).toMatchSnapshot('result');
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
});
it('show work with the "compileType" and "exportOnlyLocals" options', async () => {
const compiler = getCompiler(
'./modules/icss/tests-cases/import/source.js',
{
modules: {
compileType: 'icss',
exportOnlyLocals: true,
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource('./modules/icss/tests-cases/import/source.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('show work with the "compileType" and "namedExport" options', async () => {
const compiler = getCompiler(
'./modules/icss/tests-cases/import/source.js',
{
modules: {
compileType: 'icss',
namedExport: true,
},
}
);
const stats = await compile(compiler);
expect(
getModuleSource('./modules/icss/tests-cases/import/source.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('show work with the "compileType" option using the "module" value', async () => {
const compiler = getCompiler('./modules/composes/composes.js', {
modules: {
compileType: 'module',
},
});
const stats = await compile(compiler);
expect(
getModuleSource('./modules/composes/composes.css', stats)
).toMatchSnapshot('module');
expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
'result'
);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
it('should emit warning when localIdentName is emoji', async () => {
const compiler = getCompiler('./modules/pure/pure.js', {
modules: {
localIdentName: '[emoji:0]',
},
});
const stats = await compile(compiler);
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
});