diff --git a/jest.config.js b/jest.config.js index 200af3ed1d4..59eb975f718 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,10 @@ +const { cli } = require('webpack'); + +//ignore core-flags test for webpack@4 +const ignorePattern = typeof cli !== 'undefined' ? ['/node_modules/'] : ['/node_modules/', '/test/core-flags']; + module.exports = { - testPathIgnorePatterns: ['/node_modules/'], + testPathIgnorePatterns: ignorePattern, // transformIgnorePatterns: ['.*(node_modules)(?!.*webpack-cli.*).*$'], testEnvironment: 'node', collectCoverage: true, diff --git a/packages/webpack-cli/README.md b/packages/webpack-cli/README.md index 56dcd262574..5338a7739cf 100644 --- a/packages/webpack-cli/README.md +++ b/packages/webpack-cli/README.md @@ -22,19 +22,20 @@ yarn add webpack-cli --dev ## Supported arguments and commands -``` - -Available Commands +### Available Commands +``` init Initialize a new webpack configuration migrate Migrate a configuration to a new version loader Scaffold a loader repository plugin Scaffold a plugin repository info Outputs information about your system and dependencies serve Run the webpack Dev Server +``` -Options +### webpack 4 +``` --entry string[] The entry point(s) of your application. -c, --config string Provide path to a webpack configuration file -m, --merge string Merge a configuration file using webpack-merge @@ -57,6 +58,611 @@ Options --verbose It tells webpack to output all the information ``` +### webpack 5 + +``` + --amd You can pass `false` to disable AMD support. + --bail Report the first error as a hard error instead of tolerating it. + --cache Enable in memory caching. Disable caching. + --cache-immutable-paths string[] A path to a immutable directory (usually a package manager cache directory). + --cache-immutable-paths-reset Clear all items provided in configuration. List of paths that are managed by + a package manager and contain a version or hash in its path so all files are + immutable. + --cache-managed-paths string[] A path to a managed directory (usually a node_modules directory). + --cache-managed-paths-reset Clear all items provided in configuration. List of paths that are managed by + a package manager and can be trusted to not be modified otherwise. + --cache-type string In memory caching. Filesystem caching. + --cache-cache-directory string Base directory for the cache (defaults to node_modules/.cache/webpack). + --cache-cache-location string Locations for the cache (defaults to cacheDirectory / name). + --cache-hash-algorithm string Algorithm used for generation the hash (see node.js crypto package). + --cache-idle-timeout number Time in ms after which idle period the cache storing should happen (only for + store: 'pack' or 'idle'). + --cache-idle-timeout-for-initial-store number Time in ms after which idle period the initial cache storing should happen + (only for store: 'pack' or 'idle'). + --cache-name string Name for the cache. Different names will lead to different coexisting caches. + --cache-store string When to store data to the filesystem. (pack: Store data when compiler is idle + in a single file). + --cache-version string Version of the cache data. Different versions won't allow to reuse the cache + and override existing content. Update the version when config changed in a + way which doesn't allow to reuse cache. This will invalidate the cache. + --context string The base directory (absolute path!) for resolving the `entry` option. If + `output.pathinfo` is set, the included pathinfo is shortened to this + directory. + --dependencies string[] References to another configuration to depend on. + --dependencies-reset Clear all items provided in configuration. References to other configurations + to depend on. + --devtool string A developer tool to enhance debugging (false | eval | + [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map). + --entry-reset Clear all items provided in configuration. All modules are loaded upon + startup. The last one is exported. + --experiments-asset Allow module type 'asset' to generate assets. + --experiments-async-web-assembly Support WebAssembly as asynchronous EcmaScript Module. + --experiments-import-async Allow 'import/export' syntax to import async modules. + --experiments-import-await Allow 'import/export await' syntax to import async modules. + --experiments-mjs Support .mjs files as way to define strict ESM file (node.js). + --experiments-output-module Allow output javascript files as module source type. + --experiments-sync-web-assembly Support WebAssembly as synchronous EcmaScript Module (outdated). + --experiments-top-level-await Allow using top-level-await in EcmaScript Modules. + --externals string[] Every matched dependency becomes external. An exact matched dependency + becomes external. The same string is used as external dependency. + --externals-reset Clear all items provided in configuration. Specify dependencies that + shouldn't be resolved by webpack, but should become dependencies of the + resulting bundle. The kind of the dependency depends on + `output.libraryTarget`. + --externals-type string Specifies the default type of externals ('amd*', 'umd*', 'system' and 'jsonp' + depend on output.libraryTarget set to the same value). + --infrastructure-logging-debug string[] Enable/Disable debug logging for all loggers. Enable debug logging for + specific loggers. + --infrastructure-logging-debug-reset Clear all items provided in configuration. Enable debug logging for specific + loggers. + --infrastructure-logging-level string Log level. + --module-expr-context-critical Enable warnings for full dynamic dependencies. + --module-expr-context-recursive Enable recursive directory lookup for full dynamic dependencies. + --module-expr-context-reg-exp string Sets the default regular expression for full dynamic dependencies. + --module-expr-context-request string Set the default request for full dynamic dependencies. + --module-no-parse string[] A regular expression, when matched the module is not parsed. An absolute + path, when the module starts with this path it is not parsed. + --module-no-parse-reset Clear all items provided in configuration. Don't parse files matching. It's + matched against the full resolved request. + --module-rules-compiler string[] Match the child compiler name. + --module-rules-enforce string[] Enforce this rule as pre or post step. + --module-rules-exclude string[] Shortcut for resource.exclude. + --module-rules-include string[] Shortcut for resource.include. + --module-rules-issuer string[] Match the issuer of the module (The module pointing to this module). + --module-rules-loader string[] A loader request. + --module-rules-mimetype string[] Match module mimetype when load from Data URI. + --module-rules-options string[] Options passed to a loader. + --module-rules-real-resource string[] Match the real resource path of the module. + --module-rules-resource string[] Match the resource path of the module. + --module-rules-resource-fragment string[] Match the resource fragment of the module. + --module-rules-resource-query string[] Match the resource query of the module. + --module-rules-side-effects Flags a module as with or without side effects. + --module-rules-test string[] Shortcut for resource.test. + --module-rules-type string[] Module type to use for the module. + --module-rules-use-ident string[] Unique loader options identifier. + --module-rules-use-loader string[] A loader request. + --module-rules-use-options string[] Options passed to a loader. + --module-rules-use string[] A loader request. + --module-rules-reset Clear all items provided in configuration. A list of rules. + --module-strict-export-presence Emit errors instead of warnings when imported names don't exist in imported + module. + --module-strict-this-context-on-imports Handle the this context correctly according to the spec for namespace + objects. + --module-unknown-context-critical Enable warnings when using the require function in a not statically analyse- + able way. + --module-unknown-context-recursive Enable recursive directory lookup when using the require function in a not + statically analyse-able way. + --module-unknown-context-reg-exp string Sets the regular expression when using the require function in a not + statically analyse-able way. + --module-unknown-context-request string Sets the request when using the require function in a not statically analyse- + able way. + --module-unsafe-cache Cache the resolving of module requests. + --module-wrapped-context-critical Enable warnings for partial dynamic dependencies. + --module-wrapped-context-recursive Enable recursive directory lookup for partial dynamic dependencies. + --module-wrapped-context-reg-exp string Set the inner regular expression for partial dynamic dependencies. + --name string Name of the configuration. Used when loading multiple configurations. + --node Include polyfills or mocks for various node stuff. + --node-dirname string Include a polyfill for the '__dirname' variable. + --node-filename string Include a polyfill for the '__filename' variable. + --node-global Include a polyfill for the 'global' variable. + --optimization-check-wasm-types Check for incompatible wasm types when importing/exporting from/to ESM. + --optimization-chunk-ids string Define the algorithm to choose chunk ids (named: readable ids for better + debugging, deterministic: numeric hash ids for better long term caching, + size: numeric ids focused on minimal initial download size, total-size: + numeric ids focused on minimal total download size, false: no algorithm used, + as custom one can be provided via plugin). + --optimization-concatenate-modules Concatenate modules when possible to generate less modules, more efficient + code and enable more optimizations by the minimizer. + --optimization-emit-on-errors Emit assets even when errors occur. Critical errors are emitted into the + generated code and will case errors at runtime. + --optimization-flag-included-chunks Also flag chunks as loaded which contain a subset of the modules. + --optimization-inner-graph Creates a module-internal dependency graph for top level symbols, exports and + imports, to improve unused exports detection. + --optimization-mangle-exports Rename exports when possible to generate shorter code (depends on + optimization.usedExports and optimization.providedExports). + --optimization-mangle-wasm-imports Reduce size of WASM by changing imports to shorter strings. + --optimization-merge-duplicate-chunks Merge chunks which contain the same modules. + --optimization-minimize Enable minimizing the output. Uses optimization.minimizer. + --optimization-module-ids string Define the algorithm to choose module ids (natural: numeric ids in order of + usage, named: readable ids for better debugging, hashed: (deprecated) short + hashes as ids for better long term caching, deterministic: numeric hash ids + for better long term caching, size: numeric ids focused on minimal initial + download size, false: no algorithm used, as custom one can be provided via + plugin). + --optimization-node-env string Set process.env.NODE_ENV to a specific value. + --optimization-portable-records Generate records with relative paths to be able to move the context folder. + --optimization-provided-exports Figure out which exports are provided by modules to generate more efficient + code. + --optimization-remove-available-modules Removes modules from chunks when these modules are already included in all + parents. + --optimization-remove-empty-chunks Remove chunks which are empty. + --optimization-runtime-chunk string Create an additional chunk which contains only the webpack runtime and chunk + hash maps. + --optimization-runtime-chunk-name string The name or name factory for the runtime chunks. + --optimization-side-effects Skip over modules which are flagged to contain no side effects when exports + are not used. + --optimization-split-chunks Optimize duplication and caching by splitting chunks by shared modules and + cache group. + --optimization-split-chunks-chunks string Select chunks for determining shared modules (defaults to "async", "initial" + and "all" requires adding these chunks to the HTML). + + --optimization-split-chunks-enforce-size-threshold string Size of the javascript part of the chunk. + --optimization-split-chunks-fallback-cache-group-automatic-name-delimiter string Sets the name delimiter for created chunks + --optimization-split-chunks-fallback-cache-group-max-async-size number Size of the javascript part of the chunk + --optimization-split-chunks-fallback-cache-group-max-initial-size number Size of the javascript part of the chunk. + --optimization-split-chunks-fallback-cache-group-max-size number Size of the javascript part of the chunk. + --optimization-split-chunks-fallback-cache-group-min-size number Size of the javascript part of the chunk. + + --optimization-split-chunks-automatic-name-delimiter string Sets the name delimiter for created chunks + --optimization-split-chunks-filename string Sets the template for the filename for created chunks. + --optimization-split-chunks-hide-path-info Prevents exposing path info when creating names for parts splitted by + maxSize. + --optimization-split-chunks-max-async-requests number Maximum number of requests which are accepted for on-demand loading. + --optimization-split-chunks-max-async-size number Size of the javascript part of the chunk. + --optimization-split-chunks-max-initial-requests number Maximum number of initial chunks which are accepted for an entry point. + --optimization-split-chunks-max-initial-size number Size of the javascript part of the chunk. + --optimization-split-chunks-max-size number Size of the javascript part of the chunk. + --optimization-split-chunks-min-chunks number Minimum number of times a module has to be duplicated until it's considered + for splitting. + --optimization-split-chunks-min-remaining-size number Size of the javascript part of the chunk. + --optimization-split-chunks-min-size number Size of the javascript part of the chunk. + --optimization-split-chunks-name string Give chunks created a name (chunks with equal name are merged). + --optimization-used-exports Figure out which exports are used by modules to mangle export names, omit + unused exports and generate more efficient code. + --output-asset-module-filename string The filename of asset modules as relative path inside the `output.path` + directory. + --output-chunk-callback-name string The callback function name used by webpack for loading of chunks in + WebWorkers. + --output-chunk-filename string The filename of non-entry chunks as relative path inside the `output.path` + directory. + --output-chunk-load-timeout number Number of milliseconds before chunk request expires. + --output-compare-before-emit Check if to be emitted file already exists and have the same content before + writing to output filesystem. + --output-cross-origin-loading string This option enables cross-origin loading of chunks. + --output-devtool-fallback-module-filename-template string Similar to `output.devtoolModuleFilenameTemplate`, but used in the case of + duplicate module identifiers. + --output-devtool-module-filename-template string Filename template string of function for the sources array in a generated + SourceMap. + --output-devtool-namespace string Module namespace to use when interpolating filename template string for the + sources array in a generated SourceMap. Defaults to `output.library` if not + set. It's useful for avoiding runtime collisions in sourcemaps from multiple + webpack projects built as libraries. + --output-ecma-version number The maximum EcmaScript version of the webpack generated code (doesn't include + input source code from modules). + --output-enabled-library-types string[] Type of library. + --output-enabled-library-types-reset Clear all items provided in configuration. List of library types enabled for + use by entry points. + --output-filename string Specifies the name of each output file on disk. You must **not** specify an + absolute path here! The `output.path` option determines the location on disk + the files are written to, filename is used solely for naming the individual + files. + --output-global-object string An expression which is used to address the global object/scope in runtime + code. + --output-hash-digest string Digest type used for the hash. + --output-hash-digest-length number Number of chars which are used for the hash. + --output-hash-function string Algorithm used for generation the hash (see node.js crypto package). + --output-hash-salt string Any string which is added to the hash to salt it. + --output-hot-update-chunk-filename string The filename of the Hot Update Chunks. They are inside the output.path + directory. + --output-hot-update-function string The JSONP function used by webpack for async loading of hot update chunks. + --output-hot-update-main-filename string The filename of the Hot Update Main File. It is inside the `output.path` + directory. + --output-iife Wrap javascript code into IIFE's to avoid leaking into global scope. + --output-import-function-name string The name of the native import() function (can be exchanged for a polyfill). + --output-jsonp-function string The JSONP function used by webpack for async loading of chunks. + --output-library string[] A part of the library name. + --output-library-reset Clear all items provided in configuration. The name of the library (some + types allow unnamed libraries too). + --output-library-amd string Name of the exposed AMD library in the UMD. + --output-library-commonjs string Name of the exposed commonjs export in the UMD. + --output-library-root string[] Part of the name of the property exposed globally by a UMD library. + --output-library-root-reset Clear all items provided in configuration. Name of the property exposed + globally by a UMD library. + --output-library-auxiliary-comment string Append the same comment above each import style. + --output-library-auxiliary-comment-amd string Set comment for `amd` section in UMD. + --output-library-auxiliary-comment-commonjs string Set comment for `commonjs` (exports) section in UMD. + --output-library-auxiliary-comment-commonjs2 string Set comment for `commonjs2` (module.exports) section in UMD. + --output-library-auxiliary-comment-root string Set comment for `root` (global variable) section in UMD. + --output-library-export string[] Part of the export that should be exposed as library. + --output-library-export-reset Clear all items provided in configuration. Specify which export should be + exposed as library. + --output-library-name string[] A part of the library name. + --output-library-name-reset Clear all items provided in configuration. The name of the library (some + types allow unnamed libraries too). + --output-library-name-amd string Name of the exposed AMD library in the UMD. + --output-library-name-commonjs string Name of the exposed commonjs export in the UMD. + --output-library-name-root string[] Part of the name of the property exposed globally by a UMD library. + --output-library-name-root-reset Clear all items provided in configuration. Name of the property exposed + globally by a UMD library. + --output-library-type string Type of library. + --output-library-umd-named-define If `output.libraryTarget` is set to umd and `output.library` is set, setting + this to true will name the AMD module. + --output-module Output javascript files as module source type. + --output-path string The output directory as **absolute path** (required). + --output-pathinfo Include comments with information about the modules. + --output-public-path string The `publicPath` specifies the public URL address of the output files when + referenced in a browser. + --output-script-type string This option enables loading async chunks via a custom script type, such as + script type="module". + --output-source-map-filename string The filename of the SourceMaps for the JavaScript files. They are inside the + `output.path` directory. + --output-source-prefix string Prefixes every line of the source in the bundle with this string. + --output-strict-module-exception-handling Handles exceptions in module loading correctly at a performance cost. + --output-unique-name string A unique name of the webpack build to avoid multiple webpack runtimes to + conflict when using globals. + --output-webassembly-module-filename string The filename of WebAssembly modules as relative path inside the `output.path` + directory. + --parallelism number The number of parallel processed modules in the compilation. + --performance Configuration for web performance recommendations. + --performance-hints string Sets the format of the hints: warnings, errors or nothing at all. + --performance-max-asset-size number File size limit (in bytes) when exceeded, that webpack will provide + performance hints. + --performance-max-entrypoint-size number Total size of an entry point (in bytes). + --profile Capture timing information for each module. + --records-input-path string Store compiler state to a json file. + --records-output-path string Load compiler state from a json file. + --records-path string Store/Load compiler state from/to a json file. This will result in persistent + ids of modules and chunks. An absolute path is expected. `recordsPath` is + used for `recordsInputPath` and `recordsOutputPath` if they left undefined. + --resolve-alias-alias string[] Ignore request (replace with empty module). New request. + --resolve-alias-name string[] Request to be redirected. + --resolve-alias-only-module Redirect only exact matching request. + --resolve-alias-reset Clear all items provided in configuration. Redirect module requests. + --resolve-alias-fields string[] Field in the description file (usually package.json) which are used to + redirect requests inside the module. + --resolve-alias-fields-reset Clear all items provided in configuration. Fields in the description file + (usually package.json) which are used to redirect requests inside the module. + --resolve-cache Enable caching of successfully resolved requests (cache entries are + revalidated). + --resolve-cache-with-context Include the context information in the cache identifier when caching. + --resolve-condition-names string[] Condition names for exports field entry point. + --resolve-condition-names-reset Clear all items provided in configuration. Condition names for exports field + entry point. + --resolve-description-files string[] Filename used to find a description file (like a package.json). + --resolve-description-files-reset Clear all items provided in configuration. Filenames used to find a + description file (like a package.json). + --resolve-enforce-extension Enforce the resolver to use one of the extensions from the extensions option + (User must specify requests without extension). + --resolve-exports-fields string[] Field name from the description file (usually package.json) which is used to + provide entry points of a package. + --resolve-exports-fields-reset Clear all items provided in configuration. Field names from the description + file (usually package.json) which are used to provide entry points of a + package. + --resolve-extensions string[] Extension added to the request when trying to find the file. + --resolve-extensions-reset Clear all items provided in configuration. Extensions added to the request + when trying to find the file. + --resolve-fully-specified Treats the request specified by the user as fully specified, meaning no + extensions are added and the mainFiles in directories are not resolved (This + doesn't affect requests from mainFields, aliasFields or aliases). + --resolve-main-fields string[] Field name from the description file (package.json) which are used to find + the default entry point. + --resolve-main-fields-reset Clear all items provided in configuration. Field names from the description + file (package.json) which are used to find the default entry point. + --resolve-main-files string[] Filename used to find the default entry point if there is no description file + or main field. + --resolve-main-files-reset Clear all items provided in configuration. Filenames used to find the default + entry point if there is no description file or main field. + --resolve-modules string[] Folder name or directory path where to find modules. + --resolve-modules-reset Clear all items provided in configuration. Folder names or directory paths + where to find modules. + --resolve-restrictions string[] Resolve restriction. Resolve result must fulfill this restriction. + --resolve-restrictions-reset Clear all items provided in configuration. A list of resolve restrictions. + Resolve results must fulfill all of these restrictions to resolve + successfully. Other resolve paths are taken when restrictions are not met. + --resolve-roots string[] Directory in which requests that are server-relative URLs (starting with '/') + are resolved. + --resolve-roots-reset Clear all items provided in configuration. A list of directories in which + requests that are server-relative URLs (starting with '/') are resolved. On + non-windows system these requests are tried to resolve as absolute path + first. + --resolve-symlinks Enable resolving symlinks to the original location. + --resolve-unsafe-cache Enable caching of successfully resolved requests (cache entries are not + revalidated). + --resolve-use-sync-file-system-calls Use synchronous filesystem calls for the resolver. + --resolve-loader-alias-alias string[] Ignore request (replace with empty module). New request. + --resolve-loader-alias-name string[] Request to be redirected. + --resolve-loader-alias-only-module Redirect only exact matching request. + --resolve-loader-alias-reset Clear all items provided in configuration. Redirect module requests. + --resolve-loader-alias-fields string[] Field in the description file (usually package.json) which are used to + redirect requests inside the module. + --resolve-loader-alias-fields-reset Clear all items provided in configuration. Fields in the description file + (usually package.json) which are used to redirect requests inside the module. + --resolve-loader-cache Enable caching of successfully resolved requests (cache entries are + revalidated). + --resolve-loader-cache-with-context Include the context information in the cache identifier when caching. + --resolve-loader-condition-names string[] Condition names for exports field entry point. + --resolve-loader-condition-names-reset Clear all items provided in configuration. Condition names for exports field + entry point. + --resolve-loader-description-files string[] Filename used to find a description file (like a package.json). + --resolve-loader-description-files-reset Clear all items provided in configuration. Filenames used to find a + description file (like a package.json). + --resolve-loader-enforce-extension Enforce the resolver to use one of the extensions from the extensions option + (User must specify requests without extension). + --resolve-loader-exports-fields string[] Field name from the description file (usually package.json) which is used to + provide entry points of a package. + --resolve-loader-exports-fields-reset Clear all items provided in configuration. Field names from the description + file (usually package.json) which are used to provide entry points of a + package. + --resolve-loader-extensions string[] Extension added to the request when trying to find the file. + --resolve-loader-extensions-reset Clear all items provided in configuration. Extensions added to the request + when trying to find the file. + --resolve-loader-fully-specified Treats the request specified by the user as fully specified, meaning no + extensions are added and the mainFiles in directories are not resolved (This + doesn't affect requests from mainFields, aliasFields or aliases). + --resolve-loader-main-fields string[] Field name from the description file (package.json) which are used to find + the default entry point. + --resolve-loader-main-fields-reset Clear all items provided in configuration. Field names from the description + file (package.json) which are used to find the default entry point. + --resolve-loader-main-files string[] Filename used to find the default entry point if there is no description file + or main field. + --resolve-loader-main-files-reset Clear all items provided in configuration. Filenames used to find the default + entry point if there is no description file or main field. + --resolve-loader-modules string[] Folder name or directory path where to find modules. + --resolve-loader-modules-reset Clear all items provided in configuration. Folder names or directory paths + where to find modules. + --resolve-loader-restrictions string[] Resolve restriction. Resolve result must fulfill this restriction. + --resolve-loader-restrictions-reset Clear all items provided in configuration. A list of resolve restrictions. + Resolve results must fulfill all of these restrictions to resolve + successfully. Other resolve paths are taken when restrictions are not met. + --resolve-loader-roots string[] Directory in which requests that are server-relative URLs (starting with '/') + are resolved. + --resolve-loader-roots-reset Clear all items provided in configuration. A list of directories in which + requests that are server-relative URLs (starting with '/') are resolved. On + non-windows system these requests are tried to resolve as absolute path + first. + --resolve-loader-symlinks Enable resolving symlinks to the original location. + --resolve-loader-unsafe-cache Enable caching of successfully resolved requests (cache entries are not + revalidated). + --resolve-loader-use-sync-file-system-calls Use synchronous filesystem calls for the resolver. + --stats-all Fallback value for stats options when an option is not defined (has + precedence over local webpack defaults). + --stats-assets Add assets information. + --stats-assets-sort string Sort the assets by that field. + --stats-built-at Add built at time information. + --stats-cached Add information about cached (not built) modules. + --stats-cached-assets Show cached assets (setting this to `false` only shows emitted files). + --stats-children Add children information. + --stats-chunk-groups Display all chunk groups with the corresponding bundles. + --stats-chunk-modules Add built modules information to chunk information. + --stats-chunk-origins Add the origins of chunks and chunk merging info. + --stats-chunk-relations Add information about parent, children and sibling chunks to chunk + information. + --stats-chunk-root-modules Add root modules information to chunk information. + --stats-chunks Add chunk information. + --stats-chunks-sort string Sort the chunks by that field. + --stats-colors Enables/Disables colorful output. + --stats-colors-bold string Custom color for bold text. + --stats-colors-cyan string Custom color for cyan text. + --stats-colors-green string Custom color for green text. + --stats-colors-magenta string Custom color for magenta text. + --stats-colors-red string Custom color for red text. + --stats-colors-yellow string Custom color for yellow text. + --stats-context string Context directory for request shortening. + --stats-depth Add module depth in module graph. + --stats-entrypoints Display the entry points with the corresponding bundles. + --stats-env Add --env information. + --stats-error-details Add details to errors (like resolving log). + --stats-error-stack Add internal stack trace to errors. + --stats-errors Add errors. + --stats-exclude-assets string[] Suppress assets that match the specified filters. Filters can be Strings, + RegExps or Functions. + --stats-exclude-assets-reset Clear all items provided in configuration. Suppress assets that match the + specified filters. Filters can be Strings, RegExps or Functions. + --stats-exclude-modules string[] Suppress modules that match the specified filters. Filters can be Strings, + RegExps, Booleans or Functions. + --stats-exclude-modules-reset Clear all items provided in configuration. Suppress modules that match the + specified filters. Filters can be Strings, RegExps, Booleans or Functions. + --stats-hash Add the hash of the compilation. + --stats-ids Add ids. + --stats-logging string Specify log level of logging output. Enable/disable logging output (`true`: + shows normal logging output, loglevel: log). + --stats-logging-debug string[] Enable/Disable debug logging for all loggers. Include debug logging of + specified loggers (i. e. for plugins or loaders). Filters can be Strings, + RegExps or Functions. + --stats-logging-debug-reset Clear all items provided in configuration. Include debug logging of specified + loggers (i. e. for plugins or loaders). Filters can be Strings, RegExps or + Functions. + --stats-logging-trace Add stack traces to logging output. + --stats-max-modules number Set the maximum number of modules to be shown. + --stats-module-assets Add information about assets inside modules. + --stats-module-trace Add dependencies and origin of warnings/errors. + --stats-modules Add built modules information. + --stats-modules-sort string Sort the modules by that field. + --stats-nested-modules Add information about modules nested in other modules (like with module + concatenation). + --stats-optimization-bailout Show reasons why optimization bailed out for modules. + --stats-orphan-modules Add information about orphan modules. + --stats-output-path Add output path information. + --stats-performance Add performance hint flags. + --stats-preset string Preset for the default values. + --stats-provided-exports Show exports provided by modules. + --stats-public-path Add public path information. + --stats-reasons Add information about the reasons why modules are included. + --stats-runtime Add information about runtime modules. + --stats-source Add the source code of modules. + --stats-timings Add timing information. + --stats-used-exports Show exports used by modules. + --stats-version Add webpack version information. + --stats-warnings Add warnings. + --stats-warnings-filter string[] Suppress warnings that match the specified filters. Filters can be Strings, + RegExps or Functions. + --stats-warnings-filter-reset Clear all items provided in configuration. Suppress warnings that match the + specified filters. Filters can be Strings, RegExps or Functions. + --watch-options-aggregate-timeout number Delay the rebuilt after the first change. Value is a time in ms. + --watch-options-ignored string[] A glob pattern for files that should be ignored from watching. + --watch-options-ignored-reset Clear all items provided in configuration. Ignore some files from watching + (glob pattern). + --watch-options-poll string `number`: use polling with specified interval. `true`: use polling. + --watch-options-stdin Stop watching when stdin stream has ended. + --no-hot Negates hot + --no-stats Negates stats + --no-amd Negates amd + --no-bail Negates bail + --no-cache Negates cache + --no-cache-immutable-paths-reset Negates cache-immutable-paths-reset + --no-cache-managed-paths-reset Negates cache-managed-paths-reset + --no-dependencies-reset Negates dependencies-reset + --no-entry-reset Negates entry-reset + --no-experiments-asset Negates experiments-asset + --no-experiments-async-web-assembly Negates experiments-async-web-assembly + --no-experiments-import-async Negates experiments-import-async + --no-experiments-import-await Negates experiments-import-await + --no-experiments-mjs Negates experiments-mjs + --no-experiments-output-module Negates experiments-output-module + --no-experiments-sync-web-assembly Negates experiments-sync-web-assembly + --no-experiments-top-level-await Negates experiments-top-level-await + --no-externals-reset Negates externals-reset + --no-infrastructure-logging-debug-reset Negates infrastructure-logging-debug-reset + --no-module-expr-context-critical Negates module-expr-context-critical + --no-module-expr-context-recursive Negates module-expr-context-recursive + --no-module-no-parse-reset Negates module-no-parse-reset + --no-module-rules-side-effects Negates module-rules-side-effects + --no-module-rules-reset Negates module-rules-reset + --no-module-strict-export-presence Negates module-strict-export-presence + --no-module-strict-this-context-on-imports Negates module-strict-this-context-on-imports + --no-module-unknown-context-critical Negates module-unknown-context-critical + --no-module-unknown-context-recursive Negates module-unknown-context-recursive + --no-module-unsafe-cache Negates module-unsafe-cache + --no-module-wrapped-context-critical Negates module-wrapped-context-critical + --no-module-wrapped-context-recursive Negates module-wrapped-context-recursive + --no-node Negates node + --no-node-global Negates node-global + --no-optimization-check-wasm-types Negates optimization-check-wasm-types + --no-optimization-concatenate-modules Negates optimization-concatenate-modules + --no-optimization-emit-on-errors Negates optimization-emit-on-errors + --no-optimization-flag-included-chunks Negates optimization-flag-included-chunks + --no-optimization-inner-graph Negates optimization-inner-graph + --no-optimization-mangle-exports Negates optimization-mangle-exports + --no-optimization-mangle-wasm-imports Negates optimization-mangle-wasm-imports + --no-optimization-merge-duplicate-chunks Negates optimization-merge-duplicate-chunks + --no-optimization-minimize Negates optimization-minimize + --no-optimization-portable-records Negates optimization-portable-records + --no-optimization-provided-exports Negates optimization-provided-exports + --no-optimization-remove-available-modules Negates optimization-remove-available-modules + --no-optimization-remove-empty-chunks Negates optimization-remove-empty-chunks + --no-optimization-side-effects Negates optimization-side-effects + --no-optimization-split-chunks Negates optimization-split-chunks + --no-optimization-split-chunks-hide-path-info Negates optimization-split-chunks-hide-path-info + --no-optimization-used-exports Negates optimization-used-exports + --no-output-compare-before-emit Negates output-compare-before-emit + --no-output-enabled-library-types-reset Negates output-enabled-library-types-reset + --no-output-iife Negates output-iife + --no-output-library-reset Negates output-library-reset + --no-output-library-root-reset Negates output-library-root-reset + --no-output-library-export-reset Negates output-library-export-reset + --no-output-library-name-reset Negates output-library-name-reset + --no-output-library-name-root-reset Negates output-library-name-root-reset + --no-output-library-umd-named-define Negates output-library-umd-named-define + --no-output-module Negates output-module + --no-output-pathinfo Negates output-pathinfo + --no-output-strict-module-exception-handling Negates output-strict-module-exception-handling + --no-performance Negates performance + --no-profile Negates profile + --no-resolve-alias-only-module Negates resolve-alias-only-module + --no-resolve-alias-reset Negates resolve-alias-reset + --no-resolve-alias-fields-reset Negates resolve-alias-fields-reset + --no-resolve-cache Negates resolve-cache + --no-resolve-cache-with-context Negates resolve-cache-with-context + --no-resolve-condition-names-reset Negates resolve-condition-names-reset + --no-resolve-description-files-reset Negates resolve-description-files-reset + --no-resolve-enforce-extension Negates resolve-enforce-extension + --no-resolve-exports-fields-reset Negates resolve-exports-fields-reset + --no-resolve-extensions-reset Negates resolve-extensions-reset + --no-resolve-fully-specified Negates resolve-fully-specified + --no-resolve-main-fields-reset Negates resolve-main-fields-reset + --no-resolve-main-files-reset Negates resolve-main-files-reset + --no-resolve-modules-reset Negates resolve-modules-reset + --no-resolve-restrictions-reset Negates resolve-restrictions-reset + --no-resolve-roots-reset Negates resolve-roots-reset + --no-resolve-symlinks Negates resolve-symlinks + --no-resolve-unsafe-cache Negates resolve-unsafe-cache + --no-resolve-use-sync-file-system-calls Negates resolve-use-sync-file-system-calls + --no-resolve-loader-alias-only-module Negates resolve-loader-alias-only-module + --no-resolve-loader-alias-reset Negates resolve-loader-alias-reset + --no-resolve-loader-alias-fields-reset Negates resolve-loader-alias-fields-reset + --no-resolve-loader-cache Negates resolve-loader-cache + --no-resolve-loader-cache-with-context Negates resolve-loader-cache-with-context + --no-resolve-loader-condition-names-reset Negates resolve-loader-condition-names-reset + --no-resolve-loader-description-files-reset Negates resolve-loader-description-files-reset + --no-resolve-loader-enforce-extension Negates resolve-loader-enforce-extension + --no-resolve-loader-exports-fields-reset Negates resolve-loader-exports-fields-reset + --no-resolve-loader-extensions-reset Negates resolve-loader-extensions-reset + --no-resolve-loader-fully-specified Negates resolve-loader-fully-specified + --no-resolve-loader-main-fields-reset Negates resolve-loader-main-fields-reset + --no-resolve-loader-main-files-reset Negates resolve-loader-main-files-reset + --no-resolve-loader-modules-reset Negates resolve-loader-modules-reset + --no-resolve-loader-restrictions-reset Negates resolve-loader-restrictions-reset + --no-resolve-loader-roots-reset Negates resolve-loader-roots-reset + --no-resolve-loader-symlinks Negates resolve-loader-symlinks + --no-resolve-loader-unsafe-cache Negates resolve-loader-unsafe-cache + --no-resolve-loader-use-sync-file-system-calls Negates resolve-loader-use-sync-file-system-calls + --no-stats-all Negates stats-all + --no-stats-assets Negates stats-assets + --no-stats-built-at Negates stats-built-at + --no-stats-cached Negates stats-cached + --no-stats-cached-assets Negates stats-cached-assets + --no-stats-children Negates stats-children + --no-stats-chunk-groups Negates stats-chunk-groups + --no-stats-chunk-modules Negates stats-chunk-modules + --no-stats-chunk-origins Negates stats-chunk-origins + --no-stats-chunk-relations Negates stats-chunk-relations + --no-stats-chunk-root-modules Negates stats-chunk-root-modules + --no-stats-chunks Negates stats-chunks + --no-stats-colors Negates stats-colors + --no-stats-depth Negates stats-depth + --no-stats-entrypoints Negates stats-entrypoints + --no-stats-env Negates stats-env + --no-stats-error-details Negates stats-error-details + --no-stats-error-stack Negates stats-error-stack + --no-stats-errors Negates stats-errors + --no-stats-exclude-assets-reset Negates stats-exclude-assets-reset + --no-stats-exclude-modules-reset Negates stats-exclude-modules-reset + --no-stats-hash Negates stats-hash + --no-stats-ids Negates stats-ids + --no-stats-logging-debug-reset Negates stats-logging-debug-reset + --no-stats-logging-trace Negates stats-logging-trace + --no-stats-module-assets Negates stats-module-assets + --no-stats-module-trace Negates stats-module-trace + --no-stats-modules Negates stats-modules + --no-stats-nested-modules Negates stats-nested-modules + --no-stats-optimization-bailout Negates stats-optimization-bailout + --no-stats-orphan-modules Negates stats-orphan-modules + --no-stats-output-path Negates stats-output-path + --no-stats-performance Negates stats-performance + --no-stats-provided-exports Negates stats-provided-exports + --no-stats-public-path Negates stats-public-path + --no-stats-reasons Negates stats-reasons + --no-stats-runtime Negates stats-runtime + --no-stats-source Negates stats-source + --no-stats-timings Negates stats-timings + --no-stats-used-exports Negates stats-used-exports + --no-stats-version Negates stats-version + --no-stats-warnings Negates stats-warnings + --no-stats-warnings-filter-reset Negates stats-warnings-filter-reset + --no-watch-options-ignored-reset Negates watch-options-ignored-reset + --no-watch-options-stdin Negates watch-options-stdin +``` + ## Defaults TODO: explain defaults diff --git a/packages/webpack-cli/lib/bootstrap.js b/packages/webpack-cli/lib/bootstrap.js index 265f19278aa..57ba039f092 100644 --- a/packages/webpack-cli/lib/bootstrap.js +++ b/packages/webpack-cli/lib/bootstrap.js @@ -4,7 +4,6 @@ const logger = require('./utils/logger'); const cliExecuter = require('./utils/cli-executer'); const argParser = require('./utils/arg-parser'); require('./utils/process-log'); - process.title = 'webpack-cli'; const isCommandUsed = (commands) => diff --git a/packages/webpack-cli/lib/utils/arg-parser.js b/packages/webpack-cli/lib/utils/arg-parser.js index 1f009a3d155..7e79694d3b4 100644 --- a/packages/webpack-cli/lib/utils/arg-parser.js +++ b/packages/webpack-cli/lib/utils/arg-parser.js @@ -99,7 +99,6 @@ function argParser(options, args, argsOnly = false, name = '', helpFunction = un const opts = result.opts(); const unknownArgs = result.args; - args.forEach((arg) => { const flagName = arg.slice(5); const option = options.find((opt) => opt.name === flagName); diff --git a/packages/webpack-cli/lib/utils/cli-flags.js b/packages/webpack-cli/lib/utils/cli-flags.js index fe79445df57..9474919c3f1 100644 --- a/packages/webpack-cli/lib/utils/cli-flags.js +++ b/packages/webpack-cli/lib/utils/cli-flags.js @@ -1,3 +1,5 @@ +const { cli } = require('webpack'); + const HELP_GROUP = 'help'; const CONFIG_GROUP = 'config'; const BASIC_GROUP = 'basic'; @@ -6,6 +8,35 @@ const ADVANCED_GROUP = 'advanced'; const DISPLAY_GROUP = 'stats'; const ZERO_CONFIG_GROUP = 'zero-config'; +// Extract all the flags being exported from core. A list of cli flags generated by core +// can be found here https://github.com/webpack/webpack/blob/master/test/__snapshots__/Cli.test.js.snap +let flagsFromCore = + typeof cli !== 'undefined' + ? Object.entries(cli.getArguments()).map(([flag, meta]) => { + if (meta.simpleType === 'string') { + meta.type = String; + meta.usage = `--${flag} `; + } else if (meta.simpleType === 'number') { + meta.type = Number; + meta.usage = `--${flag} `; + } else { + meta.type = Boolean; + meta.negative = true; + meta.usage = `--${flag}`; + } + return { + ...meta, + name: flag, + group: 'core', + }; + }) + : []; + +// duplicate flags +const duplicateFlags = ['entry', 'mode', 'stats', 'watch', 'target']; + +flagsFromCore = flagsFromCore.filter((flag) => !duplicateFlags.includes(flag.name)); + module.exports = { groups: { HELP_GROUP, @@ -227,6 +258,7 @@ module.exports = { group: CONFIG_GROUP, description: 'Environment passed to the configuration when it is a function', }, + ...flagsFromCore, /* { name: "analyze", type: Boolean, @@ -241,4 +273,5 @@ module.exports = { group: BASIC_GROUP } */ ], + flagsFromCore, }; diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 416e3426b44..7d1659f4488 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -10,6 +10,7 @@ class WebpackCLI extends GroupHelper { super(); this.groupMap = new Map(); this.groups = []; + this.args = {}; this.processingMessageBuffer = []; this.compilation = new Compiler(); this.defaultEntry = 'index'; @@ -42,6 +43,26 @@ class WebpackCLI extends GroupHelper { } } + /** + * Responsible for handling flags coming from webpack/webpack + * @private\ + * @returns {void} + */ + _handleCoreFlags() { + if (!this.groupMap.has('core')) { + return; + } + const coreFlags = this.groupMap.get('core'); + + // convert all the flags from map to single object + const coreConfig = coreFlags.reduce((allFlag, curFlag) => ({ ...allFlag, ...curFlag }), {}); + + const coreCliHelper = require('webpack').cli; + const coreCliArgs = coreCliHelper.getArguments(); + // Merge the core flag config with the compilerConfiguration + coreCliHelper.processArguments(coreCliArgs, this.compilerConfiguration, coreConfig); + } + /** * Expose commander argParser * @param {...any} args args for argParser @@ -222,6 +243,7 @@ class WebpackCLI extends GroupHelper { .then(() => this._handleDefaultEntry()) .then(() => this._handleGroupHelper(this.configGroup)) .then(() => this._handleGroupHelper(this.outputGroup)) + .then(() => this._handleCoreFlags()) .then(() => this._handleGroupHelper(this.basicGroup)) .then(() => this._handleGroupHelper(this.advancedGroup)) .then(() => this._handleGroupHelper(this.statsGroup)) diff --git a/scripts/cleanupTest.js b/scripts/cleanupTest.js index 6d3c5b8e61d..1d86780adbc 100644 --- a/scripts/cleanupTest.js +++ b/scripts/cleanupTest.js @@ -3,7 +3,7 @@ const rimraf = require('rimraf'); const { join } = require('path'); const collectTestFolders = require('./utils'); -const outputDirectories = ['bin', 'binary', 'dist', 'test-assets', 'test-plugin', 'test-loader']; +const outputDirectories = ['bin', 'binary', 'dist', 'test', 'test-assets', 'test-plugin', 'test-loader']; function folderStrategy(stats, file) { return stats.isDirectory() && outputDirectories.includes(file); diff --git a/test/core-flags/amd-flag.test.js b/test/core-flags/amd-flag.test.js new file mode 100644 index 00000000000..a21db34196f --- /dev/null +++ b/test/core-flags/amd-flag.test.js @@ -0,0 +1,12 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); + +describe('--no-amd flag', () => { + it('should accept --no-amd', () => { + const { stderr, stdout } = run(__dirname, ['--no-amd']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('amd: false'); + }); +}); diff --git a/test/core-flags/bail-flag.test.js b/test/core-flags/bail-flag.test.js new file mode 100644 index 00000000000..48587933155 --- /dev/null +++ b/test/core-flags/bail-flag.test.js @@ -0,0 +1,19 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); + +describe('--bail flag', () => { + it('should set bail to true', () => { + const { stderr, stdout } = run(__dirname, ['--bail']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('bail: true'); + }); + + it('should set bail to false', () => { + const { stderr, stdout } = run(__dirname, ['--no-bail']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('bail: false'); + }); +}); diff --git a/test/core-flags/cache-flags.test.js b/test/core-flags/cache-flags.test.js new file mode 100644 index 00000000000..c98b82d2f31 --- /dev/null +++ b/test/core-flags/cache-flags.test.js @@ -0,0 +1,82 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); + +describe('cache related flags from core', () => { + it('should be successful with --cache ', () => { + const { stderr, stdout } = run(__dirname, ['--cache']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`type: 'memory'`); + }); + + it('should be successful with --no-cache ', () => { + const { stderr, stdout } = run(__dirname, ['--no-cache']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('cache: false'); + }); + + it('should set cache.type', () => { + const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`type: 'filesystem'`); + }); + + it('should set cache.cacheDirectory with --cache-cache-directory', () => { + const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-cache-directory', '/test-cache-path']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('test-cache-path'); + }); + + it('should set cache.cacheLocation with --cache-cache-locations', () => { + const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-cache-location', '/test-locate-cache']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('test-locate-cache'); + }); + + it('should set cache.hashAlgorithm with --cache-hash-algorithm', () => { + const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-hash-algorithm', 'sha256']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`hashAlgorithm: 'sha256'`); + }); + + it('should set cache.managedPaths with --cache-managed-paths', () => { + const { stderr, stdout } = run(__dirname, ['--cache-type', 'memory', '--cache-managed-paths', '/test-manage-path']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('test-manage-path'); + }); + + it('should reset cache.managedPaths with --cache-managed-paths-reset', () => { + const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-managed-paths-reset']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`managedPaths: []`); + }); + + it('should set cache.name with --cache-name', () => { + const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-name', 'cli-test']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`name: 'cli-test'`); + }); + + it('should set cache.store with --cache-store', () => { + const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-store', 'pack']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`store: 'pack'`); + }); + + it('should set cache.version with --cache-version', () => { + const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '--cache-version', '1.1.3']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`version: '1.1.3'`); + }); +}); diff --git a/test/core-flags/context-flag.test.js b/test/core-flags/context-flag.test.js new file mode 100644 index 00000000000..98f13ea2c24 --- /dev/null +++ b/test/core-flags/context-flag.test.js @@ -0,0 +1,12 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); + +describe('--context flag', () => { + it('should allow to set context', () => { + const { stderr, stdout } = run(__dirname, ['--context', '/test-context-path']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('test-context-path'); + }); +}); diff --git a/test/core-flags/dependencies-flag.test.js b/test/core-flags/dependencies-flag.test.js new file mode 100644 index 00000000000..251c6f51bf3 --- /dev/null +++ b/test/core-flags/dependencies-flag.test.js @@ -0,0 +1,19 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); + +describe('--dependencies and related flags', () => { + it('should allow to set dependencies option', () => { + const { stderr, stdout } = run(__dirname, ['--dependencies', 'lodash']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`dependencies: [ 'lodash' ]`); + }); + + it('should reset dependencies option', () => { + const { stderr, stdout } = run(__dirname, ['--dependencies-reset']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('dependencies: []'); + }); +}); diff --git a/test/core-flags/devtool-flag.test.js b/test/core-flags/devtool-flag.test.js new file mode 100644 index 00000000000..60aa498ad20 --- /dev/null +++ b/test/core-flags/devtool-flag.test.js @@ -0,0 +1,18 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); + +describe('--devtool flag', () => { + it('should set devtool option', () => { + const { stderr, stdout } = run(__dirname, ['--devtool', 'source-map']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`devtool: 'source-map'`); + }); + + it('should throw error for invalid config', () => { + const { stderr } = run(__dirname, ['--devtool', 'invalid']); + + expect(stderr).toContain('ValidationError: Invalid configuration object'); + }); +}); diff --git a/test/core-flags/experiments-flag.test.js b/test/core-flags/experiments-flag.test.js new file mode 100644 index 00000000000..b1d808c889a --- /dev/null +++ b/test/core-flags/experiments-flag.test.js @@ -0,0 +1,26 @@ +'use strict'; + +const { run, hyphenToUpperCase } = require('../utils/test-utils'); +const { flagsFromCore } = require('../../packages/webpack-cli/lib/utils/cli-flags'); + +const experimentsFlags = flagsFromCore.filter(({ name }) => name.startsWith('experiments-')); + +describe('experiments option related flag', () => { + experimentsFlags.forEach((flag) => { + // extract property name from flag name + const property = flag.name.split('experiments-')[1]; + const propName = hyphenToUpperCase(property); + + it(`should config ${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--${flag.name}`]); + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${propName}: true`); + }); + + it(`should config --no-${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--no-${flag.name}`]); + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${propName}: false`); + }); + }); +}); diff --git a/test/core-flags/externals-flags.test.js b/test/core-flags/externals-flags.test.js new file mode 100644 index 00000000000..83bc6f3c00f --- /dev/null +++ b/test/core-flags/externals-flags.test.js @@ -0,0 +1,33 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); + +describe('externals related flag', () => { + it('should set externals properly', () => { + const { stderr, stdout } = run(__dirname, ['--externals', './main.js']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`externals: [ './main.js' ]`); + }); + + it('should set externalsType properly', () => { + const { stderr, stdout } = run(__dirname, ['--externals', 'var']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`externalsType: 'var'`); + }); + + it('should accept --external-type values', () => { + const { stderr, stdout } = run(__dirname, ['--externals-type', 'var']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`externalsType: 'var'`); + }); + + it('should reset externals', () => { + const { stderr, stdout } = run(__dirname, ['--externals-reset']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`externals: []`); + }); +}); diff --git a/test/core-flags/infrastructure-logging.test.js b/test/core-flags/infrastructure-logging.test.js new file mode 100644 index 00000000000..028523bb0d9 --- /dev/null +++ b/test/core-flags/infrastructure-logging.test.js @@ -0,0 +1,26 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); + +describe('externals related flag', () => { + it('should set infrastructureLogging.debug properly', () => { + const { stderr, stdout } = run(__dirname, ['--infrastructure-logging-debug', 'myPlugin']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`debug: [ 'myPlugin' ]`); + }); + + it('should reset infrastructureLogging.debug to []', () => { + const { stderr, stdout } = run(__dirname, ['--infrastructure-logging-debug-reset']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`debug: []`); + }); + + it('should set infrastructureLogging.level properly', () => { + const { stderr, stdout } = run(__dirname, ['--infrastructure-logging-level', 'log']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`level: 'log'`); + }); +}); diff --git a/test/core-flags/main.js b/test/core-flags/main.js new file mode 100644 index 00000000000..dcab1dbfb46 --- /dev/null +++ b/test/core-flags/main.js @@ -0,0 +1 @@ +console.log('core-flags tests'); diff --git a/test/core-flags/module-flags.test.js b/test/core-flags/module-flags.test.js new file mode 100644 index 00000000000..3fa3034902c --- /dev/null +++ b/test/core-flags/module-flags.test.js @@ -0,0 +1,74 @@ +'use strict'; + +const { run, hyphenToUpperCase } = require('../utils/test-utils'); +const { flagsFromCore } = require('../../packages/webpack-cli/lib/utils/cli-flags'); +//--module-rules-options will be excluded for cli. +const moduleFlags = flagsFromCore.filter(({ name }) => name.startsWith('module-') && name !== 'module-rules-options'); + +describe('module config related flag', () => { + moduleFlags.forEach((flag) => { + // extract property name from flag name + let property = flag.name.split('module-')[1]; + if (property.includes('rules-') && property !== 'rules-reset') { + property = flag.name.split('rules-')[1]; + } + const propName = hyphenToUpperCase(property); + + if (flag.type === Boolean && !flag.name.includes('module-no-parse')) { + it(`should config --${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--${flag.name}`]); + expect(stderr).toBeFalsy(); + if (flag.name.includes('-reset')) { + const option = propName.split('Reset')[0]; + expect(stdout).toContain(`${option}: []`); + } else if (flag.name.includes('rules-')) { + expect(stdout).toContain('sideEffects: true'); + } else { + expect(stdout).toContain(`${propName}: true`); + } + }); + + it(`should config --no-${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--no-${flag.name}`]); + expect(stderr).toBeFalsy(); + if (flag.name.includes('-reset')) { + const option = propName.split('Reset')[0]; + expect(stdout).toContain(`${option}: []`); + } else if (flag.name.includes('rules-')) { + expect(stdout).toContain('sideEffects: false'); + } else { + expect(stdout).toContain(`${propName}: false`); + } + }); + } + + if (flag.type === String) { + it(`should config --${flag.name} correctly`, () => { + let { stderr, stdout } = run(__dirname, [`--${flag.name}`, 'value']); + if (flag.name === 'module-no-parse') { + expect(stderr).toBeFalsy(); + expect(stdout).toContain('value'); + } else if (flag.name.includes('reg-exp')) { + stdout = run(__dirname, [`--${flag.name}`, '/ab?c*/']).stdout; + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${propName}: /ab?c*/`); + } else if (flag.name.includes('module-rules-')) { + stdout = run(__dirname, [`--${flag.name}`, 'javascript/auto']).stdout; + if (propName === 'use' || propName === 'type') { + expect(stdout).toContain(`${propName}: 'javascript/auto'`); + } else if (property.includes('use-')) { + expect(stdout).toContain(`use: [Object]`); + } else if (propName === 'enforce') { + stdout = run(__dirname, [`--${flag.name}`, 'pre', '--module-rules-use-loader', 'myLoader']).stdout; + expect(stdout).toContain(`${propName}: 'pre'`); + } else { + stdout = run(__dirname, [`--${flag.name}`, '/rules-value']).stdout; + expect(stdout).toContain('rules-value'); + } + } else { + expect(stdout).toContain(`${propName}: 'value'`); + } + }); + } + }); +}); diff --git a/test/core-flags/node-flags.test.js b/test/core-flags/node-flags.test.js new file mode 100644 index 00000000000..85522283ace --- /dev/null +++ b/test/core-flags/node-flags.test.js @@ -0,0 +1,40 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); + +describe('node option related flags', () => { + it('should config node option', () => { + const { stderr, stdout } = run(__dirname, ['--node']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`node: { global: true, __filename: 'mock', __dirname: 'mock' }`); + }); + + it('should config node option to false', () => { + const { stderr, stdout } = run(__dirname, ['--no-node']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('node: false'); + }); + + it('should set node.global equals to true', () => { + const { stderr, stdout } = run(__dirname, ['--node']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('global: true'); + }); + + it('should set node.filename correctly', () => { + const { stderr, stdout } = run(__dirname, ['--node-filename', 'mock']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`__filename: 'mock'`); + }); + + it('should set node.filename correctly', () => { + const { stderr, stdout } = run(__dirname, ['--node-dirname', 'mock']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`__dirname: 'mock'`); + }); +}); diff --git a/test/core-flags/optimization-flags.test.js b/test/core-flags/optimization-flags.test.js new file mode 100644 index 00000000000..22502dfe87f --- /dev/null +++ b/test/core-flags/optimization-flags.test.js @@ -0,0 +1,68 @@ +'use strict'; + +const { run, hyphenToUpperCase } = require('../utils/test-utils'); +const { flagsFromCore } = require('../../packages/webpack-cli/lib/utils/cli-flags'); + +const optimizationFlags = flagsFromCore.filter(({ name }) => name.startsWith('optimization-')); + +describe('optimization config related flag', () => { + optimizationFlags.forEach((flag) => { + // extract property name from flag name + let property = flag.name.split('optimization-')[1]; + if (flag.name.includes('split-chunks')) { + property = flag.name.split('optimization-split-chunks-')[1]; + } + const propName = hyphenToUpperCase(property); + + if (flag.type === Boolean) { + it(`should config --${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--${flag.name}`]); + expect(stderr).toBeFalsy(); + if (flag.name === 'optimization-split-chunks') { + expect(stdout).toContain(`chunks: 'async'`); + expect(stdout).toContain(`minChunks: 1`); + } else { + expect(stdout).toContain(`${propName}: true`); + } + }); + + it(`should config --no-${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--no-${flag.name}`]); + expect(stderr).toBeFalsy(); + if (flag.name === 'optimization-split-chunks') { + expect(stdout).toContain('splitChunks: false'); + } else { + expect(stdout).toContain(`${propName}: false`); + } + }); + } + + // ignoring optimization-runtime-* and split-chunks-fallback-* flags because WebpackClITestPlugin logs [Object] + // need improve the plugin to log for multi-level options i.e, optimization.runtime + if (flag.type === String && !flag.name.includes('runtime-') && !flag.name.includes('fallback-')) { + it(`should config --${flag.name} correctly`, () => { + let { stderr, stdout } = run(__dirname, [`--${flag.name}`, 'named']); + expect(stderr).toBeFalsy(); + if (flag.name === 'optimization-split-chunks-chunks') { + stdout = run(__dirname, [`--${flag.name}`, 'initial']).stdout; + expect(stdout).toContain(`chunks: 'initial'`); + } else { + expect(stdout).toContain(`${propName}: 'named'`); + } + }); + } + + if (flag.type === Number && !flag.name.includes('fallback-')) { + it(`should config --${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--${flag.name}`, '10']); + expect(stderr).toBeFalsy(); + if (flag.name === 'optimization-split-chunks') { + expect(stdout).toContain(`chunks: 'async'`); + expect(stdout).toContain(`minChunks: 1`); + } else { + expect(stdout).toContain(`${propName}: 10`); + } + }); + } + }); +}); diff --git a/test/core-flags/output-flags.test.js b/test/core-flags/output-flags.test.js new file mode 100644 index 00000000000..03cb6eca03f --- /dev/null +++ b/test/core-flags/output-flags.test.js @@ -0,0 +1,124 @@ +'use strict'; + +const { run, hyphenToUpperCase } = require('../utils/test-utils'); +const { flagsFromCore } = require('../../packages/webpack-cli/lib/utils/cli-flags'); + +const outputFlags = flagsFromCore.filter(({ name }) => name.startsWith('output-')); + +describe('output config related flag', () => { + outputFlags.forEach((flag) => { + // extract property name from flag name + const property = flag.name.split('output-')[1]; + const propName = hyphenToUpperCase(property); + + if (flag.type === Boolean && !flag.name.includes('output-library')) { + it(`should config --${flag.name} correctly`, () => { + let { stderr, stdout } = run(__dirname, [`--${flag.name}`]); + + if (flag.name === 'output-module') { + //'output.module: true' is only allowed when 'experiments.outputModule' is enabled + stdout = run(__dirname, [`--${flag.name}`, '--experiments-output-module']).stdout; + expect(stdout).toContain('module: true'); + } else if (flag.name.includes('-reset')) { + const option = propName.split('Reset')[0]; + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${option}: []`); + } else { + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${propName}: true`); + } + }); + + it(`should config --no-${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--no-${flag.name}`]); + + if (flag.name.includes('-reset')) { + const option = propName.split('Reset')[0]; + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${option}: []`); + } else { + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${propName}: false`); + } + }); + } + + if (flag.type === Number) { + it(`should config --${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--${flag.name}`, '10']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${propName}: 10`); + }); + } + + if (flag.type === String && !flag.name.includes('output-library')) { + it(`should config --${flag.name} correctly`, () => { + let { stderr, stdout } = run(__dirname, [`--${flag.name}`, 'test']); + + if (flag.name === 'output-cross-origin-loading') { + stdout = run(__dirname, [`--${flag.name}`, 'anonymous']).stdout; + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${propName}: 'anonymous'`); + } else if (flag.name === 'output-enabled-library-type') { + stdout = run(__dirname, [`--${flag.name}`, 'amd']).stdout; + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${propName}: 'amd'`); + } else if (flag.name === 'output-hash-function') { + stdout = run(__dirname, [`--${flag.name}`, 'sha256']).stdout; + stderr = run(__dirname, [`--${flag.name}`, 'sha256']).stderr; + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`hashFunction: 'sha256'`); + } else if (flag.name === 'output-script-type') { + stdout = run(__dirname, [`--${flag.name}`, 'module']).stdout; + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${propName}: 'module'`); + } else if (flag.name === 'output-enabled-library-types') { + stdout = run(__dirname, [`--${flag.name}`, 'var']).stdout; + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${propName}: [ 'var' ]`); + } else if (flag.name === 'output-path') { + expect(stdout).toContain('test'); + } else { + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${propName}: 'test'`); + } + }); + } + + if (flag.name.includes('output-library')) { + it(`should config name, type and export correctly`, () => { + const { stderr, stdout } = run(__dirname, [ + '--output-library-name', + 'myLibrary', + '--output-library-type', + 'var', + '--output-library-export', + 'myExport', + '--output-library-auxiliary-comment', + 'comment', + '--output-library-umd-named-define', + ]); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('myLibrary'); + expect(stdout).toContain(`type: 'var'`); + expect(stdout).toContain('export: [Array]'); + expect(stdout).toContain(`auxiliaryComment: 'comment'`); + expect(stdout).toContain('umdNamedDefine: true'); + }); + + it('should be succesful with --output-library-reset correctly', () => { + const { stderr, stdout } = run(__dirname, ['--output-library-reset']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('name: []'); + }); + } + }); +}); diff --git a/test/core-flags/parallelism-flag.test.js b/test/core-flags/parallelism-flag.test.js new file mode 100644 index 00000000000..02f1f878be7 --- /dev/null +++ b/test/core-flags/parallelism-flag.test.js @@ -0,0 +1,12 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); + +describe('--parallelism flag', () => { + it('should set parallelism to the value passed', () => { + const { stderr, stdout } = run(__dirname, ['--parallelism', '50']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('parallelism: 50'); + }); +}); diff --git a/test/core-flags/performance-flags.test.js b/test/core-flags/performance-flags.test.js new file mode 100644 index 00000000000..106f5af725f --- /dev/null +++ b/test/core-flags/performance-flags.test.js @@ -0,0 +1,38 @@ +'use strict'; + +const { run, hyphenToUpperCase } = require('../utils/test-utils'); +const { flagsFromCore } = require('../../packages/webpack-cli/lib/utils/cli-flags'); + +const performanceFlags = flagsFromCore.filter(({ name }) => name.startsWith('performance-')); + +describe('module config related flag', () => { + it(`should config --performance option correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--no-performance`]); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('performance: false'); + }); + + performanceFlags.forEach((flag) => { + // extract property name from flag name + const property = flag.name.split('performance-')[1]; + const propName = hyphenToUpperCase(property); + + if (flag.type === Number) { + it(`should config --${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--${flag.name}`, '10']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${propName}: 10`); + }); + } + + if (flag.type === String) { + it(`should config --${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--${flag.name}`, 'warning']); + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`${propName}: 'warning'`); + }); + } + }); +}); diff --git a/test/core-flags/profile-flag.test.js b/test/core-flags/profile-flag.test.js new file mode 100644 index 00000000000..2ba4d1169b2 --- /dev/null +++ b/test/core-flags/profile-flag.test.js @@ -0,0 +1,19 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); + +describe('--profile flag', () => { + it('should set profile to true', () => { + const { stderr, stdout } = run(__dirname, ['--profile']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('profile: true'); + }); + + it('should set profile to false', () => { + const { stderr, stdout } = run(__dirname, ['--no-profile']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('profile: false'); + }); +}); diff --git a/test/core-flags/records-flag.test.js b/test/core-flags/records-flag.test.js new file mode 100644 index 00000000000..e4724266dfb --- /dev/null +++ b/test/core-flags/records-flag.test.js @@ -0,0 +1,26 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); + +describe('module config related flag', () => { + it('should config records-path correctly', () => { + const { stderr, stdout } = run(__dirname, ['--records-path', './bin/records.json']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('records.json'); + }); + + it('should config records-input-path correctly', () => { + const { stderr, stdout } = run(__dirname, ['--records-input-path', './bin/records.json']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('records.json'); + }); + + it('should config records-output-path correctly', () => { + const { stderr, stdout } = run(__dirname, ['--records-output-path', './bin/records.json']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('records.json'); + }); +}); diff --git a/test/core-flags/resolve-flags.test.js b/test/core-flags/resolve-flags.test.js new file mode 100644 index 00000000000..e71d8cc7eef --- /dev/null +++ b/test/core-flags/resolve-flags.test.js @@ -0,0 +1,81 @@ +'use strict'; + +const { run, hyphenToUpperCase } = require('../utils/test-utils'); +const { flagsFromCore } = require('../../packages/webpack-cli/lib/utils/cli-flags'); + +const resolveFlags = flagsFromCore.filter(({ name }) => name.startsWith('resolve')); + +describe('resolve config related flags', () => { + resolveFlags.forEach((flag) => { + // extract property name from flag name + let property = flag.name.split('resolve-')[1]; + if (flag.name.startsWith('resolve-loader')) { + property = flag.name.split('resolve-loader-')[1]; + } + const propName = hyphenToUpperCase(property); + + if (flag.type === Boolean && !flag.name.includes('alias-')) { + it(`should config --${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--${flag.name}`]); + + expect(stderr).toBeFalsy(); + if (flag.name.includes('reset')) { + const option = propName.split('Reset')[0]; + expect(stdout).toContain(`${option}: []`); + } else { + expect(stdout).toContain(`${propName}: true`); + } + }); + } + + if (flag.type === String && !flag.name.includes('alias-')) { + it(`should config --${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--${flag.name}`, 'browser']); + expect(stderr).toBeFalsy(); + if (propName === 'restrictions') { + expect(stdout).toContain('browser'); + } else { + expect(stdout).toContain(`${propName}: [ 'browser' ]`); + } + }); + } + + if (flag.name.includes('alias-')) { + it(`should config --${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [ + `--resolve-alias-alias`, + 'alias', + '--resolve-alias-name', + 'name', + '--resolve-alias-fields', + 'aliasField', + '--resolve-loader-alias-alias', + 'loaderAlias', + '--resolve-loader-alias-name', + 'loaderName', + '--resolve-loader-alias-fields', + 'loader-field', + ]); + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`alias: [ { alias: 'alias', name: 'name' } ]`); + expect(stdout).toContain(`aliasFields: [ 'aliasField' ]`); + expect(stdout).toContain(`alias: [ { alias: 'loaderAlias', name: 'loaderName' } ]`); + expect(stdout).toContain(`aliasFields: [ 'loader-field' ]`); + }); + + if (flag.name.includes('reset')) { + it(`should config --${flag.name} alias-reset flags correctly`, () => { + const { stderr, stdout } = run(__dirname, [ + `--resolve-alias-reset`, + '--resolve-alias-fields-reset', + '--resolve-loader-alias-reset', + '--resolve-loader-alias-fields-reset', + ]); + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`alias: []`); + expect(stdout).toContain(`aliasFields: []`); + }); + } + } + }); +}); diff --git a/test/core-flags/stats-flags.test.js b/test/core-flags/stats-flags.test.js new file mode 100644 index 00000000000..c4033cf5ef7 --- /dev/null +++ b/test/core-flags/stats-flags.test.js @@ -0,0 +1,68 @@ +'use strict'; + +const { run, hyphenToUpperCase } = require('../utils/test-utils'); +const { flagsFromCore } = require('../../packages/webpack-cli/lib/utils/cli-flags'); + +const statsFlags = flagsFromCore.filter(({ name }) => name.startsWith('stats-')); + +describe('stats config related flag', () => { + statsFlags.forEach((flag) => { + // extract property name from flag name + const property = flag.name.split('stats-')[1]; + const propName = hyphenToUpperCase(property); + + if (flag.type === Boolean) { + it(`should config --${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--${flag.name}`]); + + expect(stderr).toBeFalsy(); + if (flag.name.includes('reset')) { + const option = propName.split('Reset')[0]; + expect(stdout).toContain(`stats: { ${option}: [] }`); + } else { + expect(stdout).toContain(`stats: { ${propName}: true }`); + } + }); + + it(`should config --no-${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--no-${flag.name}`]); + + expect(stderr).toBeFalsy(); + if (flag.name.includes('reset')) { + expect(stdout).toContain(`stats: {}`); + } else { + expect(stdout).toContain(`stats: { ${propName}: false }`); + } + }); + } + + if (flag.type === Number) { + it(`should config --${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--${flag.name}`, '10']); + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`stats: { ${propName}: 10 }`); + }); + } + + if (flag.type === String) { + const acceptsSingleValue = ['preset', 'modulesSort', 'logging', 'chunksSort', 'assetsSort']; + + it(`should config --${flag.name} correctly`, () => { + let { stderr, stdout } = run(__dirname, [`--${flag.name}`, 'log']); + expect(stderr).toBeFalsy(); + if (flag.name.includes('stats-colors')) { + const option = flag.name.split('stats-colors-')[1]; + stdout = run(__dirname, [`--${flag.name}`, 'u001b[32m']).stdout; + + expect(stdout).toContain(`stats: { colors: { ${option}: 'u001b[32m' } }`); + } else if (acceptsSingleValue.includes(propName)) { + expect(stdout).toContain(`stats: { ${propName}: 'log' }`); + } else if (flag.name === 'stats-context') { + expect(stdout).toContain('log'); + } else { + expect(stdout).toContain(`stats: { ${propName}: [ 'log' ] }`); + } + }); + } + }); +}); diff --git a/test/core-flags/watch-flags.test.js b/test/core-flags/watch-flags.test.js new file mode 100644 index 00000000000..ff8208ee2e4 --- /dev/null +++ b/test/core-flags/watch-flags.test.js @@ -0,0 +1,60 @@ +'use strict'; + +const { run, hyphenToUpperCase } = require('../utils/test-utils'); +const { flagsFromCore } = require('../../packages/webpack-cli/lib/utils/cli-flags'); + +const watchFlags = flagsFromCore.filter(({ name }) => name.startsWith('watch')); + +describe('watch config related flag', () => { + watchFlags.forEach((flag) => { + // extract property name from flag name + const property = flag.name.split('watch-options-')[1]; + const propName = hyphenToUpperCase(property); + + if (flag.type === Boolean) { + it(`should config --${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--${flag.name}`]); + + expect(stderr).toBeFalsy(); + if (flag.name.includes('reset')) { + expect(stdout).toContain(`watchOptions: { ignored: [] }`); + } else { + expect(stdout).toContain(`watchOptions: { ${propName}: true }`); + } + }); + + it(`should config --no-${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--no-${flag.name}`]); + + expect(stderr).toBeFalsy(); + if (flag.name.includes('reset')) { + expect(stdout).toContain('watch: false'); + } else { + expect(stdout).toContain(`watchOptions: { ${propName}: false }`); + } + }); + } + + if (flag.type === Number) { + it(`should config --${flag.name} correctly`, () => { + const { stderr, stdout } = run(__dirname, [`--${flag.name}`, '10']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(`watchOptions: { ${propName}: 10 }`); + }); + } + + if (flag.type === String) { + it(`should config --${flag.name} correctly`, () => { + let { stderr, stdout } = run(__dirname, [`--${flag.name}`, 'ignore.js']); + expect(stderr).toBeFalsy(); + if (propName === 'poll') { + stdout = run(__dirname, [`--${flag.name}`, '10']).stdout; + expect(stdout).toContain(`watchOptions: { ${propName}: 10 }`); + } else { + expect(stdout).toContain(`watchOptions: { ${propName}: [ 'ignore.js' ] }`); + } + }); + } + }); +}); diff --git a/test/core-flags/webpack.config.js b/test/core-flags/webpack.config.js new file mode 100644 index 00000000000..47630dfc2e8 --- /dev/null +++ b/test/core-flags/webpack.config.js @@ -0,0 +1,8 @@ +const WebpackCLITestPlugin = require('../utils/webpack-cli-test-plugin'); + +module.exports = { + entry: './main.js', + mode: 'development', + name: 'compiler', + plugins: [new WebpackCLITestPlugin(['module', 'resolve', 'resolveLoader'])], +}; diff --git a/test/utils/test-utils.js b/test/utils/test-utils.js index 664d44a62f4..80faa787a27 100644 --- a/test/utils/test-utils.js +++ b/test/utils/test-utils.js @@ -252,6 +252,15 @@ const runInfo = (args, testPath) => { return run(testPath, ['info'].concat(args), false); }; +const hyphenToUpperCase = (name) => { + if (!name) { + return name; + } + return name.replace(/-([a-z])/g, function (g) { + return g[1].toUpperCase(); + }); +}; + module.exports = { run, runWatch, @@ -263,4 +272,5 @@ module.exports = { copyFileAsync, runInstall, runInfo, + hyphenToUpperCase, }; diff --git a/test/version/version-multi-args.test.js b/test/version/version-multi-args.test.js index 606290df37f..b2d31701bcf 100644 --- a/test/version/version-multi-args.test.js +++ b/test/version/version-multi-args.test.js @@ -8,7 +8,7 @@ describe('version flag with multiple arguments', () => { const { stdout, stderr } = run(__dirname, ['version', 'help'], false); expect(stdout).not.toContain(pkgJSON.version); - const uniqueIdentifier = 'Made with ♥️ by the webpack team'; + const uniqueIdentifier = '⬡ webpack ⬡'; expect(stdout).toContain(uniqueIdentifier); expect(stderr).toHaveLength(0); }); @@ -17,7 +17,7 @@ describe('version flag with multiple arguments', () => { const { stdout, stderr } = run(__dirname, ['version', '--help'], false); expect(stdout).not.toContain(pkgJSON.version); - const uniqueIdentifier = 'Made with ♥️ by the webpack team'; + const uniqueIdentifier = '⬡ webpack ⬡'; expect(stdout).toContain(uniqueIdentifier); expect(stderr).toHaveLength(0); });