Skip to content
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ before_install:
before_script:
- npm install
- node server/server.js &
- sleep 3
script: node ./server/phantom-server.js
- sleep 20
script: node ./server/phantom-server.js
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ An implementation needs to have the following two files in the **impl** director

* AMD loader implementation
* configure script
* optional installer script (for use if loader provides a Node.js server-side component. see impl/zazl for an example)

The configure script should define the following global variables:

Expand Down
33 changes: 33 additions & 0 deletions impl/zazl/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
var zazlConfig;

var config = function(cfg) {
zazlConfig = cfg;
};

var go = function(dependencies, callback) {
var cfg = zazlConfig ? zazlConfig : {};
var pathname = window.location.pathname;
pathname = pathname.substring(1);
pathname = pathname.substring(pathname.indexOf('/'));
pathname = pathname.substring(0, pathname.lastIndexOf('/')) + "/./";
cfg.baseUrl = pathname;
cfg.directInject = true;
cfg.injectUrl = "/zazl/_javascript";
cfg.scanCJSRequires = true;
zazl(cfg, dependencies, callback);
};
var implemented = {
basic: true,
anon: true,
funcString: true,
namedWrapped: true,
require: true,
plugins: true,
pathsConfig: true,
packagesConfig: true,
mapConfig: true,
moduleConfig: true,
shimConfig: true
//pluginDynamic: true
};
require = undefined;
39 changes: 39 additions & 0 deletions impl/zazl/installer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
var npm = require('npm');
var path = require('path');
var fs = require('fs');
var util = require('util');

function startZazl(zazloptimizer, app) {
var testsdir = fs.realpathSync(path.join(__dirname, "../../tests"));
var optimizer = zazloptimizer.createConnectOptimizer(testsdir, false);
app.use("/zazl/_javascript", optimizer);
app.get('/framework/zazl.js', function(req, res) {
fs.readFile(zazloptimizer.getLoaderDir()+"/loader/amd/zazl.js", function(err, data) {
res.setHeader('Content-Type', 'text/javascript');
res.end(data.toString());
});
});
}

exports.install = function(app, cb) {
npm.load([], function(err, npm) {
if (err) {
cb("zazl", false);
return;
}
var zazloptimizer;
try {
zazloptimizer = require('zazloptimizer');
util.log("zazloptimizer is already installed");
startZazl(zazloptimizer, app);
cb("zazl", true);
} catch (e) {
npm.commands.install(['zazloptimizer'], function() {
util.log("zazloptimizer has been installed");
zazloptimizer = require('zazloptimizer');
startZazl(zazloptimizer, app);
cb("zazl", true);
});
}
});
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"https://github.com/amdjs/amdjs-api/wiki/AMD"
],
"devDependencies": {
"express": "3.0.0"
"express": "3.0.0",
"npm": ">=1.2.16"
},
"dependencies": {},
"engine": "node >= 0.6.0"
Expand Down
9 changes: 8 additions & 1 deletion server/manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,11 @@ exports.manifest.lsjs = {
name: 'lsjs @ e61412da',
impl: 'lsjs/lsjs.js',
config: 'lsjs/config.js'
};
};

exports.manifest.zazl = {
name: 'zazl @ 1.0.4',
impl: 'zazl/zazl.js',
config: 'zazl/config.js',
installer: '../impl/zazl/installer'
};
278 changes: 157 additions & 121 deletions server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,125 +11,161 @@ function fourOhFour(res, msg) {
res.end('', 404);
}

app.get('/', function(req, res) {
// run all tests
if (req.query)
fs.readFile(path.normalize(path.join(__dirname, './resources/all.html')), function(err, data) {
if (err) return fourOhFour(res, err);

var frameworkConfigScriptTag = (req.query.framework) ? '<script src="/config/'+req.query.framework+'.js"></script>' : '';
var frameworkLibScriptTag = (req.query.framework) ? '<script src="/framework/'+req.query.framework+'.js"></script>' : '';

var frameworkOptions = [];
for (var id in manifest) {
frameworkOptions.push('<option value="'+id+'">'+manifest[id].name+'</option>');
}

var output = data.toString()
.replace(/\{\{HASTESTS\}\}/g, (req.query.framework) ? 'has-tests' : '')
.replace(/\{\{FRAMEWORK_OPTIONS\}\}/g, frameworkOptions.join('\n'))
.replace(/\{\{FRAMEWORK\}\}/g, req.query.framework)
.replace(/\{\{FRAMEWORK_CONFIG\}\}/, frameworkConfigScriptTag)
.replace(/\{\{FRAMEWORK_LIB\}\}/, frameworkLibScriptTag);
res.setHeader('Content-Type', 'text/html');
res.end(output);
});
});

