tests and bug fixes

This commit is contained in:
guybedford 2013-06-19 22:56:23 -07:00
parent e6df99c389
commit b9953a42e9
18 changed files with 371 additions and 87 deletions

View File

@ -48,7 +48,7 @@
var nameParts = name.split('/');
if (prefixParts.length > nameParts.length)
return false;
for (var i = 0; i < prefixParts.length; i++) {
for (var i = 0; i < prefixParts.length; i++)
if (nameParts[i] != prefixParts[i])
return false;
return true;
@ -56,6 +56,8 @@
// get the configuration package for a given module name
var getPackage = function(name) {
if (!name)
return '';
var p = '';
for (var _p in config.packages) {
if (!prefixMatch(name, _p))
@ -92,7 +94,7 @@
// hooks without plugin logic
var loaderHooks = {
normalize: function(name, options) {
var parentName = options.referer.name;
var parentName = options.referer && options.referer.name;
// if the extension is js, and not an absolute URL, remove the extension
if (name.substr(name.length - 3, 3) == '.js' && !name.match(absUrlRegEx))
@ -127,40 +129,56 @@
// do standard normalization
name = System.normalize(name, options);
return name;
},
resolve: function(name, options) {
var parentName = options.referer && options.referer.name;
// store the normalized name
options.normalizedName = name;
// do package config
var p = getPackage(name);
if (p) {
// a sub-package path
if (name.length > p.length)
name = config.packages[p].path + '/' + name.substr(p.length);
name = config.packages[p].path + name.substr(p.length);
// the exact package - the main call
else {
var main = config.packages[i].main || 'index';
var main = config.packages[p].main || 'index';
// ensure that main is a relative ID if not a plugin form
if (main.indexOf('!') == -1 && (main.substr(0, 2) != '..' || main.substr(0, 2) != './'))
main = './' + main;
// normalize the main
name = this.normalize(main, { referer: { name: name } });
name = this.normalize(main, { referer: { name: config.packages[p].path + '/' } });
}
}
return name + pluginArgument;
},
resolve: function(name, options) {
// store the normalized name
options.normalizedName = name;
// paths configuration
for (var p in config.paths) {
if (!prefixMatch(name, p))
continue;
// check the parent package first
var parentPackage = config.packages[getPackage(parentName)];
var appliedParentPaths = false;
if (parentPackage && parentPackage.paths) {
for (var p in parentPackage.paths) {
if (!prefixMatch(name, p))
continue;
name = config.paths[p] + name.substr(p.length);
break;
name = parentPackage.paths[p] + name.substr(p.length);
appliedParentPaths = true;
break;
}
}
if (!appliedParentPaths)
for (var p in config.paths) {
if (!prefixMatch(name, p))
continue;
name = config.paths[p] + name.substr(p.length);
break;
}
// then just use standard resolution
return System.resolve(name);
@ -180,56 +198,82 @@
}
System.fetch(url, options);
},
translate: function(source, options) {
link: function(source, options) {
// check if there are any import syntax. If not, use the global shim config
if (source.match(importRegEx) || source.match(exportRegEx) || source.match(moduleRegEx))
return;
var shimDeps;
// apply shim configuration with careful global management
var p = getPackage(name);
if (p.shimDeps)
for (var s in p.shimDeps) {
if (!prefixMatch(options.normalizedName, s))
var p = getPackage(options.normalizedName);
if (p)
for (var s in config.packages[p].shimDeps) {
if (!prefixMatch(options.normalizedName, p + '/' + s))
continue;
options.shimDeps = p.shimDeps[s];
shimDeps = config.packages[p].shimDeps[s];
break;
}
else
for (var s in config.shimDeps) {
if (!prefixMatch(options.normalizedName, s))
continue;
options.shimDeps = config.shimDeps[s];
shimDeps = config.shimDeps[s];
break;
}
// normalize deps
for (var i = 0; i < options.shimDeps.length; i++)
options.shimDeps[i] = loader.normalize(options.shimDeps[i], { referer: { name: options.normalizedName } });
// add adjustments to the source to prepare the global
// and then retrieve global changes after the module
source =
"requireES6.__setGlobal(" + JSON.stringify(shimDeps) + ");" +
source +
"requireES6.set('" + options.normalizedName + "', requireES6.__getGlobal());";
return source;
},
link: function(source, options) {
if (!options.shimDeps)
return;
return {
imports: options.shimDeps
imports: shimDeps || [],
execute: function(deps) {
setGlobal(deps);
loader.eval(source);
return new Module(getGlobal());
}
};
}
};
// given a module's global dependencies, prepare the global object
// to contain the union of the defined properties of its dependent modules
var globalObj = {};
function setGlobal(deps) {
// first, we add all the dependency module properties to the global
if (deps) {
for (var i = 0; i < deps.length; i++) {
var dep = deps[i];
for (var m in dep)
loader.global[m] = dep[m];
}
}
// now we store a complete copy of the global object
// in order to detect changes
for (var g in loader.global) {
if (loader.global.hasOwnProperty(g))
globalObj[g] = loader.global[g];
}
}
// go through the global object to find any changes
// the differences become the returned global for this object
// the global object is left as is
function getGlobal() {
var moduleGlobal = {};
for (var g in loader.global) {
if (loader.global.hasOwnProperty(g) && g != 'window' && globalObj[g] != loader.global[g])
moduleGlobal[g] = loader.global[g];
}
return moduleGlobal;
}
var loader = new Loader({
baseUrl: config.baseURL,
baseURL: config.baseURL,
normalize: function(name, options) {
// plugin shorthand
@ -240,7 +284,7 @@
}
// plugin normalization
option.pluginArgument = '';
options.pluginArgument = '';
var pluginIndex = name.indexOf('!');
if (pluginIndex != -1) {
options.pluginArgument = name.substr(pluginIndex);
@ -301,7 +345,7 @@
if (config.translate)
return config.translate.call(loaderHooks, source, options);
else
return loaderHooks.translate(source, options);
return source;
},
link: function(source, options) {
if (config.link)
@ -334,46 +378,9 @@
requireES6.set = loader.set.bind(loader);
requireES6.has = loader.has.bind(loader);
requireES6.delete = loader.delete.bind(loader);
requireES6.loader = loader;
// global shim functions
// given a module's global dependencies, prepare the global object
// to contain the union of the defined properties of its dependent modules
var globalObj = {};
requireES6.__setGlobal = function(deps) {
// first, we add all the dependency module properties to the global
if (deps) {
for (var i = 0; i < deps.length; i++) {
var dep = requireES6.get(deps[i]);
for (var m in dep)
loader.global[m] = dep[m];
}
}
// now we store a complete copy of the global object
// in order to detect changes
for (var g in loader.global) {
if (!loader.global.hasOwnProperty(g))
globalObj[g] = loader.global[g];
}
}
// go through the global object to find any changes
// the differences become the returned global for this object
// the global object is left as is
requireES6.__getGlobal = function() {
var moduleGlobal = {};
for (var g in loader.global) {
if (!loader.global.hasOwnProperty(g))
if (globalObj[g] != loader.global[g])
moduleGlobal[g] = loader.global[g];
}
return moduleGlobal;
}
var cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)['"]\s*\)/g;
loader.set('__require', require);

View File

@ -1,6 +1,6 @@
<!doctype html>
<html>
<script>
// also supports var r6 = ...
requireES6.config({
baseURL: '//git.jspm.io',
@ -36,7 +36,7 @@
// global dependencies
// applies to module name after normalization
deps: {
shimDeps: {
'jquery': ['hbs']
},
@ -58,7 +58,7 @@
},
// for global scripts, set dependencies
deps: {
shimDeps: {
'less': 'jquery'
}
},

3
test/jquery-test.html Normal file
View File

@ -0,0 +1,3 @@
<!doctype html>
<html>
<script src="jquery-test.js"></script>

61
test/test-runner.js Normal file
View File

@ -0,0 +1,61 @@
var TestPage = function(el) {
this.$results = el.querySelectorAll('tr td.result');
this.$summary = el.querySelector('.summary');
}
TestPage.render = function(o) {
var _ = '<table id="' + o.id + '">'
+ '<tr><th>Test</th><th>Result</th>';
for (var i = 0; i < o.tests.length; i++)
_ += '<tr><td class="name">' + o.tests[i].name + '</td><td class="result"></td></tr>';
_ += '</table>';
_ += '<p class="summary"></p>'
return _;
}
TestPage.prototype = {
setResult: function(index, result) {
if (result)
this.$results[index].innerText = result;
else
this.$results[index].innerText = 'Passed';
},
setSummary: function(passed, failed) {
this.$summary.innerText = passed + ' tests passed, ' + failed + ' tests failed.';
}
};
export function execute(tests) {
// draw the test table
document.body.innerHTML = TestPage.render({
id: 'test-table',
tests: tests
});
var testPage = new TestPage(document.body);
// run the tests
var curTest = 0;
var passed = 0;
var failed = 0;
doNextTest = function() {
tests[curTest].run(function() {
var result = tests[curTest].confirm.apply(null, arguments);
testPage.setResult(curTest, result);
if (result)
failed++;
else
passed++;
testPage.setSummary(passed, failed);
curTest++;
if (curTest == tests.length)
testPage.setSummary(passed, failed);
else
doNextTest();
});
}
doNextTest();
}

176
test/test.html Normal file
View File

@ -0,0 +1,176 @@
<!doctype html>
<html>
<script src="../../es6-loader/es6-loader.js" type="text/javascript"></script>
<script src="../require-es6.js" type="text/javascript"></script>
<script>
requireES6(['test-runner'], function(runner) {
runner.execute([
{
name: 'Global script loading',
run: function(complete) {
requireES6(['tests/global'], complete);
},
confirm: function(m) {
if (!m.jQuery || !m.another)
return 'Global objects not defined';
if (window.jQuery || window.another)
return 'Global object has leaked';
}
},
{
name: 'Global script loading with shimDeps',
run: function(complete) {
requireES6.config({
shimDeps: {
'tests/global-with-dep': ['tests/global-dep']
}
});
requireES6(['tests/global-with-dep'], complete);
},
confirm: function(m) {
if (m.jQueryVersion != '1.8.3')
return 'Global dependency not defined';
}
},
{
name: 'Global paths configuration',
run: function(complete) {
requireES6.config({
paths: {
'mypath': 'tests/path'
}
});
requireES6(['mypath'], complete);
},
confirm: function(m) {
if (m.p != 'path')
return 'module not loaded';
}
},
{
name: 'External URL loading',
run: function(complete) {
requireES6(['http://code.jquery.com/jquery-1.10.1.min.js'], complete);
},
confirm: function(m) {
if (m.jQuery.fn.jquery != '1.10.1')
return 'jQuery not loaded';
}
},
{
name: 'Global map configuration',
run: function(complete) {
requireES6.config({
map: {
'maptest': 'tests/map-test'
}
});
requireES6(['maptest'], complete)
},
confirm: function(m) {
if (m.maptest != 'maptest')
return 'Mapped module not loaded';
}
},
{
name: 'Basic package configuration',
run: function(complete) {
requireES6.config({
packages: {
myapp: {
path: 'tests/package-test',
main: 'themain'
}
}
});
requireES6(['myapp', 'myapp/sub'], complete)
},
confirm: function(m1, m2) {
if (!m1.package)
return 'Package not loaded';
if (!m2.package)
return 'Package subpath not loaded';
}
},
{
name: 'Package map configuration',
run: function(complete) {
requireES6.config({
packages: {
myapp: {
map: {
'jquery': 'myapp/jquery-mapped'
}
}
}
});
requireES6(['myapp/map-test'], complete);
},
confirm: function(m) {
if (!m.mapDep)
return 'Mapped package dependency not loaded';
}
},
{
name: 'Package paths configuration',
run: function(complete) {
requireES6.config({
packages: {
myapp: {
paths: {
'jquery-cdn': "http://code.jquery.com/jquery-1.8.1.js"
}
}
}
});
requireES6(['myapp/path-test'], complete);
},
confirm: function(m) {
if (m.jQuery.fn.jquery != '1.8.1')
return 'jQuery not defined';
}
},
{
name: 'Package shimDep configuration',
run: function(complete) {
requireES6.config({
packages: {
myapp: {
paths: {
'jquery-1.8.2': "http://code.jquery.com/jquery-1.8.2.js"
},
shimDeps: {
'shim-test': ['jquery-1.8.2']
}
}
}
});
requireES6(['myapp/shim-test'], complete);
},
confirm: function(m) {
if (m.myPlugin.jQuery.fn.jquery != '1.8.2')
return 'Wrong jQuery version';
}
},
{
name: 'Plugin modules',
run: function(complete) {
complete();
},
confirm: function(m) {
return 'Tests to be implemented';
}
},
{
name: 'Custom loader hooks',
run: function(complete) {
complete();
},
confirm: function(m) {
return 'Tests to be implemented';
}
}
]);
});
</script>

3
test/tests/global-dep.js Normal file
View File

@ -0,0 +1,3 @@
window.jQuery = {
v: '1.8.3'
};

View File

@ -0,0 +1,2 @@
window.jQueryVersion = jQuery.v;

6
test/tests/global.js Normal file
View File

@ -0,0 +1,6 @@
window.jQuery = {
v: '2.0..0'
};
window.another = {
some: 'thing'
};

View File

@ -0,0 +1 @@
export var dep = 'maptest';

4
test/tests/map-test.js Normal file
View File

@ -0,0 +1,4 @@
import { d: dep } from './map-test-dep';
export var maptest = d;

View File

@ -0,0 +1,2 @@
console.log('dep ex');
window.globalDep = 'global dep';

View File

@ -0,0 +1,5 @@
export var jQuery = {
fn: {
jquery: '1'
}
};

View File

@ -0,0 +1,3 @@
import { jQuery: jQuery } from 'jquery';
export var mapDep = jQuery.fn.jquery;

View File

@ -0,0 +1,3 @@
import { jQuery: jQuery } from 'jquery-cdn';
export var jQuery = jQuery;

View File

@ -0,0 +1,5 @@
$.fn.myPlugin = 'plugin';
window.myPlugin = {
jQuery: $
};

View File

@ -0,0 +1 @@
export var package = 'package';

View File

@ -0,0 +1 @@
export var package = 'mypackage';

1
test/tests/path.js Normal file
View File

@ -0,0 +1 @@
window.p = 'path';