|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 'use strict'; |
|
6 |
|
7 let { |
|
8 Loader, main, unload, parseStack, generateMap, resolve, nodeResolve |
|
9 } = require('toolkit/loader'); |
|
10 let { readURI } = require('sdk/net/url'); |
|
11 let { all } = require('sdk/core/promise'); |
|
12 let testOptions = require('@test/options'); |
|
13 |
|
14 let root = module.uri.substr(0, module.uri.lastIndexOf('/')) |
|
15 // The following adds Debugger constructor to the global namespace. |
|
16 const { Cu } = require('chrome'); |
|
17 const { addDebuggerToGlobal } = Cu.import('resource://gre/modules/jsdebugger.jsm', {}); |
|
18 addDebuggerToGlobal(this); |
|
19 |
|
20 |
|
21 exports['test nodeResolve'] = function (assert) { |
|
22 let rootURI = root + '/fixtures/native-addon-test/'; |
|
23 let manifest = {}; |
|
24 manifest.dependencies = {}; |
|
25 |
|
26 // Handles extensions |
|
27 resolveTest('../package.json', './dir/c.js', './package.json'); |
|
28 resolveTest('../dir/b.js', './dir/c.js', './dir/b.js'); |
|
29 |
|
30 resolveTest('./dir/b', './index.js', './dir/b.js'); |
|
31 resolveTest('../index', './dir/b.js', './index.js'); |
|
32 resolveTest('../', './dir/b.js', './index.js'); |
|
33 resolveTest('./dir/a', './index.js', './dir/a.js', 'Precedence dir/a.js over dir/a/'); |
|
34 resolveTest('../utils', './dir/a.js', './utils/index.js', 'Requiring a directory defaults to dir/index.js'); |
|
35 resolveTest('../newmodule', './dir/c.js', './newmodule/lib/file.js', 'Uses package.json main in dir to load appropriate "main"'); |
|
36 resolveTest('test-math', './utils/index.js', './node_modules/test-math/index.js', |
|
37 'Dependencies default to their index.js'); |
|
38 resolveTest('test-custom-main', './utils/index.js', './node_modules/test-custom-main/lib/custom-entry.js', |
|
39 'Dependencies use "main" entry'); |
|
40 resolveTest('test-math/lib/sqrt', './utils/index.js', './node_modules/test-math/lib/sqrt.js', |
|
41 'Dependencies\' files can be consumed via "/"'); |
|
42 |
|
43 resolveTest('sdk/tabs/utils', './index.js', undefined, |
|
44 'correctly ignores SDK references in paths'); |
|
45 resolveTest('fs', './index.js', undefined, |
|
46 'correctly ignores built in node modules in paths'); |
|
47 |
|
48 resolveTest('test-add', './node_modules/test-math/index.js', |
|
49 './node_modules/test-math/node_modules/test-add/index.js', |
|
50 'Dependencies\' dependencies can be found'); |
|
51 |
|
52 |
|
53 function resolveTest (id, requirer, expected, msg) { |
|
54 let result = nodeResolve(id, requirer, { manifest: manifest, rootURI: rootURI }); |
|
55 assert.equal(result, expected, 'nodeResolve ' + id + ' from ' + requirer + ' ' +msg); |
|
56 } |
|
57 } |
|
58 |
|
59 /* |
|
60 // TODO not working in current env |
|
61 exports['test bundle'] = function (assert, done) { |
|
62 loadAddon('/native-addons/native-addon-test/') |
|
63 }; |
|
64 */ |
|
65 |
|
66 exports['test generateMap()'] = function (assert, done) { |
|
67 getJSON('/fixtures/native-addon-test/expectedmap.json').then(expected => { |
|
68 generateMap({ |
|
69 rootURI: root + '/fixtures/native-addon-test/' |
|
70 }, map => { |
|
71 assert.deepEqual(map, expected, 'generateMap returns expected mappings'); |
|
72 assert.equal(map['./index.js']['./dir/a'], './dir/a.js', |
|
73 'sanity check on correct mappings'); |
|
74 done(); |
|
75 }); |
|
76 }).then(null, (reason) => console.error(reason)); |
|
77 }; |
|
78 |
|
79 exports['test JSM loading'] = function (assert, done) { |
|
80 getJSON('/fixtures/jsm-package/package.json').then(manifest => { |
|
81 let rootURI = root + '/fixtures/jsm-package/'; |
|
82 let loader = Loader({ |
|
83 paths: makePaths(rootURI), |
|
84 rootURI: rootURI, |
|
85 manifest: manifest, |
|
86 isNative: true |
|
87 }); |
|
88 |
|
89 let program = main(loader); |
|
90 assert.ok(program.localJSMCached, 'local relative JSMs are cached'); |
|
91 assert.ok(program.isCachedJSAbsolute , 'absolute resource:// js are cached'); |
|
92 assert.ok(program.isCachedPath, 'JSMs resolved in paths are cached'); |
|
93 assert.ok(program.isCachedAbsolute, 'absolute resource:// JSMs are cached'); |
|
94 |
|
95 assert.ok(program.localJSM, 'able to load local relative JSMs'); |
|
96 all([ |
|
97 program.isLoadedPath(10), |
|
98 program.isLoadedAbsolute(20), |
|
99 program.isLoadedJSAbsolute(30) |
|
100 ]).then(([path, absolute, jsabsolute]) => { |
|
101 assert.equal(path, 10, 'JSM files resolved from path work'); |
|
102 assert.equal(absolute, 20, 'JSM files resolved from full resource:// work'); |
|
103 assert.equal(jsabsolute, 30, 'JS files resolved from full resource:// work'); |
|
104 }).then(done, console.error); |
|
105 |
|
106 }).then(null, console.error); |
|
107 }; |
|
108 |
|
109 exports['test native Loader with mappings'] = function (assert, done) { |
|
110 all([ |
|
111 getJSON('/fixtures/native-addon-test/expectedmap.json'), |
|
112 getJSON('/fixtures/native-addon-test/package.json') |
|
113 ]).then(([expectedMap, manifest]) => { |
|
114 |
|
115 // Override dummy module and point it to `test-math` to see if the |
|
116 // require is pulling from the mapping |
|
117 expectedMap['./index.js']['./dir/dummy'] = './dir/a.js'; |
|
118 |
|
119 let rootURI = root + '/fixtures/native-addon-test/'; |
|
120 let loader = Loader({ |
|
121 paths: makePaths(rootURI), |
|
122 rootURI: rootURI, |
|
123 manifest: manifest, |
|
124 requireMap: expectedMap, |
|
125 isNative: true |
|
126 }); |
|
127 |
|
128 let program = main(loader); |
|
129 assert.equal(program.dummyModule, 'dir/a', |
|
130 'The lookup uses the information given in the mapping'); |
|
131 |
|
132 testLoader(program, assert); |
|
133 unload(loader); |
|
134 done(); |
|
135 }).then(null, (reason) => console.error(reason)); |
|
136 }; |
|
137 |
|
138 exports['test native Loader without mappings'] = function (assert, done) { |
|
139 getJSON('/fixtures/native-addon-test/package.json').then(manifest => { |
|
140 let rootURI = root + '/fixtures/native-addon-test/'; |
|
141 let loader = Loader({ |
|
142 paths: makePaths(rootURI), |
|
143 rootURI: rootURI, |
|
144 manifest: manifest, |
|
145 isNative: true |
|
146 }); |
|
147 |
|
148 let program = main(loader); |
|
149 testLoader(program, assert); |
|
150 unload(loader); |
|
151 done(); |
|
152 }).then(null, (reason) => console.error(reason)); |
|
153 }; |
|
154 |
|
155 function testLoader (program, assert) { |
|
156 // Test 'main' entries |
|
157 // no relative custom main `lib/index.js` |
|
158 assert.equal(program.customMainModule, 'custom entry file', |
|
159 'a node_module dependency correctly uses its `main` entry in manifest'); |
|
160 // relative custom main `./lib/index.js` |
|
161 assert.equal(program.customMainModuleRelative, 'custom entry file relative', |
|
162 'a node_module dependency correctly uses its `main` entry in manifest with relative ./'); |
|
163 // implicit './index.js' |
|
164 assert.equal(program.defaultMain, 'default main', |
|
165 'a node_module dependency correctly defautls to index.js for main'); |
|
166 |
|
167 // Test directory exports |
|
168 assert.equal(program.directoryDefaults, 'utils', |
|
169 '`require`ing a directory defaults to dir/index.js'); |
|
170 assert.equal(program.directoryMain, 'main from new module', |
|
171 '`require`ing a directory correctly loads the `main` entry and not index.js'); |
|
172 assert.equal(program.resolvesJSoverDir, 'dir/a', |
|
173 '`require`ing "a" resolves "a.js" over "a/index.js"'); |
|
174 |
|
175 // Test dependency's dependencies |
|
176 assert.ok(program.math.add, |
|
177 'correctly defaults to index.js of a module'); |
|
178 assert.equal(program.math.add(10, 5), 15, |
|
179 'node dependencies correctly include their own dependencies'); |
|
180 assert.equal(program.math.subtract(10, 5), 5, |
|
181 'node dependencies correctly include their own dependencies'); |
|
182 assert.equal(program.mathInRelative.subtract(10, 5), 5, |
|
183 'relative modules can also include node dependencies'); |
|
184 |
|
185 // Test SDK natives |
|
186 assert.ok(program.promise.defer, 'main entry can include SDK modules with no deps'); |
|
187 assert.ok(program.promise.resolve, 'main entry can include SDK modules with no deps'); |
|
188 assert.ok(program.eventCore.on, 'main entry can include SDK modules that have dependencies'); |
|
189 assert.ok(program.eventCore.off, 'main entry can include SDK modules that have dependencies'); |
|
190 |
|
191 // Test JSMs |
|
192 assert.ok(program.promisejsm.defer, 'can require JSM files in path'); |
|
193 assert.equal(program.localJSM.test, 'this is a jsm', |
|
194 'can require relative JSM files'); |
|
195 |
|
196 // Other tests |
|
197 assert.equal(program.areModulesCached, true, |
|
198 'modules are correctly cached'); |
|
199 assert.equal(program.testJSON.dependencies['test-math'], '*', |
|
200 'correctly requires JSON files'); |
|
201 } |
|
202 |
|
203 function getJSON (uri) { |
|
204 return readURI(root + uri).then(manifest => JSON.parse(manifest)); |
|
205 } |
|
206 |
|
207 function makePaths (uri) { |
|
208 // Uses development SDK modules if overloaded in loader |
|
209 let sdkPaths = testOptions.paths ? testOptions.paths[''] : 'resource://gre/modules/commonjs/'; |
|
210 return { |
|
211 './': uri, |
|
212 'sdk/': sdkPaths + 'sdk/', |
|
213 'toolkit/': sdkPaths + 'toolkit/', |
|
214 'modules/': 'resource://gre/modules/' |
|
215 }; |
|
216 } |
|
217 |
|
218 function loadAddon (uri, map) { |
|
219 let rootURI = root + uri; |
|
220 getJSON(uri + '/package.json').then(manifest => { |
|
221 let loader = Loader({ |
|
222 paths: makePaths(rootURI), |
|
223 rootURI: rootURI, |
|
224 manifest: manifest, |
|
225 isNative: true, |
|
226 modules: { |
|
227 '@test/options': testOptions |
|
228 } |
|
229 }); |
|
230 let program = main(loader); |
|
231 }).then(null, console.error); |
|
232 } |
|
233 |
|
234 require('test').run(exports); |