michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: 'use strict'; michael@0: michael@0: let { michael@0: Loader, main, unload, parseStack, generateMap, resolve, nodeResolve michael@0: } = require('toolkit/loader'); michael@0: let { readURI } = require('sdk/net/url'); michael@0: let { all } = require('sdk/core/promise'); michael@0: let testOptions = require('@test/options'); michael@0: michael@0: let root = module.uri.substr(0, module.uri.lastIndexOf('/')) michael@0: // The following adds Debugger constructor to the global namespace. michael@0: const { Cu } = require('chrome'); michael@0: const { addDebuggerToGlobal } = Cu.import('resource://gre/modules/jsdebugger.jsm', {}); michael@0: addDebuggerToGlobal(this); michael@0: michael@0: michael@0: exports['test nodeResolve'] = function (assert) { michael@0: let rootURI = root + '/fixtures/native-addon-test/'; michael@0: let manifest = {}; michael@0: manifest.dependencies = {}; michael@0: michael@0: // Handles extensions michael@0: resolveTest('../package.json', './dir/c.js', './package.json'); michael@0: resolveTest('../dir/b.js', './dir/c.js', './dir/b.js'); michael@0: michael@0: resolveTest('./dir/b', './index.js', './dir/b.js'); michael@0: resolveTest('../index', './dir/b.js', './index.js'); michael@0: resolveTest('../', './dir/b.js', './index.js'); michael@0: resolveTest('./dir/a', './index.js', './dir/a.js', 'Precedence dir/a.js over dir/a/'); michael@0: resolveTest('../utils', './dir/a.js', './utils/index.js', 'Requiring a directory defaults to dir/index.js'); michael@0: resolveTest('../newmodule', './dir/c.js', './newmodule/lib/file.js', 'Uses package.json main in dir to load appropriate "main"'); michael@0: resolveTest('test-math', './utils/index.js', './node_modules/test-math/index.js', michael@0: 'Dependencies default to their index.js'); michael@0: resolveTest('test-custom-main', './utils/index.js', './node_modules/test-custom-main/lib/custom-entry.js', michael@0: 'Dependencies use "main" entry'); michael@0: resolveTest('test-math/lib/sqrt', './utils/index.js', './node_modules/test-math/lib/sqrt.js', michael@0: 'Dependencies\' files can be consumed via "/"'); michael@0: michael@0: resolveTest('sdk/tabs/utils', './index.js', undefined, michael@0: 'correctly ignores SDK references in paths'); michael@0: resolveTest('fs', './index.js', undefined, michael@0: 'correctly ignores built in node modules in paths'); michael@0: michael@0: resolveTest('test-add', './node_modules/test-math/index.js', michael@0: './node_modules/test-math/node_modules/test-add/index.js', michael@0: 'Dependencies\' dependencies can be found'); michael@0: michael@0: michael@0: function resolveTest (id, requirer, expected, msg) { michael@0: let result = nodeResolve(id, requirer, { manifest: manifest, rootURI: rootURI }); michael@0: assert.equal(result, expected, 'nodeResolve ' + id + ' from ' + requirer + ' ' +msg); michael@0: } michael@0: } michael@0: michael@0: /* michael@0: // TODO not working in current env michael@0: exports['test bundle'] = function (assert, done) { michael@0: loadAddon('/native-addons/native-addon-test/') michael@0: }; michael@0: */ michael@0: michael@0: exports['test generateMap()'] = function (assert, done) { michael@0: getJSON('/fixtures/native-addon-test/expectedmap.json').then(expected => { michael@0: generateMap({ michael@0: rootURI: root + '/fixtures/native-addon-test/' michael@0: }, map => { michael@0: assert.deepEqual(map, expected, 'generateMap returns expected mappings'); michael@0: assert.equal(map['./index.js']['./dir/a'], './dir/a.js', michael@0: 'sanity check on correct mappings'); michael@0: done(); michael@0: }); michael@0: }).then(null, (reason) => console.error(reason)); michael@0: }; michael@0: michael@0: exports['test JSM loading'] = function (assert, done) { michael@0: getJSON('/fixtures/jsm-package/package.json').then(manifest => { michael@0: let rootURI = root + '/fixtures/jsm-package/'; michael@0: let loader = Loader({ michael@0: paths: makePaths(rootURI), michael@0: rootURI: rootURI, michael@0: manifest: manifest, michael@0: isNative: true michael@0: }); michael@0: michael@0: let program = main(loader); michael@0: assert.ok(program.localJSMCached, 'local relative JSMs are cached'); michael@0: assert.ok(program.isCachedJSAbsolute , 'absolute resource:// js are cached'); michael@0: assert.ok(program.isCachedPath, 'JSMs resolved in paths are cached'); michael@0: assert.ok(program.isCachedAbsolute, 'absolute resource:// JSMs are cached'); michael@0: michael@0: assert.ok(program.localJSM, 'able to load local relative JSMs'); michael@0: all([ michael@0: program.isLoadedPath(10), michael@0: program.isLoadedAbsolute(20), michael@0: program.isLoadedJSAbsolute(30) michael@0: ]).then(([path, absolute, jsabsolute]) => { michael@0: assert.equal(path, 10, 'JSM files resolved from path work'); michael@0: assert.equal(absolute, 20, 'JSM files resolved from full resource:// work'); michael@0: assert.equal(jsabsolute, 30, 'JS files resolved from full resource:// work'); michael@0: }).then(done, console.error); michael@0: michael@0: }).then(null, console.error); michael@0: }; michael@0: michael@0: exports['test native Loader with mappings'] = function (assert, done) { michael@0: all([ michael@0: getJSON('/fixtures/native-addon-test/expectedmap.json'), michael@0: getJSON('/fixtures/native-addon-test/package.json') michael@0: ]).then(([expectedMap, manifest]) => { michael@0: michael@0: // Override dummy module and point it to `test-math` to see if the michael@0: // require is pulling from the mapping michael@0: expectedMap['./index.js']['./dir/dummy'] = './dir/a.js'; michael@0: michael@0: let rootURI = root + '/fixtures/native-addon-test/'; michael@0: let loader = Loader({ michael@0: paths: makePaths(rootURI), michael@0: rootURI: rootURI, michael@0: manifest: manifest, michael@0: requireMap: expectedMap, michael@0: isNative: true michael@0: }); michael@0: michael@0: let program = main(loader); michael@0: assert.equal(program.dummyModule, 'dir/a', michael@0: 'The lookup uses the information given in the mapping'); michael@0: michael@0: testLoader(program, assert); michael@0: unload(loader); michael@0: done(); michael@0: }).then(null, (reason) => console.error(reason)); michael@0: }; michael@0: michael@0: exports['test native Loader without mappings'] = function (assert, done) { michael@0: getJSON('/fixtures/native-addon-test/package.json').then(manifest => { michael@0: let rootURI = root + '/fixtures/native-addon-test/'; michael@0: let loader = Loader({ michael@0: paths: makePaths(rootURI), michael@0: rootURI: rootURI, michael@0: manifest: manifest, michael@0: isNative: true michael@0: }); michael@0: michael@0: let program = main(loader); michael@0: testLoader(program, assert); michael@0: unload(loader); michael@0: done(); michael@0: }).then(null, (reason) => console.error(reason)); michael@0: }; michael@0: michael@0: function testLoader (program, assert) { michael@0: // Test 'main' entries michael@0: // no relative custom main `lib/index.js` michael@0: assert.equal(program.customMainModule, 'custom entry file', michael@0: 'a node_module dependency correctly uses its `main` entry in manifest'); michael@0: // relative custom main `./lib/index.js` michael@0: assert.equal(program.customMainModuleRelative, 'custom entry file relative', michael@0: 'a node_module dependency correctly uses its `main` entry in manifest with relative ./'); michael@0: // implicit './index.js' michael@0: assert.equal(program.defaultMain, 'default main', michael@0: 'a node_module dependency correctly defautls to index.js for main'); michael@0: michael@0: // Test directory exports michael@0: assert.equal(program.directoryDefaults, 'utils', michael@0: '`require`ing a directory defaults to dir/index.js'); michael@0: assert.equal(program.directoryMain, 'main from new module', michael@0: '`require`ing a directory correctly loads the `main` entry and not index.js'); michael@0: assert.equal(program.resolvesJSoverDir, 'dir/a', michael@0: '`require`ing "a" resolves "a.js" over "a/index.js"'); michael@0: michael@0: // Test dependency's dependencies michael@0: assert.ok(program.math.add, michael@0: 'correctly defaults to index.js of a module'); michael@0: assert.equal(program.math.add(10, 5), 15, michael@0: 'node dependencies correctly include their own dependencies'); michael@0: assert.equal(program.math.subtract(10, 5), 5, michael@0: 'node dependencies correctly include their own dependencies'); michael@0: assert.equal(program.mathInRelative.subtract(10, 5), 5, michael@0: 'relative modules can also include node dependencies'); michael@0: michael@0: // Test SDK natives michael@0: assert.ok(program.promise.defer, 'main entry can include SDK modules with no deps'); michael@0: assert.ok(program.promise.resolve, 'main entry can include SDK modules with no deps'); michael@0: assert.ok(program.eventCore.on, 'main entry can include SDK modules that have dependencies'); michael@0: assert.ok(program.eventCore.off, 'main entry can include SDK modules that have dependencies'); michael@0: michael@0: // Test JSMs michael@0: assert.ok(program.promisejsm.defer, 'can require JSM files in path'); michael@0: assert.equal(program.localJSM.test, 'this is a jsm', michael@0: 'can require relative JSM files'); michael@0: michael@0: // Other tests michael@0: assert.equal(program.areModulesCached, true, michael@0: 'modules are correctly cached'); michael@0: assert.equal(program.testJSON.dependencies['test-math'], '*', michael@0: 'correctly requires JSON files'); michael@0: } michael@0: michael@0: function getJSON (uri) { michael@0: return readURI(root + uri).then(manifest => JSON.parse(manifest)); michael@0: } michael@0: michael@0: function makePaths (uri) { michael@0: // Uses development SDK modules if overloaded in loader michael@0: let sdkPaths = testOptions.paths ? testOptions.paths[''] : 'resource://gre/modules/commonjs/'; michael@0: return { michael@0: './': uri, michael@0: 'sdk/': sdkPaths + 'sdk/', michael@0: 'toolkit/': sdkPaths + 'toolkit/', michael@0: 'modules/': 'resource://gre/modules/' michael@0: }; michael@0: } michael@0: michael@0: function loadAddon (uri, map) { michael@0: let rootURI = root + uri; michael@0: getJSON(uri + '/package.json').then(manifest => { michael@0: let loader = Loader({ michael@0: paths: makePaths(rootURI), michael@0: rootURI: rootURI, michael@0: manifest: manifest, michael@0: isNative: true, michael@0: modules: { michael@0: '@test/options': testOptions michael@0: } michael@0: }); michael@0: let program = main(loader); michael@0: }).then(null, console.error); michael@0: } michael@0: michael@0: require('test').run(exports);