diff --git a/README.md b/README.md index f144cd5..38bcb7f 100644 --- a/README.md +++ b/README.md @@ -105,8 +105,11 @@ All the configurations receive a single object parameter with the following prop - `input`: The path to the target entry file - `output`: The Rollup output settings for the target. - `paths`: A dictionary with the filenames formats and paths of the different files the bundle can generate (`js`, `css`, `images` and `fonts`). -- `definitions`: A dictionary of defined variables that will be replaced on the bundled code. +- `definitions`: A function that generates a dictionary of variables that will be replaced on the bundled code. - `buildType`: The indented build type (`development` or `production`). +- `copy`: A list of information for files that need to be copied during the bundling process. +- `additionalWatch`: A list of additional paths Rollup should watch for in order to restart the bundle. +- `analyze`: A flag to detect if the bundled should be analyzed or not. #### Plugins configuration @@ -201,6 +204,13 @@ That change will only be applied when building the target `myApp` on a productio If you want to write a plugin that works with this one (like a framework plugin), there are a lot of reducer events you can listen for and use to modify the Rollup configuration: +### Configuration parameters + +- Name: `rollup-configuration-parameters` +- Reduces: The parameters used by the plugin services to build a target configuration. + +This is called before generating any configuration. + ### Node target configuration - Name: `rollup-node-configuration` diff --git a/package.json b/package.json index 48c3c85..e5db354 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "projext-plugin-rollup", "description": "Allows projext to use Rollup as a build engine.", "homepage": "https://homer0.github.io/projext-plugin-rollup/", - "version": "5.0.0", + "version": "5.1.0", "repository": "homer0/projext-plugin-rollup", "author": "Leonardo Apiwan (@homer0) ", "license": "MIT", diff --git a/src/plugins/stylesheetAssets/index.js b/src/plugins/stylesheetAssets/index.js index 87535dc..f84f6b2 100644 --- a/src/plugins/stylesheetAssets/index.js +++ b/src/plugins/stylesheetAssets/index.js @@ -341,52 +341,63 @@ class ProjextRollupStylesheetAssetsPlugin { * @ignore */ _updateCSSBlock(block) { - // Get all the linked files on the block. - const paths = this._getPathsForCSSBlock(block); - let { css } = block; - // Loop all the files. - paths - // Filter those which absolute path couldn't be found. - .filter((pathChange) => !!pathChange.absPath) - // Loop the filtered list. - .forEach((pathChange) => { - const { - absPath, - line, - query, - info, - } = pathChange; - // Try to find a URL setting which filter matches a file absolute path. - const settings = this._options.urls.find((setting) => setting.filter(absPath)); - // If a URL setting was found... - if (settings) { - // Generate the output path where the file will be copied. - const output = ProjextRollupUtils.formatPlaceholder(settings.output, info); - // Get the directory where the file will be copied. - const outputDir = path.dirname(output); - // Generate the new URL for the file. - const urlBase = ProjextRollupUtils.formatPlaceholder(settings.url, info); - // Append any existing query the file originally had. - const newURL = `${urlBase}${query}`; - // Generate the new statement for the CSS. - const newLine = `url('${newURL}')`; - // Generate a RegExp that matches the old statement. - const lineRegex = new RegExp(ProjextRollupUtils.escapeRegex(line.trim()), 'ig'); - // if the directory wasn't already created, create it. - if (!this._createdDirectoriesCache.includes(outputDir)) { - fs.ensureDirSync(outputDir); - this._createdDirectoriesCache.push(outputDir); + let result; + /** + * If there's a map on the block (because on watch mode Rollup caches the files' + * transformations), then do the processing, otherwise, just set to return the same block. + */ + if (block.map) { + // Get all the linked files on the block. + const paths = this._getPathsForCSSBlock(block); + let { css } = block; + // Loop all the files. + paths + // Filter those which absolute path couldn't be found. + .filter((pathChange) => !!pathChange.absPath) + // Loop the filtered list. + .forEach((pathChange) => { + const { + absPath, + line, + query, + info, + } = pathChange; + // Try to find a URL setting which filter matches a file absolute path. + const settings = this._options.urls.find((setting) => setting.filter(absPath)); + // If a URL setting was found... + if (settings) { + // Generate the output path where the file will be copied. + const output = ProjextRollupUtils.formatPlaceholder(settings.output, info); + // Get the directory where the file will be copied. + const outputDir = path.dirname(output); + // Generate the new URL for the file. + const urlBase = ProjextRollupUtils.formatPlaceholder(settings.url, info); + // Append any existing query the file originally had. + const newURL = `${urlBase}${query}`; + // Generate the new statement for the CSS. + const newLine = `url('${newURL}')`; + // Generate a RegExp that matches the old statement. + const lineRegex = new RegExp(ProjextRollupUtils.escapeRegex(line.trim()), 'ig'); + // if the directory wasn't already created, create it. + if (!this._createdDirectoriesCache.includes(outputDir)) { + fs.ensureDirSync(outputDir); + this._createdDirectoriesCache.push(outputDir); + } + // Copy the file. + fs.copySync(absPath, output); + // Add an stats entry that the file was copied. + this._options.stats(this.name, output); + // Replace the old statement with the new one. + css = css.replace(lineRegex, newLine); } - // Copy the file. - fs.copySync(absPath, output); - // Add an stats entry that the file was copied. - this._options.stats(this.name, output); - // Replace the old statement with the new one. - css = css.replace(lineRegex, newLine); - } - }); - // Return the updated block with the new CSS code. - return Object.assign({}, block, { css }); + }); + // set to return the updated block with the new CSS code. + result = Object.assign({}, block, { css }); + } else { + result = block; + } + + return result; } /** * Gets a list of dictionaries with the information of all the files linked on a CSS block. diff --git a/src/services/building/configuration.js b/src/services/building/configuration.js index c859e4e..615624e 100644 --- a/src/services/building/configuration.js +++ b/src/services/building/configuration.js @@ -50,11 +50,17 @@ class RollupConfiguration { } /** * This method generates a complete Rollup configuration for a target. + * Before creating the configuration, it uses the reducer event + * `rollup-configuration-parameters-for-browser` or `rollup-configuration-parameters-for-node`, + * depending on the target type, and then `rollup-configuration-parameters` to reduce + * the parameters ({@link RollupConfigurationParams}) the services will use to generate the + * configuration. The event recevies the parameters and expects updated parameters in return. * @param {Target} target The target information. * @param {string} buildType The intended build type: `production` or `development`. * @return {Object} * @throws {Error} If there's no base configuration for the target type. * @throws {Error} If there's no base configuration for the target type and build type. + * @todo Stop using `events` from `targets` and inject it directly on the class. */ getConfig(target, buildType) { const targetType = target.type; @@ -64,39 +70,14 @@ class RollupConfiguration { throw new Error(`There's no configuration for the selected build type: ${buildType}`); } - const paths = Object.assign({}, target.output[buildType]); - const input = path.join(target.paths.source, target.entry[buildType]); - const defaultFormat = this._getTargetDefaultFormat(target); - const output = { - sourcemap: !!(target.sourceMap && target.sourceMap[buildType]), - name: target.name.replace(/-(\w)/ig, (match, letter) => letter.toUpperCase()), - }; - - if (target.library) { - output.format = this._getLibraryFormat(target.libraryOptions); - output.exports = 'named'; - } else { - output.format = defaultFormat; - } - - const filepath = `./${target.folders.build}/${paths.js}`; - + const paths = Object.assign({}, target.output[buildType]); if (paths.jsChunks === true) { paths.jsChunks = this._generateChunkName(paths.js); } - if (paths.jsChunks) { - output.chunkFileNames = path.basename(paths.jsChunks); - output.entryFileNames = path.basename(paths.js); - output.dir = path.dirname(filepath); - if (target.is.browser && !target.library) { - output.format = 'es'; - } - } else { - output.file = filepath; - } + const output = this._getTargetOutput(target, paths, buildType); const copy = []; if (target.is.browser || target.bundle) { @@ -106,7 +87,7 @@ class RollupConfiguration { const definitions = this._getDefinitionsGenerator(target, buildType); const additionalWatch = this._getBrowserTargetConfigurationDefinitions(target).files; - const params = { + let params = { input, output, target, @@ -123,6 +104,15 @@ class RollupConfiguration { analyze: !!target.analyze, }; + const eventName = target.is.node ? + 'rollup-configuration-parameters-for-node' : + 'rollup-configuration-parameters-for-browser'; + + params = this.targets.events.reduce( + [eventName, 'rollup-configuration-parameters'], + params + ); + let config = this.targetConfiguration( `rollup/${target.name}.config.js`, this.rollupConfigurations[targetType][buildType] @@ -134,6 +124,61 @@ class RollupConfiguration { return config; } + /** + * Generates the Rollup output configuration setting based on the target information, its + * pared paths and the type of build. + * @param {Target} target The target information. + * @param {Object} formattedPaths The target `paths` setting for the selected build type. The + * reason they are received as a separated parameter is because + * in case the paths originally had a `jsChunk` property, the + * service parsed it in order to inject the paths to the + * actual chunks. Check the method `getConfig` for more + * information. + * @param {string} buildType The intended build type: `production` or `development`. + * @return {Object} The Rollup output configuration. + * @property {boolean} sourcemap Whether or not to include source maps. + * @property {string} name The name of the bundle, in case it exports something. + * @property {string} format The bundle format (`es`, `iifee` or `cjs`). + * @property {string} file The name of the bundle when code splitting is not used. + * @property {?string} exports In case the target is a library, this will `named`, as the + * default export mode for libraries. + * @property {?string} chunkFileNames If code splitting is used, this will be the base name of + * the chunk files. + * @property {?string} entryFileNames If code splitting is used, this will be the base name of + * the main bundle. + * @property {?string} dir If code splitting is used, this will be the directory + * where the chunk files will be saved. + * @access protected + * @ignore + */ + _getTargetOutput(target, formattedPaths, buildType) { + const output = { + sourcemap: !!(target.sourceMap && target.sourceMap[buildType]), + name: target.name.replace(/-(\w)/ig, (match, letter) => letter.toUpperCase()), + }; + + if (target.library) { + output.format = this._getLibraryFormat(target.libraryOptions); + output.exports = 'named'; + } else { + output.format = this._getTargetDefaultFormat(target); + } + + const filepath = `./${target.folders.build}/${formattedPaths.js}`; + + if (formattedPaths.jsChunks) { + output.chunkFileNames = path.basename(formattedPaths.jsChunks); + output.entryFileNames = path.basename(formattedPaths.js); + output.dir = path.dirname(filepath); + if (target.is.browser && !target.library) { + output.format = 'es'; + } + } else { + output.file = filepath; + } + + return output; + } /** * Based on the taget type, this method will decide which will be the default output format * the target will use. The reason this is the "default" format, it's because the service @@ -245,8 +290,8 @@ class RollupConfiguration { return result; } /** - * This is a small helper function that parses the default path of the JS file webpack will - * emmit and adds a `[name]` placeholder for webpack to replace with the chunk name. + * This is a small helper function that parses the default path of the JS file Rollup will + * emmit and adds a `[name]` placeholder for Rollup to replace with the chunk name. * @param {string} jsPath The original path for the JS file. * @return {string} * @access protected diff --git a/src/services/configurations/pluginsConfiguration.js b/src/services/configurations/pluginsConfiguration.js index 99b55da..1292f49 100644 --- a/src/services/configurations/pluginsConfiguration.js +++ b/src/services/configurations/pluginsConfiguration.js @@ -731,9 +731,9 @@ class RollupPluginSettingsConfiguration extends ConfigurationFile { ); } /** - * Defines the settings for the `stylesheetAssets` plugin, which is a projext's plugin that - * transform files matching a filter by copying its contents into a new file on the output - * directory and replacing its default export with a URL for them. + * Defines the settings for the `urls` plugin, which is a projext's plugin that transforms + * files matching a filter and copies its contents into a new file on the output directory, + * then it replaces its default export with a URL for them. * This method uses the reducer event `rollup-urls-plugin-settings-configuration-for-browser` or * `rollup-urls-plugin-settings-configuration-for-node`, depending on the target type, and then * `rollup-urls-plugin-settings-configuration`. The event receives the settings, the `params` diff --git a/src/typedef.js b/src/typedef.js index 7341531..eafb976 100644 --- a/src/typedef.js +++ b/src/typedef.js @@ -555,7 +555,7 @@ * A list of {@link TargetExtraFile} with the information of files that need to be copied during * the bundling process. * @property {Array} additionalWatch - * A list of additional paths webpack should watch for in order to restart the bundle. + * A list of additional paths Rollup should watch for in order to restart the bundle. */ /** diff --git a/tests/plugins/stylesheetAssets/index.test.js b/tests/plugins/stylesheetAssets/index.test.js index 3fc7d99..f94da89 100644 --- a/tests/plugins/stylesheetAssets/index.test.js +++ b/tests/plugins/stylesheetAssets/index.test.js @@ -431,6 +431,59 @@ describe('plugins:stylesheetAssets', () => { ); }); + it('shouldn\'t fail to process a file without a map', () => { + // Given + const extension = '.png'; + const assetOne = `file${extension}`; + const assetTwo = `fileB${extension}`; + const assetThree = 'fileC.html'; + const assetFour = `fileD${extension}`; + const firstCodePart = [ + `a { background: url('./${assetOne}'); }`, + `a.blue { background: url('./${assetTwo}?v=1.0'); }`, + `a.light-blue { background: url('./${assetTwo}?v=1.0'); }`, + `a.green { background: url('./${assetThree}'); }`, + ] + .join('\n'); + const fileContents = [ + `${firstCodePart}`, + `a.red { background: url('./${assetFour}'); }`, + ] + .join('\n'); + const filter = jest.fn((filepath) => filepath.endsWith(extension)); + rollupUtils.createFilter.mockImplementationOnce(() => filter); + ProjextRollupUtils.escapeRegex + .mockImplementation((exp) => exp.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')); + fs.pathExistsSync.mockImplementationOnce(() => true); + fs.readFileSync.mockImplementationOnce(() => fileContents); + const url = { + include: ['include-some-files'], + exclude: ['exclude-some-files'], + output: 'output', + url: 'url', + }; + const options = { + stylesheet: 'some-file.css', + urls: [url], + stats: jest.fn(), + }; + let sut = null; + // When + sut = new ProjextRollupStylesheetAssetsPlugin(options); + sut.writeBundle(); + // Then + expect(fs.pathExistsSync).toHaveBeenCalledTimes(1); + expect(fs.pathExistsSync).toHaveBeenCalledWith(options.stylesheet); + expect(fs.readFileSync).toHaveBeenCalledTimes(1); + expect(fs.readFileSync).toHaveBeenCalledWith(options.stylesheet, 'utf-8'); + expect(ProjextRollupUtils.formatPlaceholder).toHaveBeenCalledTimes(0); + expect(fs.writeFileSync).toHaveBeenCalledTimes(1); + expect(fs.writeFileSync).toHaveBeenCalledWith( + options.stylesheet, + fileContents + ); + }); + it('should provide a shorthand method to instantiate the plugin', () => { // Given const filter = 'filter'; diff --git a/tests/services/building/configuration.test.js b/tests/services/building/configuration.test.js index c77221d..97f530a 100644 --- a/tests/services/building/configuration.test.js +++ b/tests/services/building/configuration.test.js @@ -113,12 +113,16 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const envVarName = 'ROSARIO'; const envVarValue = 'Charito'; const targets = { loadTargetDotEnvFile: jest.fn(() => ({ [envVarName]: envVarValue, })), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -162,6 +166,23 @@ describe('services/building:configuration', () => { let result = null; let definitionsGenerator = null; let generatedDefinitions = null; + const expectedParams = { + input: path.join(target.paths.source, target.entry[buildType]), + output: { + file: `./${target.folders.build}/${target.output[buildType].js}`, + format: 'cjs', + sourcemap: false, + name: 'target', + }, + target, + buildType, + targetRules, + definitions: expect.any(Function), + paths: target.output[buildType], + copy: [], + additionalWatch: [], + analyze: false, + }; // When sut = new RollupConfiguration( buildVersion, @@ -196,23 +217,15 @@ describe('services/building:configuration', () => { expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(1); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledWith(target, buildType); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - input: path.join(target.paths.source, target.entry[buildType]), - output: { - file: `./${target.folders.build}/${target.output[buildType].js}`, - format: 'cjs', - sourcemap: false, - name: 'target', - }, - target, - buildType, - targetRules, - definitions: expect.any(Function), - paths: target.output[buildType], - copy: [], - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'rollup-configuration-parameters-for-node', + 'rollup-configuration-parameters', + ], + expectedParams + ); }); it('should generate the configuration for a Node target that requires bundling', () => { @@ -231,10 +244,14 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const filesToCopy = ['copy']; const targets = { getFilesToCopy: jest.fn(() => filesToCopy), loadTargetDotEnvFile: jest.fn(() => ({})), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -277,6 +294,23 @@ describe('services/building:configuration', () => { }; let sut = null; let result = null; + const expectedParams = { + input: path.join(target.paths.source, target.entry[buildType]), + output: { + file: `./${target.folders.build}/${target.output[buildType].js}`, + format: 'cjs', + sourcemap: false, + name: 'target', + }, + target, + buildType, + targetRules, + definitions: expect.any(Function), + paths: target.output[buildType], + copy: filesToCopy, + additionalWatch: [], + analyze: false, + }; // When sut = new RollupConfiguration( buildVersion, @@ -303,25 +337,17 @@ describe('services/building:configuration', () => { ); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(0); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - input: path.join(target.paths.source, target.entry[buildType]), - output: { - file: `./${target.folders.build}/${target.output[buildType].js}`, - format: 'cjs', - sourcemap: false, - name: 'target', - }, - target, - buildType, - targetRules, - definitions: expect.any(Function), - paths: target.output[buildType], - copy: filesToCopy, - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); expect(targets.getFilesToCopy).toHaveBeenCalledTimes(1); expect(targets.getFilesToCopy).toHaveBeenCalledWith(target, buildType); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'rollup-configuration-parameters-for-node', + 'rollup-configuration-parameters', + ], + expectedParams + ); }); it('should generate the configuration for a Node target that requires code splitting', () => { @@ -340,10 +366,14 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const filesToCopy = ['copy']; const targets = { getFilesToCopy: jest.fn(() => filesToCopy), loadTargetDotEnvFile: jest.fn(() => ({})), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -387,6 +417,27 @@ describe('services/building:configuration', () => { }; let sut = null; let result = null; + const expectedParams = { + input: path.join(target.paths.source, target.entry[buildType]), + output: { + chunkFileNames: target.output[buildType].js.replace(/\.js$/, '.[name].js'), + entryFileNames: target.output[buildType].js, + dir: `./${target.folders.build}`, + format: 'cjs', + sourcemap: false, + name: 'target', + }, + target, + buildType, + targetRules, + definitions: expect.any(Function), + paths: Object.assign({}, target.output[buildType], { + jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), + }), + copy: filesToCopy, + additionalWatch: [], + analyze: false, + }; // When sut = new RollupConfiguration( buildVersion, @@ -413,29 +464,17 @@ describe('services/building:configuration', () => { ); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(0); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - input: path.join(target.paths.source, target.entry[buildType]), - output: { - chunkFileNames: target.output[buildType].js.replace(/\.js$/, '.[name].js'), - entryFileNames: target.output[buildType].js, - dir: `./${target.folders.build}`, - format: 'cjs', - sourcemap: false, - name: 'target', - }, - target, - buildType, - targetRules, - definitions: expect.any(Function), - paths: Object.assign({}, target.output[buildType], { - jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), - }), - copy: filesToCopy, - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); expect(targets.getFilesToCopy).toHaveBeenCalledTimes(1); expect(targets.getFilesToCopy).toHaveBeenCalledWith(target, buildType); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'rollup-configuration-parameters-for-node', + 'rollup-configuration-parameters', + ], + expectedParams + ); }); it('should generate the configuration for a browser target', () => { @@ -456,10 +495,14 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const filesToCopy = ['copy']; const targets = { getFilesToCopy: jest.fn(() => filesToCopy), loadTargetDotEnvFile: jest.fn(() => ({})), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -501,6 +544,23 @@ describe('services/building:configuration', () => { }; let sut = null; let result = null; + const expectedParams = { + input: path.join(target.paths.source, target.entry[buildType]), + output: { + file: `./${target.folders.build}/${target.output[buildType].js}`, + format: 'iife', + sourcemap: false, + name: 'target', + }, + target, + buildType, + targetRules, + definitions: expect.any(Function), + paths: target.output[buildType], + copy: filesToCopy, + additionalWatch: [], + analyze: false, + }; // When sut = new RollupConfiguration( buildVersion, @@ -525,25 +585,17 @@ describe('services/building:configuration', () => { ); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(0); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - input: path.join(target.paths.source, target.entry[buildType]), - output: { - file: `./${target.folders.build}/${target.output[buildType].js}`, - format: 'iife', - sourcemap: false, - name: 'target', - }, - target, - buildType, - targetRules, - definitions: expect.any(Function), - paths: target.output[buildType], - copy: filesToCopy, - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); expect(targets.getFilesToCopy).toHaveBeenCalledTimes(1); expect(targets.getFilesToCopy).toHaveBeenCalledWith(target, buildType); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'rollup-configuration-parameters-for-browser', + 'rollup-configuration-parameters', + ], + expectedParams + ); }); it('should generate the configuration for a browser target with code splitting', () => { @@ -564,10 +616,14 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const filesToCopy = ['copy']; const targets = { getFilesToCopy: jest.fn(() => filesToCopy), loadTargetDotEnvFile: jest.fn(() => ({})), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -610,6 +666,25 @@ describe('services/building:configuration', () => { }; let sut = null; let result = null; + const expectedParams = { + input: path.join(target.paths.source, target.entry[buildType]), + output: { + chunkFileNames: path.basename(target.output[buildType].jsChunks), + entryFileNames: path.basename(target.output[buildType].js), + dir: path.dirname(`./${target.folders.build}/${target.output[buildType].js}`), + format: 'es', + sourcemap: false, + name: 'target', + }, + target, + buildType, + targetRules, + definitions: expect.any(Function), + paths: target.output[buildType], + copy: filesToCopy, + additionalWatch: [], + analyze: false, + }; // When sut = new RollupConfiguration( buildVersion, @@ -634,27 +709,17 @@ describe('services/building:configuration', () => { ); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(0); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - input: path.join(target.paths.source, target.entry[buildType]), - output: { - chunkFileNames: path.basename(target.output[buildType].jsChunks), - entryFileNames: path.basename(target.output[buildType].js), - dir: path.dirname(`./${target.folders.build}/${target.output[buildType].js}`), - format: 'es', - sourcemap: false, - name: 'target', - }, - target, - buildType, - targetRules, - definitions: expect.any(Function), - paths: target.output[buildType], - copy: filesToCopy, - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); expect(targets.getFilesToCopy).toHaveBeenCalledTimes(1); expect(targets.getFilesToCopy).toHaveBeenCalledWith(target, buildType); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'rollup-configuration-parameters-for-browser', + 'rollup-configuration-parameters', + ], + expectedParams + ); }); it('should generate the configuration for a browser target and `define` its config', () => { @@ -673,6 +738,9 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const targetBrowserConfigFiles = ['some-config-file']; const targetBrowserConfig = { someProp: 'someValue', @@ -685,6 +753,7 @@ describe('services/building:configuration', () => { })), getFilesToCopy: jest.fn(() => filesToCopy), loadTargetDotEnvFile: jest.fn(() => ({})), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -728,6 +797,23 @@ describe('services/building:configuration', () => { let result = null; let definitionsGenerator = null; let generatedDefinitions = null; + const expectedParams = { + input: path.join(target.paths.source, target.entry[buildType]), + output: { + file: `./${target.folders.build}/${target.output[buildType].js}`, + format: 'iife', + sourcemap: false, + name: 'target', + }, + target, + buildType, + targetRules, + definitions: expect.any(Function), + paths: target.output[buildType], + copy: filesToCopy, + additionalWatch: targetBrowserConfigFiles, + analyze: false, + }; // When sut = new RollupConfiguration( buildVersion, @@ -760,28 +846,20 @@ describe('services/building:configuration', () => { expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(1); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledWith(target, buildType); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - input: path.join(target.paths.source, target.entry[buildType]), - output: { - file: `./${target.folders.build}/${target.output[buildType].js}`, - format: 'iife', - sourcemap: false, - name: 'target', - }, - target, - buildType, - targetRules, - definitions: expect.any(Function), - paths: target.output[buildType], - copy: filesToCopy, - additionalWatch: targetBrowserConfigFiles, - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); expect(targets.getBrowserTargetConfiguration).toHaveBeenCalledTimes(2); expect(targets.getBrowserTargetConfiguration).toHaveBeenCalledWith(target); expect(targets.getBrowserTargetConfiguration).toHaveBeenCalledWith(target); expect(targets.getFilesToCopy).toHaveBeenCalledTimes(1); expect(targets.getFilesToCopy).toHaveBeenCalledWith(target, buildType); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'rollup-configuration-parameters-for-browser', + 'rollup-configuration-parameters', + ], + expectedParams + ); }); it('should generate the configuration for a Node library target', () => { @@ -802,8 +880,12 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const targets = { loadTargetDotEnvFile: jest.fn(() => ({})), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -855,6 +937,24 @@ describe('services/building:configuration', () => { }; let sut = null; let result = null; + const expectedParams = { + input: path.join(target.paths.source, target.entry[buildType]), + output: { + file: `./${target.folders.build}/${target.output[buildType].js}`, + format: 'cjs', + sourcemap: false, + name: 'target', + exports: 'named', + }, + target, + buildType, + targetRules, + definitions: expect.any(Function), + paths: target.output[buildType], + copy: [], + additionalWatch: [], + analyze: false, + }; // When sut = new RollupConfiguration( buildVersion, @@ -879,24 +979,15 @@ describe('services/building:configuration', () => { ); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(0); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - input: path.join(target.paths.source, target.entry[buildType]), - output: { - file: `./${target.folders.build}/${target.output[buildType].js}`, - format: 'cjs', - sourcemap: false, - name: 'target', - exports: 'named', - }, - target, - buildType, - targetRules, - definitions: expect.any(Function), - paths: target.output[buildType], - copy: [], - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'rollup-configuration-parameters-for-node', + 'rollup-configuration-parameters', + ], + expectedParams + ); }); it('should generate the configuration for a browser library target', () => { @@ -918,10 +1009,14 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const filesToCopy = ['copy']; const targets = { getFilesToCopy: jest.fn(() => filesToCopy), loadTargetDotEnvFile: jest.fn(() => ({})), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -967,6 +1062,8 @@ describe('services/building:configuration', () => { [buildType]: {}, }, }; + let sut = null; + let result = null; const expectedConfig = { output: { path: 'some-output-path', @@ -975,8 +1072,24 @@ describe('services/building:configuration', () => { sourcemap: true, }, }; - let sut = null; - let result = null; + const expectedParams = { + input: path.join(target.paths.source, target.entry[buildType]), + output: { + file: `./${target.folders.build}/${target.output[buildType].js}`, + format: 'umd', + sourcemap: true, + name: 'someTarget', + exports: 'named', + }, + target, + buildType, + targetRules, + definitions: expect.any(Function), + paths: target.output[buildType], + copy: filesToCopy, + additionalWatch: [], + analyze: false, + }; // When sut = new RollupConfiguration( buildVersion, @@ -1001,26 +1114,17 @@ describe('services/building:configuration', () => { ); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(0); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - input: path.join(target.paths.source, target.entry[buildType]), - output: { - file: `./${target.folders.build}/${target.output[buildType].js}`, - format: 'umd', - sourcemap: true, - name: 'someTarget', - exports: 'named', - }, - target, - buildType, - targetRules, - definitions: expect.any(Function), - paths: target.output[buildType], - copy: filesToCopy, - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); expect(targets.getFilesToCopy).toHaveBeenCalledTimes(1); expect(targets.getFilesToCopy).toHaveBeenCalledWith(target, buildType); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'rollup-configuration-parameters-for-browser', + 'rollup-configuration-parameters', + ], + expectedParams + ); }); it('should map window to UMD as library target', () => { @@ -1042,8 +1146,12 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const targets = { loadTargetDotEnvFile: jest.fn(() => ({})), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -1089,6 +1197,8 @@ describe('services/building:configuration', () => { [buildType]: {}, }, }; + let sut = null; + let result = null; const expectedConfig = { output: { path: 'some-output-path', @@ -1097,8 +1207,24 @@ describe('services/building:configuration', () => { sourcemap: true, }, }; - let sut = null; - let result = null; + const expectedParams = { + input: path.join(target.paths.source, target.entry[buildType]), + output: { + file: `./${target.folders.build}/${target.output[buildType].js}`, + format: 'umd', + sourcemap: true, + name: 'someTarget', + exports: 'named', + }, + target, + buildType, + targetRules, + definitions: expect.any(Function), + paths: target.output[buildType], + copy: [], + additionalWatch: [], + analyze: false, + }; // When sut = new RollupConfiguration( buildVersion, @@ -1123,24 +1249,15 @@ describe('services/building:configuration', () => { ); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(0); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - input: path.join(target.paths.source, target.entry[buildType]), - output: { - file: `./${target.folders.build}/${target.output[buildType].js}`, - format: 'umd', - sourcemap: true, - name: 'someTarget', - exports: 'named', - }, - target, - buildType, - targetRules, - definitions: expect.any(Function), - paths: target.output[buildType], - copy: [], - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'rollup-configuration-parameters-for-node', + 'rollup-configuration-parameters', + ], + expectedParams + ); }); it('should include a provider for the DIC', () => {