app.get('/util/reporter.js', function(req, res) {
// load the reporters
fs.readFile(path.normalize(path.join(__dirname, './resources/reporter.js')), function(err, data) {
if (err) return fourOhFour(res, err);
res.setHeader('Content-Type', 'text/javascript');
res.end(data.toString());
});
});

app.get('/util/all.js', function(req, res) {
// load the reporters
fs.readFile(path.normalize(path.join(__dirname, './resources/all.js')), function(err, data) {
if (err) return fourOhFour(res, err);
res.setHeader('Content-Type', 'text/javascript');
res.end(data.toString());
});
});

app.get('/util/all.css', function(req, res) {
// load the reporters
fs.readFile(path.normalize(path.join(__dirname, './resources/all.css')), function(err, data) {
if (err) return fourOhFour(res, err);
res.setHeader('Content-Type', 'text/css');
res.end(data.toString());
});
});

app.get('/framework/:framework', function(req, res) {
// load a framework file
var framework = req.params.framework.replace(/\.js$/, '');
fs.readFile(path.normalize(path.join(__dirname, '../impl/'+manifest[framework].impl)), function(err, data) {
if (err) return fourOhFour(res, err);
res.setHeader('Content-Type', 'text/javascript');
res.end(data.toString());
});
});

app.get('/config/:framework', function(req, res) {
// load a config file
var framework = req.params.framework.replace(/\.js$/, '');
fs.readFile(path.normalize(path.join(__dirname, '../impl/'+manifest[framework].config)), function(err, data) {
if (err) return fourOhFour(res, err);
res.setHeader('Content-Type', 'text/javascript');
res.end(data.toString());
});
});

