diff --git a/tools/tests/app-config.js b/tools/tests/app-config.js
new file mode 100644
index 0000000000..d6acbd7e8e
--- /dev/null
+++ b/tools/tests/app-config.js
@@ -0,0 +1,110 @@
+var selftest = require('../tool-testing/selftest.js');
+var Sandbox = selftest.Sandbox;
+
+selftest.define("mainModule", function () {
+ const s = new Sandbox();
+ s.createApp("app-config-mainModule", "app-config");
+ s.cd("app-config-mainModule");
+
+ const run = s.run(
+ "test",
+ "--full-app",
+ "--driver-package", "dispatch:mocha-phantomjs"
+ );
+
+ run.waitSecs(60);
+ run.match("App running at");
+
+ function check(mainModule) {
+ const json = JSON.parse(s.read("package.json"));
+
+ let shouldWrite = true;
+ if (typeof mainModule === "undefined") {
+ if ("meteor" in json) {
+ delete json.meteor;
+ } else {
+ shouldWrite = false;
+ }
+ } else {
+ json.meteor = { mainModule };
+ }
+
+ if (shouldWrite) {
+ s.write("package.json", JSON.stringify(json, null, 2) + "\n");
+ }
+
+ run.waitSecs(10);
+ run.match("SERVER FAILURES: 0");
+ run.match("CLIENT FAILURES: 0");
+ }
+
+ check();
+
+ check(null);
+
+ check("oyez");
+
+ check({});
+
+ check({
+ client: "a",
+ os: "bc",
+ });
+
+ check({
+ client: "b.js",
+ server: "abc",
+ });
+
+ check({
+ client: "./c",
+ server: "/ac",
+ });
+
+ check({
+ server: "./a",
+ web: "ab",
+ });
+
+ check({
+ client: "ac.js",
+ os: "a",
+ });
+
+ check({
+ web: "bc",
+ server: "a",
+ });
+
+ check({
+ server: "b.js",
+ client: "abc",
+ });
+
+ check({
+ client: "abc",
+ });
+
+ check({
+ server: "b.js",
+ });
+
+ check({
+ client: "/ac",
+ server: "./c",
+ });
+
+ check({
+ os: "ab",
+ client: "./a",
+ });
+
+ check({
+ server: "ac.js",
+ web: "a",
+ });
+
+ check(null);
+
+ check();
+});
diff --git a/tools/tests/apps/app-config/.gitignore b/tools/tests/apps/app-config/.gitignore
new file mode 100644
index 0000000000..c2658d7d1b
--- /dev/null
+++ b/tools/tests/apps/app-config/.gitignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/tools/tests/apps/app-config/.meteor/.finished-upgraders b/tools/tests/apps/app-config/.meteor/.finished-upgraders
new file mode 100644
index 0000000000..910574ce2d
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/.finished-upgraders
@@ -0,0 +1,17 @@
+# This file contains information which helps Meteor properly upgrade your
+# app when you run 'meteor update'. You should check it into version control
+# with your project.
+
+notices-for-0.9.0
+notices-for-0.9.1
+0.9.4-platform-file
+notices-for-facebook-graph-api-2
+1.2.0-standard-minifiers-package
+1.2.0-meteor-platform-split
+1.2.0-cordova-changes
+1.2.0-breaking-changes
+1.3.0-split-minifiers-package
+1.4.0-remove-old-dev-bundle-link
+1.4.1-add-shell-server-package
+1.4.3-split-account-service-packages
+1.5-add-dynamic-import-package
diff --git a/tools/tests/apps/app-config/.meteor/.gitignore b/tools/tests/apps/app-config/.meteor/.gitignore
new file mode 100644
index 0000000000..4083037423
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/.gitignore
@@ -0,0 +1 @@
+local
diff --git a/tools/tests/apps/app-config/.meteor/.id b/tools/tests/apps/app-config/.meteor/.id
new file mode 100644
index 0000000000..a7468fe68d
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/.id
@@ -0,0 +1,7 @@
+# This file contains a token that is unique to your project.
+# Check it into your repository along with the rest of this directory.
+# It can be used for purposes such as:
+# - ensuring you don't accidentally deploy one app on top of another
+# - providing package authors with aggregated statistics
+
+h9uim8gzzdn7.vu1xo1jmqcme
diff --git a/tools/tests/apps/app-config/.meteor/packages b/tools/tests/apps/app-config/.meteor/packages
new file mode 100644
index 0000000000..46098f7d48
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/packages
@@ -0,0 +1,14 @@
+# Meteor packages used by this project, one per line.
+# Check this file (and the other files in this directory) into your repository.
+#
+# 'meteor add' and 'meteor remove' will edit this file for you,
+# but you can also edit it by hand.
+
+meteor-base # Packages every Meteor app needs to have
+static-html # Define static page content in .html files
+standard-minifier-css # CSS minifier run for production mode
+standard-minifier-js # JS minifier run for production mode
+es5-shim # ECMAScript 5 compatibility for older browsers
+ecmascript # Enable ECMAScript2015+ syntax in app code
+shell-server # Server-side component of the `meteor shell` command
+less # Support .less files for defining CSS styles
diff --git a/tools/tests/apps/app-config/.meteor/platforms b/tools/tests/apps/app-config/.meteor/platforms
new file mode 100644
index 0000000000..efeba1b50c
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/platforms
@@ -0,0 +1,2 @@
+server
+browser
diff --git a/tools/tests/apps/app-config/.meteor/release b/tools/tests/apps/app-config/.meteor/release
new file mode 100644
index 0000000000..621e94f0ec
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/release
@@ -0,0 +1 @@
+none
diff --git a/tools/tests/apps/app-config/.meteor/versions b/tools/tests/apps/app-config/.meteor/versions
new file mode 100644
index 0000000000..8b323e2c75
--- /dev/null
+++ b/tools/tests/apps/app-config/.meteor/versions
@@ -0,0 +1,66 @@
+allow-deny@1.1.0
+autoupdate@1.4.0
+babel-compiler@7.0.5
+babel-runtime@1.2.2
+base64@1.0.11
+binary-heap@1.0.10
+blaze-tools@1.0.10
+boilerplate-generator@1.5.0
+caching-compiler@1.1.11
+caching-html-compiler@1.1.2
+callback-hook@1.1.0
+check@1.3.0
+ddp@1.4.0
+ddp-client@2.3.1
+ddp-common@1.4.0
+ddp-server@2.1.2
+diff-sequence@1.1.0
+dispatch:mocha-browser@0.0.4
+dynamic-import@0.3.0
+ecmascript@0.10.5
+ecmascript-runtime@0.5.0
+ecmascript-runtime-client@0.6.2
+ecmascript-runtime-server@0.5.0
+ejson@1.1.0
+es5-shim@4.7.3
+geojson-utils@1.0.10
+hot-code-push@1.0.4
+html-tools@1.0.11
+htmljs@1.0.11
+http@1.4.0
+id-map@1.1.0
+less@2.7.12
+livedata@1.0.18
+logging@1.1.19
+meteor@1.8.3
+meteor-base@1.3.0
+minifier-css@1.3.1
+minifier-js@2.3.3
+minimongo@1.4.3
+modules@0.11.5
+modules-runtime@0.9.2
+mongo@1.4.4
+mongo-dev-server@1.1.0
+mongo-id@1.0.6
+npm-mongo@2.2.33
+ordered-dict@1.1.0
+practicalmeteor:mocha-core@1.0.1
+promise@0.10.2
+random@1.1.0
+reload@1.2.0
+retry@1.1.0
+routepolicy@1.0.12
+server-render@0.3.0
+shell-server@0.3.1
+shim-common@0.1.0
+socket-stream-client@0.1.0
+spacebars-compiler@1.1.3
+standard-minifier-css@1.4.1
+standard-minifier-js@2.3.2
+static-html@1.2.2
+templating-tools@1.1.2
+tracker@1.2.0
+underscore@1.0.10
+url@1.2.0
+webapp@1.5.0
+webapp-hashing@1.0.9
diff --git a/tools/tests/apps/app-config/a.js b/tools/tests/apps/app-config/a.js
new file mode 100644
index 0000000000..508c569e06
--- /dev/null
+++ b/tools/tests/apps/app-config/a.js
@@ -0,0 +1,2 @@
+import { report } from "./tests.js";
+report(module.id);
diff --git a/tools/tests/apps/app-config/ab.js b/tools/tests/apps/app-config/ab.js
new file mode 100644
index 0000000000..a4c5b25568
--- /dev/null
+++ b/tools/tests/apps/app-config/ab.js
@@ -0,0 +1,2 @@
+import "./a.js";
+import "./b.js";
diff --git a/tools/tests/apps/app-config/abc.js b/tools/tests/apps/app-config/abc.js
new file mode 100644
index 0000000000..07d1effb8f
--- /dev/null
+++ b/tools/tests/apps/app-config/abc.js
@@ -0,0 +1,2 @@
+import "./ab.js";
+import "./c.js";
diff --git a/tools/tests/apps/app-config/ac.js b/tools/tests/apps/app-config/ac.js
new file mode 100644
index 0000000000..7dc139edf8
--- /dev/null
+++ b/tools/tests/apps/app-config/ac.js
@@ -0,0 +1,2 @@
+import "./a.js";
+import "./c.js";
diff --git a/tools/tests/apps/app-config/b.js b/tools/tests/apps/app-config/b.js
new file mode 100644
index 0000000000..508c569e06
--- /dev/null
+++ b/tools/tests/apps/app-config/b.js
@@ -0,0 +1,2 @@
+import { report } from "./tests.js";
+report(module.id);
diff --git a/tools/tests/apps/app-config/bc.js b/tools/tests/apps/app-config/bc.js
new file mode 100644
index 0000000000..402dc1115a
--- /dev/null
+++ b/tools/tests/apps/app-config/bc.js
@@ -0,0 +1,2 @@
+import "./b.js";
+import "./c.js";
diff --git a/tools/tests/apps/app-config/c.js b/tools/tests/apps/app-config/c.js
new file mode 100644
index 0000000000..508c569e06
--- /dev/null
+++ b/tools/tests/apps/app-config/c.js
@@ -0,0 +1,2 @@
+import { report } from "./tests.js";
+report(module.id);
diff --git a/tools/tests/apps/app-config/client/main.css b/tools/tests/apps/app-config/client/main.css
new file mode 100644
index 0000000000..5b5a91897d
--- /dev/null
+++ b/tools/tests/apps/app-config/client/main.css
@@ -0,0 +1,3 @@
+body {
+ font-weight: 700;
+}
diff --git a/tools/tests/apps/app-config/client/main.html b/tools/tests/apps/app-config/client/main.html
new file mode 100644
index 0000000000..c0e549e637
--- /dev/null
+++ b/tools/tests/apps/app-config/client/main.html
@@ -0,0 +1,14 @@
+
+ app-config
+
+
+
+ Welcome to Meteor!
+ Learn Meteor!
+
+
diff --git a/tools/tests/apps/app-config/client/main.js b/tools/tests/apps/app-config/client/main.js
new file mode 100644
index 0000000000..bebaa30ed8
--- /dev/null
+++ b/tools/tests/apps/app-config/client/main.js
@@ -0,0 +1,2 @@
+import { report } from "../tests.js";
+report(module.id);
diff --git a/tools/tests/apps/app-config/client/main.less b/tools/tests/apps/app-config/client/main.less
new file mode 100644
index 0000000000..579899c6d3
--- /dev/null
+++ b/tools/tests/apps/app-config/client/main.less
@@ -0,0 +1,3 @@
+body {
+ background: #add8e6;
+}
diff --git a/tools/tests/apps/app-config/package-lock.json b/tools/tests/apps/app-config/package-lock.json
new file mode 100644
index 0000000000..82fe1359d1
--- /dev/null
+++ b/tools/tests/apps/app-config/package-lock.json
@@ -0,0 +1,683 @@
+{
+ "name": "app-config",
+ "requires": true,
+ "lockfileVersion": 1,
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.0.0-beta.40",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0-beta.40.tgz",
+ "integrity": "sha512-vIM68NUCWauZJTFoVUG1lggva1I8FLB9zFKwWG7Xjin4FkHpEKJv2y4x1DGVPVt93S5/zHSBj1bXYEuxOkFGzg==",
+ "requires": {
+ "core-js": "2.5.3",
+ "regenerator-runtime": "0.11.1"
+ }
+ },
+ "core-js": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz",
+ "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4="
+ },
+ "meteor-node-stubs": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-0.3.2.tgz",
+ "integrity": "sha512-l93SS/HutbqBRJODO2m7hup8cYI2acF5bB39+ZvP2BX8HMmCSCXeFH7v0sr4hD7zrVvHQA5UqS0pcDYKn0VM6g==",
+ "requires": {
+ "assert": "1.4.1",
+ "browserify-zlib": "0.1.4",
+ "buffer": "4.9.1",
+ "console-browserify": "1.1.0",
+ "constants-browserify": "1.0.0",
+ "crypto-browserify": "3.11.1",
+ "domain-browser": "1.1.7",
+ "events": "1.1.1",
+ "http-browserify": "1.7.0",
+ "https-browserify": "0.0.1",
+ "os-browserify": "0.2.1",
+ "path-browserify": "0.0.0",
+ "process": "0.11.10",
+ "punycode": "1.4.1",
+ "querystring-es3": "0.2.1",
+ "readable-stream": "git+https://github.com/meteor/readable-stream.git#d64a64aa6061b9b6855feff4d09e58fb3b2e4502",
+ "stream-browserify": "2.0.1",
+ "string_decoder": "1.0.3",
+ "timers-browserify": "1.4.2",
+ "tty-browserify": "0.0.0",
+ "url": "0.11.0",
+ "util": "0.10.3",
+ "vm-browserify": "0.0.4"
+ },
+ "dependencies": {
+ "Base64": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz",
+ "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg="
+ },
+ "asn1.js": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz",
+ "integrity": "sha1-SLokC0WpKA6UdImQull9IWYX/UA=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "inherits": "2.0.1",
+ "minimalistic-assert": "1.0.0"
+ }
+ },
+ "assert": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
+ "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
+ "requires": {
+ "util": "0.10.3"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "base64-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
+ "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw=="
+ },
+ "bn.js": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
+ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA=="
+ },
+ "brace-expansion": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
+ "requires": {
+ "balanced-match": "1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
+ },
+ "browserify-aes": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.0.tgz",
+ "integrity": "sha512-W2bIMLYoZ9oow7TyePpMJk9l9LY7O3R61a/68bVCDOtnJynnwe3ZeW2IzzSkrQnPKNdJrxVDn3ALZNisSBwb7g==",
+ "requires": {
+ "buffer-xor": "1.0.3",
+ "cipher-base": "1.0.4",
+ "create-hash": "1.1.3",
+ "evp_bytestokey": "1.0.3",
+ "inherits": "2.0.1",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz",
+ "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=",
+ "requires": {
+ "browserify-aes": "1.1.0",
+ "browserify-des": "1.0.0",
+ "evp_bytestokey": "1.0.3"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz",
+ "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=",
+ "requires": {
+ "cipher-base": "1.0.4",
+ "des.js": "1.0.0",
+ "inherits": "2.0.1"
+ }
+ },
+ "browserify-rsa": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "randombytes": "2.0.5"
+ }
+ },
+ "browserify-sign": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
+ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "browserify-rsa": "4.0.1",
+ "create-hash": "1.1.3",
+ "create-hmac": "1.1.6",
+ "elliptic": "6.4.0",
+ "inherits": "2.0.1",
+ "parse-asn1": "5.1.0"
+ }
+ },
+ "browserify-zlib": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz",
+ "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=",
+ "requires": {
+ "pako": "0.2.9"
+ }
+ },
+ "buffer": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
+ "requires": {
+ "base64-js": "1.2.1",
+ "ieee754": "1.1.8",
+ "isarray": "1.0.0"
+ }
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "requires": {
+ "inherits": "2.0.1",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "console-browserify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
+ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+ "requires": {
+ "date-now": "0.1.4"
+ }
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
+ },
+ "create-ecdh": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz",
+ "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "elliptic": "6.4.0"
+ }
+ },
+ "create-hash": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz",
+ "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=",
+ "requires": {
+ "cipher-base": "1.0.4",
+ "inherits": "2.0.1",
+ "ripemd160": "2.0.1",
+ "sha.js": "2.4.9"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz",
+ "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=",
+ "requires": {
+ "cipher-base": "1.0.4",
+ "create-hash": "1.1.3",
+ "inherits": "2.0.1",
+ "ripemd160": "2.0.1",
+ "safe-buffer": "5.1.1",
+ "sha.js": "2.4.9"
+ }
+ },
+ "crypto-browserify": {
+ "version": "3.11.1",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz",
+ "integrity": "sha512-Na7ZlwCOqoaW5RwUK1WpXws2kv8mNhWdTlzob0UXulk6G9BDbyiJaGTYBIX61Ozn9l1EPPJpICZb4DaOpT9NlQ==",
+ "requires": {
+ "browserify-cipher": "1.0.0",
+ "browserify-sign": "4.0.4",
+ "create-ecdh": "4.0.0",
+ "create-hash": "1.1.3",
+ "create-hmac": "1.1.6",
+ "diffie-hellman": "5.0.2",
+ "inherits": "2.0.1",
+ "pbkdf2": "3.0.14",
+ "public-encrypt": "4.0.0",
+ "randombytes": "2.0.5"
+ }
+ },
+ "date-now": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs="
+ },
+ "des.js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
+ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+ "requires": {
+ "inherits": "2.0.1",
+ "minimalistic-assert": "1.0.0"
+ }
+ },
+ "diffie-hellman": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz",
+ "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "miller-rabin": "4.0.1",
+ "randombytes": "2.0.5"
+ }
+ },
+ "domain-browser": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz",
+ "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw="
+ },
+ "elliptic": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
+ "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "brorand": "1.1.0",
+ "hash.js": "1.1.3",
+ "hmac-drbg": "1.0.1",
+ "inherits": "2.0.1",
+ "minimalistic-assert": "1.0.0",
+ "minimalistic-crypto-utils": "1.0.1"
+ }
+ },
+ "events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "requires": {
+ "md5.js": "1.3.4",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.1",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "hash-base": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz",
+ "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=",
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ },
+ "hash.js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
+ "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
+ "requires": {
+ "inherits": "2.0.3",
+ "minimalistic-assert": "1.0.0"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ }
+ }
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "requires": {
+ "hash.js": "1.1.3",
+ "minimalistic-assert": "1.0.0",
+ "minimalistic-crypto-utils": "1.0.1"
+ }
+ },
+ "http-browserify": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz",
+ "integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=",
+ "requires": {
+ "Base64": "0.2.1",
+ "inherits": "2.0.1"
+ }
+ },
+ "https-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz",
+ "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI="
+ },
+ "ieee754": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
+ "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q="
+ },
+ "indexof": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "md5.js": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
+ "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
+ "requires": {
+ "hash-base": "3.0.4",
+ "inherits": "2.0.1"
+ },
+ "dependencies": {
+ "hash-base": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "requires": {
+ "inherits": "2.0.1",
+ "safe-buffer": "5.1.1"
+ }
+ }
+ }
+ },
+ "miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+ "requires": {
+ "bn.js": "4.11.8",
+ "brorand": "1.1.0"
+ }
+ },
+ "minimalistic-assert": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz",
+ "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M="
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "1.1.8"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "os-browserify": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz",
+ "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8="
+ },
+ "pako": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="
+ },
+ "parse-asn1": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz",
+ "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=",
+ "requires": {
+ "asn1.js": "4.9.1",
+ "browserify-aes": "1.1.0",
+ "create-hash": "1.1.3",
+ "evp_bytestokey": "1.0.3",
+ "pbkdf2": "3.0.14"
+ }
+ },
+ "path-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
+ "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo="
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "pbkdf2": {
+ "version": "3.0.14",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz",
+ "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==",
+ "requires": {
+ "create-hash": "1.1.3",
+ "create-hmac": "1.1.6",
+ "ripemd160": "2.0.1",
+ "safe-buffer": "5.1.1",
+ "sha.js": "2.4.9"
+ }
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+ },
+ "public-encrypt": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz",
+ "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=",
+ "requires": {
+ "bn.js": "4.11.8",
+ "browserify-rsa": "4.0.1",
+ "create-hash": "1.1.3",
+ "parse-asn1": "5.1.0",
+ "randombytes": "2.0.5"
+ }
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
+ },
+ "randombytes": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz",
+ "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==",
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "readable-stream": {
+ "version": "git+https://github.com/meteor/readable-stream.git#d64a64aa6061b9b6855feff4d09e58fb3b2e4502",
+ "requires": {
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ }
+ }
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+ "requires": {
+ "glob": "7.1.2"
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
+ "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=",
+ "requires": {
+ "hash-base": "2.0.2",
+ "inherits": "2.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
+ },
+ "sha.js": {
+ "version": "2.4.9",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.9.tgz",
+ "integrity": "sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==",
+ "requires": {
+ "inherits": "2.0.1",
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "stream-browserify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
+ "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
+ "requires": {
+ "inherits": "2.0.1",
+ "readable-stream": "git+https://github.com/meteor/readable-stream.git#d64a64aa6061b9b6855feff4d09e58fb3b2e4502"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "timers-browserify": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz",
+ "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=",
+ "requires": {
+ "process": "0.11.10"
+ }
+ },
+ "tty-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY="
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
+ }
+ }
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "vm-browserify": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
+ "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
+ "requires": {
+ "indexof": "0.0.1"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ }
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+ }
+ }
+}
diff --git a/tools/tests/apps/app-config/package.json b/tools/tests/apps/app-config/package.json
new file mode 100644
index 0000000000..eeb7e1bb75
--- /dev/null
+++ b/tools/tests/apps/app-config/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "app-config",
+ "private": true,
+ "scripts": {
+ "start": "meteor run"
+ },
+ "dependencies": {
+ "@babel/runtime": "^7.0.0-beta.36",
+ "meteor-node-stubs": "^0.3.2"
+ }
+}
diff --git a/tools/tests/apps/app-config/server/main.js b/tools/tests/apps/app-config/server/main.js
new file mode 100644
index 0000000000..bebaa30ed8
--- /dev/null
+++ b/tools/tests/apps/app-config/server/main.js
@@ -0,0 +1,2 @@
+import { report } from "../tests.js";
+report(module.id);
diff --git a/tools/tests/apps/app-config/tests.js b/tools/tests/apps/app-config/tests.js
new file mode 100644
index 0000000000..0882961844
--- /dev/null
+++ b/tools/tests/apps/app-config/tests.js
@@ -0,0 +1,97 @@
+import assert from "assert";
+
+const ids = [];
+export function report(id) {
+ ids.push(id);
+}
+
+const startupPromise = new Promise(resolve => {
+ Meteor.startup(resolve);
+});
+
+describe("meteor.mainModule", () => {
+ // These tests test the consequences of having various meteor.mainModule
+ // configurations in package.json.
+ const config = require("./package.json").meteor;
+
+ if (Meteor.isClient) {
+ it("always loads static HTML", () => {
+ assert.strictEqual(
+ document.getElementsByTagName("h1").item(0).innerText,
+ "Welcome to Meteor!"
+ );
+
+ assert.strictEqual(
+ document.getElementsByTagName("h2").item(0).innerText,
+ "Learn Meteor!"
+ );
+
+ const listItems = document
+ .getElementById("meteor-reading-list")
+ .getElementsByTagName("li");
+ assert.strictEqual(listItems.length, 4);
+ });
+
+ it("always loads CSS resources", () => {
+ let { fontWeight } = getComputedStyle(document.body);
+ assert(fontWeight === "bold" ||
+ fontWeight === "700",
+ fontWeight);
+ });
+
+ it("always loads LESS styles", () => {
+ assert.strictEqual(
+ getComputedStyle(document.body)["background-color"],
+ "rgb(173, 216, 230)" // #add8e6
+ );
+ });
+ }
+
+ it("loads the right files", async () => {
+ await startupPromise;
+
+ function checkNoMainModule() {
+ assert.deepEqual(ids, [
+ "/a.js",
+ "/b.js",
+ "/c.js",
+ Meteor.isClient
+ ? "/client/main.js"
+ : "/server/main.js"
+ ]);
+ }
+
+ if (! config ||
+ ! config.mainModule) {
+ return checkNoMainModule();
+ }
+
+ let mainId;
+
+ if (Meteor.isClient) {
+ mainId =
+ config.mainModule.client ||
+ config.mainModule.web;
+ console.log("client config:", config);
+ } else if (Meteor.isServer) {
+ mainId =
+ config.mainModule.server ||
+ config.mainModule.os;
+ console.log("server config:", config);
+ }
+
+ if (! mainId) {
+ return checkNoMainModule();
+ }
+
+ const absId = require.resolve("./" + mainId);
+ const basename = absId.split("/").pop();
+ const name = basename.split(".", 1)[0];
+ const chars = name.split("");
+
+ assert.deepEqual(
+ ids,
+ chars.map(ch => "/" + ch + ".js"),
+ );
+ });
+});