Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #894 from isao/tests

unit tests for build/*.js
  • Loading branch information...
commit 2bde38a2bccd84688eb07445c17396b7004f54a6 2 parents 3269354 + 99b3224
@isao isao authored
View
17 lib/app/commands/build/index.js
@@ -70,7 +70,7 @@ function getConfigs(opts, buildtype, builddir, store) {
* @method run
* @param {Array} args Trailing cli arguments passed to cli.js
* @param {Object} opts Parsed cli options like -c (see exports.options)
- * @param {Function} cb callback to cli.js, takes string parameter for errors
+ * @param {Function} cb Callback params are: [errmsg], [show_usage], [die]
*/
function run(args, opts, cb) {
var csvctx = util.contextCsvToObject, // shortcut
@@ -78,27 +78,22 @@ function run(args, opts, cb) {
store,
conf;
- function die(err) {
- cb(err, null, true);
- }
-
switch (buildtype) {
case 'html5app':
break;
case 'hybridapp':
if (!opts.snapshotName || !opts.snapshotTag) {
- die('Build hybridapp requires --snapshotName and --snapshotTag');
+ return cb('Build hybridapp requires --snapshotName and --snapshotTag', null, true);
}
break;
case 'undefined':
- die('Missing type');
- break;
+ return cb('Missing type', null, true);
default:
- die('Invalid type');
+ return cb('Invalid type', null, true);
}
if (!util.isMojitoApp(CWD)) {
- die('Not a Mojito directory');
+ return cb('Not a Mojito directory', null, true);
}
// hash a cli context string like 'device:iphone,environment:test'
@@ -115,7 +110,7 @@ function run(args, opts, cb) {
function next(err) {
if (err) {
- return die('Error removing ' + conf.build.dir + "\n" + err);
+ return cb('Error removing ' + conf.build.dir + "\n" + err, null, true);
}
var Mojito = require(BASE + 'lib/mojito'),
View
1  lib/app/commands/build/shared.js
@@ -127,6 +127,7 @@ function mungePage(conf, mapuri, contents) {
}
wr.write(file, contents);
+ return contents;
}
module.exports = {
View
4 lib/app/commands/build/writer.js
@@ -17,8 +17,8 @@ function write(filepath, str) {
fs.writeFileSync(filepath, str, 'utf-8');
}
-function writeJson(filepath, str) {
- write(filepath, JSON.stringify(str, null, 4));
+function writeJson(filepath, obj) {
+ write(filepath, JSON.stringify(obj, null, 4));
}
function copy(from, to) {
View
13 tests/base/mojito-test.js
@@ -5,7 +5,7 @@
*/
-/*jslint anon:true, sloppy:true, nomen:true, node:true*/
+/*jslint anon:true, sloppy:true, nomen:true, node:true, unparam: true, todo: true*/
/*global YUI*/
@@ -206,16 +206,19 @@ YUI.add('mojito-test', function(Y, NAME) {
}, '0.1.0', {requires: [
'event',
- "node",
- "node-event-simulate"
+ 'node',
+ 'node-event-simulate'
]});
YUI.add('mojito-test-extra', function(Y, NAME) {
var A = Y.Assert;
- Y.MOJITO_DIR = ('undefined' !== typeof require) ?
- require('path').resolve(__dirname, '../../') + '/' : null;
+ // move to mojito-test, under Y.mojito namespace? i.e. Y.mojito.BASEDIR
+ if (require && ('function' === typeof require.resolve)) {
+ // define the abs path to the mojito base dir on nodejs only
+ Y.MOJITO_DIR = require('path').resolve(__dirname, '../../') + '/';
+ }
// path doesn't need to be given, mainly used during recursion
Y.TEST_CMP = function (x, y, msg, path) {
View
172 tests/cli/lib/app/commands/build/test-html5app.js
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2011-2013, Yahoo! Inc. All rights reserved.
+ * Copyrights licensed under the New BSD License.
+ * See the accompanying LICENSE file for terms.
+ */
+YUI().use('mojito-test-extra', 'test', function(Y) {
+
+ var A = Y.Assert,
+ V = Y.Mock.Value,
+ AA = Y.ArrayAssert,
+ OA = Y.ObjectAssert,
+ cases,
+
+ mockery = require('mockery'),
+ srcpath = Y.MOJITO_DIR + 'lib/app/commands/build/html5app.js',
+ App,
+ app,
+ mocks = {},
+ conf,
+ count;
+
+
+ mocks.init = function() {count++;};
+ mocks.mapStoreUris = mocks.init;
+ mocks.mapDefxUris = mocks.init;
+ mocks.mapFunkySpecUris = mocks.init;
+ mocks.makeManifest = mocks.init;
+ mocks.copyModule = mocks.init;
+ mocks.mungePage = mocks.init;
+
+ mockery.registerAllowable(srcpath);
+ mockery.registerMock('./shared', mocks);
+ mockery.enable({'warnOnUnregistered': false});
+ App = require(srcpath);
+
+ conf = {
+ mojitodir: '/Users/isao/Repos/mojito/myfork/',
+ app: {
+ name: 'staticpf',
+ version: '0.0.1',
+ specs: {
+ frame: {},
+ tunnelProxy: {}
+ },
+ dir: '/path/to/app'
+ },
+ snapshot: {
+ name: '',
+ tag: '',
+ packages: {}
+ },
+ build: {
+ attachManifest: false,
+ forceRelativePaths: false,
+ insertCharset: 'UTF-8',
+ port: 1111,
+ dir: '/path/to/build/dir',
+ type: 'html5app',
+ uris: []
+ },
+ context: {
+ device: 'iphone'
+ },
+ contextqs: '?device=iphone',
+ tunnelpf: '/tunnel',
+ staticpf: 'staticpf'
+ };
+
+ cases = {
+ name: 'build/html5app cases',
+
+ setUp: function() {
+ count = 0;
+ },
+
+ tearDown: function() {
+ mockery.disable();
+ },
+
+ 'test instance': function () {
+ app = new App(null, null);
+ A.isObject(app);
+ A.isFunction(app.exec);
+ A.isNull(app.scraper);
+
+ app = new App(null, 'bam');
+ A.areSame('bam', app.scraper);
+ },
+
+ 'test shared.init() is called by constructore': function () {
+ A.areSame(0, count);
+ app = new App(null, null);
+ A.areSame(1, count);
+ },
+
+ 'test mock store': function () {
+ var store = Y.Mock,
+ scraper = {
+ on: function() {
+ return scraper;
+ },
+ start: function() {
+ return scraper;
+ },
+ fetch: function() {
+ return scraper;
+ },
+ };
+
+ Y.Mock.expect(store, {method: 'getAllURLs', args:[]});
+
+ app = new App(null, scraper);
+ app.exec(conf, store, function() {});
+ Y.Mock.verify(store);
+ },
+
+ 'test exec calls shared.js X times': function () {
+ var store = Y.Mock,
+ scraper = {
+ on: function() {
+ return scraper;
+ },
+ start: function() {
+ return scraper;
+ },
+ fetch: function() {
+ return scraper;
+ },
+ };
+
+ Y.Mock.expect(store, {method: 'getAllURLs', args:[]});
+
+ A.areSame(0, count);
+ app = new App(null, scraper);
+ A.areSame(1, count);
+
+ app.exec(conf, store, function() {});
+ Y.Mock.verify(store);
+ A.areSame(6, count);
+ },
+
+ 'test exec calls scraper.js X times': function () {
+ var store = Y.Mock,
+ scraper = {
+ on: function() {
+ count++;
+ return scraper;
+ },
+ start: function() {
+ count++;
+ return scraper;
+ },
+ fetch: function() {
+ count++;
+ return scraper;
+ },
+ };
+
+ Y.Mock.expect(store, {method: 'getAllURLs', args:[]});
+
+ A.areSame(0, count);
+ app = new App(null, scraper);
+ A.areSame(1, count);
+
+ app.exec(conf, store, function() {});
+ Y.Mock.verify(store);
+ A.areSame(10, count);
+ },
+ };
+
+ Y.Test.Runner.add(new Y.Test.Case(cases));
+});
View
206 tests/cli/lib/app/commands/build/test-hybridapp.js
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2011-2013, Yahoo! Inc. All rights reserved.
+ * Copyrights licensed under the New BSD License.
+ * See the accompanying LICENSE file for terms.
+ */
+YUI().use('mojito-test-extra', 'test', function(Y) {
+
+ var A = Y.Assert,
+ V = Y.Mock.Value,
+ AA = Y.ArrayAssert,
+ OA = Y.ObjectAssert,
+ cases,
+
+ mockery = require('mockery'),
+ srcpath = Y.MOJITO_DIR + 'lib/app/commands/build/hybridapp.js',
+ App,
+ app,
+ mocks = {},
+ conf,
+ count,
+ counter = function() {count++;},
+ fake_package_json = '{"dependencies":{}}';
+
+
+ mocks = {
+ shared: {
+ init: counter,
+ mapStoreUris: counter,
+ mapDefxUris: counter,
+ mapFunkySpecUris: counter,
+ makeManifest: counter,
+ copyModule: counter,
+ mungePage: counter,
+ },
+ writer: {
+ read: function() {counter(); return fake_package_json},
+ write: counter,
+ writeJson: counter,
+ }
+ }
+
+ mockery.registerAllowable(srcpath);
+ mockery.registerMock('./shared', mocks.shared);
+ mockery.enable({'warnOnUnregistered': false});
+ App = require(srcpath);
+
+ conf = {
+ mojitodir: '/Users/isao/Repos/mojito/myfork/',
+ app: {
+ name: 'staticpf',
+ version: '0.0.1',
+ specs: {
+ frame: {},
+ tunnelProxy: {}
+ },
+ dir: '/path/to/app'
+ },
+ snapshot: {
+ name: '',
+ tag: '',
+ packages: {}
+ },
+ build: {
+ attachManifest: false,
+ forceRelativePaths: false,
+ insertCharset: 'UTF-8',
+ port: 1111,
+ dir: '/path/to/build/dir',
+ type: 'html5app',
+ uris: []
+ },
+ context: {
+ device: 'iphone'
+ },
+ contextqs: '?device=iphone',
+ tunnelpf: '/tunnel',
+ staticpf: 'staticpf'
+ };
+
+ cases = {
+ name: 'build/html5app cases',
+
+ setUp: function() {
+ count = 0;
+ },
+
+ tearDown: function() {
+ mockery.disable();
+ },
+
+ 'test instance': function () {
+ app = new App(null, null);
+ A.isObject(app);
+ A.isFunction(app.exec);
+ A.isNull(app.scraper);
+
+ app = new App(null, 'bam');
+ A.areSame('bam', app.scraper);
+ },
+
+ 'test shared.init() is called by constructor': function () {
+ A.areSame(0, count);
+ app = new App(null, null);
+ A.areSame(1, count);
+ },
+
+ 'test exec w/mock store': function () {
+ var store = Y.Mock,
+ scraper = {
+ on: function() {
+ return scraper;
+ },
+ start: function() {
+ return scraper;
+ },
+ fetch: function() {
+ return scraper;
+ },
+ };
+
+ Y.Mock.expect(store, {method: 'getAllURLs', args:[]});
+
+ app = new App(mocks.writer, scraper);
+ app.exec(conf, store, function() {});
+ Y.Mock.verify(store);
+ },
+
+ 'test exec and mojito dep case': function () {
+ var store = Y.Mock,
+ scraper = {
+ on: function() {
+ return scraper;
+ },
+ start: function() {
+ return scraper;
+ },
+ fetch: function() {
+ return scraper;
+ },
+ };
+
+ Y.Mock.expect(store, {method: 'getAllURLs', args:[]});
+ fake_package_json = '{"dependencies":{"mojito":"*"}}';
+
+ app = new App(mocks.writer, scraper);
+ app.exec(conf, store, function() {});
+ Y.Mock.verify(store);
+ },
+
+ 'test exec calls shared.js X times': function () {
+ var store = Y.Mock,
+ scraper = {
+ on: function() {
+ return scraper;
+ },
+ start: function() {
+ return scraper;
+ },
+ fetch: function() {
+ return scraper;
+ },
+ };
+
+ Y.Mock.expect(store, {method: 'getAllURLs', args:[]});
+
+ A.areSame(0, count);
+ app = new App(mocks.writer, scraper);
+ A.areSame(1, count);
+
+ app.exec(conf, store, function() {});
+ Y.Mock.verify(store);
+ A.areSame(7, count);
+ },
+
+ 'test exec calls scraper.js X times': function () {
+ var store = Y.Mock,
+ scraper = {
+ on: function() {
+ count++;
+ return scraper;
+ },
+ start: function() {
+ count++;
+ return scraper;
+ },
+ fetch: function() {
+ count++;
+ return scraper;
+ },
+ };
+
+ Y.Mock.expect(store, {method: 'getAllURLs', args:[]});
+
+ A.areSame(0, count);
+ app = new App(mocks.writer, scraper);
+ A.areSame(1, count);
+
+ app.exec(conf, store, function() {});
+ Y.Mock.verify(store);
+ A.areSame(11, count);
+ },
+
+ };
+
+ Y.Test.Runner.add(new Y.Test.Case(cases));
+});
View
206 tests/cli/lib/app/commands/build/test-index.js
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2011-2013, Yahoo! Inc. All rights reserved.
+ * Copyrights licensed under the New BSD License.
+ * See the accompanying LICENSE file for terms.
+ */
+YUI().use('mojito-test-extra', 'test', function(Y) {
+
+ var A = Y.Assert,
+ V = Y.Mock.Value,
+ AA = Y.ArrayAssert,
+ OA = Y.ObjectAssert,
+ cases,
+
+ mockery = require('mockery'),
+ srcpath = Y.MOJITO_DIR + 'lib/app/commands/build/index.js',
+ mocks,
+ index;
+
+
+ // curry/factory for simple cb functions
+ function valfn(val/*return value*/, assert/*arg type assertion cb*/) {
+ return function(arg) {
+ if (assert) {
+ assert(arg);
+ }
+ return val;
+ };
+ }
+
+ // so we can mutate mocks, and refresh
+ function getMocks() {
+ return {
+ store: {
+ createStore: function (opts) {
+ A.isObject(opts);
+ A.isString(opts.root);
+ A.isObject(opts.context);
+
+ return {
+ getAppConfig: valfn({}, A.isObject),
+ getResourceVersions: function(obj) {
+ A.areSame(obj.name, 'package');
+ return [{
+ source:{
+ pkg:{
+ name:'name',
+ version:'0.0',
+ },
+ fs: 'some/dir'
+ }
+ }];
+ }
+ };
+ },
+ },
+ util: {
+ contextCsvToObject: valfn({}, A.isString),
+ isMojitoApp: valfn(true, A.isString)
+ },
+ writer: {
+ rmrf: function (dir, cb) {
+ A.isString(dir);
+ cb();
+ }
+ }
+ };
+ }
+
+ // mock functions within the modules require()'d by index.js
+ mocks = getMocks();
+ mockery.registerAllowable(srcpath);
+ mockery.registerMock(Y.MOJITO_DIR + 'lib/store', mocks.store);
+ mockery.registerMock(Y.MOJITO_DIR + 'lib/management/utils', mocks.util);
+ mockery.registerMock('./writer', mocks.writer);
+ mockery.enable({'warnOnUnregistered': false});
+ index = require(srcpath);
+
+ cases = {
+ name: 'build/index.js cases',
+
+ setUp: function() {
+ },
+
+ tearDown: function() {
+ // need to update just the leaf values so references in mockery are
+ // preserved
+ var cleanmocks = getMocks();
+ Object.keys(cleanmocks).forEach(function(key1) {
+ Object.keys(cleanmocks[key1]).forEach(function(key2) {
+ mocks[key1][key2] = cleanmocks[key1][key2];
+ });
+ });
+ },
+
+ 'test exports': function () {
+ A.isArray(index.options);
+ A.isString(index.usage);
+ A.areSame(6, index.options.length);
+ A.isFunction(index.run);
+ },
+
+ 'test missing type arg': function () {
+ index.run([], {}, function(err, usg, seppuku) {
+ A.isString(err);
+ A.isNull(usg);
+ A.isTrue(seppuku);
+ A.areSame('Missing type', err);
+ });
+ },
+
+ 'test invalid type arg': function () {
+ index.run(['chubby'], {}, function(err, usg, seppuku) {
+ A.isString(err);
+ A.isNull(usg);
+ A.isTrue(seppuku);
+ A.areSame('Invalid type', err);
+ });
+ },
+
+ 'test missing type arg': function () {
+ index.run([], {}, function(err, usg, seppuku) {
+ A.isString(err);
+ A.isNull(usg);
+ A.isTrue(seppuku);
+ A.areSame('Missing type', err);
+ });
+ },
+
+ 'test valid type, invalid cwd': function () {
+ var expected = 'Not a Mojito directory';
+
+ // purposely having run() "fail" early to limit test scope
+ mocks.util.isMojitoApp = valfn(false, A.isString);
+
+ index.run(['html5app'], {}, function(err, usg, seppuku) {
+ A.isString(err);
+ A.isNull(usg);
+ A.isTrue(seppuku);
+ A.areSame(expected, err);
+ });
+ },
+
+ 'test type is case-insensitive': function () {
+ var expected = 'Not a Mojito directory';// this msg says
+
+ // purposely having run() "fail" early to limit test scope
+ mocks.util.isMojitoApp = valfn(false, A.isString);
+
+ index.run(['HTML5APP'], {}, function(err, usg, seppuku) {
+ A.isString(err);
+ A.isNull(usg);
+ A.isTrue(seppuku);
+ A.areSame(expected, err);
+ });
+
+ index.run(['htML5apP'], {}, function(err, usg, seppuku) {
+ A.isString(err);
+ A.isNull(usg);
+ A.isTrue(seppuku);
+ A.areSame(expected, err);
+ });
+ },
+
+ 'test hybridapp requires snapshot options': function () {
+ var expected = 'Not a Mojito directory';
+
+ // purposely having run() "fail" early to limit test scope
+ mocks.util.isMojitoApp = valfn(false, A.isString);
+
+ index.run(['hybridapp'], {}, function(err, usg, seppuku) {
+ A.isString(err);
+ A.isNull(usg);
+ A.isTrue(seppuku);
+ // err is from options check
+ A.areSame('Build hybridapp requires --snapshotName and --snapshotTag', err);
+ });
+
+ index.run(['hybridapp'], {snapshotName: 1, snapshotTag:1}, function(err, usg, seppuku) {
+ A.isString(err);
+ A.isNull(usg);
+ A.isTrue(seppuku);
+ // no options error
+ A.areSame(expected, err);
+ });
+ },
+
+ 'test -r invokes rmrf': function () {
+
+ mocks.writer.rmrf = function(dir, cb) {
+ A.isTrue(/artifacts\/builds/.test(dir), 'expected default build dir str');
+ cb('fake rm -rf error');
+ }
+
+ index.run(['html5app'], {replace: true}, function(err, usg, seppuku) {
+ A.isString(err);
+ A.isNull(usg);
+ A.isTrue(seppuku);
+ A.isTrue(/Error removing /.test(err));
+ A.isTrue(/fake rm -rf error/.test(err));
+ });
+ },
+
+ };
+
+ Y.Test.Runner.add(new Y.Test.Case(cases));
+});
View
208 tests/cli/lib/app/commands/build/test-scraper.js
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2011-2013, Yahoo! Inc. All rights reserved.
+ * Copyrights licensed under the New BSD License.
+ * See the accompanying LICENSE file for terms.
+ */
+YUI().use('mojito-test-extra', 'test', function(Y) {
+
+ var A = Y.Assert,
+ V = Y.Mock.Value,
+ AA = Y.ArrayAssert,
+ OA = Y.ObjectAssert,
+ cases,
+
+ Scraper = require(Y.MOJITO_DIR + 'lib/app/commands/build/scraper.js');
+
+ cases = {
+ name: 'build/scraper cases',
+ setUp: function() {},
+ tearDown: function() {},
+
+ 'test instance': function () {
+ var scraper = new Scraper({});
+ A.isFunction(scraper.start);
+ A.isFunction(scraper.fetch);
+ A.isFunction(scraper.on);
+ A.isFunction(scraper.emit);
+
+ A.isObject(scraper);
+ A.isObject(scraper.mojito);
+ A.isNull(scraper.server);
+ },
+
+ 'test start calls mojito and returns itself': function () {
+ var mojito = Y.Mock(),
+ scraper,
+ self;
+
+ Y.Mock.expect(mojito, {
+ method: 'createServer',
+ args: [V.Object],
+ });
+
+ scraper = new Scraper(mojito);
+ self = scraper.start({port: 12345, context: ''});
+
+ Y.Mock.verify(mojito);
+ OA.areEqual(self, scraper);
+ },
+
+ 'test fetch, listen() mock': function () {
+ var server = Y.Mock(),
+ mojito = {
+ createServer: function() {
+ return server;
+ }
+ };
+
+ Y.Mock.expect(server, {
+ method: 'listen',
+ args: [null, null, V.Function],
+ });
+
+ scraper = new Scraper(mojito);
+ scraper.start({port: 12345, context: ''});
+ scraper.fetch({}, function(err) {});
+
+ Y.Mock.verify(server);
+ },
+
+ 'test fetch, listen() error': function () {
+ var getweb = Y.Mock(),
+ errmsg = "that's gonna leave a mark"
+ mojito = {
+ createServer: function() {
+ return {
+ listen: function(a, b, cb) {
+ cb(errmsg);
+ },
+ getWebPage: getweb
+ };
+ }
+ };
+
+ Y.Mock.expect(getweb, {
+ method: 'getWebPage',
+ args: [V.String, V.Object, V.Function],
+ });
+
+ scraper = new Scraper(mojito);
+ scraper.on('error', function(err) {
+ A.areSame(errmsg, err);
+ });
+ scraper.start({port: 12345, context: ''});
+ scraper.fetch({'a':'b'}, function(err) {});
+ },
+
+ 'test fetch, getWebPage() no error': function () {
+ var getweb = Y.Mock(),
+ mojito = {
+ createServer: function() {
+ getweb.listen = function(a, b, cb) {cb('')};
+ return getweb;
+ }
+ };
+
+ Y.Mock.expect(getweb, {
+ method: 'getWebPage',
+ args: [V.String, V.Object, V.Function],
+ });
+
+ scraper = new Scraper(mojito);
+
+ scraper.start({port: 12345, context: ''});
+ scraper.fetch({'a':'b'}, function(err) {});
+
+ Y.Mock.verify(getweb);
+ },
+
+ 'test fetch, AND the getWebPage() callback, w/ warning': function () {
+ var errmsg = 'HOLEE SHNIKEES',
+ uri = "/BROTHERS/DON'T/SHAKE/HANDS/BROTHERS/GOTTA/HUG",
+ mojito = {
+ createServer: function() {
+ return {
+ listen: function(a, b, cb) {cb('')},
+ getWebPage: function(key, opts, cb) {
+ cb(errmsg, uri, 'some content');
+ },
+ close: function() {
+ A.isTrue(true);
+ }
+ }
+ }
+ };
+
+ scraper = new Scraper(mojito);
+ scraper.on('warn', function(err) {
+ A.areSame('FAILED to get ' + uri, err);
+ });
+
+ scraper.start({port: 12345, context: ''});
+ scraper.fetch({'aa':'bb'}, function(err) {});
+ },
+
+ 'test fetch scraped-one event': function () {
+ var errmsg = '',
+ uri = '/Ketchup/Popsicle/?eat=no',
+ content = 'some content',
+ mojito = {
+ createServer: function() {
+ return {
+ listen: function(a, b, cb) {cb('')},
+ getWebPage: function(key, opts, cb) {
+ cb(errmsg, uri, content);
+ },
+ close: function() {
+ A.isTrue(true);
+ }
+ }
+ }
+ };
+
+ scraper = new Scraper(mojito);
+ scraper.on('scraped-one', function(cb_uri, cb_content) {
+ A.areSame(undefined, cb_uri);// ??
+ A.areSame(content, cb_content);
+ });
+
+ scraper.on('scraping-done', function(err, have, failed) {
+ A.areSame(1, have);
+ A.areSame(0, failed);
+ });
+
+ scraper.start({port: 12345, context: ''});
+ scraper.fetch({'aa':uri}, function(err) {});
+ },
+
+ 'test fetch, scraping-done event is called': function () {
+ var errmsg = '',
+ uri = '/cheeze/itz/?eat=yes',
+ content = 'some content',
+ mojito = {
+ createServer: function() {
+ return {
+ listen: function(a, b, cb) {cb('')},
+ getWebPage: function(key, opts, cb) {
+ cb(errmsg, uri, content);
+ },
+ close: function() {
+ A.isTrue(true);
+ }
+ }
+ }
+ };
+
+ scraper = new Scraper(mojito);
+ scraper.on('scraping-done', function(err, have, failed) {
+ A.areSame(2, have);
+ A.areSame(0, failed);
+ });
+
+ scraper.start({port: 12345, context: ''});
+ scraper.fetch({'aab':uri, 'bbb':uri.toUpperCase()}, function(err) {});
+ },
+ };
+
+ Y.Test.Runner.add(new Y.Test.Case(cases));
+});
View
457 tests/cli/lib/app/commands/build/test-shared.js
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2011-2013, Yahoo! Inc. All rights reserved.
+ * Copyrights licensed under the New BSD License.
+ * See the accompanying LICENSE file for terms.
+ */
+YUI().use('mojito-test-extra', 'test', function(Y) {
+
+ var A = Y.Assert,
+ AA = Y.ArrayAssert,
+ OA = Y.ObjectAssert,
+ cases,
+
+ shared = require(Y.MOJITO_DIR + 'lib/app/commands/build/shared.js'),
+ count,
+ conf;
+
+ conf = {
+ mojitodir: '/Users/isao/Repos/mojito/myfork/',
+ app: {
+ name: 'staticpf',
+ version: '0.0.1',
+ specs: {
+ frame: {},
+ tunnelProxy: {}
+ },
+ dir: '/path/to/app'
+ },
+ snapshot: {
+ name: '',
+ tag: '',
+ packages: {}
+ },
+ build: {
+ attachManifest: false,
+ forceRelativePaths: false,
+ insertCharset: 'UTF-8',
+ port: 1111,
+ dir: '/path/to/build/dir',
+ type: 'html5app',
+ uris: []
+ },
+ context: {
+ device: 'iphone'
+ },
+ contextqs: '?device=iphone',
+ tunnelpf: '/tunnel',
+ staticpf: 'staticpf'
+ };
+
+
+ cases = {
+ name: 'build/shared cases',
+ setUp: function() {
+ count = 0;
+ shared.init({
+ copydir: function(file) { count++; return file; },
+ copy: function(from, to) { count++; },
+ write: function(file, str) { count++; },
+ });
+ },
+ tearDown: function() {},
+
+ 'test init': function () {
+ A.areSame(0, count);
+ A.areSame(undefined, shared.init({}));
+ A.areSame(0, count);
+ },
+
+ 'test copyModule': function () {
+ A.areSame(0, count);
+ shared.copyModule('package/dir', 'module_name', 'dest/dir');
+ A.areSame(1, count);
+ },
+
+ 'test mapStoreUris modifies buildmap param by reference': function () {
+ var buildmap = {},
+ storemap = {
+ '/staticpf/top_frame/assets/index.css': '/path/to/app/mojits/top_frame/assets/index.css'
+ },
+ expected = {
+ '/staticpf/top_frame/assets/index.css?device=iphone': '/staticpf/top_frame/assets/index.css'
+ };
+
+ shared.mapStoreUris(buildmap, conf, storemap);
+ OA.areEqual(expected, buildmap);
+ },
+
+ 'test mapStoreUris maps css, js, json files': function () {
+ var buildmap = {
+ '/?device=iphone': '/index.html'
+ },
+ storemap = {
+ '/staticpf/top_frame/assets/index.css': '/path/to/app/mojits/top_frame/assets/index.css',
+ '/staticpf/top_frameBinderIndex.js': '/path/to/app/mojits/top_frame/binders/index.js',
+ '/staticpf/top_frame/package.json': '/path/to/app/mojits/top_frame/package.json',
+ '/staticpf/top_frame/views/index.hb.html': '/path/to/app/mojits/top_frame/views/index.hb.html',
+ '/favicon.ico': '/Users/isao/Repos/mojito/myfork/lib/app/assets/favicon.ico',
+ },
+ expected = {
+ '/?device=iphone': '/index.html',
+ '/staticpf/top_frame/assets/index.css?device=iphone': '/staticpf/top_frame/assets/index.css',
+ '/staticpf/top_frameBinderIndex.js?device=iphone': '/staticpf/top_frameBinderIndex.js',
+ '/staticpf/top_frame/package.json?device=iphone': '/staticpf/top_frame/package.json'
+ };
+
+ shared.mapStoreUris(buildmap, conf, storemap);
+ OA.areEqual(expected, buildmap);
+ },
+
+ 'test mapStoreUris maps copies html, favicon, etc files to build dir': function () {
+ var buildmap = {},
+ storemap = {
+ '/staticpf/top_frame/assets/index.css': '/path/to/app/mojits/top_frame/assets/index.css',
+ '/staticpf/top_frameBinderIndex.js': '/path/to/app/mojits/top_frame/binders/index.js',
+ '/staticpf/top_frame/package.json': '/path/to/app/mojits/top_frame/package.json',
+ '/staticpf/top_frame/views/index.hb.html': '/path/to/app/mojits/top_frame/views/index.hb.html',
+ '/favicon.ico': '/Users/isao/Repos/mojito/myfork/lib/app/assets/favicon.ico',
+ },
+ expected = {
+ '/staticpf/top_frame/assets/index.css?device=iphone': '/staticpf/top_frame/assets/index.css',
+ '/staticpf/top_frameBinderIndex.js?device=iphone': '/staticpf/top_frameBinderIndex.js',
+ '/staticpf/top_frame/package.json?device=iphone': '/staticpf/top_frame/package.json'
+ };
+
+ A.areSame(0, count);
+ shared.mapStoreUris(buildmap, conf, storemap);
+ OA.areEqual(expected, buildmap);
+ A.areSame(2, count);
+ },
+
+ 'test mapDefxUris adds definition.json for client mojits': function () {
+ var mojits = [
+ {source: {
+ fs: {
+ fullPath: '/Users/isao/Repos/mojito/apps/test50/test50/mojits/top_frame',
+ rootDir: '/Users/isao/Repos/mojito/apps/test50/test50/mojits/top_frame',
+ rootType: 'app',
+ subDir: '.',
+ subDirArray: [ '.' ],
+ isFile: false,
+ ext: '',
+ basename: ''
+ },
+ pkg: { name: 'yahoo.application.test50', version: '0.0.1', depth: 0 } },
+ type: 'mojit',
+ name: 'top_frame',
+ id: 'mojit--top_frame',
+ affinity: { affinity: 'common' },
+ selector: '*',
+ mime: { type: 'application/octet-stream', charset: undefined },
+ url: '/yahoo.application.test50/top_frame'
+ }
+ ],
+ store = {
+ getResources: function(type, ctx, filter) {return mojits;}
+ },
+ buildmap = {},
+ expected = {'/tunnel/yahoo.application.test50/top_frame/definition.json?device=iphone': '/yahoo.application.test50/top_frame/definition.json'};
+
+ A.areSame(0, count);
+ shared.mapDefxUris(buildmap, conf, store);
+ OA.areEqual(expected, buildmap);
+ A.areSame(0, count);
+ },
+
+ 'test mapDefxUris does nothing if mojit has no "url"': function () {
+ var mojits = [
+ {source: {
+ fs: {
+ fullPath: '/Users/isao/Repos/mojito/apps/test50/test50/mojits/top_frame',
+ rootDir: '/Users/isao/Repos/mojito/apps/test50/test50/mojits/top_frame',
+ rootType: 'app',
+ subDir: '.',
+ subDirArray: [ '.' ],
+ isFile: false,
+ ext: '',
+ basename: ''
+ },
+ pkg: { name: 'yahoo.application.test50', version: '0.0.1', depth: 0 } },
+ type: 'mojit',
+ name: 'top_frame',
+ id: 'mojit--top_frame',
+ affinity: { affinity: 'common' },
+ selector: '*',
+ mime: { type: 'application/octet-stream', charset: undefined },
+ REDACTED_URL: '/yahoo.application.test50/top_frame'
+ }
+ ],
+ store = {
+ getResources: function(type, ctx, filter) {return mojits;}
+ },
+ buildmap = {},
+ expected = {};
+
+ A.areSame(0, count);
+ shared.mapDefxUris(buildmap, conf, store);
+ OA.areEqual(expected, buildmap);
+ A.areSame(0, count);
+ },
+
+ 'test mapFunkySpecUris maps app.json specs to default.json files': function () {
+ var buildmap = {},
+ expected = {
+ '/tunnel/staticpf/frame/specs/default.json?device=iphone': '/staticpf/frame/specs/default.json',
+ '/tunnel/staticpf/tunnelProxy/specs/default.json?device=iphone': '/staticpf/tunnelProxy/specs/default.json'
+ };
+
+ A.areSame(0, count);
+ shared.mapFunkySpecUris(buildmap, conf);
+ OA.areEqual(expected, buildmap);
+ A.areSame(0, count);
+ },
+
+ 'test mapFunkySpecUris handles obscure Livestand mojit specs': function () {
+ var buildmap = {},
+ expected = {'tunnelpf/staticpf/foo/specs/bar.json?foo=bar': '/staticpf/foo/specs/bar.json'};
+
+ A.areSame(0, count);
+
+ shared.mapFunkySpecUris(buildmap, {staticpf:'staticpf', contextqs: '?foo=bar', tunnelpf:'tunnelpf',app:{specs:{'foo:bar':{}}}});
+
+ OA.areEqual(expected, buildmap);
+ A.areSame(0, count);
+ },
+
+ 'test makeManifest writes a file': function () {
+ var buildmap = buildmap = {
+ '/?device=iphone': '/index.html'
+ };
+
+ A.areSame(0, count);
+ shared.makeManifest(buildmap, 'build/dir', new Date());
+ A.areSame(1, count);
+ },
+
+ 'test mungePage does nothing unless attachManifest, insertCharset, forceRelativePaths are true': function () {
+ var uri = '/uri.html',
+ oldstr = 'blah blah <html> blah blah',
+ newstr;
+
+ A.areSame(0, count);
+ newstr = shared.mungePage(conf, uri, oldstr);
+ A.areSame(newstr, oldstr);
+ A.areSame(1, count);
+ },
+
+ 'test mungePage does nothing if uri is not *.html': function () {
+ var uri = '/uri.css',
+ oldstr = 'blah blah <html> blah blah',
+ newstr,
+ expected = 'blah blah <html manifest="some/uri"> blah blah',
+ oldbuildconf = conf.build;
+
+ conf.build = {
+ attachManifest: true,
+ forceRelativePaths: true,
+ insertCharset: 'UTF-8',
+ };
+
+ A.areSame(0, count);
+
+ newstr = shared.mungePage(conf, uri, oldstr);
+
+ A.areSame(newstr, oldstr);
+ A.areSame(1, count);
+
+ conf.build = oldbuildconf;
+ },
+
+ 'test mungePage for attachManifest:true': function () {
+ var uri = '/uri.html',
+ oldstr = 'blah blah <html> blah blah',
+ newstr,
+ expected = 'blah blah <html manifest="cache.manifest"> blah blah',
+ oldbuildconf = conf.build;
+
+ conf.build = {
+ attachManifest: true,
+ forceRelativePaths: true,
+ insertCharset: 'UTF-8',
+ };
+
+ A.areSame(0, count);
+
+ newstr = shared.mungePage(conf, uri, oldstr);
+
+ A.areNotSame(newstr, oldstr);
+ A.areSame(expected, newstr);
+ A.areSame(1, count);
+
+ conf.build = oldbuildconf;
+ },
+
+ 'test mungePage for attachManifest:true can apply relative path': function () {
+ var uri = '/foo/bar/uri.html',
+ oldstr = 'blah blah <html> blah blah',
+ newstr,
+ expected = 'blah blah <html manifest="../../cache.manifest"> blah blah',
+ oldbuildconf = conf.build;
+
+ conf.build = {
+ attachManifest: true,
+ forceRelativePaths: true,
+ insertCharset: 'UTF-8',
+ };
+
+ A.areSame(0, count);
+
+ newstr = shared.mungePage(conf, uri, oldstr);
+
+ A.areNotSame(newstr, oldstr);
+ A.areSame(expected, newstr);
+ A.areSame(1, count);
+
+ conf.build = oldbuildconf;
+ },
+
+ 'test mungePage for forceRelativePaths:true': function () {
+ var uri = '/foo/bar/uri.html',
+ oldstr = 'blah blah <a href="/foo/bar/baz/bah.html"> blah blah',
+ newstr,
+ expected = 'blah blah <a href="baz/bah.html"> blah blah',
+ oldbuildconf = conf.build;
+
+ conf.build = {
+ attachManifest: true,
+ forceRelativePaths: true,
+ insertCharset: 'UTF-8',
+ };
+
+ A.areSame(0, count);
+
+ newstr = shared.mungePage(conf, uri, oldstr);
+
+ A.areNotSame(newstr, oldstr);
+ A.areSame(expected, newstr);
+ A.areSame(1, count);
+
+ uri = '/foo/bar/baz/bah/uri.html';
+ oldstr = 'blah blah <a href="/foo/bah.html"> blah blah';
+ expected = 'blah blah <a href="../../../bah.html"> blah blah';
+ newstr = shared.mungePage(conf, uri, oldstr);
+
+ A.areNotSame(newstr, oldstr);
+ A.areSame(expected, newstr);
+ A.areSame(2, count);
+
+ conf.build = oldbuildconf;
+ },
+
+ 'test mungePage for forceRelativePaths:true with no common root': function () {
+ var uri = '/a/b/c/uri.html',
+ oldstr = 'blah blah <a href="/foo/bar/baz/bah.html"> blah blah',
+ newstr,
+ expected = 'blah blah <a href="../../../foo/bar/baz/bah.html"> blah blah',
+ oldbuildconf = conf.build;
+
+ conf.build = {
+ attachManifest: true,
+ forceRelativePaths: true,
+ insertCharset: 'UTF-8',
+ };
+
+ A.areSame(0, count);
+
+ newstr = shared.mungePage(conf, uri, oldstr);
+
+ A.areNotSame(newstr, oldstr);
+ A.areSame(expected, newstr);
+ A.areSame(1, count);
+
+ uri = '/foo/bar/baz/bah/uri.html';
+ oldstr = 'blah blah <a href="/foo/bah.html"> blah blah';
+ expected = 'blah blah <a href="../../../bah.html"> blah blah';
+ newstr = shared.mungePage(conf, uri, oldstr);
+
+ A.areNotSame(newstr, oldstr);
+ A.areSame(expected, newstr);
+ A.areSame(2, count);
+
+ conf.build = oldbuildconf;
+ },
+
+ 'test mungePage for insertCharset:true': function () {
+ var uri = '/',
+ oldstr = 'blah blah <head beepoo="boppoo"\npoo> blah blah',
+ newstr,
+ expected = 'blah blah <head beepoo="boppoo"\npoo>\n<meta charset="UTF-8">\n blah blah',
+ oldbuildconf = conf.build;
+
+ conf.build = {
+ attachManifest: true,
+ forceRelativePaths: true,
+ insertCharset: 'UTF-8',
+ };
+
+ A.areSame(0, count);
+
+ newstr = shared.mungePage(conf, uri, oldstr);
+
+ A.areNotSame(newstr, oldstr);
+ A.areSame(expected, newstr);
+ A.areSame(1, count);
+
+ conf.build = oldbuildconf;
+ },
+
+ 'test mungePage for insertCharset:true simple tag': function () {
+ var uri = '/',
+ oldstr = 'blah blah <head> blah blah',
+ newstr,
+ expected = 'blah blah <head>\n<meta charset="UTF-8">\n blah blah',
+ oldbuildconf = conf.build;
+
+ conf.build = {
+ attachManifest: true,
+ forceRelativePaths: true,
+ insertCharset: 'UTF-8',
+ };
+
+ A.areSame(0, count);
+
+ newstr = shared.mungePage(conf, uri, oldstr);
+
+ A.areNotSame(newstr, oldstr);
+ A.areSame(expected, newstr);
+ A.areSame(1, count);
+
+ conf.build = oldbuildconf;
+ },
+
+ 'test mungePage for insertCharset:true does nothing if there already is a charset metatag': function () {
+ var uri = '/',
+ oldstr = 'blah blah <head boo\npoo> blah blah<meta charset="zippy">',
+ newstr,
+ oldbuildconf = conf.build;
+
+ conf.build = {
+ attachManifest: true,
+ forceRelativePaths: true,
+ insertCharset: 'UTF-8',
+ };
+
+ A.areSame(0, count);
+
+ newstr = shared.mungePage(conf, uri, oldstr);
+
+ A.areSame(newstr, oldstr);
+ A.areSame(1, count);
+
+ conf.build = oldbuildconf;
+ },
+
+ };
+
+ Y.Test.Runner.add(new Y.Test.Case(cases));
+});
View
96 tests/cli/lib/app/commands/build/test-writer.js
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2011-2013, Yahoo! Inc. All rights reserved.
+ * Copyrights licensed under the New BSD License.
+ * See the accompanying LICENSE file for terms.
+ */
+YUI().use('mojito-test-extra', 'test', function(Y) {
+
+ var A = Y.Assert,
+ AA = Y.ArrayAssert,
+ OA = Y.ObjectAssert,
+ cases,
+
+ mockery = require('mockery'),
+ srcpath = Y.MOJITO_DIR + 'lib/app/commands/build/writer.js',
+ count,
+ mocks,
+ writer;
+
+ mocks = {
+ fs: {
+ readFileSync: function(file) { count++; return file; },
+ writeFileSync: function(file, str) { count++; },
+ copy: function(from, to) { count++; }
+ },
+ mkdirp: {
+ sync: function(dir) { count++; }
+ },
+ rimraf: function(dir, cb) { count++;cb(dir); },
+ wrench: {
+ copyDirSyncRecursive: function(dir) { count++; }
+ }
+ };
+
+ mockery.registerAllowable(srcpath);
+ mockery.registerMock('fs', mocks.fs);
+ mockery.registerMock('mkdirp', mocks.mkdirp);
+ mockery.registerMock('rimraf', mocks.rimraf);
+ mockery.registerMock('wrench', mocks.wrench);
+ mockery.enable({'warnOnUnregistered': false});
+ writer = require(srcpath);
+
+ cases = {
+ name: 'build/writer.js test cases',
+
+ setUp: function() {
+ count = 0;
+ },
+
+ tearDown: function() {
+ mockery.disable();
+ },
+
+ 'test read': function () {
+ A.areSame('abc', writer.read('abc'));
+ },
+
+ 'test write': function () {
+ var f = 'moby/dick',
+ c = 'they call me Ishmael';
+ A.areSame(0, count);
+ writer.write(f, c);
+ A.areSame(2, count);
+ },
+
+ 'test writeJson': function () {
+ var f = 'moby/dick',
+ c = {they: 'call me Ishmael'};
+ A.areSame(0, count);
+ writer.writeJson(f, c);
+ A.areSame(2, count);
+ },
+
+ 'test copy': function () {
+ A.areSame(0, count);
+ writer.copy('from', 'to');
+ A.areSame(3, count);
+ },
+
+ 'test copydir': function () {
+ A.areSame(0, count);
+ writer.copydir('from', 'to');
+ A.areSame(1, count);
+ },
+
+ 'test rmrf': function () {
+ var dir = 'doomed/dir';
+ A.areSame(0, count);
+ writer.rmrf(dir, function (d) {
+ A.areSame(dir, d);
+ });
+ A.areSame(1, count);
+ }
+ };
+
+ Y.Test.Runner.add(new Y.Test.Case(cases));
+});
View
39 tests/cli/lib/lib_test_descriptor.json
@@ -21,10 +21,43 @@
"driver": "nodejs"
},
"group": "fw,cli"
+ },
+ "build/writer.js": {
+ "params": {
+ "test": "./app/commands/build/test-writer.js",
+ "driver": "nodejs"
+ }
+ },
+ "build/shared.js": {
+ "params": {
+ "test": "./app/commands/build/test-shared.js",
+ "driver": "nodejs"
+ }
+ },
+ "build/index.js": {
+ "params": {
+ "test": "./app/commands/build/test-index.js",
+ "driver": "nodejs"
+ }
+ },
+ "build/scraper.js": {
+ "params": {
+ "test": "./app/commands/build/test-scraper.js",
+ "driver": "nodejs"
+ }
+ },
+ "build/hybridapp.js": {
+ "params": {
+ "test": "./app/commands/build/test-hybridapp.js",
+ "driver": "nodejs"
+ }
+ },
+ "build/html5app.js": {
+ "params": {
+ "test": "./app/commands/build/test-html5app.js",
+ "driver": "nodejs"
+ }
}
}
- },
- {
- "settings": [ "environment:development" ]
}
]
Please sign in to comment.
Something went wrong with that request. Please try again.