Skip to content

Commit

Permalink
Increase unit test code coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
chuckdumont committed Nov 27, 2017
1 parent 0554089 commit f9fc9ad
Show file tree
Hide file tree
Showing 15 changed files with 151 additions and 130 deletions.
3 changes: 2 additions & 1 deletion NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ https://github.com/webpack/webpack/blob/v1.14.0/lib/dependencies/CommonJsRequire
https://github.com/webpack/webpack/blob/v3.6.0/test/ConfigTestCases.test.js (test only)
https://github.com/webpack/webpack/blob/v3.6.0/test/checkArrayExpectation.js (test only)
https://github.com/webpack/webpack/blob/v3.6.0/lib/node/NodeMainTemplatePlugin.js (test only)
https"//github.com/webpack/webpack/blob/v3.6.0/lib/JsonpMainTemplatePlugin.js (test only)

The product includes third party code that has been modified and adapted from the following file, originating in the Dojo Util project, and licensed under the Dojo License - http://dojotoolkit.org/license:
https://github.com/dojo/util/blob/1.10/build/transforms/writeDojo.js
https://github.com/dojo/util/blob/1.10/build/transforms/writeDojo.js
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ This property is optional and specifies an array of regular expressions to use i

See [CommonJS require vs. Dojo synchronous require](#commonjs-require-vs-dojo-synchronous-require). Some Webpack plugins (e.g. [ProvidePlugin](https://webpack.js.org/plugins/provide-plugin/)) can inject CommonJS calls directly into your AMD modules. This property provides a mechanism for those modules to be loaded as CommonJS modules. If any of the regular expressions specified match the module identifier in a candidate require call (within an AMD module), then the module will be loaded as a CommonJS module. If none of the patterns match, then the require call will be processed as a Dojo synchronous require call.

If not specified, the default pattern `imports-loader|exports-loader)[?!]` is used. This pattern will match many of the common use cases for the ProvidePlugin. Note that if you specify this property, the values you specify **replace** the default value.
If not specified, the default pattern `(imports-loader|exports-loader)[?!]` is used. This pattern will match many of the common use cases for the ProvidePlugin. Note that if you specify this property, the values you specify **replace** the default value.

### coerceUndefinedToFalse

Expand Down Expand Up @@ -274,7 +274,7 @@ There are two ways to use the embedded Dojo loader without the config API.
]
```

1. If you are specifying a pre-built embedded loader using the [loader](#loader) option, then build the loader without the config API as described in [Overriding profile features](#overriding-profile-features). Note that an exception will be thrown if the [loaderConfig](#loaderconfig) option specifies a module name and the provided loader does not include the config API.
1. If you are specifying a pre-built embedded loader using the [loader](#loader) option, then build the loader without the config API as described in [Overriding profile features](#overriding-profile-features). Note that a build-time exception will be thrown if the [loaderConfig](#loaderconfig) option specifies a module name and the provided loader does not include the config API.

# ES6 Promise dependency in Webpack 2.x

Expand All @@ -288,11 +288,11 @@ When using Webpack's NormalModuleReplacementPlugin, the order of the plugin regi

Webpack normally transforms async `require()` calls into `__webpack_require__()` calls for the purpose of loading modules at application runtime. However, if the call references dependencies which cannot be evaluated at build time, then the `require()` call will not be transformed. Instead, `require()`, as implemented by this plugin, will be called at application runtime on the client and will complete synchronously (callback invoked prior to returning) provided the requested modules are available from chunks that have already been loaded in the client. If any of the modules requested are not available, then an exception will be thrown. This restriction is necessary because webpack uses a synchronous model for resolving dependencies at application runtime. Only the loading of webpack chunks is allowed to complete asynchronously.

This can be an issue if your application utilizes the Dojo parser's [Auto-Require](https://dojotoolkit.org/documentation/tutorials/1.10/declarative/#auto-require) capability for loading modules of declaratively instanciated widgets. Although useful for prototyping and demo purposes, Dojo itself recommends against using Auto-Require for production code because of it's negative performance consequences, and to instead be explicit about your application's dependencies.
This can be an issue if your application utilizes the Dojo parser's [Auto-Require](https://dojotoolkit.org/documentation/tutorials/1.10/declarative/#auto-require) capability for loading modules of declaratively instantiated widgets. Although useful for prototyping and demo purposes, Dojo itself recommends against using Auto-Require for production code because of it's negative performance consequences, and to instead be explicit about your application's dependencies.

# Dependency requirements

**dojo-webpack-plugin** has a peer dependency on webpack. **dojo-webpack-plugin**'s webpack dependencies must resolve to the same modules as your applicaiton's webpack dependencies, otherwise you may encounter errors similar to the following when building.
**dojo-webpack-plugin** has a peer dependency on webpack. **dojo-webpack-plugin**'s webpack dependencies must resolve to the same modules as your application's webpack dependencies, otherwise you may encounter errors similar to the following when building.

```
Error: Cannot find module 'webpack-core/lib/ConcatSource'
Expand Down
17 changes: 14 additions & 3 deletions lib/DojoAMDPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ module.exports = class DojoAMDPlugin {

apply(compiler) {

compiler.apply(new DojoAMDMainTemplatePlugin(this.options));
compiler.apply(new DojoAMDChunkTemplatePlugin(this.options));
compiler.apply(
new DojoLoaderPlugin(this.options),
new DojoAMDMainTemplatePlugin(this.options),
new DojoAMDChunkTemplatePlugin(this.options)
);

compiler.plugin("compilation", (compilation, params) => {
compilation.dependencyFactories.set(DojoAMDRequireItemDependency, params.normalModuleFactory);
Expand All @@ -60,6 +63,15 @@ module.exports = class DojoAMDPlugin {
return true;
}
});
// Ensure that the embedded loader doesn't pull in node dependencies for process and global
const embeddedLoaderFileName = parser.applyPluginsBailResult("evaluate Identifier __embedded_dojo_loader__").string;
["process", "global"].forEach(name => {
parser.plugin(`expression ${name}`, function() {
if(this.state.module && this.state.module.request === embeddedLoaderFileName) {
return false;
}
});
});
});
});