app.get('/:framework/:test/system.js', function(req, res) {
// get a file for the specified test
res.setHeader('Content-Type', 'text/javascript');
if (!systemNotify) {
systemNotify = true;
console.log('"system" module requested by browser. Usually a side-effect of doing static analysis');
function start() {
app.get('/', function(req, res) {
// run all tests
if (req.query)
fs.readFile(path.normalize(path.join(__dirname, './resources/all.html')), function(err, data) {
if (err) return fourOhFour(res, err);

var frameworkConfigScriptTag = (req.query.framework) ? '<script src="/config/'+req.query.framework+'.js"></script>' : '';
var frameworkLibScriptTag = (req.query.framework) ? '<script src="/framework/'+req.query.framework+'.js"></script>' : '';

var frameworkOptions = [];
for (var id in manifest) {
frameworkOptions.push('<option value="'+id+'">'+manifest[id].name+'</option>');
}

var output = data.toString()
.replace(/\{\{HASTESTS\}\}/g, (req.query.framework) ? 'has-tests' : '')
.replace(/\{\{FRAMEWORK_OPTIONS\}\}/g, frameworkOptions.join('\n'))
.replace(/\{\{FRAMEWORK\}\}/g, req.query.framework)
.replace(/\{\{FRAMEWORK_CONFIG\}\}/, frameworkConfigScriptTag)
.replace(/\{\{FRAMEWORK_LIB\}\}/, frameworkLibScriptTag);
res.setHeader('Content-Type', 'text/html');
res.end(output);
});
});

app.get('/util/reporter.js', function(req, res) {
// load the reporters
fs.readFile(path.normalize(path.join(__dirname, './resources/reporter.js')), function(err, data) {
if (err) return fourOhFour(res, err);
res.setHeader('Content-Type', 'text/javascript');
res.end(data.toString());
});
});

app.get('/util/all.js', function(req, res) {
// load the reporters
fs.readFile(path.normalize(path.join(__dirname, './resources/all.js')), function(err, data) {
if (err) return fourOhFour(res, err);
res.setHeader('Content-Type', 'text/javascript');
res.end(data.toString());
});
});

app.get('/util/all.css', function(req, res) {
// load the reporters
fs.readFile(path.normalize(path.join(__dirname, './resources/all.css')), function(err, data) {
if (err) return fourOhFour(res, err);
res.setHeader('Content-Type', 'text/css');
res.end(data.toString());
});
});

app.get('/framework/:framework', function(req, res) {
// load a framework file
var framework = req.params.framework.replace(/\.js$/, '');
fs.readFile(path.normalize(path.join(__dirname, '../impl/'+manifest[framework].impl)), function(err, data) {
if (err) return fourOhFour(res, err);
res.setHeader('Content-Type', 'text/javascript');
res.end(data.toString());
});
});

app.get('/config/:framework', function(req, res) {
// load a config file
var framework = req.params.framework.replace(/\.js$/, '');
fs.readFile(path.normalize(path.join(__dirname, '../impl/'+manifest[framework].config)), function(err, data) {
if (err) return fourOhFour(res, err);
res.setHeader('Content-Type', 'text/javascript');
res.end(data.toString());
});
});

app.get('/:framework/:test/system.js', function(req, res) {
// get a file for the specified test
res.setHeader('Content-Type', 'text/javascript');
if (!systemNotify) {
systemNotify = true;
console.log('"system" module requested by browser. Usually a side-effect of doing static analysis');
}
res.end('', 404);
});

app.get('/:framework/:test/test.html', function(req, res) {
// run one test
fs.readFile(path.normalize(path.join(__dirname, './resources/template.html')), function(err, data) {
if (err) return fourOhFour(res, err);

var framework = '/framework/'+req.params.framework+'.js';
var fwkConfig = '/config/'+req.params.framework+'.js';
var reporter = '/util/reporter.js';
var testFile = '/'+req.params.framework+'/'+req.params.test+'/_test.js';
var testName = req.params.test;

var output = data.toString()
.replace(/\{\{FRAMEWORK\}\}/g, framework)
.replace(/\{\{FRAMEWORK_CONFIG\}\}/g, fwkConfig)
.replace(/\{\{REPORTER\}\}/g, reporter)
.replace(/\{\{TEST\}\}/g, testFile)
.replace(/\{\{TEST_NAME\}\}/g, testName);
res.setHeader('Content-Type', 'text/html');
res.end(output);
});
});

app.get('/:framework/:test/*', function(req, res) {
// get a file for the specified test
var testPath = '../tests/'+req.params.test+'/'+req.params[0];
fs.readFile(path.normalize(path.join(__dirname, testPath)), function(err, data) {
if (err) return fourOhFour(res, err);
res.setHeader('Content-Type', 'text/javascript');
res.end(data.toString());
});
});

app.get('*', function(req, res){
res.send('', 404);
});

app.listen(4000);

util.log('AMD JS Test server running on port 4000');
util.log('To run: http://localhost:4000');
}

// This will be called when an installer has completed. If there are more than one
// manifest with an installer wait for all of them to complete before starting.
function installerCallback(framework, installed) {
manifest[framework].installed = installed;
var readyToStart = true;
for (var framework in manifest) {
if (manifest[framework].installer && manifest[framework].installed === false) {
readyToStart = false;
}
}

if (readyToStart) {
util.log("Installers have completed");
start();
}
}

// Look in the manifests for any installers and run them.
var installer;
for (var framework in manifest) {
if (manifest[framework].installer) {
manifest[framework].installed = false;
installer = require(manifest[framework].installer);
// Call the installer with the express app object allowing it to setup any handlers
installer.install(app, installerCallback);
}
res.end('', 404);
});

app.get('/:framework/:test/test.html', function(req, res) {
// run one test
fs.readFile(path.normalize(path.join(__dirname, './resources/template.html')), function(err, data) {
if (err) return fourOhFour(res, err);

var framework = '/framework/'+req.params.framework+'.js';
var fwkConfig = '/config/'+req.params.framework+'.js';
var reporter = '/util/reporter.js';
var testFile = '/'+req.params.framework+'/'+req.params.test+'/_test.js';
var testName = req.params.test;

var output = data.toString()
.replace(/\{\{FRAMEWORK\}\}/g, framework)
.replace(/\{\{FRAMEWORK_CONFIG\}\}/g, fwkConfig)
.replace(/\{\{REPORTER\}\}/g, reporter)
.replace(/\{\{TEST\}\}/g, testFile)
.replace(/\{\{TEST_NAME\}\}/g, testName);
res.setHeader('Content-Type', 'text/html');
res.end(output);
});
});

app.get('/:framework/:test/*', function(req, res) {
// get a file for the specified test
var testPath = '../tests/'+req.params.test+'/'+req.params[0];
fs.readFile(path.normalize(path.join(__dirname, testPath)), function(err, data) {
if (err) return fourOhFour(res, err);
res.setHeader('Content-Type', 'text/javascript');
res.end(data.toString());
});
});

app.get('*', function(req, res){
res.send('', 404);
});

app.listen(4000);

util.log('AMD JS Test server running on port 4000');
util.log('To run: http://localhost:4000');
}

// Check for any installers. If none found call start();
if (!installer) {
start();
}