diff --git a/index.js b/index.js index 45bff14..88c9ed8 100644 --- a/index.js +++ b/index.js @@ -1,78 +1,19 @@ 'use strict'; -if (global._cssModulesPolyfill) { - throw new Error('only one instance of css-modules/polyfill is allowed'); -} - -global._cssModulesPolyfill = true; - -var assign = require('object-assign'); -var options = {}; +var path = require('path'); -/** - * Posibility to pass custom options to the module - * @param {object} opts - */ -module.exports = function (opts) { - assign(options, opts); +var escape = function (str) { + return str.replace(/[\[\]\/{}()*+?.\\^$|-]/g, '\\$&'); }; -var Core = require('css-modules-loader-core'); -var pluginsCache; - -/** - * Caching plugins for the future calls - * @return {array} - */ -function loadPlugins() { - // retrieving from cache if they are already loaded - if (pluginsCache) { - return pluginsCache; - } - - // PostCSS plugins passed to FileSystemLoader - var plugins = options.use || options.u; - if (!plugins) { - plugins = Core.defaultPlugins; - } else { - if (typeof plugins === 'string') { - plugins = [ plugins ]; - } - - plugins = plugins.map(function requirePlugin (name) { - // assume functions are already required plugins - if (typeof name === 'function') { - return name; - } - - var plugin = require(require.resolve(name)); +var regexp = ['src', 'test'].map(function (i) { + return '^' + escape(path.join(__dirname, i) + path.sep); +}).join('|'); - // custom scoped name generation - if (name === 'postcss-modules-scope') { - options[name] = options[name] || {}; - options[name].generateScopedName = createScopedNameFunc(plugin); - } +require('babel/register')({ + only: new RegExp('(' + regexp + ')'), + ignore: false, + loose: 'all' +}); - if (name in options) { - plugin = plugin(options[name]); - } else { - plugin = plugin.postcss || plugin(); - } - - return plugin; - }); - } - - return pluginsCache = plugins; -} - -var FileSystemLoader = require('css-modules-loader-core/lib/file-system-loader'); -var path = require('path'); - -require.extensions['.css'] = function (m, filename) { - var plugins = loadPlugins(); - var loader = new FileSystemLoader(path.dirname(filename), plugins); - var tokens = loader.fetchSync(path.basename(filename), '/'); - - return m._compile('module.exports = ' + JSON.stringify(tokens), filename); -}; +module.exports = require('./src'); diff --git a/package.json b/package.json index 58d91c1..bf40324 100644 --- a/package.json +++ b/package.json @@ -4,18 +4,18 @@ "description": "A require hook to compile CSS Modules on the fly", "main": "index.js", "dependencies": { - "babel": "^5.6.14", - "object-assign": "^3.0.0" + "babel": "^5.8.20", + "css-modules-loader-core": "0.0.11", + "postcss": "^4.1.16", + "postcss-modules-extract-imports": "0.0.5", + "postcss-modules-local-by-default": "0.0.9", + "postcss-modules-scope": "0.0.8" }, "devDependencies": { "mocha": "^2.2.5" }, "scripts": { - "clone": "git clone https://github.com/sullenor/css-modules-loader-core.git node_modules/css-modules-loader-core", - "deps": "cd node_modules/css-modules-loader-core && npm i", - "postinstall": "npm run clone && npm run deps", - "preinstall": "rm -rf node_modules/css-modules-loader-core", - "test": "mocha test" + "test": "mocha --compilers js:babel/register" }, "repository": { "type": "git", diff --git a/src/guard.js b/src/guard.js new file mode 100644 index 0000000..c4a1c14 --- /dev/null +++ b/src/guard.js @@ -0,0 +1,7 @@ +'use strict'; + +if (global._cssModulesPolyfill) { + throw new Error('only one instance of css-modules/polyfill is allowed'); +} + +global._cssModulesPolyfill = true; diff --git a/src/hook.js b/src/hook.js new file mode 100644 index 0000000..d7bbd81 --- /dev/null +++ b/src/hook.js @@ -0,0 +1,11 @@ +'use strict'; + +/** + * @param {function} compile + */ +module.exports = function (compile) { + require.extensions['.css'] = function (m, filename) { + var tokens = compile(filename); + return m._compile('module.exports = ' + JSON.stringify(tokens), filename); + }; +}; diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..5f2eb40 --- /dev/null +++ b/src/index.js @@ -0,0 +1,68 @@ +'use strict'; + +import './guard'; +import hook from './hook'; +import postcss from 'postcss'; +import { basename, dirname, join, resolve } from 'path'; +import { readFileSync } from 'fs'; + +import extractImports from 'postcss-modules-extract-imports'; +import localByDefault from 'postcss-modules-local-by-default'; +import scope from 'postcss-modules-scope'; +import parser from './parser'; + +let plugins = [localByDefault, extractImports, scope]; + +const load = (sourceString, sourcePath, trace, pathFetcher) => { + let exportTokens = {}; + let result = postcss(plugins.concat(new parser({ exportTokens, pathFetcher, trace }))) + .process(sourceString, {from: '/' + sourcePath}) + .stringify(); + + return { injectableSource: result.css, exportTokens: exportTokens }; +} + +hook(filename => { + const root = dirname(filename); + const sources = {}; + const tokensByFile = {}; + let importNr = 0; + + const fetch = (_newPath, _relativeTo, _trace) => { + let newPath = _newPath.replace(/^["']|["']$/g, ''); + let trace = _trace || String.fromCharCode(importNr++); + + let relativeDir = dirname(_relativeTo); + let rootRelativePath = resolve(relativeDir, newPath); + let fileRelativePath = resolve(join(root, relativeDir), newPath); + + const tokens = tokensByFile[fileRelativePath]; + if (tokens) { + return tokens; + } + + let source = readFileSync(fileRelativePath, 'utf-8'); + let { injectableSource, exportTokens } = load(source, rootRelativePath, trace, fetch); + + sources[trace] = injectableSource; + tokensByFile[fileRelativePath] = exportTokens; + + return exportTokens; + } + + return fetch(basename(filename), '/'); +}); + +/** + * @param {object} opts + * @param {array} opts.u + * @param {array} opts.use + */ +export default function configure(opts) { + opts = opts || {}; + + let customPlugins = opts.u || opts.use; + plugins = Array.isArray(customPlugins) + ? customPlugins + : [localByDefault, extractImports, scope]; +} diff --git a/src/parser.js b/src/parser.js new file mode 100644 index 0000000..ae2b55f --- /dev/null +++ b/src/parser.js @@ -0,0 +1,66 @@ +'use strict'; + +import { plugin } from 'postcss'; + +const importRegexp = /^:import\((.+)\)$/ + +export default plugin('parser', function (opts) { + opts = opts || {}; + + let exportTokens = opts.exportTokens; + let translations = {}; + + const fetchImport = (importNode, relativeTo, depNr) => { + let file = importNode.selector.match( importRegexp )[1]; + let depTrace = opts.trace + String.fromCharCode(depNr); + let exports = opts.pathFetcher(file, relativeTo, depTrace); + + importNode.each(decl => { + if (decl.type === 'decl') { + translations[decl.prop] = exports[decl.value]; + } + }); + + importNode.removeSelf(); + } + + const fetchAllImports = css => { + let imports = 0; + + css.each(node => { + if (node.type === 'rule' && node.selector.match(importRegexp)) { + fetchImport(node, css.source.input.from, imports++); + } + }); + } + + const linkImportedSymbols = css => css.eachDecl(decl => { + Object.keys(translations).forEach(translation => { + decl.value = decl.value.replace(translation, translations[translation]) + }); + }); + + const handleExport = exportNode => { + exportNode.each(decl => { + if (decl.type === 'decl') { + Object.keys(translations).forEach(translation => { + decl.value = decl.value.replace(translation, translations[translation]) + }); + + exportTokens[decl.prop] = decl.value; + } + }); + + exportNode.removeSelf(); + } + + const extractExports = css => css.each(node => { + if (node.type === 'rule' && node.selector === ':export') handleExport(node); + }); + + return css => { + fetchAllImports(css); + linkImportedSymbols(css); + extractExports(css); + } +}); diff --git a/test/cssi/interchange-format/colors.css b/test/cssi/interchange-format/colors.css new file mode 100644 index 0000000..4057aae --- /dev/null +++ b/test/cssi/interchange-format/colors.css @@ -0,0 +1,7 @@ +:export { + blackShadow: x__single_import_export_colors__blackShadow; +} + +.x__single_import_export_colors__blackShadow { + box-shadow: 0 0 10px -2px black; +} diff --git a/test/cssi/interchange-format/expected.css b/test/cssi/interchange-format/expected.css new file mode 100644 index 0000000..36f1092 --- /dev/null +++ b/test/cssi/interchange-format/expected.css @@ -0,0 +1,6 @@ +.x__single_import_export_colors__blackShadow { + box-shadow: 0 0 10px -2px black; +} +.x__single_import_export_source__localName { + color: red; +} diff --git a/test/cssi/interchange-format/expected.json b/test/cssi/interchange-format/expected.json new file mode 100644 index 0000000..43311c7 --- /dev/null +++ b/test/cssi/interchange-format/expected.json @@ -0,0 +1,3 @@ +{ + "localName": "x__single_import_export_source__localName x__single_import_export_colors__blackShadow" +} diff --git a/test/cssi/interchange-format/source.css b/test/cssi/interchange-format/source.css new file mode 100644 index 0000000..d7125a0 --- /dev/null +++ b/test/cssi/interchange-format/source.css @@ -0,0 +1,11 @@ +:import("./colors.css") { + i__tmp_import_djhgdsag: blackShadow; +} + +:export { + localName: x__single_import_export_source__localName i__tmp_import_djhgdsag; +} + +.x__single_import_export_source__localName { + color: red; +} diff --git a/test/cssi/pseudo-variables/colors.css b/test/cssi/pseudo-variables/colors.css new file mode 100644 index 0000000..3ac72d9 --- /dev/null +++ b/test/cssi/pseudo-variables/colors.css @@ -0,0 +1,4 @@ +:export { + black: #222; + white: #ddd; +} diff --git a/test/cssi/pseudo-variables/expected.css b/test/cssi/pseudo-variables/expected.css new file mode 100644 index 0000000..371497c --- /dev/null +++ b/test/cssi/pseudo-variables/expected.css @@ -0,0 +1,5 @@ + +.x__lol { + color: #222; + background: #ddd; +} diff --git a/test/cssi/pseudo-variables/expected.json b/test/cssi/pseudo-variables/expected.json new file mode 100644 index 0000000..b8c3c23 --- /dev/null +++ b/test/cssi/pseudo-variables/expected.json @@ -0,0 +1,3 @@ +{ + "lol": "x__lol" +} diff --git a/test/cssi/pseudo-variables/source.css b/test/cssi/pseudo-variables/source.css new file mode 100644 index 0000000..cc4b95a --- /dev/null +++ b/test/cssi/pseudo-variables/source.css @@ -0,0 +1,13 @@ +:import("./colors.css") { + i__black: black; + i__white: white; +} + +:export { + lol: x__lol; +} + +.x__lol { + color: i__black; + background: i__white; +} diff --git a/test/example.css b/test/example.css deleted file mode 100644 index c28336c..0000000 --- a/test/example.css +++ /dev/null @@ -1,4 +0,0 @@ -.app -{ - background: #999; -} diff --git a/test/index.js b/test/index.js deleted file mode 100644 index 0c09386..0000000 --- a/test/index.js +++ /dev/null @@ -1,31 +0,0 @@ -describe('css-modules-require-hook', function () { - 'use strict'; - - var assert = require('assert'); - var styles; - - before(function (done) { - // loading hook - require('..'); - - try { - styles = require('./example.css'); - done(); - } catch(e) { - done(e); - } - }); - - it('loaded an object from "example.css" as a module', function () { - assert.strictEqual(typeof styles, 'object'); - }); - - it('module has the "app" key', function () { - assert(styles.hasOwnProperty('app')); - }); - - it('the value of the "app" key is not an empty string', function () { - assert.strictEqual(typeof styles.app, 'string', 'app\'s value is not a string'); - assert(styles.app, 'app contains an empty string'); - }); -}); diff --git a/test/test-cases.js b/test/test-cases.js new file mode 100644 index 0000000..bd93e8a --- /dev/null +++ b/test/test-cases.js @@ -0,0 +1,59 @@ +'use strict'; + +import assert from 'assert' +import fs from 'fs' +import path from 'path' +import FileSystemLoader from 'css-modules-loader-core/lib/file-system-loader' + +let normalize = ( str ) => { + return str.replace( /\r\n?/g, '\n' ); +} + +const pipelines = { + 'test-cases': undefined, + 'cssi': [] +} + +Object.keys( pipelines ).forEach( dirname => { + describe( dirname, () => { + let testDir = path.join( __dirname, dirname ) + + fs.readdirSync( testDir ).forEach( testCase => { + if ( fs.existsSync( path.join( testDir, testCase, 'source.css' ) ) ) { + it( 'should ' + testCase.replace( /-/g, ' ' ), done => { + let expected = normalize( fs.readFileSync( path.join( testDir, testCase, 'expected.css' ), 'utf-8' ) ) + let loader = new FileSystemLoader( testDir, pipelines[dirname] ) + let expectedTokens = JSON.parse( fs.readFileSync( path.join( testDir, testCase, 'expected.json' ), 'utf-8' ) ) + + loader.fetch( `${testCase}/source.css`, '/' ).then( tokens => { + assert.equal( loader.finalSource, expected ) + assert.equal( JSON.stringify( tokens ), JSON.stringify( expectedTokens ) ) + } ).then( done, done ) + } ); + } + } ); + } ); +} ) + +// special case for testing multiple sources +describe( 'multiple sources', () => { + let testDir = path.join( __dirname, 'test-cases' ) + let testCase = 'multiple-sources'; + let dirname = 'test-cases'; + + if ( fs.existsSync( path.join( testDir, testCase, 'source1.css' ) ) ) { + it( 'should ' + testCase.replace( /-/g, ' ' ), done => { + let expected = normalize( fs.readFileSync( path.join( testDir, testCase, 'expected.css' ), 'utf-8' ) ) + let loader = new FileSystemLoader( testDir, pipelines[dirname] ) + let expectedTokens = JSON.parse( fs.readFileSync( path.join( testDir, testCase, 'expected.json' ), 'utf-8' ) ) + + loader.fetch( `${testCase}/source1.css`, '/' ).then( tokens1 => { + loader.fetch( `${testCase}/source2.css`, '/' ).then( tokens2 => { + assert.equal( loader.finalSource, expected ) + const tokens = Object.assign({}, tokens1, tokens2); + assert.equal( JSON.stringify( tokens ), JSON.stringify( expectedTokens ) ) + } ).then( done, done ) + }) + } ); + } +} ); diff --git a/test/test-cases/localise-export/expected.css b/test/test-cases/localise-export/expected.css new file mode 100644 index 0000000..c4be0d9 --- /dev/null +++ b/test/test-cases/localise-export/expected.css @@ -0,0 +1,9 @@ +._localise_export_source__one { + color: red; +} +._localise_export_source__two { + color: green; +} +._localise_export_source__three { + color: blue; +} diff --git a/test/test-cases/localise-export/expected.json b/test/test-cases/localise-export/expected.json new file mode 100644 index 0000000..85eb15c --- /dev/null +++ b/test/test-cases/localise-export/expected.json @@ -0,0 +1,5 @@ +{ + "one": "_localise_export_source__one", + "two": "_localise_export_source__two", + "three": "_localise_export_source__three" +} diff --git a/test/test-cases/localise-export/source.css b/test/test-cases/localise-export/source.css new file mode 100644 index 0000000..8fdc200 --- /dev/null +++ b/test/test-cases/localise-export/source.css @@ -0,0 +1,9 @@ +:local(.one) { + color: red; +} +:local(.two) { + color: green; +} +:local(.three) { + color: blue; +} diff --git a/test/test-cases/multiple-dependencies/b.css b/test/test-cases/multiple-dependencies/b.css new file mode 100644 index 0000000..e29560a --- /dev/null +++ b/test/test-cases/multiple-dependencies/b.css @@ -0,0 +1,8 @@ +.b1 { + composes: d1 d2 from "./d.css"; + color: #b1b1b1; +} + +.b2 { + color: #b2b2b2; +} diff --git a/test/test-cases/multiple-dependencies/c.css b/test/test-cases/multiple-dependencies/c.css new file mode 100644 index 0000000..e5a7b52 --- /dev/null +++ b/test/test-cases/multiple-dependencies/c.css @@ -0,0 +1,3 @@ +.c { + color: #ccc; +} diff --git a/test/test-cases/multiple-dependencies/d.css b/test/test-cases/multiple-dependencies/d.css new file mode 100644 index 0000000..4e7ec24 --- /dev/null +++ b/test/test-cases/multiple-dependencies/d.css @@ -0,0 +1,6 @@ +.d1 { + color: #d1d1d1; +} +.d2 { + color: #d2d2d2; +} diff --git a/test/test-cases/multiple-dependencies/expected.css b/test/test-cases/multiple-dependencies/expected.css new file mode 100644 index 0000000..01b0d9f --- /dev/null +++ b/test/test-cases/multiple-dependencies/expected.css @@ -0,0 +1,20 @@ +._multiple_dependencies_d__d1 { + color: #d1d1d1; +} +._multiple_dependencies_d__d2 { + color: #d2d2d2; +} +._multiple_dependencies_b__b1 { + color: #b1b1b1; +} + +._multiple_dependencies_b__b2 { + color: #b2b2b2; +} +._multiple_dependencies_c__c { + color: #ccc; +} +._multiple_dependencies_source__a { + color: #aaa; +} + diff --git a/test/test-cases/multiple-dependencies/expected.json b/test/test-cases/multiple-dependencies/expected.json new file mode 100644 index 0000000..047434d --- /dev/null +++ b/test/test-cases/multiple-dependencies/expected.json @@ -0,0 +1,3 @@ +{ + "a": "_multiple_dependencies_source__a _multiple_dependencies_b__b1 _multiple_dependencies_d__d1 _multiple_dependencies_d__d2 _multiple_dependencies_b__b2 _multiple_dependencies_c__c" +} diff --git a/test/test-cases/multiple-dependencies/source.css b/test/test-cases/multiple-dependencies/source.css new file mode 100644 index 0000000..46e1595 --- /dev/null +++ b/test/test-cases/multiple-dependencies/source.css @@ -0,0 +1,6 @@ +.a { + composes: b1 b2 from "./b.css"; + composes: c from "./c.css"; + color: #aaa; +} + diff --git a/test/test-cases/multiple-sources/b.css b/test/test-cases/multiple-sources/b.css new file mode 100644 index 0000000..c4dcd92 --- /dev/null +++ b/test/test-cases/multiple-sources/b.css @@ -0,0 +1,4 @@ +.b { + composes: d from "./d.css"; + color: #bbb; +} diff --git a/test/test-cases/multiple-sources/c.css b/test/test-cases/multiple-sources/c.css new file mode 100644 index 0000000..e5a7b52 --- /dev/null +++ b/test/test-cases/multiple-sources/c.css @@ -0,0 +1,3 @@ +.c { + color: #ccc; +} diff --git a/test/test-cases/multiple-sources/d.css b/test/test-cases/multiple-sources/d.css new file mode 100644 index 0000000..4638a27 --- /dev/null +++ b/test/test-cases/multiple-sources/d.css @@ -0,0 +1,3 @@ +.d { + color: #ddd; +} diff --git a/test/test-cases/multiple-sources/expected.css b/test/test-cases/multiple-sources/expected.css new file mode 100644 index 0000000..da64401 --- /dev/null +++ b/test/test-cases/multiple-sources/expected.css @@ -0,0 +1,15 @@ +._multiple_sources_d__d { + color: #ddd; +} +._multiple_sources_b__b { + color: #bbb; +} +._multiple_sources_c__c { + color: #ccc; +} +._multiple_sources_source1__a { + color: #aaa; +} +._multiple_sources_source2__foo { + color: #f00; +} diff --git a/test/test-cases/multiple-sources/expected.json b/test/test-cases/multiple-sources/expected.json new file mode 100644 index 0000000..074abf9 --- /dev/null +++ b/test/test-cases/multiple-sources/expected.json @@ -0,0 +1,4 @@ +{ + "a": "_multiple_sources_source1__a _multiple_sources_b__b _multiple_sources_d__d _multiple_sources_c__c", + "foo": "_multiple_sources_source2__foo _multiple_sources_b__b _multiple_sources_d__d" +} diff --git a/test/test-cases/multiple-sources/source1.css b/test/test-cases/multiple-sources/source1.css new file mode 100644 index 0000000..983c7fd --- /dev/null +++ b/test/test-cases/multiple-sources/source1.css @@ -0,0 +1,5 @@ +.a { + composes: b from "./b.css"; + composes: c from "./c.css"; + color: #aaa; +} diff --git a/test/test-cases/multiple-sources/source2.css b/test/test-cases/multiple-sources/source2.css new file mode 100644 index 0000000..151a720 --- /dev/null +++ b/test/test-cases/multiple-sources/source2.css @@ -0,0 +1,4 @@ +.foo { + composes: b from "./b.css"; + color: #f00; +} diff --git a/test/test-cases/simple-export/expected.css b/test/test-cases/simple-export/expected.css new file mode 100644 index 0000000..2f8e4da --- /dev/null +++ b/test/test-cases/simple-export/expected.css @@ -0,0 +1,7 @@ +._simple_export_source__localName { + color: red; +} + +._simple_export_source__localName:hover { + color: blue; +} diff --git a/test/test-cases/simple-export/expected.json b/test/test-cases/simple-export/expected.json new file mode 100644 index 0000000..c8ee742 --- /dev/null +++ b/test/test-cases/simple-export/expected.json @@ -0,0 +1,3 @@ +{ + "localName": "_simple_export_source__localName" +} diff --git a/test/test-cases/simple-export/source.css b/test/test-cases/simple-export/source.css new file mode 100644 index 0000000..fbb8713 --- /dev/null +++ b/test/test-cases/simple-export/source.css @@ -0,0 +1,7 @@ +.localName { + color: red; +} + +.localName:hover { + color: blue; +} diff --git a/test/test-cases/single-import-export/colors.css b/test/test-cases/single-import-export/colors.css new file mode 100644 index 0000000..a7c1ce1 --- /dev/null +++ b/test/test-cases/single-import-export/colors.css @@ -0,0 +1,7 @@ +.blackShadow { + box-shadow: 0 0 10px -2px black; +} + +.redBorder { + border: 1px solid red; +} diff --git a/test/test-cases/single-import-export/expected.css b/test/test-cases/single-import-export/expected.css new file mode 100644 index 0000000..74398b2 --- /dev/null +++ b/test/test-cases/single-import-export/expected.css @@ -0,0 +1,10 @@ +._single_import_export_colors__blackShadow { + box-shadow: 0 0 10px -2px black; +} + +._single_import_export_colors__redBorder { + border: 1px solid red; +} +._single_import_export_source__localName { + color: red; +} diff --git a/test/test-cases/single-import-export/expected.json b/test/test-cases/single-import-export/expected.json new file mode 100644 index 0000000..802cd4e --- /dev/null +++ b/test/test-cases/single-import-export/expected.json @@ -0,0 +1,3 @@ +{ + "localName": "_single_import_export_source__localName _single_import_export_colors__blackShadow _single_import_export_colors__redBorder" +} diff --git a/test/test-cases/single-import-export/source.css b/test/test-cases/single-import-export/source.css new file mode 100644 index 0000000..57dbc17 --- /dev/null +++ b/test/test-cases/single-import-export/source.css @@ -0,0 +1,4 @@ +.localName { + composes: blackShadow redBorder from "./colors.css"; + color: red; +} diff --git a/test/test-hook.js b/test/test-hook.js new file mode 100644 index 0000000..a87328c --- /dev/null +++ b/test/test-hook.js @@ -0,0 +1,49 @@ +'use strict'; + +import fs from 'fs' +import path from 'path' +import { equal } from 'assert'; + +import hook from '../src'; + +const pipelines = { + 'test-cases': undefined, + 'cssi': [] +} + +Object.keys(pipelines).forEach(dirname => { + describe(dirname, () => { + let testDir = path.join(__dirname, dirname); + + fs.readdirSync(testDir).forEach(testCase => { + if (fs.existsSync(path.join(testDir, testCase, 'source.css'))) { + it('should ' + testCase.replace(/-/g, ' '), () => { + hook({use: pipelines[dirname]}); + let expectedTokens = JSON.parse(fs.readFileSync(path.join(testDir, testCase, 'expected.json'), 'utf-8')); + let tokens = require(`${testDir}/${testCase}/source.css`); + + equal(JSON.stringify(tokens), JSON.stringify(expectedTokens)); + }); + } + }); + }); +}); + +// special case for testing multiple sources +describe( 'multiple sources', () => { + let testDir = path.join(__dirname, 'test-cases'); + let testCase = 'multiple-sources'; + let dirname = 'test-cases'; + + if (fs.existsSync(path.join(testDir, testCase, 'source1.css'))) { + it('should ' + testCase.replace(/-/g, ' '), () => { + hook({use: pipelines[dirname]}); + let expectedTokens = JSON.parse(fs.readFileSync(path.join(testDir, testCase, 'expected.json'), 'utf-8')); + let tokens1 = require(`${testDir}/${testCase}/source1.css`); + let tokens2 = require(`${testDir}/${testCase}/source2.css`); + let tokens = Object.assign({}, tokens1, tokens2); + + equal(JSON.stringify(tokens), JSON.stringify(expectedTokens)); + }); + } +});