http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/58047a3d/node_modules/winjs/package.json ---------------------------------------------------------------------- diff --git a/node_modules/winjs/package.json b/node_modules/winjs/package.json index 50dd0d2..938812a 100644 --- a/node_modules/winjs/package.json +++ b/node_modules/winjs/package.json @@ -2,7 +2,7 @@ "name": "winjs", "title": "Windows Library for JavaScript (WinJS)", "description": "WinJS is a set of JavaScript toolkits that allow developers to build applications using HTML/JS/CSS technology.", - "version": "4.0.1", + "version": "4.4.0", "main": "js/ui.js", "homepage": "http://try.buildwinjs.com/", "author": { @@ -11,7 +11,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/winjs/winjs" + "url": "git+https://github.com/winjs/winjs.git" }, "licenses": [ { @@ -23,11 +23,13 @@ "url": "https://github.com/winjs/winjs/issues" }, "devDependencies": { + "bowser": "~1.0.0", "chalk": "~0.5.1", "fs-extra": "^0.10.0", "glob": "^4.0.5", "grunt": "~0.4.5", "grunt-contrib-clean": "~0.6.0", + "grunt-contrib-compress": "^0.13.0", "grunt-contrib-concat": "~0.5.0", "grunt-contrib-connect": "^0.8.0", "grunt-contrib-copy": "~0.5.0", @@ -36,7 +38,10 @@ "grunt-contrib-less": "~0.11.4", "grunt-contrib-requirejs": "^0.4.4", "grunt-contrib-uglify": "^0.5.1", - "grunt-jscs": "^0.6.2", + "grunt-git": "^0.3.5", + "grunt-github-releaser": "^0.1.17", + "grunt-jscs": "^1.8.0", + "grunt-nuget": "^0.1.4", "grunt-replace": "~0.7.8", "grunt-saucelabs": "git+https://github.com/xirzec/grunt-saucelabs.git#debug", "grunt-shell": "~0.7.0", @@ -51,24 +56,33 @@ "typescript": "1.4.1", "websocket": "^1.0.8" }, - "_id": "[email protected]", + "_id": "[email protected]", "scripts": {}, - "_shasum": "7bf65fadab719fec2bed306540e2cf69948e2e30", - "_from": "winjs@>=4.0.0", - "_npmVersion": "2.7.4", - "_nodeVersion": "0.12.2", + "_shasum": "ca43f1d75eefa6e04e995262bb0e76ac51160c9a", + "_from": "winjs@>=4.4.0 <5.0.0", + "_resolved": "https://registry.npmjs.org/winjs/-/winjs-4.4.0.tgz", + "_npmVersion": "2.14.0", + "_nodeVersion": "4.1.1", "_npmUser": { - "name": "rigdern", - "email": "[email protected]" + "name": "amazingjaze", + "email": "[email protected]" }, "dist": { - "shasum": "7bf65fadab719fec2bed306540e2cf69948e2e30", - "tarball": "http://registry.npmjs.org/winjs/-/winjs-4.0.1.tgz" + "shasum": "ca43f1d75eefa6e04e995262bb0e76ac51160c9a", + "tarball": "http://registry.npmjs.org/winjs/-/winjs-4.4.0.tgz" }, "maintainers": [ { - "name": "xirzec", - "email": "[email protected]" + "name": "amazingjaze", + "email": "[email protected]" + }, + { + "name": "jdalton", + "email": "[email protected]" + }, + { + "name": "jseanxu", + "email": "[email protected]" }, { "name": "phosphoer", @@ -77,9 +91,16 @@ { "name": "rigdern", "email": "[email protected]" + }, + { + "name": "winjs", + "email": "[email protected]" + }, + { + "name": "xirzec", + "email": "[email protected]" } ], "directories": {}, - "_resolved": "https://registry.npmjs.org/winjs/-/winjs-4.0.1.tgz", "readme": "ERROR: No README data found!" }
http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/58047a3d/package.json ---------------------------------------------------------------------- diff --git a/package.json b/package.json index 265bc88..4054421 100644 --- a/package.json +++ b/package.json @@ -1,46 +1,50 @@ { - "name": "cordova-windows", - "version": "4.3.0-dev", - "description": "cordova-windows release", - "main": "bin/create", - "repository": { - "type": "git", - "url": "https://github.com/apache/cordova-windows" - }, - "keywords": [ - "windows", - "cordova", - "apache" - ], - "scripts": { - "test": "npm run jshint && npm run test-unit && npm run test-e2e", - "test-unit": "node node_modules/jasmine-node/lib/jasmine-node/cli.js --captureExceptions spec/unit", - "test-e2e": "node node_modules/jasmine-node/lib/jasmine-node/cli.js --captureExceptions spec/e2e", - "cover": "node node_modules/istanbul/lib/cli.js cover --root template --print detail node_modules/jasmine-node/bin/jasmine-node -- spec/unit", - "jshint": "node node_modules/jshint/bin/jshint bin && node node_modules/jshint/bin/jshint template && node node_modules/jshint/bin/jshint spec" - }, - "dependencies": { - "elementtree": "~0.1.5", - "node-uuid": "~1.4", - "nopt": "~3", - "q": ">0.9.0", - "shelljs": "~0.3", - "winjs": "^4.0.0" - }, - "devDependencies": { - "jasmine-node": "1.14.5", - "jshint": "^2.6.0", - "rewire": ">=2.1.3", - "istanbul": "^0.3.4" - }, - "bundledDependencies": [ - "q", - "nopt", - "node-uuid", - "shelljs", - "elementtree", - "winjs" - ], - "author": "Apache Software Foundation", - "license": "Apache Version 2.0" -} \ No newline at end of file + "name": "cordova-windows", + "version": "4.3.0-dev", + "description": "cordova-windows release", + "bin": "bin/create", + "main": "template/cordova/Api.js", + "repository": { + "type": "git", + "url": "https://github.com/apache/cordova-windows" + }, + "keywords": [ + "windows", + "cordova", + "apache" + ], + "scripts": { + "test": "npm run jshint && npm run test-unit && npm run test-e2e", + "test-unit": "jasmine-node --captureExceptions spec/unit", + "test-e2e": "jasmine-node --captureExceptions spec/e2e", + "cover": "istanbul cover --root template --print detail node_modules/jasmine-node/bin/jasmine-node -- spec/unit", + "jshint": "jshint bin && jshint template && jshint spec" + }, + "dependencies": { + "cordova-common": "^1.0.0", + "elementtree": "^0.1.6", + "node-uuid": "^1.4.3", + "nopt": "^3.0.4", + "q": "^1.4.1", + "semver": "^5.0.3", + "shelljs": "^0.5.3", + "winjs": "^4.4.0" + }, + "devDependencies": { + "istanbul": "^0.4.0", + "jasmine-node": "1.14.5", + "jshint": "^2.8.0", + "rewire": "^2.1.3" + }, + "bundledDependencies": [ + "cordova-common", + "elementtree", + "node-uuid", + "nopt", + "q", + "shelljs", + "winjs" + ], + "author": "Apache Software Foundation", + "license": "Apache-2.0" +} http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/58047a3d/spec/unit/AppxManifest.spec.js ---------------------------------------------------------------------- diff --git a/spec/unit/AppxManifest.spec.js b/spec/unit/AppxManifest.spec.js new file mode 100644 index 0000000..d158144 --- /dev/null +++ b/spec/unit/AppxManifest.spec.js @@ -0,0 +1,102 @@ +/** + 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 rewire = require('rewire'); +var et = require('elementtree'); +var xml = require('cordova-common').xmlHelpers; +var AppxManifest = rewire('../../template/cordova/lib/AppxManifest'); +var Win10AppxManifest = AppxManifest.__get__('Win10AppxManifest'); + +var WINDOWS_MANIFEST = 'template/package.windows.appxmanifest'; +var WINDOWS_PHONE_MANIFEST = 'template/package.phone.appxmanifest'; + +describe('AppxManifest', function () { + + var XMLS = { + '/no/prefixed': new et.ElementTree(et.XML('<?xml version="1.0" encoding="UTF-8"?><Package/>')), + '/uap/prefixed': new et.ElementTree(et.XML('<?xml version="1.0" encoding="UTF-8"?><Package xmlns:uap=""/>')) + }; + + beforeEach(function () { + var parseElementtreeSyncOrig = xml.parseElementtreeSync; + spyOn(xml, 'parseElementtreeSync').andCallFake(function (manifestPath) { + return XMLS[manifestPath] || parseElementtreeSyncOrig(manifestPath); + }); + }); + + describe('constructor', function () { + + it('should create a new AppxManifest instance', function () { + var manifest; + expect(function () { manifest = new AppxManifest(WINDOWS_MANIFEST); }).not.toThrow(); + expect(manifest instanceof AppxManifest).toBe(true); + }); + + it('should throw if first parameter is not a file', function () { + expect(function () { new AppxManifest('/invalid/path'); }).toThrow(); + }); + + it('should throw if first parameter is not a valid manifest file (no "Package" tag)', function () { + expect(function () { new AppxManifest('/invalid/manifest'); }).toThrow(); + }); + + it('should add ":" to manifest prefix if needed', function () { + expect(new AppxManifest(WINDOWS_MANIFEST, 'prefix').prefix).toEqual('prefix:'); + }); + }); + + describe('static get() method', function () { + + it('should return an AppxManifest instance', function () { + expect(AppxManifest.get(WINDOWS_MANIFEST) instanceof AppxManifest).toBe(true); + }); + + it('should detect manifest prefix based on "Package" element attributes', function () { + expect(AppxManifest.get(WINDOWS_MANIFEST).prefix).toEqual('m2:'); + expect(AppxManifest.get(WINDOWS_PHONE_MANIFEST).prefix).toEqual('m3:'); + }); + + it('should instantiate either AppxManifest or Windows 10 AppxManifest based on manifest prefix', function () { + expect(AppxManifest.get('/no/prefixed').prefix).toEqual(''); + expect(AppxManifest.get('/no/prefixed') instanceof AppxManifest).toBe(true); + expect(AppxManifest.get('/no/prefixed') instanceof Win10AppxManifest).toBe(false); + + expect(AppxManifest.get('/uap/prefixed').prefix).toEqual('uap:'); + expect(AppxManifest.get('/uap/prefixed') instanceof Win10AppxManifest).toBe(true); + }); + }); + + describe('instance get* methods', function () { + var methods = ['getPhoneIdentity','getIdentity','getProperties','getApplication','getVisualElements']; + + it('should exists', function () { + var manifest = AppxManifest.get(WINDOWS_PHONE_MANIFEST); + var emptyManifest = AppxManifest.get('/no/prefixed'); + + methods.forEach(function (method) { + expect(manifest[method]).toBeDefined(); + expect(manifest[method]).toEqual(jasmine.any(Function)); + expect(function () { manifest[method](); }).not.toThrow(); + expect(function () { emptyManifest[method](); }).toThrow(); + expect(manifest[method]()).toBeDefined(); + }); + }); + }); +}); + http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/58047a3d/spec/unit/MSBuildTools.spec.js ---------------------------------------------------------------------- diff --git a/spec/unit/MSBuildTools.spec.js b/spec/unit/MSBuildTools.spec.js index d9ed253..4850946 100644 --- a/spec/unit/MSBuildTools.spec.js +++ b/spec/unit/MSBuildTools.spec.js @@ -16,12 +16,12 @@ specific language governing permissions and limitations under the License. */ -var Q = require('q'), - shell = require('shelljs'), - rewire = require('rewire'), - platformRoot = '../../template', - buildTools = rewire(platformRoot + '/cordova/lib/MSBuildTools.js'), - Version = require(platformRoot + '/cordova/lib/Version.js'); +var Q = require('q'); +var shell = require('shelljs'); +var rewire = require('rewire'); +var platformRoot = '../../template'; +var buildTools = rewire(platformRoot + '/cordova/lib/MSBuildTools.js'); +var Version = require(platformRoot + '/cordova/lib/Version.js'); var fakeToolsPath = function (version) { return 'C:\\Program Files (x86)\\MSBuild\\' + version; @@ -89,23 +89,26 @@ describe('findAvailableVersion method', function(){ }); describe('checkMSBuildVersion method', function(){ - var checkMSBuildVersion = buildTools.__get__('checkMSBuildVersion'), - execOriginal; + var checkMSBuildVersion = buildTools.__get__('checkMSBuildVersion'); + + var spawnOriginal = buildTools.__get__('spawn'); + var spawnSpy = jasmine.createSpy('spawn'); beforeEach(function () { - execOriginal = buildTools.__get__('exec'); + buildTools.__set__('spawn', spawnSpy); }); afterEach(function () { - buildTools.__set__('exec', execOriginal); + buildTools.__set__('spawn', spawnOriginal); }); it('spec.6 should return valid version and path', function(){ var version = '14.0'; - buildTools.__set__('exec', function(cmd) { - return Q.resolve('\r\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\12.0\r\n\tMSBuildToolsPath\tREG_SZ\t' + fakeToolsPath(version) + '\r\n\r\n'); - }); + spawnSpy.andReturn(Q.resolve( + '\r\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\12.0\r\n\t' + + 'MSBuildToolsPath\tREG_SZ\t' + fakeToolsPath(version) + '\r\n\r\n') + ); checkMSBuildVersion(version).then(function (actual) { expect(actual.version).toBe(version); @@ -114,37 +117,24 @@ describe('checkMSBuildVersion method', function(){ }); it('spec.7 should return null if no tools found for version', function(){ - buildTools.__set__('exec', function(cmd) { - return Q.resolve('ERROR: The system was unable to find the specified registry key or value.'); - }); + spawnSpy.andReturn(Q.resolve('ERROR: The system was unable to find the specified registry key or value.')); checkMSBuildVersion('14.0').then(function (actual) { - expect(actual).toBeNull(); + expect(actual).not.toBeDefined(); }); }); it('spec.8 should return null on internal error', function(){ - buildTools.__set__('exec', function(cmd) { - return Q.reject(); - }); + spawnSpy.andReturn(Q.reject()); checkMSBuildVersion('14.0').then(function (actual) { - expect(actual).toBeNull(); + expect(actual).not.toBeDefined(); }); }); }); describe('MSBuildTools object', function(){ - var MSBuildTools = buildTools.__get__('MSBuildTools'), - spawnOriginal; - - beforeEach(function () { - spawnOriginal = buildTools.__get__('spawn'); - }); - - afterEach(function () { - buildTools.__set__('spawn', spawnOriginal); - }); + var MSBuildTools = buildTools.__get__('MSBuildTools'); it('spec.9 should have fields and methods defined', function() { var version = '14.0', http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/58047a3d/spec/unit/Prepare.Win10.spec.js ---------------------------------------------------------------------- diff --git a/spec/unit/Prepare.Win10.spec.js b/spec/unit/Prepare.Win10.spec.js index dc1568d..caa2e3b 100644 --- a/spec/unit/Prepare.Win10.spec.js +++ b/spec/unit/Prepare.Win10.spec.js @@ -19,100 +19,22 @@ var rewire = require('rewire'), prepare = rewire('../../template/cordova/lib/prepare'), - Version = require('../../template/cordova/lib/Version'), - et = require('elementtree'), + AppxManifest = require('../../template/cordova/lib/AppxManifest'), + ConfigParser = require('../../template/cordova/lib/ConfigParser'), fs = require('fs'), - getAllMinMaxUAPVersions = prepare.__get__('getAllMinMaxUAPVersions'), + et = require('elementtree'), + events = require('cordova-common').events, + xml = require('cordova-common').xmlHelpers, + updateManifestFile = prepare.__get__('updateManifestFile'), applyCoreProperties = prepare.__get__('applyCoreProperties'), applyAccessRules = prepare.__get__('applyAccessRules'), - checkForRestrictedCaps = prepare.__get__('checkForRestrictedCapabilities'), - ensureUapPrefixedCapabilities = prepare.__get__('ensureUapPrefixedCapabilities'); + applyNavigationWhitelist = prepare.__get__('applyNavigationWhitelist'), + applyStartPage = prepare.__get__('applyStartPage'); var Win10ManifestPath = 'template/package.windows10.appxmanifest', Win81ManifestPath = 'template/package.windows.appxmanifest'; /*** - * Unit tests for validating that min/max versions are correctly obtained - * (for the function getAllMinMaxUAPVersions) from prepare.js. - **/ -describe('Min/Max UAP versions are correctly read from the config file.', function() { - - var mockConfig = { - getMatchingPreferences: function(regexp) { - return [ - { name: 'Windows.Universal-MinVersion', value: '10.0.9910.0' }, - { name: 'Windows.Universal-MaxVersionTested', value: '10.0.9917.0' }, - { name: 'Windows.Desktop-MinVersion', value: '10.0.9910.0' }, - { name: 'Microsoft.Xbox-MaxVersionTested', value: '10.0.9917.0' } - ]; - } - }; - - it('Should correctly transform all versions as a baseline.', function() { - var versionSet = getAllMinMaxUAPVersions(mockConfig); - var ver9910 = new Version(10, 0, 9910, 0); - var ver9917 = new Version(10, 0, 9917, 0); - - expect(versionSet['Windows.Universal']).toBeDefined(); - expect(ver9910.eq(versionSet['Windows.Universal'].MinVersion)).toBe(true); - expect(ver9917.eq(versionSet['Windows.Universal'].MaxVersionTested)).toBe(true); - - expect(versionSet['Windows.Desktop']).toBeDefined(); - expect(ver9910.eq(versionSet['Windows.Desktop'].MinVersion)).toBe(true); - expect(ver9910.eq(versionSet['Windows.Desktop'].MaxVersionTested)).toBe(true); - - expect(versionSet['Microsoft.Xbox']).toBeDefined(); - expect(ver9917.eq(versionSet['Microsoft.Xbox'].MinVersion)).toBe(true); - expect(ver9917.eq(versionSet['Microsoft.Xbox'].MaxVersionTested)).toBe(true); - - expect(Object.keys(versionSet).length).toBe(3); - }); - -}); - -describe('Min/Max UAP versions are produced correctly even when the config file has no settings.', function() { - var mockConfig = { - getMatchingPreferences: function(regexp) { - return []; - } - }; - - it('Should correctly transform all versions as a baseline.', function() { - var versionSet = getAllMinMaxUAPVersions(mockConfig); - var verBaseline = prepare.__get__('BASE_UAP_VERSION'); - - expect(versionSet['Windows.Universal']).toBeDefined(); - expect(verBaseline.eq(versionSet['Windows.Universal'].MinVersion)).toBe(true); - expect(verBaseline.eq(versionSet['Windows.Universal'].MaxVersionTested)).toBe(true); - - expect(Object.keys(versionSet).length).toBe(1); - }); -}); - -describe('Min/Max UAP versions are correctly read from the config file.', function() { - - var mockConfig = { - getMatchingPreferences: function(regexp) { - return [ - { name: 'Windows.Universal-MinVersion', value: '10.0.9910.f' }, - { name: 'Windows.Universal-MaxVersionTested', value: '10.0.9917.0' }, - ]; - } - }; - - it('Should fail to produce min/max versions with a RangeError.', function() { - try { - getAllMinMaxUAPVersions(mockConfig); - expect(false).toBe(true); - } - catch (ex) { - expect(ex.constructor).toBe(RangeError); - } - }); - -}); - -/*** * Unit tests for validating default ms-appx-web:// URI scheme in Win10 * (for the function applyCoreProperties) from prepare.js. **/ @@ -124,6 +46,7 @@ var PreferencesBaseline = { WindowsStorePublisherName: null, WindowsStoreIdentityName: null }; + function createMockConfigAndManifestForApplyCoreProperties(startPage, preferences, win10, winPackageVersion) { if (!preferences) { preferences = { }; @@ -148,128 +71,135 @@ function createMockConfigAndManifestForApplyCoreProperties(startPage, preference }; var filePath = win10 ? Win10ManifestPath : Win81ManifestPath; - var fileContents = fs.readFileSync(filePath, 'utf-8'); - var manifest = new et.ElementTree(et.XML(fileContents.trim())); + var manifest = AppxManifest.get(filePath); + spyOn(fs, 'writeFileSync'); return { config: config, manifest: manifest }; } function addCapabilityDeclarationToMockManifest(manifest, capability) { - var capRoot = manifest.find('.//Capabilities'); + var capRoot = manifest.doc.find('.//Capabilities'); var cap = new et.Element('Capability'); cap.attrib.Name = capability; capRoot.append(cap); } -describe('A Windows 8.1 project should not have an HTTP or HTTPS scheme for its startup URI.', function() { +describe('Windows 8.1 project', function() { - // arrange - var mockConfig = createMockConfigAndManifestForApplyCoreProperties('index.html', { 'WindowsDefaultUriPrefix': 'http://' }, false); + it('should not have an HTTP or HTTPS scheme for its startup URI.', function() { - // act - applyCoreProperties(mockConfig.config, mockConfig.manifest, 'fake-path', 'm2:', false); + // arrange + var mockConfig = createMockConfigAndManifestForApplyCoreProperties('index.html', { 'WindowsDefaultUriPrefix': 'http://' }, false); - var app = mockConfig.manifest.find('.//Application'); - expect(app.attrib.StartPage).toBe('www/index.html'); -}); + // act + applyCoreProperties(mockConfig.config, mockConfig.manifest, 'fake-path', 'm2:', false); -describe('A Windows 8.1 project should not have any scheme for its startup URI.', function() { + var app = mockConfig.manifest.doc.find('.//Application'); + expect(app.attrib.StartPage).toBe('www/index.html'); + }); - // arrange - var mockConfig = createMockConfigAndManifestForApplyCoreProperties('index.html', { 'WindowsDefaultUriPrefix': 'ms-appx://' }, false); + it('should not have any scheme for its startup URI.', function() { - // act - applyCoreProperties(mockConfig.config, mockConfig.manifest, 'fake-path', 'm2:', false); + // arrange + var mockConfig = createMockConfigAndManifestForApplyCoreProperties('index.html', { 'WindowsDefaultUriPrefix': 'ms-appx://' }, false); - var app = mockConfig.manifest.find('.//Application'); - expect(app.attrib.StartPage).toBe('www/index.html'); + // act + applyCoreProperties(mockConfig.config, mockConfig.manifest, 'fake-path', 'm2:', false); + + var app = mockConfig.manifest.doc.find('.//Application'); + expect(app.attrib.StartPage).toBe('www/index.html'); + }); }); -describe('A Windows 10 project default to ms-appx-web for its startup URI.', function() { +describe('Windows 10 project', function() { + it('should default to ms-appx-web for its startup URI.', function() { - // arrange - var mockConfig = createMockConfigAndManifestForApplyCoreProperties('index.html', { }, true); + // arrange + var mockConfig = createMockConfigAndManifestForApplyCoreProperties('index.html', { }, true); - // act - applyCoreProperties(mockConfig.config, mockConfig.manifest, 'fake-path', 'uap:', true); + // act + applyStartPage(mockConfig.config, mockConfig.manifest, true); - var app = mockConfig.manifest.find('.//Application'); - expect(app.attrib.StartPage).toBe('ms-appx-web:///www/index.html'); -}); + var app = mockConfig.manifest.doc.find('.//Application'); + expect(app.attrib.StartPage).toBe('ms-appx-web:///www/index.html'); + }); -describe('A Windows 10 project should allow ms-appx as its startup URI, and it gets removed from the final output.', function() { + it ('should allow ms-appx as its startup URI, and it gets removed from the final output.', function() { - // arrange - var mockConfig = createMockConfigAndManifestForApplyCoreProperties('index.html', { 'WindowsDefaultUriPrefix': 'ms-appx://' }, true); + // arrange + var mockConfig = createMockConfigAndManifestForApplyCoreProperties('index.html', { 'WindowsDefaultUriPrefix': 'ms-appx://' }, true); - // act - applyCoreProperties(mockConfig.config, mockConfig.manifest, 'fake-path', 'uap:', true); + // act + applyStartPage(mockConfig.config, mockConfig.manifest, true); - var app = mockConfig.manifest.find('.//Application'); - expect(app.attrib.StartPage).toBe('www/index.html'); -}); + var app = mockConfig.manifest.doc.find('.//Application'); + expect(app.attrib.StartPage).toBe('www/index.html'); + }); -describe('A Windows 10 project should allow an HTTP or HTTPS scheme for its startup URI.', function() { + it('should allow an HTTP or HTTPS scheme for its startup URI.', function() { - // arrange - var mockConfig = createMockConfigAndManifestForApplyCoreProperties('www.contoso.com/', { 'WindowsDefaultUriPrefix': 'http://' }, true); + // arrange + var mockConfig = createMockConfigAndManifestForApplyCoreProperties('www.contoso.com/', { 'WindowsDefaultUriPrefix': 'http://' }, true); - // act - applyCoreProperties(mockConfig.config, mockConfig.manifest, 'fake-path', 'uap:', true); + // act + applyStartPage(mockConfig.config, mockConfig.manifest, true); - var app = mockConfig.manifest.find('.//Application'); - expect(app.attrib.StartPage).toBe('http://www.contoso.com/'); + var app = mockConfig.manifest.doc.find('.//Application'); + expect(app.attrib.StartPage).toBe('http://www.contoso.com/'); + }); }); -describe('An app specifying a Store DisplayName in its config.xml should have it reflected in the manifest.', function() { - // arrange - var mockConfig = createMockConfigAndManifestForApplyCoreProperties('www.contoso.com/', { 'WindowsDefaultUriPrefix': 'http://', 'WindowsStoreDisplayName': 'ContosoApp' }, true); +describe('Windows Store preference', function () { - // act - applyCoreProperties(mockConfig.config, mockConfig.manifest, 'fake-path', 'uap:', true); + it('"WindowsStoreDisplayName" should be reflected in the manifest.', function() { - var app = mockConfig.manifest.find('.//Properties/DisplayName'); - expect(app.text).toBe('ContosoApp'); -}); + // arrange + var mockConfig = createMockConfigAndManifestForApplyCoreProperties('www.contoso.com/', { 'WindowsDefaultUriPrefix': 'http://', 'WindowsStoreDisplayName': 'ContosoApp' }, true); -describe('An app specifying a Store PublisherName in its config.xml should have it reflected in the manifest.', function() { + // act + applyCoreProperties(mockConfig.config, mockConfig.manifest, 'fake-path', 'uap:', true); - // arrange - var mockConfig = createMockConfigAndManifestForApplyCoreProperties('www.contoso.com/', { 'WindowsDefaultUriPrefix': 'http://', 'WindowsStorePublisherName': 'Contoso Inc' }, true); + var app = mockConfig.manifest.doc.find('.//Properties/DisplayName'); + expect(app.text).toBe('ContosoApp'); + }); + + it('"WindowsStorePublisherName" should be reflected in the manifest.', function() { - // act - applyCoreProperties(mockConfig.config, mockConfig.manifest, 'fake-path', 'uap:', true); + // arrange + var mockConfig = createMockConfigAndManifestForApplyCoreProperties('www.contoso.com/', { 'WindowsDefaultUriPrefix': 'http://', 'WindowsStorePublisherName': 'Contoso Inc' }, true); - var app = mockConfig.manifest.find('.//Properties/PublisherDisplayName'); - expect(app.text).toBe('Contoso Inc'); + // act + applyCoreProperties(mockConfig.config, mockConfig.manifest, 'fake-path', 'uap:', true); + + var app = mockConfig.manifest.doc.find('.//Properties/PublisherDisplayName'); + expect(app.text).toBe('Contoso Inc'); + }); }); describe('A Windows 10 project should warn if it supports remote mode and restricted capabilities.', function() { // arrange - var mockConfig = createMockConfigAndManifestForApplyAccessRules(true, 'http://www.bing.com/*'); - addCapabilityDeclarationToMockManifest(mockConfig.manifest, 'documentsLibrary'); - + var mockConfig; var stringFound = false, - searchStr = ' documentsLibrary', - oldConsoleWarn = console.warn; + searchStr = 'documentsLibrary'; beforeEach(function() { + mockConfig = createMockConfigAndManifestForApplyAccessRules(true, 'http://www.bing.com/*'); + addCapabilityDeclarationToMockManifest(mockConfig.manifest, 'documentsLibrary'); + + spyOn(AppxManifest, 'get').andReturn(mockConfig.manifest); + stringFound = false; - spyOn(console, 'warn').andCallFake(function(msg) { - if (msg === searchStr) + events.on('warn', function (msg) { + if (msg.indexOf(searchStr) >= 0) stringFound = true; }); }); - afterEach(function() { - console.warn = oldConsoleWarn; - }); - it('asserts that the documentsLibrary capability is restricted', function() { // act - checkForRestrictedCaps(mockConfig.config, mockConfig.manifest); + updateManifestFile(mockConfig.config, '/manifest/path'); // assert expect(stringFound).toBe(true); @@ -287,143 +217,158 @@ function createMockConfigAndManifestForApplyAccessRules(isWin10) { rules.push(arguments[i]); } - var config = { - version: function() { return '1.0.0.0'; }, - name: function() { return 'HelloCordova'; }, - packageName: function() { return 'org.apache.cordova.HelloCordova'; }, - author: function() { return 'Apache'; }, - startPage: function() { return 'index.html'; }, - getPreference: function(preferenceName) { - if (preferenceName === 'WindowsDefaultUriPrefix') { - return isWin10 ? 'ms-appx-web://' : 'ms-appx://'; - } - else { - throw new RangeError('Unexpected call to config.getPreference in unit test.'); - } - }, - getAccessRules: function() { - if (isWin10) { - return []; - } + 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 = "org.apache.cordova.HelloCordova"\n' + + ' version = "1.0.0.0">\n' + + ' <name>HelloCordova</name>\n' + + ' <author href="http://cordova.io" email="[email protected]">\n' + + ' Apache\n' + + ' </author>\n' + + ' <content src="index.html" />\n' + + '</widget>\n'; + + var origParseElementtreeSync = xml.parseElementtreeSync; + spyOn(xml, 'parseElementtreeSync').andCallFake(function(path) { + if (path ==='config.xml') return new et.ElementTree(et.XML(TEST_XML)); + return origParseElementtreeSync(path); + }); - return rules; - }, - getNavigationWhitelistRules: function() { - if (isWin10) { - return rules; - } + var config = new ConfigParser('config.xml'); + + var origGetPreference = config.getPreference; + spyOn(config, 'getPreference').andCallFake(function (prefName) { + if (prefName === 'WindowsDefaultUriPrefix') { + return isWin10 ? 'ms-appx-web://' : 'ms-appx://'; + } + return origGetPreference.call(config, prefName); + }); + + config.getAccesses = function() { + if (isWin10) { return []; } + + return rules.map(function (rule) { + return { 'origin': rule }; + }); + }; + + config.getAllowNavigations = function() { + if (isWin10) { + return rules.map(function (rule) { + return { 'href': rule }; + }); + } + + return []; }; var filePath = isWin10 ? Win10ManifestPath : Win81ManifestPath; - var fileContents = fs.readFileSync(filePath, 'utf-8'); - var manifest = new et.ElementTree(et.XML(fileContents.trim())); + var manifest = AppxManifest.get(filePath); + spyOn(fs, 'writeFileSync'); return { config: config, manifest: manifest }; } -describe('A Windows 8.1 project should not have WindowsRuntimeAccess attributes in access rules.', function() { +describe('Access rules management', function () { + // body... + it('A Windows 8.1 project should not have WindowsRuntimeAccess attributes in access rules.', function() { - var mockConfig = createMockConfigAndManifestForApplyAccessRules(false, 'https://www.contoso.com'); + var mockConfig = createMockConfigAndManifestForApplyAccessRules(false, 'https://www.contoso.com'); - applyAccessRules(mockConfig.config, mockConfig.manifest, false); + applyAccessRules(mockConfig.config, mockConfig.manifest); - var app = mockConfig.manifest.find('.//Application'), - accessRules = app.find('.//ApplicationContentUriRules'); + var app = mockConfig.manifest.doc.find('.//Application'), + accessRules = app.find('.//ApplicationContentUriRules'); - expect(accessRules).toBeDefined(); - expect(accessRules.len()).toBe(1); + expect(accessRules).toBeDefined(); + expect(accessRules.len()).toBe(1); - var rule = accessRules.getItem(0); - expect(rule).toBeDefined(); - expect(rule.attrib.WindowsRuntimeAccess).toBeUndefined(); + var rule = accessRules.getItem(0); + expect(rule).toBeDefined(); + expect(rule.attrib.WindowsRuntimeAccess).toBeUndefined(); -}); + }); -describe('A Windows 10 project should have WindowsRuntimeAccess attributes in access rules.', function() { + it('A Windows 10 project should have WindowsRuntimeAccess attributes in access rules.', function() { - var mockConfig = createMockConfigAndManifestForApplyAccessRules(true, 'https://www.contoso.com'); + var mockConfig = createMockConfigAndManifestForApplyAccessRules(true, 'https://www.contoso.com'); - applyAccessRules(mockConfig.config, mockConfig.manifest, true); + applyNavigationWhitelist(mockConfig.config, mockConfig.manifest, true); - var app = mockConfig.manifest.find('.//Application'), - accessRules = app.find('.//uap:ApplicationContentUriRules'); + var app = mockConfig.manifest.doc.find('.//Application'), + accessRules = app.find('.//uap:ApplicationContentUriRules'); - expect(accessRules).toBeDefined(); - expect(accessRules.len()).toBe(2); + expect(accessRules).toBeDefined(); + expect(accessRules.len()).toBe(2); - var rule = accessRules.getItem(0); - expect(rule).toBeDefined(); - expect(rule.attrib.WindowsRuntimeAccess).toBeDefined(); - expect(rule.attrib.WindowsRuntimeAccess).toBe('all'); + var rule = accessRules.getItem(0); + expect(rule).toBeDefined(); + expect(rule.attrib.WindowsRuntimeAccess).toBeDefined(); + expect(rule.attrib.WindowsRuntimeAccess).toBe('all'); -}); + }); -describe('A Windows 8.1 project should reject http:// URI scheme rules.', function() { - - var stringIndex = -1, - searchStr = 'Access rules must begin with "https://", the following rule will be ignored: ', - oldConsoleWarn = console.warn; - beforeEach(function() { - spyOn(console, 'warn').andCallFake(function(msg) { - stringIndex = msg.indexOf(searchStr); + describe('A Windows 8.1 project should reject http:// URI scheme rules.', function() { + + var stringIndex = -1, + searchStr = 'Access rules must begin with "https://", the following rule will be ignored: '; + + beforeEach(function() { + require('cordova-common').events.on('warn', function (evt) { + stringIndex = evt.indexOf(searchStr); + }); }); - }); - afterEach(function() { - console.warn = oldConsoleWarn; - }); - - it('applies access rules and verifies at least one was rejected', function() { - var mockConfig = createMockConfigAndManifestForApplyAccessRules(false, 'http://www.contoso.com'); - applyAccessRules(mockConfig.config, mockConfig.manifest, false); - expect(stringIndex).toBe(0); + it('applies access rules and verifies at least one was rejected', function() { + var mockConfig = createMockConfigAndManifestForApplyAccessRules(false, 'http://www.contoso.com'); + applyAccessRules(mockConfig.config, mockConfig.manifest, false); + + expect(stringIndex).toBe(0); + }); }); -}); -describe('A Windows 10 project should accept http:// URI access rules.', function() { + describe('A Windows 10 project should accept http:// URI access rules.', function() { - var stringIndex = -1, - searchStr = 'The following navigation rule had an invalid URI scheme and is ignored:', - oldConsoleWarn = console.warn; - beforeEach(function() { - spyOn(console, 'warn').andCallFake(function(msg) { - stringIndex = msg.indexOf(searchStr); + var stringIndex = -1, + searchStr = 'The following navigation rule had an invalid URI scheme and is ignored:'; + beforeEach(function() { + require('cordova-common').events.on('warn', function (evt) { + stringIndex = evt.indexOf(searchStr); + }); }); - }); - afterEach(function() { - console.warn = oldConsoleWarn; - }); - it('applies access rules and verifies they were accepted', function() { - var mockConfig = createMockConfigAndManifestForApplyAccessRules(true, 'http://www.contoso.com'); - applyAccessRules(mockConfig.config, mockConfig.manifest, true); + it('applies access rules and verifies they were accepted', function() { + var mockConfig = createMockConfigAndManifestForApplyAccessRules(true, 'http://www.contoso.com'); + applyAccessRules(mockConfig.config, mockConfig.manifest, true); - expect(stringIndex).toBe(-1); + expect(stringIndex).toBe(-1); + }); }); - }); describe('A Windows 10 project should apply the uap: namespace prefix to certain capabilities.', function() { - - var element = null; + + var manifest; beforeEach(function() { - element = new et.Element('Capabilities'); + manifest = createMockConfigAndManifestForApplyAccessRules(true, 'https://www.contoso.com').manifest; + var element = manifest.doc.find('.//Capabilities'); + element.clear(); element.append(new et.Element('Capability', { Name: 'internetClient' })); element.append(new et.Element('Capability', { Name: 'documentsLibrary' })); element.append(new et.Element('DeviceCapability', { Name: 'location' })); + manifest.write(); }); it('Applies the uap: prefix to the documentsLibrary capability.', function() { - ensureUapPrefixedCapabilities(element); - var children = element.getchildren(); var testResults = {}; // map capabilities to tag - children.forEach(function(child) { - testResults[child.attrib.Name] = child.tag; + manifest.getCapabilities().forEach(function(child) { + testResults[child.name] = child.type; }); expect(testResults.internetClient).toBe('Capability'); http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/58047a3d/spec/unit/Version.spec.js ---------------------------------------------------------------------- diff --git a/spec/unit/Version.spec.js b/spec/unit/Version.spec.js index 074afb2..4ee16a8 100644 --- a/spec/unit/Version.spec.js +++ b/spec/unit/Version.spec.js @@ -19,29 +19,30 @@ var Version = require('../../template/cordova/lib/Version.js'); -describe('Version constructors behave correctly.', function() { - - var v1 = new Version(1); - expect(v1.major).toBe(1); - expect(v1.minor).toBe(0); - expect(v1.build).toBe(0); - expect(v1.qfe).toBe(0); - var v2 = new Version(1, 2); - expect(v2.major).toBe(1); - expect(v2.minor).toBe(2); - expect(v2.build).toBe(0); - expect(v2.qfe).toBe(0); - var v3 = new Version(1, 2, 4); - expect(v3.major).toBe(1); - expect(v3.minor).toBe(2); - expect(v3.build).toBe(4); - expect(v3.qfe).toBe(0); - var v4 = new Version(1, 2, 4, 7); - expect(v4.major).toBe(1); - expect(v4.minor).toBe(2); - expect(v4.build).toBe(4); - expect(v4.qfe).toBe(7); - +describe('Version constructor', function () { + + it('should behave correctly', function () { + var v1 = new Version(1); + expect(v1.major).toBe(1); + expect(v1.minor).toBe(0); + expect(v1.build).toBe(0); + expect(v1.qfe).toBe(0); + var v2 = new Version(1, 2); + expect(v2.major).toBe(1); + expect(v2.minor).toBe(2); + expect(v2.build).toBe(0); + expect(v2.qfe).toBe(0); + var v3 = new Version(1, 2, 4); + expect(v3.major).toBe(1); + expect(v3.minor).toBe(2); + expect(v3.build).toBe(4); + expect(v3.qfe).toBe(0); + var v4 = new Version(1, 2, 4, 7); + expect(v4.major).toBe(1); + expect(v4.minor).toBe(2); + expect(v4.build).toBe(4); + expect(v4.qfe).toBe(7); + }); }); describe('Version parse functions work as expected.', function() { http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/58047a3d/spec/unit/WindowsConfigParser.spec.js ---------------------------------------------------------------------- diff --git a/spec/unit/WindowsConfigParser.spec.js b/spec/unit/WindowsConfigParser.spec.js new file mode 100644 index 0000000..a4b1bd3 --- /dev/null +++ b/spec/unit/WindowsConfigParser.spec.js @@ -0,0 +1,104 @@ +/** + 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 rewire = require('rewire'); +var et = require('elementtree'); +var xml = require('cordova-common').xmlHelpers; +var ConfigParser = require('../../template/cordova/lib/ConfigParser'); +var ConfigParserOrig = require('cordova-common').ConfigParser; + +var TEST_XML = '<?xml version="1.0" encoding="UTF-8"?><widget/>'; + +describe('Windows ConfigParser', function () { + it('should extend ConfigParser from cordova-common', function () { + expect(ConfigParser.prototype instanceof ConfigParserOrig).toBe(true); + }); +}); + +/*** + * Unit tests for validating that min/max versions are correctly obtained + * (for the function getAllMinMaxUAPVersions) from prepare.js. + **/ + +describe('getAllMinMaxUAPVersions method', function () { + + var mockConfig; + beforeEach(function () { + spyOn(xml, 'parseElementtreeSync').andReturn(new et.ElementTree(et.XML(TEST_XML))); + + mockConfig = new ConfigParser('/some/file'); + }); + + it('should correctly transform all versions as a baseline.', function() { + spyOn(mockConfig, 'getMatchingPreferences').andReturn([ + { name: 'Windows.Universal-MinVersion', value: '10.0.9910.0' }, + { name: 'Windows.Universal-MaxVersionTested', value: '10.0.9917.0' }, + { name: 'Windows.Desktop-MinVersion', value: '10.0.9910.0' }, + { name: 'Microsoft.Xbox-MaxVersionTested', value: '10.0.9917.0' } + ]); + + var versionSet = mockConfig.getAllMinMaxUAPVersions(); + var ver9910 = '10.0.9910.0'; + var ver9917 = '10.0.9917.0'; + + expect(versionSet.length).toBe(3); + + expect(versionSet[0].Name).toBe('Windows.Universal'); + expect(versionSet[0].MinVersion).toBe(ver9910); + expect(versionSet[0].MaxVersionTested).toBe(ver9917); + + expect(versionSet[1].Name).toBe('Windows.Desktop'); + expect(versionSet[1].MinVersion).toBe(ver9910); + expect(versionSet[1].MaxVersionTested).toBe(ver9910); + + expect(versionSet[2].Name).toBe('Microsoft.Xbox'); + expect(versionSet[2].MinVersion).toBe(ver9917); + expect(versionSet[2].MaxVersionTested).toBe(ver9917); + }); + + it('should produce versions correctly even when the config file has no settings.', function() { + spyOn(mockConfig, 'getMatchingPreferences').andReturn([]); + + var versionSet = mockConfig.getAllMinMaxUAPVersions(); + var verBaseline = rewire('../../template/cordova/lib/ConfigParser') + .__get__('BASE_UAP_VERSION').toString(); + + expect(versionSet.length).toBe(1); + expect(versionSet[0].Name).toBe('Windows.Universal'); + expect(versionSet[0].MinVersion).toBe(verBaseline); + expect(versionSet[0].MaxVersionTested).toBe(verBaseline); + + }); + + it('should fail with a RangeError if version specified incorrectly', function() { + spyOn(mockConfig, 'getMatchingPreferences') + .andReturn([ + { name: 'Windows.Universal-MinVersion', value: '10.0.9910.f' }, + { name: 'Windows.Universal-MaxVersionTested', value: '10.0.9917.0' }, + ]); + + try { + mockConfig.getAllMinMaxUAPVersions(); + expect(false).toBe(true); + } + catch (ex) { + expect(ex.constructor).toBe(RangeError); + } + }); +}); http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/58047a3d/spec/unit/build.spec.js ---------------------------------------------------------------------- diff --git a/spec/unit/build.spec.js b/spec/unit/build.spec.js index e87ca3e..5638d63 100644 --- a/spec/unit/build.spec.js +++ b/spec/unit/build.spec.js @@ -157,7 +157,7 @@ describe('run method', function() { createFindAllAvailableVersionsMock([{version: '14.0', buildProject: buildSpy, path: testPath }]); build.__set__('prepare.applyPlatformConfig', function() {} ); - build.run([ 'node', buildPath, '--release' ]) + build.run({ release: true }) .finally(function() { expect(buildSpy).toHaveBeenCalled(); done(); @@ -189,7 +189,7 @@ describe('run method', function() { createFindAllAvailableVersionsMock([{version: '14.0', buildProject: buildSpy, path: testPath }]); build.__set__('prepare.applyPlatformConfig', function() {} ); - build.run([ 'node', buildPath, '--archs=arm' ]) + build.run({argv: ['--archs=arm'] }) .finally(function() { expect(buildSpy).toHaveBeenCalled(); done(); @@ -230,7 +230,7 @@ describe('run method', function() { }]); build.__set__('prepare.applyPlatformConfig', function() {} ); - build.run([ 'node', buildPath, '--archs=arm x86 x64 anycpu', '--phone' ]) + build.run({ argv: ['--archs=arm x86 x64 anycpu', '--phone'] }) .finally(function() { expect(armBuild).toHaveBeenCalled(); expect(x86Build).toHaveBeenCalled(); @@ -248,7 +248,7 @@ describe('run method', function() { build.__set__('prepare.applyPlatformConfig', function() {} ); createConfigParserMock('8.0'); - build.run([ 'node', buildPath, '--win' ]) + build.run({argv: ['--win']}) .finally(function() { expect(buildSpy).toHaveBeenCalled(); done(); @@ -263,7 +263,7 @@ describe('run method', function() { build.__set__('prepare.applyPlatformConfig', function() {} ); createConfigParserMock('8.1'); - build.run([ 'node', buildPath, '--win' ]) + build.run({argv: ['--win']}) .finally(function() { expect(buildSpy).toHaveBeenCalled(); done(); @@ -279,7 +279,7 @@ describe('run method', function() { build.__set__('prepare.applyPlatformConfig', function() {} ); createConfigParserMock('unsupported value here'); - build.run([ 'node', buildPath, '--win' ]) + build.run({argv: ['--win']}) .fail(function(error) { errorSpy(); expect(error).toBeDefined(); @@ -299,7 +299,7 @@ describe('run method', function() { build.__set__('prepare.applyPlatformConfig', function() {} ); createConfigParserMock(null, '8.1'); - build.run([ 'node', buildPath, '--phone' ]) + build.run({argv: ['--phone']}) .finally(function() { expect(buildSpy).toHaveBeenCalled(); done(); @@ -315,7 +315,7 @@ describe('run method', function() { build.__set__('prepare.applyPlatformConfig', function() {} ); createConfigParserMock(null, 'unsupported value here'); - build.run([ 'node', buildPath, '--phone' ]) + build.run({argv: ['--phone']}) .fail(function(error) { errorSpy(); expect(error).toBeDefined(); @@ -339,7 +339,7 @@ describe('run method', function() { // provision config to target Windows 8.1 createConfigParserMock('8.1', '8.1'); // explicitly specify Windows 10 as target - build.run([ 'node', buildPath, '--appx=uap' ]) + build.run({argv: ['--appx=uap']}) .finally(function() { expect(buildSpy).toHaveBeenCalled(); done(); http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/58047a3d/spec/unit/deployment.spec.js ---------------------------------------------------------------------- diff --git a/spec/unit/deployment.spec.js b/spec/unit/deployment.spec.js index 46393bb..97365fb 100644 --- a/spec/unit/deployment.spec.js +++ b/spec/unit/deployment.spec.js @@ -19,10 +19,8 @@ var rewire = require('rewire'), deployment = rewire('../../template/cordova/lib/deployment'), - run = deployment.__get__('run'), Q = require('q'), path = require('path'), - AppDeployCmdTool = deployment.__get__('AppDeployCmdTool'), WinAppDeployCmdTool = deployment.__get__('WinAppDeployCmdTool'); @@ -44,12 +42,11 @@ describe('The correct version of the app deployment tool is obtained.', function expect(tool instanceof WinAppDeployCmdTool).toBe(true); }); - }); describe('Windows 10 deployment interacts with the file system as expected.', function() { - function runMock(cmd, args, cwd) { + function fakeSpawn(cmd, args, cwd) { expect(cmd).toBe(path.join('c:/Program Files (x86)/Windows Kits/10/bin/x86/WinAppDeployCmd.exe')); switch (args[0]) { case 'devices': @@ -70,13 +67,16 @@ describe('Windows 10 deployment interacts with the file system as expected.', fu } } + var mockedSpawn = deployment.__get__('spawn'); var mockedProgramFiles = process.env['ProgramFiles(x86)']; + beforeEach(function() { - deployment.__set__('run', runMock); + deployment.__set__('spawn', fakeSpawn); process.env['ProgramFiles(x86)'] = path.join('c:/Program Files (x86)'); }); + afterEach(function() { - deployment.__set__('run', run); + deployment.__set__('spawn', mockedSpawn); if (mockedProgramFiles) { process.env['ProgramFiles(x86)'] = mockedProgramFiles; } else { @@ -93,7 +93,7 @@ describe('Windows 10 deployment interacts with the file system as expected.', fu expect(deviceList[0].name).toBe('Lumia 1520 (RM-940)'); expect(deviceList[0].index).toBe(0); expect(deviceList[0].type).toBe('device'); - + done = true; }); @@ -107,7 +107,7 @@ describe('Windows 10 deployment interacts with the file system as expected.', fu deploymentTool.enumerateDevices().then(function(deviceList) { deploymentTool.installAppPackage(TEST_APP_PACKAGE_NAME, deviceList[0], /*shouldLaunch*/ false, /*shouldUpdate*/ false).then(function() { - // expect() calls are in the runMock function + // expect() calls are in the fakeSpawn function done = true; }); @@ -122,7 +122,7 @@ describe('Windows 10 deployment interacts with the file system as expected.', fu deploymentTool.enumerateDevices().then(function(deviceList) { deploymentTool.installAppPackage(TEST_APP_PACKAGE_NAME, deviceList[0], /*shouldLaunch*/ false, /*shouldUpdate*/ true).then(function() { - // expect() calls are in the runMock function + // expect() calls are in the fakeSpawn function done = true; }); @@ -137,7 +137,7 @@ describe('Windows 10 deployment interacts with the file system as expected.', fu deploymentTool.enumerateDevices().then(function(deviceList) { deploymentTool.uninstallAppPackage(TEST_APP_PACKAGE_ID, deviceList[2]).then(function() { - // expect() calls are in the runMock function + // expect() calls are in the fakeSpawn function done = true; }); @@ -145,12 +145,11 @@ describe('Windows 10 deployment interacts with the file system as expected.', fu waitsFor(function() { return done; }); }); - }); describe('Windows 8.1 deployment interacts with the file system as expected.', function() { - function runMock(cmd, args, cwd) { + function fakeSpawn(cmd, args, cwd) { expect(cmd).toBe(path.join('c:/Program Files (x86)/Microsoft SDKs/Windows Phone/v8.1/Tools/AppDeploy/AppDeployCmd.exe')); switch (args[0]) { case '/EnumerateDevices': @@ -176,13 +175,16 @@ describe('Windows 8.1 deployment interacts with the file system as expected.', f } } + var mockedSpawn = deployment.__get__('spawn'); var mockedProgramFiles = process.env['ProgramFiles(x86)']; + beforeEach(function() { - deployment.__set__('run', runMock); + deployment.__set__('spawn', fakeSpawn); process.env['ProgramFiles(x86)'] = path.join('c:/Program Files (x86)'); }); + afterEach(function() { - deployment.__set__('run', run); + deployment.__set__('spawn', mockedSpawn); if (mockedProgramFiles) { process.env['ProgramFiles(x86)'] = mockedProgramFiles; } else { @@ -216,7 +218,7 @@ describe('Windows 8.1 deployment interacts with the file system as expected.', f deploymentTool.enumerateDevices().then(function(deviceList) { deploymentTool.installAppPackage(TEST_APP_PACKAGE_NAME, deviceList[0], /*shouldLaunch*/ false, /*shouldUpdate*/ false).then(function() { - // expect() calls are in the runMock function + // expect() calls are in the fakeSpawn function done = true; }); @@ -230,7 +232,7 @@ describe('Windows 8.1 deployment interacts with the file system as expected.', f deploymentTool.enumerateDevices().then(function(deviceList) { deploymentTool.installAppPackage(TEST_APP_PACKAGE_NAME, deviceList[0], /*shouldLaunch*/ false, /*shouldUpdate*/ true).then(function() { - // expect() calls are in the runMock function + // expect() calls are in the fakeSpawn function done = true; }); @@ -244,7 +246,7 @@ describe('Windows 8.1 deployment interacts with the file system as expected.', f deploymentTool.enumerateDevices().then(function(deviceList) { deploymentTool.installAppPackage(TEST_APP_PACKAGE_NAME, deviceList[0], /*shouldLaunch*/ true, /*shouldUpdate*/ false).then(function() { - // expect() calls are in the runMock function + // expect() calls are in the fakeSpawn function done = true; }); @@ -258,7 +260,7 @@ describe('Windows 8.1 deployment interacts with the file system as expected.', f deploymentTool.enumerateDevices().then(function(deviceList) { deploymentTool.installAppPackage(TEST_APP_PACKAGE_NAME, deviceList[0], /*shouldLaunch*/ true, /*shouldUpdate*/ true).then(function() { - // expect() calls are in the runMock function + // expect() calls are in the fakeSpawn function done = true; }); @@ -272,12 +274,11 @@ describe('Windows 8.1 deployment interacts with the file system as expected.', f deploymentTool.enumerateDevices().then(function(deviceList) { deploymentTool.uninstallAppPackage(TEST_APP_PACKAGE_ID, deviceList[5]).then(function() { - // expect() calls are in the runMock function + // expect() calls are in the fakeSpawn function done = true; }); }); waitsFor(function() { return done; }); }); - -}); \ No newline at end of file +}); http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/58047a3d/spec/unit/run.spec.js ---------------------------------------------------------------------- diff --git a/spec/unit/run.spec.js b/spec/unit/run.spec.js index 3171dfb..179c4a7 100644 --- a/spec/unit/run.spec.js +++ b/spec/unit/run.spec.js @@ -89,7 +89,7 @@ describe('run method', function() { return Q.reject(); // rejecting to break run chain }); - run.run([ 'node', buildPath, '--release', '--debug' ]) + run.run({ release: true, debug: true }) .finally(function() { expect(buildRun).not.toHaveBeenCalled(); done(); @@ -105,7 +105,7 @@ describe('run method', function() { return Q.reject(); // rejecting to break run chain }); - run.run([ 'node', buildPath, '--device', '--emulator' ]) + run.run({ device: true, emulator: true }) .finally(function() { expect(buildRun).not.toHaveBeenCalled(); done(); @@ -121,7 +121,7 @@ describe('run method', function() { return Q.reject(); // rejecting to break run chain }); - run.run([ 'node', buildPath, '--device', '--target=sometargethere' ]) + run.run({ device: true, target: 'sometargethere' }) .finally(function() { expect(buildRun).not.toHaveBeenCalled(); done(); @@ -237,7 +237,7 @@ describe('run method', function() { return Q(); }); - run.run([ 'node', buildPath, '--nobuild' ]) + run.run({ nobuild: true }) .finally(function() { expect(deployToDesktop).toHaveBeenCalled(); expect(build).not.toHaveBeenCalled(); http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/58047a3d/template/cordova/Api.js ---------------------------------------------------------------------- diff --git a/template/cordova/Api.js b/template/cordova/Api.js new file mode 100644 index 0000000..5803817 --- /dev/null +++ b/template/cordova/Api.js @@ -0,0 +1,470 @@ +/** + 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 Q = require('q'); +var fs = require('fs'); +var path = require('path'); +var shell = require('shelljs'); + +var JsprojManager = require('./lib/JsprojManager'); +var PluginHandler = require('./lib/PluginHandler'); +var ConsoleLogger = require('./lib/ConsoleLogger'); +var ActionStack = require('cordova-common').ActionStack; +var CordovaError = require('cordova-common').CordovaError; +var PlatformJson = require('cordova-common').PlatformJson; +var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger; +var PluginInfoProvider = require('cordova-common').PluginInfoProvider; + +var PLATFORM = 'windows'; + +/** + * Class, that acts as abstraction over particular platform. Encapsulates the + * platform's properties and methods. + * + * Platform that implements own PlatformApi instance _should implement all + * prototype methods_ of this class to be fully compatible with cordova-lib. + * + * The PlatformApi instance also should define the following field: + * + * * platform: String that defines a platform name. + */ +function Api(platform, platformRootDir, events) { + this.platform = PLATFORM; + this.root = path.resolve(__dirname, '..'); + this.events = events || ConsoleLogger.get(); + // NOTE: trick to share one EventEmitter instance across all js code + require('cordova-common').events = this.events; + + this._platformJson = PlatformJson.load(this.root, platform); + this._pluginInfoProvider = new PluginInfoProvider(); + this._munger = new PlatformMunger(this.platform, this.root, this._platformJson, this._pluginInfoProvider); + + var self = this; + + this.locations = { + root: self.root, + www: path.join(self.root, 'www'), + platformWww: path.join(self.root, 'platform_www'), + configXml: path.join(self.root, 'config.xml'), + defaultConfigXml: path.join(self.root, 'cordova/defaults.xml'), + // NOTE: Due to platformApi spec we need to return relative paths here + cordovaJs: 'template/www/cordova.js', + cordovaJsSrc: 'cordova-js-src' + }; +} + +/** + * Installs platform to specified directory and creates a platform project. + * + * @param {String} destinationDir A directory, where platform should be + * created/installed. + * @param {ConfigParser} [projectConfig] A ConfigParser instance, used to get + * some application properties for new platform like application name, package + * id, etc. If not defined, this means that platform is used as standalone + * project and is not a part of cordova project, so platform will use some + * default values. + * @param {Object} [options] An options object. The most common options are: + * @param {String} [options.customTemplate] A path to custom template, that + * should override the default one from platform. + * @param {Boolean} [options.link=false] Flag that indicates that platform's + * sources will be linked to installed platform instead of copying. + * + * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi + * instance or rejected with CordovaError. + */ +Api.createPlatform = function (destinationDir, projectConfig, options, events) { + return require('../../bin/lib/create') + .create(destinationDir, projectConfig, options, events || ConsoleLogger.get()) + .then(function () { + var PlatformApi = require(path.resolve(destinationDir, 'cordova/Api')); + return new PlatformApi(PLATFORM, destinationDir, events); + }); +}; + +/** + * Updates already installed platform. + * + * @param {String} destinationDir A directory, where existing platform + * installed, that should be updated. + * @param {Object} [options] An options object. The most common options are: + * @param {String} [options.customTemplate] A path to custom template, that + * should override the default one from platform. + * @param {Boolean} [options.link=false] Flag that indicates that platform's sources + * will be linked to installed platform instead of copying. + * + * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi + * instance or rejected with CordovaError. + */ +Api.updatePlatform = function (destinationDir, options, events) { + return require('../../bin/lib/update') + .update(destinationDir, options, events || ConsoleLogger.get()) + .then(function () { + var PlatformApi = require(path.resolve(destinationDir, 'cordova/Api')); + return new PlatformApi(PLATFORM, destinationDir, events); + }); +}; + +/** + * Gets a CordovaPlatform object, that represents the platform structure. + * + * @return {CordovaPlatform} A structure that contains the description of + * platform's file structure and other properties of platform. + */ +Api.prototype.getPlatformInfo = function () { + + var result = {}; + result.locations = this.locations; + result.root = this.root; + result.name = this.platform; + result.version = require('./version'); + result.projectConfig = this._config; + + return result; +}; + +/** + * Updates installed platform with provided www assets and new app + * configuration. This method is required for CLI workflow and will be called + * each time before build, so the changes, made to app configuration and www + * code, will be applied to platform. + * + * @param {CordovaProject} cordovaProject A CordovaProject instance, that defines a + * project structure and configuration, that should be applied to platform + * (contains project's www location and ConfigParser instance for project's + * config). + * + * @return {Promise} Return a promise either fulfilled, or rejected with + * CordovaError instance. + */ +Api.prototype.prepare = function (cordovaProject) { + return require('./lib/prepare').prepare.call(this, cordovaProject); +}; + +/** + * Installs a new plugin into platform. This method only copies non-www files + * (sources, libs, etc.) to platform. It also doesn't resolves the + * dependencies of plugin. Both of handling of www files, such as assets and + * js-files and resolving dependencies are the responsibility of caller. + * + * @param {PluginInfo} plugin A PluginInfo instance that represents plugin + * that will be installed. + * @param {Object} installOptions An options object. Possible options below: + * @param {Boolean} installOptions.link: Flag that specifies that plugin + * sources will be symlinked to app's directory instead of copying (if + * possible). + * @param {Object} installOptions.variables An object that represents + * variables that will be used to install plugin. See more details on plugin + * variables in documentation: + * https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html + * + * @return {Promise} Return a promise either fulfilled, or rejected with + * CordovaError instance. + */ +Api.prototype.addPlugin = function (plugin, installOptions) { + + if (!plugin || plugin.constructor.name !== 'PluginInfo') + return Q.reject(new CordovaError('The parameter is incorrect. The first parameter ' + + 'should be valid PluginInfo instance')); + + installOptions = installOptions || {}; + installOptions.variables = installOptions.variables || {}; + + var self = this; + var actions = new ActionStack(); + var jsProject = JsprojManager.getProject(this.root); + + // Add PACKAGE_NAME variable into vars + if (!installOptions.variables.PACKAGE_NAME) { + installOptions.variables.PACKAGE_NAME = jsProject.getPackageName(); + } + + // gather all files needs to be handled during install + plugin.getFilesAndFrameworks(this.platform) + .concat(plugin.getAssets(this.platform)) + .concat(plugin.getJsModules(this.platform)) + .forEach(function(item) { + actions.push(actions.createAction( + PluginHandler.getInstaller(item.itemType), [item, plugin, jsProject, installOptions], + PluginHandler.getUninstaller(item.itemType), [item, plugin, jsProject, installOptions])); + }); + + // run through the action stack + return actions.process(this.platform) + .then(function () { + jsProject.write(); + + self._munger + // Ignore passed `is_top_level` option since platform itself doesn't know + // anything about managing dependencies - it's responsibility of caller. + .add_plugin_changes(plugin, installOptions.variables, /*is_top_level=*/true, /*should_increment=*/true) + .save_all(); + + var targetDir = installOptions.usePlatformWww ? + self.getPlatformInfo().locations.platformWww : + self.getPlatformInfo().locations.www; + + self._addModulesInfo(plugin, targetDir); + }); +}; + +/** + * Removes an installed plugin from platform. + * + * Since method accepts PluginInfo instance as input parameter instead of plugin + * id, caller shoud take care of managing/storing PluginInfo instances for + * future uninstalls. + * + * @param {PluginInfo} plugin A PluginInfo instance that represents plugin + * that will be installed. + * + * @return {Promise} Return a promise either fulfilled, or rejected with + * CordovaError instance. + */ +Api.prototype.removePlugin = function (plugin, uninstallOptions) { + + var self = this; + var actions = new ActionStack(); + var projectFile = JsprojManager.getProject(this.root); + + // queue up plugin files + plugin.getFilesAndFrameworks(this.platform) + .concat(plugin.getAssets(this.platform)) + .concat(plugin.getJsModules(this.platform)) + .forEach(function(item) { + actions.push(actions.createAction( + PluginHandler.getUninstaller(item.itemType), [item, plugin, projectFile, uninstallOptions], + PluginHandler.getInstaller(item.itemType), [item, plugin, projectFile, uninstallOptions])); + }); + + // run through the action stack + return actions.process(this.platform) + .then(function() { + projectFile.write(); + + self._munger + // Ignore passed `is_top_level` option since platform itself doesn't know + // anything about managing dependencies - it's responsibility of caller. + .remove_plugin_changes(plugin, /*is_top_level=*/true) + .save_all(); + + var targetDir = uninstallOptions.usePlatformWww ? + self.getPlatformInfo().locations.platformWww : + self.getPlatformInfo().locations.www; + + self._removeModulesInfo(plugin, targetDir); + // Remove stale plugin directory + shell.rm('-rf', path.resolve(self.root, 'Plugins', plugin.id)); + }); +}; + + +/** + * Builds an application package for current platform. + * + * @param {Object} buildOptions A build options. This object's structure is + * highly depends on platform's specific. The most common options are: + * @param {Boolean} buildOptions.debug Indicates that packages should be + * built with debug configuration. This is set to true by default unless the + * 'release' option is not specified. + * @param {Boolean} buildOptions.release Indicates that packages should be + * built with release configuration. If not set to true, debug configuration + * will be used. + * @param {Boolean} buildOptions.device Specifies that built app is intended + * to run on device + * @param {Boolean} buildOptions.emulator: Specifies that built app is + * intended to run on emulator + * @param {String} buildOptions.target Specifies the device id that will be + * used to run built application. + * @param {Boolean} buildOptions.nobuild Indicates that this should be a + * dry-run call, so no build artifacts will be produced. + * @param {String[]} buildOptions.archs Specifies chip architectures which + * app packages should be built for. List of valid architectures is depends on + * platform. + * @param {String} buildOptions.buildConfig The path to build configuration + * file. The format of this file is depends on platform. + * @param {String[]} buildOptions.argv Raw array of command-line arguments, + * passed to `build` command. The purpose of this property is to pass a + * platform-specific arguments, and eventually let platform define own + * arguments processing logic. + * + * @return {Promise<Object[]>} A promise either fulfilled with an array of build + * artifacts (application packages) if package was built successfully, + * or rejected with CordovaError. The resultant build artifact objects is not + * strictly typed and may conatin arbitrary set of fields as in sample below. + * + * { + * architecture: 'x86', + * buildType: 'debug', + * path: '/path/to/build', + * type: 'app' + * } + * + * The return value in most cases will contain only one item but in some cases + * there could be multiple items in output array, e.g. when multiple + * arhcitectures is specified. + */ +Api.prototype.build = function(buildOptions) { + // TODO: Should we run check_reqs first? Android does this, but Windows appears doesn't. + return require('./lib/build').run.call(this, buildOptions) + .then(function (result) { + // Wrap result into array according to PlatformApi spec + return [result]; + }); +}; + +/** + * Builds an application package for current platform and runs it on + * specified/default device. If no 'device'/'emulator'/'target' options are + * specified, then tries to run app on default device if connected, otherwise + * runs the app on emulator. + * + * @param {Object} runOptions An options object. The structure is the same + * as for build options. + * + * @return {Promise} A promise either fulfilled if package was built and ran + * successfully, or rejected with CordovaError. + */ +Api.prototype.run = function(runOptions) { + // TODO: Should we run check_reqs first? Android does this, but Windows appears doesn't. + return require('./lib/run').run.call(this, runOptions); +}; + +/** + * Cleans out the build artifacts from platform's directory. + * + * @return {Promise} Return a promise either fulfilled, or rejected with + * CordovaError. + */ +Api.prototype.clean = function(cleanOpts) { + return require('./lib/build').clean.call(this, cleanOpts); +}; + +/** + * Performs a requirements check for current platform. Each platform defines its + * own set of requirements, which should be resolved before platform can be + * built successfully. + * + * @return {Promise<Requirement[]>} Promise, resolved with set of Requirement + * objects for current platform. + */ +Api.prototype.requirements = function() { + return require('./lib/check_reqs').check_all(); +}; + +module.exports = Api; + +/** + * Removes the specified modules from list of installed modules and updates + * platform_json and cordova_plugins.js on disk. + * + * @param {PluginInfo} plugin PluginInfo instance for plugin, which modules + * needs to be added. + * @param {String} targetDir The directory, where updated cordova_plugins.js + * should be written to. + */ +Api.prototype._addModulesInfo = function(plugin, targetDir) { + var installedModules = this._platformJson.root.modules || []; + + var installedPaths = installedModules.map(function (installedModule) { + return installedModule.file; + }); + + var modulesToInstall = plugin.getJsModules(this.platform) + .filter(function (moduleToInstall) { + return installedPaths.indexOf(moduleToInstall.file) === -1; + }).map(function (moduleToInstall) { + var moduleName = plugin.id + '.' + ( moduleToInstall.name || moduleToInstall.src.match(/([^\/]+)\.js/)[1] ); + var obj = { + file: ['plugins', plugin.id, moduleToInstall.src].join('/'), + id: moduleName, + pluginId: plugin.id + }; + if (moduleToInstall.clobbers.length > 0) { + obj.clobbers = moduleToInstall.clobbers.map(function(o) { return o.target; }); + } + if (moduleToInstall.merges.length > 0) { + obj.merges = moduleToInstall.merges.map(function(o) { return o.target; }); + } + if (moduleToInstall.runs) { + obj.runs = true; + } + + return obj; + }); + + this._platformJson.root.modules = installedModules.concat(modulesToInstall); + this._writePluginModules(targetDir); + this._platformJson.save(); +}; + +/** + * Removes the specified modules from list of installed modules and updates + * platform_json and cordova_plugins.js on disk. + * + * @param {PluginInfo} plugin PluginInfo instance for plugin, which modules + * needs to be removed. + * @param {String} targetDir The directory, where updated cordova_plugins.js + * should be written to. + */ +Api.prototype._removeModulesInfo = function(plugin, targetDir) { + var installedModules = this._platformJson.root.modules || []; + var modulesToRemove = plugin.getJsModules(this.platform) + .map(function (jsModule) { + return ['plugins', plugin.id, jsModule.src].join('/'); + }); + + var updatedModules = installedModules + .filter(function (installedModule) { + return (modulesToRemove.indexOf(installedModule.file) === -1); + }); + + this._platformJson.root.modules = updatedModules; + this._writePluginModules(targetDir); + this._platformJson.save(); +}; + +/** + * Fetches all installed modules, generates cordova_plugins contents and writes + * it to file. + * + * @param {String} targetDir Directory, where write cordova_plugins.js to. + * Ususally it is either <platform>/www or <platform>/platform_www + * directories. + */ +Api.prototype._writePluginModules = function (targetDir) { + var self = this; + // Write out moduleObjects as JSON wrapped in a cordova module to cordova_plugins.js + var final_contents = 'cordova.define(\'cordova/plugin_list\', function(require, exports, module) {\n'; + final_contents += 'module.exports = ' + JSON.stringify(this._platformJson.root.modules, null, ' ') + ';\n'; + final_contents += 'module.exports.metadata = \n'; + final_contents += '// TOP OF METADATA\n'; + + var pluginMetadata = Object.keys(this._platformJson.root.installed_plugins) + .reduce(function (metadata, plugin) { + metadata[plugin] = self._platformJson.root.installed_plugins[plugin].version; + return metadata; + }, {}); + + final_contents += JSON.stringify(pluginMetadata, null, ' ') + '\n'; + final_contents += '// BOTTOM OF METADATA\n'; + final_contents += '});'; // Close cordova.define. + + shell.mkdir('-p', targetDir); + fs.writeFileSync(path.join(targetDir, 'cordova_plugins.js'), final_contents, 'utf-8'); +}; http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/58047a3d/template/cordova/build ---------------------------------------------------------------------- diff --git a/template/cordova/build b/template/cordova/build index 8fbceae..181cd63 100644 --- a/template/cordova/build +++ b/template/cordova/build @@ -19,16 +19,62 @@ under the License. */ -var build = require('./lib/build'), - args = process.argv; - -// Handle help flag -if (['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(args[2]) > -1) { - build.help(); -} else { - build.run(args).done(null, function(err) { - var errorMessage = (err && err.stack) ? err.stack : err; - console.error('ERROR: ' + errorMessage); - process.exit(2); - }); -} \ No newline at end of file +var Api = require('./Api'); +var nopt = require('nopt'); +var path = require('path'); + +// Support basic help commands +if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) { + console.log(''); + console.log('Usage: build [--debug | --release] [--phone | --win] [--bundle]'); + console.log(' [--archs="<list of architectures...>"'); + console.log(' [--packageCertificateKeyFile="key path"]'); + console.log(' [--packageThumbprint="thumbprint"] [--publisherId]'); + console.log(' [--buildConfig="file path"]'); + console.log(' --help : Displays this dialog.'); + console.log(' --debug : Builds project in debug mode. (Default).'); + console.log(' --release (-r) : Builds project in release mode.'); + console.log(' --phone, --win : Specifies, what type of project to build.'); + console.log(' --bundle : Tells the compiler to create a .appxbundle.'); + console.log(' Bundling is disabled when `anycpu` is built.'); + console.log(' --archs : Builds project binaries for specific chip'); + console.log(' architectures (`anycpu`, `arm`, `x86`, `x64`).'); + console.log(' Separate multiple choices with spaces and if'); + console.log(' passing multiple choices, enclose with " ".'); + console.log(' --appx=<8.1-win|8.1-phone|uap>'); + console.log(' : Overrides windows-target-version to build'); + console.log(' Windows 8.1, Windows Phone 8.1, or'); + console.log(' Windows 10 Universal.'); + console.log(' --packageCertificateKeyFile : Builds the project using provided certificate.'); + console.log(' --packageThumbprint : Thumbprint associated with the certificate.'); + console.log(' --publisherId : Sets publisher id field in manifest.'); + console.log(' --buildConfig : Sets build settings from configuration file.'); + console.log(''); + console.log('examples:'); + console.log(' build '); + console.log(' build --debug'); + console.log(' build --release'); + console.log(' build --release --archs="arm x86" --bundle'); + console.log(' build --appx=8.1-phone -r'); + console.log(' build --packageCertificateKeyFile="CordovaApp_TemporaryKey.pfx"'); + console.log(' build --publisherId="CN=FakeCorp, C=US"'); + console.log(' build --buildConfig="build.json"'); + console.log(''); + + process.exit(0); +} + +// Do some basic argument parsing +var buildOpts = nopt({ + 'silent' : Boolean, + 'verbose' : Boolean, + 'debug' : Boolean, + 'release' : Boolean, + 'nobuild': Boolean, + 'buildConfig' : path +}, { d : '--verbose', r: '--release' }); + +// Make buildOptions compatible with PlatformApi build method spec +buildOpts.argv = buildOpts.argv.original; + +new Api().build(buildOpts).done(); http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/58047a3d/template/cordova/clean ---------------------------------------------------------------------- diff --git a/template/cordova/clean b/template/cordova/clean index 71877fe..2964746 100644 --- a/template/cordova/clean +++ b/template/cordova/clean @@ -19,9 +19,13 @@ under the License. */ -var clean = require('./lib/clean'); +var Api = require('./Api'); -clean.run(process.argv).done(null, function(err) { - console.error('ERROR: ' + err); - process.exit(2); -}); \ No newline at end of file +// Support basic help commands +if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) { + console.log('Usage: \n clean\n'); + console.log('Cleans the project directory.'); + process.exit(0); +} + +new Api().clean().done(); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