Expand All @@ -85,7 +97,6 @@ module.exports = class DojoAMDPlugin {

compiler.apply(
new DojoAMDModuleFactoryPlugin(this.options),
new DojoLoaderPlugin(this.options),
new DojoAMDResolverPlugin()
);

Expand Down
1 change: 1 addition & 0 deletions lib/DojoAMDResolverPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module.exports = class DojoAMDResolverPlugin {
if (request.directory) return;
const dojoRequire = compiler.applyPluginsBailResult("get dojo require");
const url = dojoRequire.toUrl(request.request, {mid: path.join(request.path, "x").replace('\\', '/')});
/* istanbul ignore else */
if (url && url != request.request) {
const obj = {
path: path.normalize(url), // sets path separators to platform specific values
Expand Down
6 changes: 5 additions & 1 deletion lib/DojoLoaderPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const dojoLoaderUtils = require("./dojoLoaderUtils");
const embeddedLoaderFilenameExpression = "__embedded_dojo_loader__";

function containsModule(chunk, module) {
/* istanbul ignore else */
if (chunk.containsModule) {
return chunk.containsModule(module);
} else {
Expand Down Expand Up @@ -126,7 +127,8 @@ Refer to https://github.com/OpenNTF/dojo-webpack-plugin/blob/master/README.md#bu
}
return callback(err, scope);
}
callback();
/* istanbul ignore next */
callback(err);
});
}

Expand Down Expand Up @@ -235,9 +237,11 @@ module.exports = class DojoLoaderPlugin {
// only in the entry chunks that contain the webpack runtime.
chunks.forEach((chunk) => {
if (chunk.hasRuntime()) {
/* istanbul ignore if */
if (!loaderModule) {
throw Error("Can't locate " + this.options.loader + " in compilation");
}
/* istanbul ignore if */
if (util.isString(this.options.loaderConfig) && !configModule) {
throw Error("Can't locate " + this.options.loaderConfig + " in compilation");
}
Expand Down
1 change: 1 addition & 0 deletions loaders/dojo/loaderProxy/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module.exports = function() {
const dojoRequire = this._compiler.applyPluginsBailResult("get dojo require");
const query = this.query ? loaderUtils.parseQuery(this.query) : {};
const loader = query.loader;
/* istanbul ignore if */
if (!loader) {
throw new Error("No loader specified");
}
Expand Down
8 changes: 8 additions & 0 deletions test/TestCases/misc/loaderRuntime/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
define(["test/a"], function(a) {
it("should compile", function(done) {
done();
});
it("should load dependency", function() {
a.should.be.eql("a");
});
});
3 changes: 3 additions & 0 deletions test/TestCases/misc/loaderRuntime/loaderConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
packages:[{name:"test", location: "./subdir"}]
};
3 changes: 3 additions & 0 deletions test/TestCases/misc/loaderRuntime/subdir/a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
define([], function() {
return "a";
});
5 changes: 5 additions & 0 deletions test/TestCases/misc/loaderRuntime/test.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
findBundle: function() {
return ["./vendor.js", "./app.js"];
}
};
3 changes: 3 additions & 0 deletions test/TestCases/misc/loaderRuntime/vendor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
vendor: "vendor"
};
27 changes: 27 additions & 0 deletions test/TestCases/misc/loaderRuntime/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
var path = require("path");
var webpack = require("webpack");
var DojoWebpackPlugin = require("../../../../index");
module.exports = [
require("./loaderConfig"),
require.resolve("./loaderConfig")
].map(config => {
return {
entry: {
app: "./index"
},
output: {
filename: "app.js"
},
plugins: [
new DojoWebpackPlugin({
loaderConfig: config,
loader: path.join(__dirname, "../../../js/dojo/dojo.js")
}),
new webpack.optimize.CommonsChunkPlugin({
name: "vendor",
filename: "vendor.js",
minChunks: Infinity
})
]
};
});
73 changes: 63 additions & 10 deletions test/plugins/MainTemplatePlugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/

"use strict";
const ConcatSource = require("webpack-sources").ConcatSource;

module.exports = class PatchRequireScopePlugin {
module.exports = class MainTemplatePlugin {
apply(compiler) {
compiler.plugin("compilation", function(compilation) {
compilation.mainTemplate.plugin("require", function(source) {
Expand All @@ -26,7 +32,6 @@ module.exports = class PatchRequireScopePlugin {
return source.replace(/__webpack_require__\);/g, "__webpack_require__, req);");
});

// For unit testing only
compilation.moduleTemplate.plugin("render", function(source, module) {
var result = source;
if (module.isAMD) {
Expand All @@ -39,14 +44,62 @@ module.exports = class PatchRequireScopePlugin {
return result;
});

compilation.mainTemplate.plugin("bootstrap", function(source, chunk) {
const buf = [];
if(chunk.chunks.length > 0) {
var jsonpFn = JSON.stringify(this.outputOptions.jsonpFunction);
buf.push(`this[${jsonpFn}] = this[${jsonpFn}] || {}`);
}
buf.push(source);
return this.asString(buf);
compilation.mainTemplate.plugin("require-ensure", function(__, chunk, hash) {
const chunkFilename = this.outputOptions.chunkFilename;
const chunkMaps = chunk.getChunkMaps();
return this.asString([
"var installedChunkData = installedChunks[chunkId];",
"if(installedChunkData === 0) {",
this.indent([
"return new Promise(function(resolve) { resolve(); });"
]),
"}",
"",
"// a Promise means \"currently loading\".",
"if(installedChunkData) {",
this.indent([
"return installedChunkData[2];"
]),
"}",
"",
"// setup Promise in chunk cache",
"var promise = new Promise(function(resolve, reject) {",
this.indent([
"installedChunkData = installedChunks[chunkId] = [resolve, reject];"
]),
"});",
"installedChunkData[2] = promise;",
"",
"// start chunk loading",
"var filename = __dirname + " + this.applyPluginsWaterfall("asset-path", JSON.stringify(`/${chunkFilename}`), {
hash: `" + ${this.renderCurrentHashCode(hash)} + "`,
hashWithLength: (length) => `" + ${this.renderCurrentHashCode(hash, length)} + "`,
chunk: {
id: "\" + chunkId + \"",
hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`,
hashWithLength: (length) => {
const shortChunkHashMap = {};
Object.keys(chunkMaps.hash).forEach((chunkId) => {
if(typeof chunkMaps.hash[chunkId] === "string")
shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr(0, length);
});
return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`;
},
name: `" + (${JSON.stringify(chunkMaps.name)}[chunkId]||chunkId) + "`
}
}) + ";",
"require('fs').readFile(filename, 'utf-8', function(err, content) {",
this.indent([
"if(err) return reject(err);",
"var chunk = {}, i;",
"var vm = require('vm');",
"var context = vm.createContext(global);",
"vm.runInContext('(function(exports, require, __dirname, __filename, global, window) {' + content + '\\n})', context, filename)" +
".call(global, chunk, require, require('path').dirname(filename), filename, context, context);"
]),
"});",
"return promise;"
]);
});
});
}
Expand Down
102 changes: 0 additions & 102 deletions test/plugins/NodeRequireEnsurePatchPlugin/index.js

This file was deleted.

Loading

0 comments on commit f9fc9ad

Please sign in to comment.