You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ka...@apache.org on 2014/05/02 20:33:30 UTC
[11/24] Split out cordova-lib: move cordova-cli files
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b51e1c12/cordova-lib/spec-cordova/hooker.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/hooker.spec.js b/cordova-lib/spec-cordova/hooker.spec.js
new file mode 100644
index 0000000..c85cc59
--- /dev/null
+++ b/cordova-lib/spec-cordova/hooker.spec.js
@@ -0,0 +1,261 @@
+ /**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+**/
+
+
+var cordova = require('../cordova'),
+ hooker = require('../src/hooker'),
+ shell = require('shelljs'),
+ path = require('path'),
+ fs = require('fs'),
+ os = require('os'),
+ Q = require('q'),
+ child_process = require('child_process'),
+ helpers = require('./helpers');
+
+var platform = os.platform();
+var tmpDir = helpers.tmpDir('hooks_test');
+var project = path.join(tmpDir, 'project');
+var dotCordova = path.join(project, '.cordova');
+var hooksDir = path.join(project, '.cordova', 'hooks');
+var ext = platform.match(/(win32|win64)/)?'bat':'sh';
+
+
+// copy fixture
+shell.rm('-rf', project);
+shell.mkdir('-p', project);
+shell.cp('-R', path.join(__dirname, 'fixtures', 'base', '*'), project);
+shell.mkdir('-p', dotCordova);
+shell.cp('-R', path.join(__dirname, 'fixtures', 'hooks_' + ext), dotCordova);
+shell.mv(path.join(dotCordova, 'hooks_' + ext), hooksDir);
+shell.chmod('-R', 'ug+x', hooksDir);
+
+
+describe('hooker', function() {
+ it('should throw if provided directory is not a cordova project', function() {
+ expect(function() {
+ new hooker(tmpDir);
+ }).toThrow();
+ });
+});
+
+describe('global (static) fire method', function() {
+ it('should execute listeners serially', function(done) {
+ var test_event = 'foo';
+ var h1_fired = false;
+ var h1 = function() {
+ expect(h2_fired).toBe(false);
+ // Delay 100 ms here to check that h2 is not executed until after
+ // the promise returned by h1 is resolved.
+ var q = Q.delay(100).then(function() {
+ h1_fired = true;
+ });
+ return q;
+ };
+ var h2_fired = false;
+ var h2 = function() {
+ h2_fired = true;
+ expect(h1_fired).toBe(true);
+ return Q();
+ };
+
+ cordova.on(test_event, h1);
+ cordova.on(test_event, h2);
+ hooker.fire(test_event).then(function() {
+ expect(h1_fired).toBe(true);
+ expect(h2_fired).toBe(true);
+ done();
+ });
+ });
+});
+
+describe('module-level hooks', function() {
+ var handler = jasmine.createSpy().andReturn(Q());
+ var test_event = 'before_build';
+ var h;
+
+ beforeEach(function() {
+ h = new hooker(project);
+ });
+
+ afterEach(function() {
+ cordova.removeAllListeners(test_event);
+ handler.reset();
+ });
+
+ it('should fire handlers using cordova.on', function(done) {
+ cordova.on(test_event, handler);
+ h.fire(test_event)
+ .then(function() {
+ expect(handler).toHaveBeenCalled();
+ })
+ .fail(function(err) {
+ expect(err).not.toBeDefined();
+ })
+ .fin(done);
+ });
+
+ it('should pass the project root folder as parameter into the module-level handlers', function(done) {
+ cordova.on(test_event, handler);
+ h.fire(test_event)
+ .then(function() {
+ expect(handler).toHaveBeenCalledWith({root:project});
+ })
+ .fail(function(err) {
+ console.log(err);
+ expect(err).not.toBeDefined();
+ })
+ .fin(done);
+ });
+
+ it('should be able to stop listening to events using cordova.off', function(done) {
+ cordova.on(test_event, handler);
+ cordova.off(test_event, handler);
+ h.fire(test_event)
+ .then(function() {
+ expect(handler).not.toHaveBeenCalled();
+ })
+ .fail(function(err) {
+ console.log(err);
+ expect(err).toBeUndefined();
+ })
+ .fin(done);
+ });
+
+ it('should allow for hook to opt into asynchronous execution and block further hooks from firing using the done callback', function(done) {
+ var h1_fired = false;
+ var h1 = function() {
+ h1_fired = true;
+ expect(h2_fired).toBe(false);
+ return Q();
+ };
+ var h2_fired = false;
+ var h2 = function() {
+ h2_fired = true;
+ expect(h1_fired).toBe(true);
+ return Q();
+ };
+
+ cordova.on(test_event, h1);
+ cordova.on(test_event, h2);
+ h.fire(test_event).then(function() {
+ expect(h1_fired).toBe(true);
+ expect(h2_fired).toBe(true);
+ done();
+ });
+ });
+
+ it('should pass data object that fire calls into async handlers', function(done) {
+ var data = {
+ "hi":"ho",
+ "offtowork":"wego"
+ };
+ var async = function(opts) {
+ data.root = tmpDir;
+ expect(opts).toEqual(data);
+ return Q();
+ };
+ cordova.on(test_event, async);
+ h.fire(test_event, data).then(done);
+ });
+
+ it('should pass data object that fire calls into sync handlers', function(done) {
+ var data = {
+ "hi":"ho",
+ "offtowork":"wego"
+ };
+ var async = function(opts) {
+ data.root = tmpDir;
+ expect(opts).toEqual(data);
+ };
+ cordova.on(test_event, async);
+ h.fire(test_event, data).then(done);
+ });
+});
+
+
+describe('hooks', function() {
+ var h;
+ beforeEach(function() {
+ h = new hooker(project);
+ });
+
+
+ it('should not error if the hook is unrecognized', function(done) {
+ h.fire('CLEAN YOUR SHORTS GODDAMNIT LIKE A BIG BOY!')
+ .fail(function (err) {
+ expect('Call with unrecogized hook ').toBe('successful.\n' + err);
+ })
+ .fin(done);
+ });
+
+ it('should error if any script exits with non-zero code', function(done) {
+ h.fire('fail').then(function() {
+ expect('the call').toBe('a failure');
+ }, function(err) {
+ expect(err).toBeDefined();
+ })
+ .fin(done);
+ });
+
+ it('should execute all scripts in order', function(done) {
+ h.fire('test')
+ .then(function() {
+ var hooksOrderFile = path.join(project, 'hooks_order.txt');
+ var hooksEnvFile = path.join(project, 'hooks_env.json');
+ var hooksParamsFile = path.join(project, 'hooks_params.txt');
+ expect(hooksOrderFile).toExist();
+ expect(hooksEnvFile).toExist();
+ expect(hooksParamsFile).toExist();
+ expect(path.join(project, 'dotted_hook_should_not_fire.txt')).not.toExist();
+
+ var order = fs.readFileSync(hooksOrderFile, 'ascii').replace(/\W/gm, '');
+ expect(order).toBe('ab');
+
+ var params = fs.readFileSync(hooksParamsFile, 'ascii').trim().trim('"');
+ expect(params).toMatch(project.replace(/\\/g, '\\\\'));
+
+ var env = JSON.parse(fs.readFileSync(hooksEnvFile, 'ascii'));
+ expect(env.CORDOVA_VERSION).toEqual(require('../package').version);
+ })
+ .fail(function(err) {
+ console.log(err);
+ expect('Test hook call').toBe('successful');
+ })
+ .fin(done);
+
+ });
+
+ // Cleanup. Must be the last spec. Is there a better place for final cleanup in Jasmine?
+ it('should not fail during cleanup', function() {
+ process.chdir(path.join(__dirname, '..')); // Non e2e tests assume CWD is repo root.
+ if(ext == 'sh') {
+ //shell.rm('-rf', tmpDir);
+ } else { // Windows:
+ // For some mysterious reason, both shell.rm and RMDIR /S /Q won't
+ // delete the dir on Windows, but they do remove the files leaving
+ // only folders. But the dir is removed just fine by
+ // shell.rm('-rf', tmpDir) at the top of this file with the next
+ // invocation of this test. The benefit of RMDIR /S /Q is that it
+ // doesn't print warnings like shell.rmdir() that look like this:
+ // rm: could not remove directory (code ENOTEMPTY): C:\Users\...
+ var cmd = 'RMDIR /S /Q ' + tmpDir;
+ child_process.exec(cmd);
+ }
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b51e1c12/cordova-lib/spec-cordova/lazy_load.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/lazy_load.spec.js b/cordova-lib/spec-cordova/lazy_load.spec.js
new file mode 100644
index 0000000..1a92ee9
--- /dev/null
+++ b/cordova-lib/spec-cordova/lazy_load.spec.js
@@ -0,0 +1,200 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+var lazy_load = require('../src/lazy_load'),
+ config = require('../src/config'),
+ util = require('../src/util'),
+ shell = require('shelljs'),
+ npmconf = require('npmconf');
+ path = require('path'),
+ hooker = require('../src/hooker'),
+ request = require('request'),
+ fs = require('fs'),
+ Q = require('q'),
+ platforms = require('../platforms');
+
+describe('lazy_load module', function() {
+ var custom_path;
+ beforeEach(function() {
+ custom_path = spyOn(config, 'has_custom_path').andReturn(false);
+ });
+ describe('cordova method (loads stock cordova libs)', function() {
+ var custom;
+ beforeEach(function() {
+ custom = spyOn(lazy_load, 'custom').andReturn(Q(path.join('lib','dir')));
+ });
+ it('should throw if platform is not a stock cordova platform', function(done) {
+ lazy_load.cordova('atari').then(function() {
+ expect('this call').toEqual('to fail');
+ }, function(err) {
+ expect('' + err).toContain('Cordova library "atari" not recognized.');
+ }).fin(done);
+ });
+ it('should invoke lazy_load.custom with appropriate url, platform, and version as specified in platforms manifest', function(done) {
+ lazy_load.cordova('android').then(function(dir) {
+ expect(custom).toHaveBeenCalledWith(platforms.android.url + ';a=snapshot;h=' + platforms.android.version + ';sf=tgz', 'cordova', 'android', platforms.android.version);
+ expect(dir).toBeDefined();
+ done();
+ });
+ });
+ });
+
+ describe('custom method (loads custom cordova libs)', function() {
+ var exists, fire, rm;
+ beforeEach(function() {
+ spyOn(shell, 'mkdir');
+ rm = spyOn(shell, 'rm');
+ mv = spyOn(shell, 'mv');
+ exists = spyOn(fs, 'existsSync').andReturn(false);
+ readdir = spyOn(fs, 'readdirSync').andReturn(['somefile.txt']);
+ fire = spyOn(hooker, 'fire').andReturn(Q());
+ });
+
+ it('should callback with no errors and not fire event hooks if library already exists', function(done) {
+ exists.andReturn(true);
+ lazy_load.custom('http://some remote url', 'some id', 'platform X', 'three point five').then(function() {
+ expect(fire).not.toHaveBeenCalled()
+ }, function(err) {
+ expect(err).not.toBeDefined();
+ }).fin(done);
+ });
+ it('should callback with no errors and fire event hooks even if library already exists if the lib url is a local dir', function(done) {
+ exists.andReturn(true);
+ lazy_load.custom('some local dir', 'some id', 'platform X', 'three point six').then(function() {
+ expect(fire).not.toHaveBeenCalled()
+ }, function(err) {
+ expect(err).not.toBeDefined();
+ }).fin(done);
+ });
+
+ describe('remote URLs for libraries', function() {
+ var npmConfProxy;
+ var req,
+ load_spy,
+ events = {},
+ fakeRequest = {
+ on: jasmine.createSpy().andCallFake(function(event, cb) {
+ events[event] = cb;
+ return fakeRequest;
+ }),
+ pipe: jasmine.createSpy().andCallFake(function() { return fakeRequest; })
+ };
+ beforeEach(function() {
+ npmConfProxy = null;
+ events = {};
+ fakeRequest.on.reset();
+ fakeRequest.pipe.reset();
+ req = spyOn(request, 'get').andCallFake(function() {
+ // Fire the 'end' event shortly.
+ setTimeout(function() {
+ events['end']();
+ }, 10);
+ return fakeRequest;
+ });
+ load_spy = spyOn(npmconf, 'load').andCallFake(function(cb) { cb(null, { get: function() { return npmConfProxy }}); });
+ });
+
+ it('should call request with appopriate url params', function(done) {
+ var url = 'https://github.com/apache/someplugin';
+ lazy_load.custom(url, 'random', 'android', '1.0').then(function() {
+ expect(req).toHaveBeenCalledWith({
+ uri:url
+ }, jasmine.any(Function));
+ }, function(err) {
+ expect(err).not.toBeDefined();
+ }).fin(done);
+ });
+ it('should take into account https-proxy npm configuration var if exists for https:// calls', function(done) {
+ var proxy = 'https://somelocalproxy.com';
+ npmConfProxy = proxy;
+ var url = 'https://github.com/apache/someplugin';
+ lazy_load.custom(url, 'random', 'android', '1.0').then(function() {
+ expect(req).toHaveBeenCalledWith({
+ uri:url,
+ proxy:proxy
+ }, jasmine.any(Function));
+ }, function(err) {
+ expect(err).not.toBeDefined();
+ }).fin(done);
+ });
+ it('should take into account proxy npm config var if exists for http:// calls', function(done) {
+ var proxy = 'http://somelocalproxy.com';
+ npmConfProxy = proxy;
+ var url = 'http://github.com/apache/someplugin';
+ lazy_load.custom(url, 'random', 'android', '1.0').then(function() {
+ expect(req).toHaveBeenCalledWith({
+ uri:url,
+ proxy:proxy
+ }, jasmine.any(Function));
+ }, function(err) {
+ expect(err).not.toBeDefined();
+ }).fin(done);
+ });
+ });
+
+ describe('local paths for libraries', function() {
+ it('should return the local path, no symlink', function(done) {
+ lazy_load.custom('/some/random/lib', 'id', 'X', 'three point eight').then(function(dir) {
+ expect(dir).toEqual('/some/random/lib');
+ }, function(err) {
+ expect(err).toBeUndefined();
+ }).fin(done);
+ });
+ it('should not file download hook', function(done) {
+ lazy_load.custom('/some/random/lib', 'id', 'X', 'three point nine').then(function() {
+ expect(fire).not.toHaveBeenCalledWith('after_library_download', {platform:'X',url:'/some/random/lib',id:'id',version:'three point nine',path:'/some/random/lib', symlink:false});
+ }, function(err) {
+ expect(err).toBeUndefined();
+ }).fin(done);
+ });
+ });
+ });
+
+ describe('based_on_config method', function() {
+ var cordova, custom;
+ beforeEach(function() {
+ cordova = spyOn(lazy_load, 'cordova').andReturn(Q());
+ custom = spyOn(lazy_load, 'custom').andReturn(Q());
+ });
+ it('should invoke custom if a custom lib is specified', function(done) {
+ var read = spyOn(config, 'read').andReturn({
+ lib:{
+ maybe:{
+ uri:'you or eye?',
+ id:'eye dee',
+ version:'four point twenty'
+ }
+ }
+ });
+ var p = '/some/random/custom/path';
+ custom_path.andReturn(p);
+ lazy_load.based_on_config('yup', 'maybe').then(function() {
+ expect(custom).toHaveBeenCalledWith('you or eye?', 'eye dee', 'maybe', 'four point twenty');
+ }, function(err) {
+ expect(err).toBeUndefined();
+ }).fin(done);
+ });
+ it('should invoke cordova if no custom lib is specified', function(done) {
+ lazy_load.based_on_config('yup', 'ios').then(function() {
+ expect(cordova).toHaveBeenCalledWith('ios');
+ }, function(err) {
+ expect(err).toBeUndefined();
+ }).fin(done);
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b51e1c12/cordova-lib/spec-cordova/metadata/android_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/android_parser.spec.js b/cordova-lib/spec-cordova/metadata/android_parser.spec.js
new file mode 100644
index 0000000..6c6ea41
--- /dev/null
+++ b/cordova-lib/spec-cordova/metadata/android_parser.spec.js
@@ -0,0 +1,211 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+var platforms = require('../../platforms'),
+ util = require('../../src/util'),
+ path = require('path'),
+ shell = require('shelljs'),
+ fs = require('fs'),
+ et = require('elementtree'),
+ xmlHelpers = require('../../src/xml-helpers'),
+ Q = require('q'),
+ config = require('../../src/config'),
+ ConfigParser = require('../../src/ConfigParser'),
+ cordova = require('../../cordova');
+
+// Create a real config object before mocking out everything.
+var cfg = new ConfigParser(path.join(__dirname, '..', 'test-config.xml'));
+
+var STRINGS_XML = '<resources> <string name="app_name">mobilespec</string> </resources>';
+var MANIFEST_XML = '<manifest android:versionCode="1" android:versionName="0.0.1" package="org.apache.mobilespec">\n' +
+ '<application android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="@string/app_name">\n' +
+ ' <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/app_name" android:name="mobilespec" android:screenOrientation="VAL">\n' +
+ ' <intent-filter>\n' +
+ ' <action android:name="android.intent.action.MAIN" />\n' +
+ ' <category android:name="android.intent.category.LAUNCHER" />\n' +
+ ' </intent-filter>\n' +
+ ' </activity>\n' +
+ '</application>\n' +
+ '</manifest>\n';
+
+describe('android project parser', function() {
+ var proj = path.join('some', 'path');
+ var exists;
+ beforeEach(function() {
+ exists = spyOn(fs, 'existsSync').andReturn(true);
+ spyOn(config, 'has_custom_path').andReturn(false);
+ });
+
+ function wrapper(p, done, post) {
+ p.then(post, function(err) {
+ expect(err).toBeUndefined();
+ }).fin(done);
+ }
+
+ function errorWrapper(p, done, post) {
+ p.then(function() {
+ expect('this call').toBe('fail');
+ }, post).fin(done);
+ }
+
+ describe('constructions', function() {
+ it('should throw if provided directory does not contain an AndroidManifest.xml', function() {
+ exists.andReturn(false);
+ expect(function() {
+ new platforms.android.parser(proj);
+ }).toThrow();
+ });
+ it('should create an instance with path, strings, manifest and android_config properties', function() {
+ expect(function() {
+ var p = new platforms.android.parser(proj);
+ expect(p.path).toEqual(proj);
+ expect(p.strings).toEqual(path.join(proj, 'res', 'values', 'strings.xml'));
+ expect(p.manifest).toEqual(path.join(proj, 'AndroidManifest.xml'));
+ expect(p.android_config).toEqual(path.join(proj, 'res', 'xml', 'config.xml'));
+ }).not.toThrow();
+ });
+ });
+
+ describe('instance', function() {
+ var p, cp, rm, mkdir, is_cordova, write, read;
+ var android_proj = path.join(proj, 'platforms', 'android');
+ var stringsRoot;
+ var manifestRoot;
+ beforeEach(function() {
+ stringsRoot = null;
+ manifestRoot = null;
+ p = new platforms.android.parser(android_proj);
+ cp = spyOn(shell, 'cp');
+ rm = spyOn(shell, 'rm');
+ is_cordova = spyOn(util, 'isCordova').andReturn(proj);
+ write = spyOn(fs, 'writeFileSync');
+ read = spyOn(fs, 'readFileSync');
+ mkdir = spyOn(shell, 'mkdir');
+ spyOn(xmlHelpers, 'parseElementtreeSync').andCallFake(function(path) {
+ if (/strings/.exec(path)) {
+ return stringsRoot = new et.ElementTree(et.XML(STRINGS_XML));
+ } else if (/AndroidManifest/.exec(path)) {
+ return manifestRoot = new et.ElementTree(et.XML(MANIFEST_XML));
+ }
+ });
+ });
+
+ describe('update_from_config method', function() {
+ beforeEach(function() {
+ spyOn(fs, 'readdirSync').andReturn([path.join(proj, 'src', 'android_pkg', 'MyApp.java')]);
+ cfg.name = function() { return 'testname' };
+ cfg.packageName = function() { return 'testpkg' };
+ cfg.version = function() { return 'one point oh' };
+ read.andReturn('package org.cordova.somepackage; public class MyApp extends CordovaActivity { }');
+ });
+
+ it('should handle no orientation', function() {
+ cfg.getPreference = function() { return null; };
+ p.update_from_config(cfg);
+ expect(manifestRoot.getroot().find('./application/activity').attrib['android:screenOrientation']).toEqual('VAL');
+ });
+ it('should handle default orientation', function() {
+ cfg.getPreference = function() { return 'default'; };
+ p.update_from_config(cfg);
+ expect(manifestRoot.getroot().find('./application/activity').attrib['android:screenOrientation']).toBeUndefined();
+ });
+ it('should handle portrait orientation', function() {
+ cfg.getPreference = function() { return 'portrait'; };
+ p.update_from_config(cfg);
+ expect(manifestRoot.getroot().find('./application/activity').attrib['android:screenOrientation']).toEqual('portrait');
+ });
+ it('should handle invalid orientation', function() {
+ cfg.getPreference = function() { return 'prtrait'; };
+ p.update_from_config(cfg);
+ expect(manifestRoot.getroot().find('./application/activity').attrib['android:screenOrientation']).toEqual('VAL');
+ });
+ it('should write out the app name to strings.xml', function() {
+ p.update_from_config(cfg);
+ expect(stringsRoot.getroot().find('string').text).toEqual('testname');
+ });
+ it('should write out the app id to androidmanifest.xml and update the cordova-android entry Java class', function() {
+ p.update_from_config(cfg);
+ expect(manifestRoot.getroot().attrib.package).toEqual('testpkg');
+ });
+ it('should write out the app version to androidmanifest.xml', function() {
+ p.update_from_config(cfg);
+ expect(manifestRoot.getroot().attrib['android:versionName']).toEqual('one point oh');
+ });
+ });
+ describe('www_dir method', function() {
+ it('should return assets/www', function() {
+ expect(p.www_dir()).toEqual(path.join(android_proj, 'assets', 'www'));
+ });
+ });
+ describe('config_xml method', function() {
+ it('should return the location of the config.xml', function() {
+ expect(p.config_xml()).toEqual(p.android_config);
+ });
+ });
+ describe('update_www method', function() {
+ it('should rm project-level www and cp in platform agnostic www', function() {
+ p.update_www();
+ expect(rm).toHaveBeenCalled();
+ expect(cp).toHaveBeenCalled();
+ });
+ });
+ describe('update_overrides method', function() {
+ it('should do nothing if merges directory does not exist', function() {
+ exists.andReturn(false);
+ p.update_overrides();
+ expect(cp).not.toHaveBeenCalled();
+ });
+ it('should copy merges path into www', function() {
+ p.update_overrides();
+ expect(cp).toHaveBeenCalled();
+ });
+ });
+ describe('update_project method', function() {
+ var config, www, overrides, svn;
+ beforeEach(function() {
+ config = spyOn(p, 'update_from_config');
+ www = spyOn(p, 'update_www');
+ overrides = spyOn(p, 'update_overrides');
+ svn = spyOn(util, 'deleteSvnFolders');
+ });
+ it('should call update_from_config', function() {
+ p.update_project();
+ expect(config).toHaveBeenCalled();
+ });
+ it('should throw if update_from_config throws', function(done) {
+ var err = new Error('uh oh!');
+ config.andCallFake(function() { throw err; });
+ errorWrapper(p.update_project({}), done, function(err) {
+ expect(err).toEqual(err);
+ });
+ });
+ it('should not call update_www', function() {
+ p.update_project();
+ expect(www).not.toHaveBeenCalled();
+ });
+ it('should call update_overrides', function() {
+ p.update_project();
+ expect(overrides).toHaveBeenCalled();
+ });
+ it('should call deleteSvnFolders', function() {
+ p.update_project();
+ expect(svn).toHaveBeenCalled();
+ });
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b51e1c12/cordova-lib/spec-cordova/metadata/blackberry_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/blackberry_parser.spec.js b/cordova-lib/spec-cordova/metadata/blackberry_parser.spec.js
new file mode 100644
index 0000000..b1d0b47
--- /dev/null
+++ b/cordova-lib/spec-cordova/metadata/blackberry_parser.spec.js
@@ -0,0 +1,225 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var platforms = require('../../platforms'),
+ util = require('../../src/util'),
+ path = require('path'),
+ shell = require('shelljs'),
+ fs = require('fs'),
+ et = require('elementtree'),
+ xmlHelpers = require('../../src/xml-helpers'),
+ Q = require('q'),
+ child_process = require('child_process'),
+ config = require('../../src/config'),
+ ConfigParser = require('../../src/ConfigParser'),
+ cordova = require('../../cordova');
+
+var cfg = new ConfigParser(path.join(__dirname, '..', 'test-config.xml'));
+
+var TEST_XML = '<?xml version="1.0" encoding="UTF-8"?>\n' +
+ '<widget xmlns = "http://www.w3.org/ns/widgets"\n' +
+ ' xmlns:cdv = "http://cordova.apache.org/ns/1.0"\n' +
+ ' id = "io.cordova.hellocordova"\n' +
+ ' version = "0.0.1">\n' +
+ ' <name>Hello Cordova</name>\n' +
+ ' <description>\n' +
+ ' A sample Apache Cordova application that responds to the deviceready event.\n' +
+ ' </description>\n' +
+ ' <author href="http://cordova.io" email="dev@cordova.apache.org">\n' +
+ ' Apache Cordova Team\n' +
+ ' </author>\n' +
+ ' <content src="index.html" />\n' +
+ ' <access origin="*" />\n' +
+ ' <preference name="fullscreen" value="true" />\n' +
+ ' <preference name="webviewbounce" value="true" />\n' +
+ '</widget>\n';
+
+describe('blackberry10 project parser', function() {
+ var proj = '/some/path';
+ var exists, custom, sh;
+ beforeEach(function() {
+ exists = spyOn(fs, 'existsSync').andReturn(true);
+ custom = spyOn(config, 'has_custom_path').andReturn(false);
+ sh = spyOn(child_process, 'exec').andCallFake(function(cmd, opts, cb) {
+ (cb || opts)(0, '', '');
+ });
+ spyOn(ConfigParser.prototype, 'write');
+ spyOn(xmlHelpers, 'parseElementtreeSync').andCallFake(function() {
+ return new et.ElementTree(et.XML(TEST_XML));
+ });
+ });
+
+ function wrapper(p, done, post) {
+ p.then(post, function(err) {
+ expect(err).toBeUndefined();
+ }).fin(done);
+ }
+
+ function errorWrapper(p, done, post) {
+ p.then(function() {
+ expect('this call').toBe('fail');
+ }, post).fin(done);
+ }
+
+ describe('constructions', function() {
+ it('should throw an exception with a path that is not a native blackberry project', function() {
+ exists.andReturn(false);
+ expect(function() {
+ new platforms.blackberry10.parser(proj);
+ }).toThrow();
+ });
+ it('should accept a proper native blackberry project path as construction parameter', function() {
+ var project;
+ expect(function() {
+ project = new platforms.blackberry10.parser(proj);
+ }).not.toThrow();
+ expect(project).toBeDefined();
+ });
+ });
+
+ describe('check_requirements', function() {
+ it('should fire a callback if the blackberry-deploy shell-out fails', function(done) {
+ sh.andCallFake(function(cmd, opts, cb) {
+ (cb || opts)(1, 'no bb-deploy dewd!');
+ });
+ errorWrapper(platforms.blackberry10.parser.check_requirements(proj), done, function(err) {
+ expect(err).toContain('no bb-deploy dewd');
+ });
+ });
+ it('should fire a callback with no error if shell out is successful', function(done) {
+ wrapper(platforms.blackberry10.parser.check_requirements(proj), done, function() {
+ expect(1).toBe(1);
+ });
+ });
+ });
+ describe('instance', function() {
+ var p, cp, rm, mkdir, is_cordova, write, read;
+ var bb_proj = path.join(proj, 'platforms', 'blackberry10');
+ beforeEach(function() {
+ p = new platforms.blackberry10.parser(bb_proj);
+ cp = spyOn(shell, 'cp');
+ rm = spyOn(shell, 'rm');
+ mkdir = spyOn(shell, 'mkdir');
+ is_cordova = spyOn(util, 'isCordova').andReturn(proj);
+ write = spyOn(fs, 'writeFileSync');
+ read = spyOn(fs, 'readFileSync');
+ });
+
+ describe('update_from_config method', function() {
+ var xml_name, xml_pkg, xml_version, xml_access_rm, xml_update, xml_append, xml_content;
+ beforeEach(function() {
+ xml_content = jasmine.createSpy('xml content');
+ xml_name = jasmine.createSpy('xml name');
+ xml_pkg = jasmine.createSpy('xml pkg');
+ xml_version = jasmine.createSpy('xml version');
+ xml_access_rm = jasmine.createSpy('xml access rm');
+ xml_access_add = jasmine.createSpy('xml access add');
+ xml_update = jasmine.createSpy('xml update');
+ xml_append = jasmine.createSpy('xml append');
+ xml_preference_remove = jasmine.createSpy('xml preference rm');
+ xml_preference_add = jasmine.createSpy('xml preference add');
+ p.xml.name = xml_name;
+ p.xml.packageName = xml_pkg;
+ p.xml.version = xml_version;
+ p.xml.content = xml_content;
+ p.xml.access = {
+ remove:xml_access_rm,
+ add: xml_access_add
+ };
+ p.xml.update = xml_update;
+ p.xml.doc = {
+ getroot:function() { return { append:xml_append}; }
+ };
+ p.xml.preference = {
+ add: xml_preference_add,
+ remove: xml_preference_remove
+ };
+ cfg.name = function() { return 'testname'; };
+ cfg.packageName = function() { return 'testpkg'; };
+ cfg.version = function() { return 'one point oh'; };
+ });
+ });
+ describe('www_dir method', function() {
+ it('should return /www', function() {
+ expect(p.www_dir()).toEqual(path.join(bb_proj, 'www'));
+ });
+ });
+ describe('config_xml method', function() {
+ it('should return the location of the config.xml', function() {
+ expect(p.config_xml()).toEqual(path.join(proj, 'platforms', 'blackberry10', 'www', 'config.xml'));
+ });
+ });
+ describe('update_www method', function() {
+
+ it('should rm project-level www and cp in platform agnostic www', function() {
+ p.update_www();
+ expect(rm).toHaveBeenCalled();
+ expect(cp).toHaveBeenCalled();
+ });
+ });
+ describe('update_overrides method', function() {
+ it('should do nothing if merges directory does not exist', function() {
+ exists.andReturn(false);
+ p.update_overrides();
+ expect(cp).not.toHaveBeenCalled();
+ });
+ it('should copy merges path into www', function() {
+ p.update_overrides();
+ expect(cp).toHaveBeenCalledWith('-rf', path.join(proj, 'merges', 'blackberry10', '*'), path.join(proj, 'platforms', 'blackberry10', 'www'));
+ });
+ });
+ describe('update_project method', function() {
+ var config, www, overrides, svn, parse, get_env, write_env;
+ beforeEach(function() {
+ config = spyOn(p, 'update_from_config');
+ www = spyOn(p, 'update_www');
+ overrides = spyOn(p, 'update_overrides');
+ svn = spyOn(util, 'deleteSvnFolders');
+ parse = spyOn(JSON, 'parse').andReturn({blackberry:{qnx:{}}});
+ });
+ it('should call update_from_config', function(done) {
+ wrapper(p.update_project(), done, function() {
+ expect(config).toHaveBeenCalled();
+ });
+ });
+ it('should throw if update_from_config throws', function(done) {
+ var err = new Error('uh oh!');
+ config.andCallFake(function() { throw err; });
+ errorWrapper(p.update_project({}), done, function(e) {
+ expect(e).toEqual(err);
+ });
+ });
+ it('should not call update_www', function(done) {
+ wrapper(p.update_project(), done, function() {
+ expect(www).not.toHaveBeenCalled();
+ });
+ });
+ it('should call update_overrides', function(done) {
+ wrapper(p.update_project(), done, function() {
+ expect(overrides).toHaveBeenCalled();
+ });
+ });
+ it('should call deleteSvnFolders', function(done) {
+ wrapper(p.update_project(), done, function() {
+ expect(svn).toHaveBeenCalled();
+ });
+ });
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b51e1c12/cordova-lib/spec-cordova/metadata/firefoxos_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/firefoxos_parser.spec.js b/cordova-lib/spec-cordova/metadata/firefoxos_parser.spec.js
new file mode 100644
index 0000000..49694eb
--- /dev/null
+++ b/cordova-lib/spec-cordova/metadata/firefoxos_parser.spec.js
@@ -0,0 +1,74 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+var platforms = require('../../platforms'),
+ util = require('../../src/util'),
+ path = require('path'),
+ shell = require('shelljs'),
+ fs = require('fs'),
+ config = require('../../src/config'),
+ ConfigParser = require('../../src/ConfigParser'),
+ cordova = require('../../cordova');
+
+var cfg = new ConfigParser(path.join(__dirname, '..', 'test-config.xml'));
+describe('firefoxos project parser', function() {
+ var proj = path.join('some', 'path');
+ var exists, exec, custom;
+ beforeEach(function() {
+ exists = spyOn(fs, 'existsSync').andReturn(true);
+ exec = spyOn(shell, 'exec').andCallFake(function(cmd, opts, cb) {
+ cb(0, '');
+ });
+ custom = spyOn(config, 'has_custom_path').andReturn(false);
+ });
+
+ describe('constructions', function() {
+ it('should create an instance with a path', function() {
+ expect(function() {
+ var p = new platforms.android.parser(proj);
+ expect(p.path).toEqual(proj);
+ }).not.toThrow();
+ });
+ });
+
+ describe('instance', function() {
+ var p, cp, rm, is_cordova, write, read;
+ var ff_proj = path.join(proj, 'platforms', 'firefoxos');
+ beforeEach(function() {
+ p = new platforms.firefoxos.parser(ff_proj);
+ cp = spyOn(shell, 'cp');
+ rm = spyOn(shell, 'rm');
+ is_cordova = spyOn(util, 'isCordova').andReturn(proj);
+ write = spyOn(fs, 'writeFileSync');
+ read = spyOn(fs, 'readFileSync').andReturn('');
+ });
+
+ describe('update_from_config method', function() {
+ beforeEach(function() {
+ cfg.name = function() { return 'testname'; };
+ cfg.packageName = function() { return 'testpkg'; };
+ cfg.version = function() { return '1.0'; };
+ });
+
+ /* it('should write manifest.webapp', function() {
+ //p.update_from_config(cfg);
+ //expect(write.mostRecentCall.args[0]).toEqual('manifest.webapp');
+ });*/
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b51e1c12/cordova-lib/spec-cordova/metadata/ios_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/ios_parser.spec.js b/cordova-lib/spec-cordova/metadata/ios_parser.spec.js
new file mode 100644
index 0000000..5b2977e
--- /dev/null
+++ b/cordova-lib/spec-cordova/metadata/ios_parser.spec.js
@@ -0,0 +1,199 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+var platforms = require('../../platforms'),
+ util = require('../../src/util'),
+ path = require('path'),
+ shell = require('shelljs'),
+ plist = require('plist-with-patches'),
+ xcode = require('xcode'),
+ et = require('elementtree'),
+ fs = require('fs'),
+ Q = require('q'),
+ config = require('../../src/config'),
+ ConfigParser = require('../../src/ConfigParser'),
+ cordova = require('../../cordova');
+
+// Create a real config object before mocking out everything.
+var cfg = new ConfigParser(path.join(__dirname, '..', 'test-config.xml'));
+
+describe('ios project parser', function () {
+ var proj = path.join('some', 'path');
+ var custom, readdir;
+ beforeEach(function() {
+ custom = spyOn(config, 'has_custom_path').andReturn(false);
+ readdir = spyOn(fs, 'readdirSync').andReturn(['test.xcodeproj']);
+ });
+
+ function wrapper(p, done, post) {
+ p.then(post, function(err) {
+ expect(err).toBeUndefined();
+ }).fin(done);
+ }
+
+ function errorWrapper(p, done, post) {
+ p.then(function() {
+ expect('this call').toBe('fail');
+ }, post).fin(done);
+ }
+
+ describe('constructions', function() {
+ it('should throw if provided directory does not contain an xcodeproj file', function() {
+ readdir.andReturn(['noxcodehere']);
+ expect(function() {
+ new platforms.ios.parser(proj);
+ }).toThrow();
+ });
+ it('should create an instance with path, pbxproj, xcodeproj, originalName and cordovaproj properties', function() {
+ expect(function() {
+ var p = new platforms.ios.parser(proj);
+ expect(p.path).toEqual(proj);
+ expect(p.pbxproj).toEqual(path.join(proj, 'test.xcodeproj', 'project.pbxproj'));
+ expect(p.xcodeproj).toEqual(path.join(proj, 'test.xcodeproj'));
+ }).not.toThrow();
+ });
+ });
+
+ describe('instance', function() {
+ var p, cp, rm, mkdir, is_cordova, write, read;
+ var ios_proj = path.join(proj, 'platforms', 'ios');
+ beforeEach(function() {
+ p = new platforms.ios.parser(ios_proj);
+ cp = spyOn(shell, 'cp');
+ rm = spyOn(shell, 'rm');
+ mkdir = spyOn(shell, 'mkdir');
+ is_cordova = spyOn(util, 'isCordova').andReturn(proj);
+ write = spyOn(fs, 'writeFileSync');
+ read = spyOn(fs, 'readFileSync').andReturn('');
+ });
+
+ describe('update_from_config method', function() {
+ var mv;
+ var cfg_access_add, cfg_access_rm, cfg_pref_add, cfg_pref_rm, cfg_content;
+ var plist_parse, plist_build, xc;
+ var update_name, xc_write;
+ beforeEach(function() {
+ mv = spyOn(shell, 'mv');
+ plist_parse = spyOn(plist, 'parseFileSync').andReturn({
+ });
+ plist_build = spyOn(plist, 'build').andReturn('');
+ update_name = jasmine.createSpy('update_name');
+ xc_write = jasmine.createSpy('xcode writeSync');
+ xc = spyOn(xcode, 'project').andReturn({
+ parse:function(cb) {cb();},
+ updateProductName:update_name,
+ writeSync:xc_write
+ });
+ cfg.name = function() { return 'testname' };
+ cfg.packageName = function() { return 'testpkg' };
+ cfg.version = function() { return 'one point oh' };
+ p = new platforms.ios.parser(ios_proj);
+ });
+
+ it('should update the app name in pbxproj by calling xcode.updateProductName, and move the ios native files to match the new name', function(done) {
+ var test_path = path.join(proj, 'platforms', 'ios', 'test');
+ var testname_path = path.join(proj, 'platforms', 'ios', 'testname');
+ wrapper(p.update_from_config(cfg), done, function() {
+ expect(update_name).toHaveBeenCalledWith('testname');
+ expect(mv).toHaveBeenCalledWith(path.join(test_path, 'test-Info.plist'), path.join(test_path, 'testname-Info.plist'));
+ expect(mv).toHaveBeenCalledWith(path.join(test_path, 'test-Prefix.pch'), path.join(test_path, 'testname-Prefix.pch'));
+ expect(mv).toHaveBeenCalledWith(test_path + '.xcodeproj', testname_path + '.xcodeproj');
+ expect(mv).toHaveBeenCalledWith(test_path, testname_path);
+ });
+ });
+ it('should write out the app id to info plist as CFBundleIdentifier', function(done) {
+ wrapper(p.update_from_config(cfg), done, function() {
+ expect(plist_build.mostRecentCall.args[0].CFBundleIdentifier).toEqual('testpkg');
+ });
+ });
+ it('should write out the app version to info plist as CFBundleVersion', function(done) {
+ wrapper(p.update_from_config(cfg), done, function() {
+ expect(plist_build.mostRecentCall.args[0].CFBundleShortVersionString).toEqual('one point oh');
+ });
+ });
+ });
+ describe('www_dir method', function() {
+ it('should return /www', function() {
+ expect(p.www_dir()).toEqual(path.join(ios_proj, 'www'));
+ });
+ });
+ describe('config_xml method', function() {
+ it('should return the location of the config.xml', function() {
+ expect(p.config_xml()).toEqual(path.join(ios_proj, 'test', 'config.xml'));
+ });
+ });
+ describe('update_www method', function() {
+ it('should rm project-level www and cp in platform agnostic www', function() {
+ p.update_www(path.join('lib','dir'));
+ expect(rm).toHaveBeenCalled();
+ expect(cp).toHaveBeenCalled();
+ });
+ });
+ describe('update_overrides method', function() {
+ var exists;
+ beforeEach(function() {
+ exists = spyOn(fs, 'existsSync').andReturn(true);
+ });
+ it('should do nothing if merges directory does not exist', function() {
+ exists.andReturn(false);
+ p.update_overrides();
+ expect(cp).not.toHaveBeenCalled();
+ });
+ it('should copy merges path into www', function() {
+ p.update_overrides();
+ expect(cp).toHaveBeenCalled();
+ });
+ });
+ describe('update_project method', function() {
+ var config, www, overrides, svn;
+ beforeEach(function() {
+ config = spyOn(p, 'update_from_config').andReturn(Q());
+ www = spyOn(p, 'update_www');
+ overrides = spyOn(p, 'update_overrides');
+ svn = spyOn(util, 'deleteSvnFolders');
+ });
+ it('should call update_from_config', function(done) {
+ wrapper(p.update_project(), done, function() {
+ expect(config).toHaveBeenCalled();
+ });
+ });
+ it('should throw if update_from_config errors', function(done) {
+ var e = new Error('uh oh!');
+ config.andReturn(Q.reject(e));
+ errorWrapper(p.update_project({}), done, function(err) {
+ expect(err).toEqual(e);
+ });
+ });
+ it('should not call update_www', function(done) {
+ wrapper(p.update_project({}), done, function() {
+ expect(www).not().toHaveBeenCalled();
+ });
+ });
+ it('should call update_overrides', function(done) {
+ wrapper(p.update_project(), done, function() {
+ expect(overrides).toHaveBeenCalled();
+ });
+ });
+ it('should call deleteSvnFolders', function(done) {
+ wrapper(p.update_project(), done, function() {
+ expect(svn).toHaveBeenCalled();
+ });
+ });
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b51e1c12/cordova-lib/spec-cordova/metadata/windows8_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/windows8_parser.spec.js b/cordova-lib/spec-cordova/metadata/windows8_parser.spec.js
new file mode 100644
index 0000000..726391f
--- /dev/null
+++ b/cordova-lib/spec-cordova/metadata/windows8_parser.spec.js
@@ -0,0 +1,189 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var platforms = require('../../platforms'),
+ util = require('../../src/util'),
+ path = require('path'),
+ shell = require('shelljs'),
+ child_process = require('child_process'),
+ xmlHelpers = require('../../src/xml-helpers'),
+ et = require('elementtree'),
+ Q = require('q'),
+ fs = require('fs'),
+ config = require('../../src/config'),
+ ConfigParser = require('../../src/ConfigParser'),
+ cordova = require('../../cordova');
+
+// Create a real config object before mocking out everything.
+var cfg = new ConfigParser(path.join(__dirname, '..', 'test-config.xml'));
+
+describe('windows8 project parser', function() {
+
+ var proj = '/some/path';
+ var exists, exec, custom, readdir, cfg_parser;
+ var winXml;
+ beforeEach(function() {
+ exists = spyOn(fs, 'existsSync').andReturn(true);
+ exec = spyOn(child_process, 'exec').andCallFake(function(cmd, opts, cb) {
+ if (!cb) cb = opts;
+ cb(null, '', '');
+ });
+ custom = spyOn(config, 'has_custom_path').andReturn(false);
+ readdir = spyOn(fs, 'readdirSync').andReturn(['test.jsproj']);
+ winXml = null;
+ spyOn(xmlHelpers, 'parseElementtreeSync').andCallFake(function(path) {
+ return winXml = new et.ElementTree(et.XML('<foo><Application/><Identity/><VisualElements><a/></VisualElements><Capabilities><a/></Capabilities></foo>'));
+ });
+ });
+
+ function wrapper(promise, done, post) {
+ promise.then(post, function(err) {
+ expect(err).toBeUndefined();
+ }).fin(done);
+ }
+
+ function errorWrapper(promise, done, post) {
+ promise.then(function() {
+ expect('this call').toBe('fail');
+ }, post).fin(done);
+ }
+
+ describe('constructions', function() {
+ it('should throw if provided directory does not contain a jsproj file', function() {
+ readdir.andReturn([]);
+ expect(function() {
+ new platforms.windows8.parser(proj);
+ }).toThrow();
+ });
+ it('should create an instance with path, manifest properties', function() {
+ expect(function() {
+ var parser = new platforms.windows8.parser(proj);
+ expect(parser.windows8_proj_dir).toEqual(proj);
+ expect(parser.manifest_path).toEqual(path.join(proj, 'package.appxmanifest'));
+ }).not.toThrow();
+ });
+ });
+
+ describe('check_requirements', function() {
+ it('should fire a callback if there is an error during shelling out', function(done) {
+ exec.andCallFake(function(cmd, opts, cb) {
+ if (!cb) cb = opts;
+ cb(50, 'there was an errorz!', '');
+ });
+ errorWrapper(platforms.windows8.parser.check_requirements(proj), done, function(err) {
+ expect(err).toContain('there was an errorz!');
+ });
+ });
+ it('should check by calling check_reqs on the stock lib path if no custom path is defined', function(done) {
+ wrapper(platforms.windows8.parser.check_requirements(proj), done, function() {
+ expect(exec.mostRecentCall.args[0]).toContain(util.libDirectory);
+ expect(exec.mostRecentCall.args[0]).toMatch(/check_reqs"$/);
+ });
+ });
+ it('should check by calling check_reqs on a custom path if it is so defined', function(done) {
+ var custom_path = path.join('some','custom','path','to','windows8','lib');
+ custom.andReturn(custom_path);
+ wrapper(platforms.windows8.parser.check_requirements(proj),done, function() {
+ expect(exec.mostRecentCall.args[0]).toContain(custom_path);
+ expect(exec.mostRecentCall.args[0]).toMatch(/check_reqs"$/);
+ });
+ done();
+ });
+ });
+
+ describe('instance', function() {
+ var parser, cp, rm, is_cordova, write, read, mv, mkdir;
+ var windows8_proj = path.join(proj, 'platforms', 'windows8');
+ beforeEach(function() {
+ parser = new platforms.windows8.parser(windows8_proj);
+ cp = spyOn(shell, 'cp');
+ rm = spyOn(shell, 'rm');
+ mv = spyOn(shell, 'mv');
+ mkdir = spyOn(shell, 'mkdir');
+ is_cordova = spyOn(util, 'isCordova').andReturn(proj);
+ write = spyOn(fs, 'writeFileSync');
+ read = spyOn(fs, 'readFileSync').andReturn('');
+ });
+
+ describe('update_from_config method', function() {
+ beforeEach(function() {
+ cfg.name = function() { return 'testname' };
+ cfg.content = function() { return 'index.html' };
+ cfg.packageName = function() { return 'testpkg' };
+ cfg.version = function() { return 'one point oh' };
+ readdir.andReturn(['test.sln']);
+ });
+
+ it('should write out the app name to package.appxmanifest', function() {
+ parser.update_from_config(cfg);
+ var identityNode = winXml.getroot().find('.//Identity');
+ expect(identityNode.attrib.Name).toEqual(cfg.packageName());
+ });
+
+ it('should write out the app version to package.appxmanifest', function() {
+ parser.update_from_config(cfg);
+ var identityNode = winXml.getroot().find('.//Identity');
+ expect(identityNode.attrib.Version).toEqual('one point oh');
+ });
+ });
+
+ describe('www_dir method', function() {
+ it('should return www', function() {
+ expect(parser.www_dir()).toEqual(path.join(windows8_proj, 'www'));
+ });
+ });
+ describe('update_www method', function() {
+ var update_jsproj;
+ beforeEach(function() {
+ update_jsproj = spyOn(parser, 'update_jsproj');
+ });
+ it('should rm project-level www and cp in platform agnostic www', function() {
+ parser.update_www(path.join('lib','dir'));
+ expect(rm).toHaveBeenCalled();
+ expect(cp).toHaveBeenCalled();
+ });
+ });
+ describe('update_project method', function() {
+ var config, www, overrides, svn;
+ beforeEach(function() {
+ config = spyOn(parser, 'update_from_config');
+ www = spyOn(parser, 'update_www');
+ www = spyOn(parser, 'update_jsproj');
+ svn = spyOn(util, 'deleteSvnFolders');
+ exists.andReturn(false);
+ });
+ it('should call update_from_config', function() {
+ parser.update_project();
+ expect(config).toHaveBeenCalled();
+ });
+ it('should throw if update_from_config throws', function(done) {
+ var err = new Error('uh oh!');
+ config.andCallFake(function() { throw err; });
+ errorWrapper(parser.update_project({}), done, function(err) {
+ expect(err).toEqual(err);
+ });
+ });
+ it('should call deleteSvnFolders', function(done) {
+ wrapper(parser.update_project(), done, function() {
+ expect(svn).toHaveBeenCalled();
+ });
+ });
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b51e1c12/cordova-lib/spec-cordova/metadata/wp7_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/wp7_parser.spec.js b/cordova-lib/spec-cordova/metadata/wp7_parser.spec.js
new file mode 100644
index 0000000..0856391
--- /dev/null
+++ b/cordova-lib/spec-cordova/metadata/wp7_parser.spec.js
@@ -0,0 +1,208 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var platforms = require('../../platforms'),
+ util = require('../../src/util'),
+ path = require('path'),
+ shell = require('shelljs'),
+ fs = require('fs'),
+ et = require('elementtree'),
+ xmlHelpers = require('../../src/xml-helpers'),
+ Q = require('q'),
+ child_process = require('child_process'),
+ config = require('../../src/config'),
+ ConfigParser = require('../../src/ConfigParser'),
+ CordovaError = require('../../src/CordovaError'),
+ cordova = require('../../cordova');
+
+// Create a real config object before mocking out everything.
+var cfg = new ConfigParser(path.join(__dirname, '..', 'test-config.xml'));
+
+describe('wp7 project parser', function() {
+ var proj = '/some/path';
+ var exists, exec, custom, readdir, cfg_parser;
+ var projXml, manifestXml;
+ beforeEach(function() {
+ exists = spyOn(fs, 'existsSync').andReturn(true);
+ exec = spyOn(child_process, 'exec').andCallFake(function(cmd, opts, cb) {
+ (cb || opts)(0, '', '');
+ });
+ custom = spyOn(config, 'has_custom_path').andReturn(false);
+ readdir = spyOn(fs, 'readdirSync').andReturn(['test.csproj']);
+ projXml = manifestXml = null;
+ spyOn(xmlHelpers, 'parseElementtreeSync').andCallFake(function(path) {
+ if (/WMAppManifest.xml$/.exec(path)) {
+ return manifestXml = new et.ElementTree(et.XML('<foo><App Title="s"><PrimaryToken /><RootNamespace/><SilverlightAppEntry/><XapFilename/><AssemblyName/></App></foo>'));
+ } else if (/csproj$/.exec(path)) {
+ return projXml = new et.ElementTree(et.XML('<foo><App Title="s"><PrimaryToken /><RootNamespace/><SilverlightAppEntry/><XapFilename/><AssemblyName/></App></foo>'));
+ } else if (/xaml$/.exec(path)) {
+ return new et.ElementTree(et.XML('<foo><App Title="s"><PrimaryToken /><RootNamespace/><SilverlightAppEntry/><XapFilename/><AssemblyName/></App></foo>'));
+ } else {
+ throw new CordovaError('Unexpected parseElementtreeSync: ' + path);
+ }
+ });
+ });
+
+ function wrapper(p, done, post) {
+ p.then(post, function(err) {
+ expect(err).toBeUndefined();
+ }).fin(done);
+ }
+
+ function errorWrapper(p, done, post) {
+ p.then(function() {
+ expect('this call').toBe('fail');
+ }, post).fin(done);
+ }
+
+ describe('constructions', function() {
+ it('should throw if provided directory does not contain a csproj file', function() {
+ readdir.andReturn([]);
+ expect(function() {
+ new platforms.wp7.parser(proj);
+ }).toThrow();
+ });
+ it('should create an instance with path, manifest properties', function() {
+ expect(function() {
+ var p = new platforms.wp7.parser(proj);
+ expect(p.wp7_proj_dir).toEqual(proj);
+ expect(p.manifest_path).toEqual(path.join(proj, 'Properties', 'WMAppManifest.xml'));
+ }).not.toThrow();
+ });
+ });
+
+ describe('check_requirements', function() {
+ it('should fire a callback if there is an error during shelling out', function(done) {
+ exec.andCallFake(function(cmd, opts, cb) {
+ (cb || opts)(50, 'there was an errorz!');
+ });
+ errorWrapper(platforms.wp7.parser.check_requirements(proj), done, function(err) {
+ expect(err).toContain('there was an errorz!');
+ });
+ });
+ it('should check by calling check_reqs on the stock lib path if no custom path is defined', function(done) {
+ wrapper(platforms.wp7.parser.check_requirements(proj), done, function(err) {
+ expect(exec.mostRecentCall.args[0]).toContain(util.libDirectory);
+ expect(exec.mostRecentCall.args[0]).toMatch(/check_reqs"$/);
+ });
+ });
+ it('should check by calling check_reqs on a custom path if it is so defined', function(done) {
+ var custom_path = path.join('some','custom','path','to','wp7','lib');
+ custom.andReturn(custom_path);
+ wrapper(platforms.wp7.parser.check_requirements(proj), done, function() {
+ expect(exec.mostRecentCall.args[0]).toContain(custom_path);
+ expect(exec.mostRecentCall.args[0]).toMatch(/check_reqs"$/);
+ });
+ });
+ });
+
+ describe('instance', function() {
+ var p, cp, rm, is_cordova, write, read, mv, mkdir;
+ var wp7_proj = path.join(proj, 'platforms', 'wp7');
+ beforeEach(function() {
+ p = new platforms.wp7.parser(wp7_proj);
+ cp = spyOn(shell, 'cp');
+ rm = spyOn(shell, 'rm');
+ mv = spyOn(shell, 'mv');
+ mkdir = spyOn(shell, 'mkdir');
+ is_cordova = spyOn(util, 'isCordova').andReturn(proj);
+ write = spyOn(fs, 'writeFileSync');
+ read = spyOn(fs, 'readFileSync').andReturn('');
+ });
+
+ describe('update_from_config method', function() {
+ beforeEach(function() {
+ cfg.name = function() { return 'testname' };
+ cfg.content = function() { return 'index.html' };
+ cfg.packageName = function() { return 'testpkg' };
+ cfg.version = function() { return 'one point oh' };
+ readdir.andReturn(['test.sln']);
+ });
+
+ it('should write out the app name to wmappmanifest.xml', function() {
+ p.update_from_config(cfg);
+ var appEl = manifestXml.getroot().find('.//App');
+ expect(appEl.attrib.Title).toEqual('testname');
+ });
+ it('should write out the app id to csproj file', function() {
+ p.update_from_config(cfg);
+ var appEl = projXml.getroot().find('.//RootNamespace');
+ expect(appEl.text).toContain('testpkg');
+ });
+ it('should write out the app version to wmappmanifest.xml', function() {
+ p.update_from_config(cfg);
+ var appEl = manifestXml.getroot().find('.//App');
+ expect(appEl.attrib.Version).toEqual('one point oh');
+ });
+ });
+ describe('www_dir method', function() {
+ it('should return www', function() {
+ expect(p.www_dir()).toEqual(path.join(wp7_proj, 'www'));
+ });
+ });
+ describe('config_xml method', function() {
+ it('should return the location of the config.xml', function() {
+ expect(p.config_xml()).toEqual(path.join(wp7_proj, 'config.xml'));
+ });
+ });
+ describe('update_www method', function() {
+ var update_csproj;
+ beforeEach(function() {
+ update_csproj = spyOn(p, 'update_csproj');
+ });
+ it('should rm project-level www and cp in platform agnostic www', function() {
+ p.update_www();
+ expect(rm).toHaveBeenCalled();
+ expect(cp).toHaveBeenCalled();
+ });
+ });
+ describe('update_project method', function() {
+ var config, www, overrides, svn, cfg, csproj;
+ beforeEach(function() {
+ config = spyOn(p, 'update_from_config');
+ www = spyOn(p, 'update_www');
+ svn = spyOn(util, 'deleteSvnFolders');
+ csproj = spyOn(p, 'update_csproj');
+ exists.andReturn(false);
+ });
+ it('should call update_from_config', function(done) {
+ wrapper(p.update_project(), done, function(){
+ expect(config).toHaveBeenCalled();
+ });
+ });
+ it('should throw if update_from_config throws', function(done) {
+ var err = new Error('uh oh!');
+ config.andCallFake(function() { throw err; });
+ errorWrapper(p.update_project({}), done, function(e) {
+ expect(e).toEqual(err);
+ });
+ });
+ it('should call update_www', function(done) {
+ wrapper(p.update_project(), done, function() {
+ expect(www).not.toHaveBeenCalled();
+ });
+ });
+ it('should call deleteSvnFolders', function(done) {
+ wrapper(p.update_project(), done, function() {
+ expect(svn).toHaveBeenCalled();
+ });
+ });
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b51e1c12/cordova-lib/spec-cordova/metadata/wp8_parser.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/metadata/wp8_parser.spec.js b/cordova-lib/spec-cordova/metadata/wp8_parser.spec.js
new file mode 100644
index 0000000..5ea461e
--- /dev/null
+++ b/cordova-lib/spec-cordova/metadata/wp8_parser.spec.js
@@ -0,0 +1,208 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var platforms = require('../../platforms'),
+ util = require('../../src/util'),
+ path = require('path'),
+ shell = require('shelljs'),
+ fs = require('fs'),
+ et = require('elementtree'),
+ xmlHelpers = require('../../src/xml-helpers'),
+ Q = require('q'),
+ child_process = require('child_process'),
+ config = require('../../src/config'),
+ ConfigParser = require('../../src/ConfigParser'),
+ CordovaError = require('../../src/CordovaError'),
+ cordova = require('../../cordova');
+
+// Create a real config object before mocking out everything.
+var cfg = new ConfigParser(path.join(__dirname, '..', 'test-config.xml'));
+
+describe('wp8 project parser', function() {
+ var proj = '/some/path';
+ var exists, exec, custom, readdir, cfg_parser;
+ var manifestXml, projXml;
+ beforeEach(function() {
+ exists = spyOn(fs, 'existsSync').andReturn(true);
+ exec = spyOn(child_process, 'exec').andCallFake(function(cmd, opts, cb) {
+ (cb || opts)(0, '', '');
+ });
+ custom = spyOn(config, 'has_custom_path').andReturn(false);
+ readdir = spyOn(fs, 'readdirSync').andReturn(['test.csproj']);
+ projXml = manifestXml = null;
+ spyOn(xmlHelpers, 'parseElementtreeSync').andCallFake(function(path) {
+ if (/WMAppManifest.xml$/.exec(path)) {
+ return manifestXml = new et.ElementTree(et.XML('<foo><App Title="s"><PrimaryToken /><RootNamespace/><SilverlightAppEntry/><XapFilename/><AssemblyName/></App></foo>'));
+ } else if (/csproj$/.exec(path)) {
+ return projXml = new et.ElementTree(et.XML('<foo><App Title="s"><PrimaryToken /><RootNamespace/><SilverlightAppEntry/><XapFilename/><AssemblyName/></App></foo>'));
+ } else if (/xaml$/.exec(path)) {
+ return new et.ElementTree(et.XML('<foo><App Title="s"><PrimaryToken /><RootNamespace/><SilverlightAppEntry/><XapFilename/><AssemblyName/></App></foo>'));
+ } else {
+ throw new CordovaError('Unexpected parseElementtreeSync: ' + path);
+ }
+ });
+ });
+
+ function wrapper(p, done, post) {
+ p.then(post, function(err) {
+ expect(err).toBeUndefined();
+ }).fin(done);
+ }
+
+ function errorWrapper(p, done, post) {
+ p.then(function() {
+ expect('this call').toBe('fail');
+ }, post).fin(done);
+ }
+
+ describe('constructions', function() {
+ it('should throw if provided directory does not contain a csproj file', function() {
+ readdir.andReturn([]);
+ expect(function() {
+ new platforms.wp8.parser(proj);
+ }).toThrow();
+ });
+ it('should create an instance with path, manifest properties', function() {
+ expect(function() {
+ var p = new platforms.wp8.parser(proj);
+ expect(p.wp8_proj_dir).toEqual(proj);
+ expect(p.manifest_path).toEqual(path.join(proj, 'Properties', 'WMAppManifest.xml'));
+ }).not.toThrow();
+ });
+ });
+
+ describe('check_requirements', function() {
+ it('should fire a callback if there is an error during shelling out', function(done) {
+ exec.andCallFake(function(cmd, opts, cb) {
+ (cb || opts)(50, 'there was an errorz!');
+ });
+ errorWrapper(platforms.wp8.parser.check_requirements(proj), done, function(err) {
+ expect(err).toContain('there was an errorz!');
+ });
+ });
+ it('should check by calling check_reqs on the stock lib path if no custom path is defined', function(done) {
+ wrapper(platforms.wp8.parser.check_requirements(proj), done, function() {
+ expect(exec.mostRecentCall.args[0]).toContain(util.libDirectory);
+ expect(exec.mostRecentCall.args[0]).toMatch(/check_reqs"$/);
+ });
+ });
+ it('should check by calling check_reqs on a custom path if it is so defined', function(done) {
+ var custom_path = path.join('some','custom','path','to','wp8','lib');
+ custom.andReturn(custom_path);
+ wrapper(platforms.wp8.parser.check_requirements(proj), done, function(err) {
+ expect(exec.mostRecentCall.args[0]).toContain(custom_path);
+ expect(exec.mostRecentCall.args[0]).toMatch(/check_reqs"$/);
+ });
+ });
+ });
+
+ describe('instance', function() {
+ var p, cp, rm, is_cordova, write, read, mv, mkdir;
+ var wp8_proj = path.join(proj, 'platforms', 'wp8');
+ beforeEach(function() {
+ p = new platforms.wp8.parser(wp8_proj);
+ cp = spyOn(shell, 'cp');
+ rm = spyOn(shell, 'rm');
+ mv = spyOn(shell, 'mv');
+ mkdir = spyOn(shell, 'mkdir');
+ is_cordova = spyOn(util, 'isCordova').andReturn(proj);
+ write = spyOn(fs, 'writeFileSync');
+ read = spyOn(fs, 'readFileSync').andReturn('');
+ });
+
+ describe('update_from_config method', function() {
+ beforeEach(function() {
+ cfg.name = function() { return 'testname' };
+ cfg.content = function() { return 'index.html' };
+ cfg.packageName = function() { return 'testpkg' };
+ cfg.version = function() { return 'one point oh' };
+ readdir.andReturn(['test.sln']);
+ });
+
+ it('should write out the app name to wmappmanifest.xml', function() {
+ p.update_from_config(cfg);
+ var appEl = manifestXml.getroot().find('.//App');
+ expect(appEl.attrib.Title).toEqual('testname');
+ });
+ it('should write out the app id to csproj file', function() {
+ p.update_from_config(cfg);
+ var appEl = projXml.getroot().find('.//RootNamespace');
+ expect(appEl.text).toContain('testpkg');
+ });
+ it('should write out the app version to wmappmanifest.xml', function() {
+ p.update_from_config(cfg);
+ var appEl = manifestXml.getroot().find('.//App');
+ expect(appEl.attrib.Version).toEqual('one point oh');
+ });
+ });
+ describe('www_dir method', function() {
+ it('should return www', function() {
+ expect(p.www_dir()).toEqual(path.join(wp8_proj, 'www'));
+ });
+ });
+ describe('config_xml method', function() {
+ it('should return the location of the config.xml', function() {
+ expect(p.config_xml()).toEqual(path.join(wp8_proj, 'config.xml'));
+ });
+ });
+ describe('update_www method', function() {
+ var update_csproj;
+ beforeEach(function() {
+ update_csproj = spyOn(p, 'update_csproj');
+ });
+ it('should rm project-level www and cp in platform agnostic www', function() {
+ p.update_www();
+ expect(rm).toHaveBeenCalled();
+ expect(cp).toHaveBeenCalled();
+ });
+ });
+ describe('update_project method', function() {
+ var config, www, overrides, svn, csproj;
+ beforeEach(function() {
+ config = spyOn(p, 'update_from_config');
+ www = spyOn(p, 'update_www');
+ svn = spyOn(util, 'deleteSvnFolders');
+ csproj = spyOn(p, 'update_csproj');
+ exists.andReturn(false);
+ });
+ it('should call update_from_config', function(done) {
+ wrapper(p.update_project(), done, function() {
+ expect(config).toHaveBeenCalled();
+ });
+ });
+ it('should throw if update_from_config throws', function(done) {
+ var err = new Error('uh oh!');
+ config.andCallFake(function() { throw err; });
+ errorWrapper(p.update_project({}), done, function(e) {
+ expect(e).toEqual(err);
+ });
+ });
+ it('should not call update_www', function(done) {
+ wrapper(p.update_project(), done, function() {
+ expect(www).not.toHaveBeenCalled();
+ });
+ });
+ it('should call deleteSvnFolders', function(done) {
+ wrapper(p.update_project(), done, function() {
+ expect(svn).toHaveBeenCalled();
+ });
+ });
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/b51e1c12/cordova-lib/spec-cordova/platform.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/platform.spec.js b/cordova-lib/spec-cordova/platform.spec.js
new file mode 100644
index 0000000..e16d51d
--- /dev/null
+++ b/cordova-lib/spec-cordova/platform.spec.js
@@ -0,0 +1,108 @@
+
+var helpers = require('./helpers'),
+ path = require('path'),
+ fs = require('fs'),
+ shell = require('shelljs'),
+ platforms = require('../platforms'),
+ superspawn = require('../src/superspawn'),
+ config = require('../src/config'),
+ Q = require('q'),
+ events = require('../src/events'),
+ cordova = require('../cordova');
+
+var tmpDir = helpers.tmpDir('platform_test');
+var project = path.join(tmpDir, 'project');
+
+var platformParser = platforms[helpers.testPlatform].parser;
+
+describe('platform end-to-end', function() {
+ var results;
+
+ beforeEach(function() {
+ shell.rm('-rf', tmpDir);
+ });
+ afterEach(function() {
+ process.chdir(path.join(__dirname, '..')); // Needed to rm the dir on Windows.
+ shell.rm('-rf', tmpDir);
+ });
+
+ // Factoring out some repeated checks.
+ function emptyPlatformList() {
+ return cordova.raw.platform('list').then(function() {
+ var installed = results.match(/Installed platforms: (.*)/);
+ expect(installed).toBeDefined();
+ expect(installed[1].indexOf(helpers.testPlatform)).toBe(-1);
+ });
+ }
+
+ function fullPlatformList() {
+ return cordova.raw.platform('list').then(function() {
+ var installed = results.match(/Installed platforms: (.*)/);
+ expect(installed).toBeDefined();
+ expect(installed[1].indexOf(helpers.testPlatform)).toBeGreaterThan(-1);
+ });
+ }
+
+ // The flows we want to test are add, rm, list, and upgrade.
+ // They should run the appropriate hooks.
+ // They should fail when not inside a Cordova project.
+ // These tests deliberately have no beforeEach and afterEach that are cleaning things up.
+ it('should successfully run', function(done) {
+ // cp then mv because we need to copy everything, but that means it'll copy the whole directory.
+ // Using /* doesn't work because of hidden files.
+ shell.cp('-R', path.join(__dirname, 'fixtures', 'base'), tmpDir);
+ shell.mv(path.join(tmpDir, 'base'), project);
+ process.chdir(project);
+
+ // Now we load the config.json in the newly created project and edit the target platform's lib entry
+ // to point at the fixture version. This is necessary so that cordova.prepare can find cordova.js there.
+ var c = config.read(project);
+ c.lib[helpers.testPlatform].uri = path.join(__dirname, 'fixtures', 'platforms', helpers.testPlatform + '-lib');
+ config.write(project, c);
+
+ // The config.json in the fixture project points at fake "local" paths.
+ // Since it's not a URL, the lazy-loader will just return the junk path.
+ spyOn(superspawn, 'spawn').andCallFake(function(cmd, args) {
+ if (cmd.match(/create\b/)) {
+ // This is a call to the bin/create script, so do the copy ourselves.
+ shell.cp('-R', path.join(__dirname, 'fixtures', 'platforms', 'android'), path.join(project, 'platforms'));
+ } else if(cmd.match(/version\b/)) {
+ return Q('3.3.0');
+ } else if(cmd.match(/update\b/)) {
+ fs.writeFileSync(path.join(project, 'platforms', helpers.testPlatform, 'updated'), 'I was updated!', 'utf-8');
+ }
+ return Q();
+ });
+
+ events.on('results', function(res) { results = res; });
+
+ // Check there are no platforms yet.
+ emptyPlatformList().then(function() {
+ // Add the testing platform.
+ return cordova.raw.platform('add', [helpers.testPlatform]);
+ }).then(function() {
+ // Check the platform add was successful.
+ expect(path.join(project, 'platforms', helpers.testPlatform)).toExist();
+ expect(path.join(project, 'merges', helpers.testPlatform)).toExist();
+ expect(path.join(project, 'platforms', helpers.testPlatform, 'cordova')).toExist();
+ }).then(fullPlatformList) // Check for it in platform ls.
+ .then(function() {
+ // Try to update the platform.
+ return cordova.raw.platform('update', [helpers.testPlatform]);
+ }).then(function() {
+ // Our fake update script in the exec mock above creates this dummy file.
+ expect(path.join(project, 'platforms', helpers.testPlatform, 'updated')).toExist();
+ }).then(fullPlatformList) // Platform should still be in platform ls.
+ .then(function() {
+ // And now remove it.
+ return cordova.raw.platform('rm', [helpers.testPlatform]);
+ }).then(function() {
+ // It should be gone.
+ expect(path.join(project, 'platforms', helpers.testPlatform)).not.toExist();
+ }).then(emptyPlatformList) // platform ls should be empty too.
+ .fail(function(err) {
+ expect(err).toBeUndefined();
+ }).fin(done);
+ });
+});
+