123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- /**
- 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 create = rewire('../../bin/lib/create');
- var check_reqs = require('../../bin/templates/cordova/lib/check_reqs');
- var fs = require('fs');
- var path = require('path');
- var Q = require('q');
- var shell = require('shelljs');
-
- describe('create', function () {
- describe('validatePackageName helper method', function () {
- describe('happy path (valid package names)', function () {
- var valid = [
- 'org.apache.mobilespec',
- 'com.example',
- 'com.floors42.package',
- 'ball8.ball8.ball8ball'
- ];
- valid.forEach(function (package_name) {
- it('Test#001 : should accept ' + package_name, () => {
- return create.validatePackageName(package_name);
- });
- });
- });
-
- describe('failure cases (invalid package names)', function () {
- function expectPackageNameToBeRejected (name) {
- return create.validatePackageName(name).then(() => {
- fail('Expected promise to be rejected');
- }, err => {
- expect(err).toEqual(jasmine.any(Error));
- expect(err.message).toContain('Error validating package name');
- });
- }
-
- it('should reject empty package names', () => {
- return expectPackageNameToBeRejected('');
- });
- it('should reject package names containing "class"', () => {
- return expectPackageNameToBeRejected('com.class.is.bad');
- });
- it('should reject package names that do not start with a latin letter', () => {
- return expectPackageNameToBeRejected('_un.der.score');
- });
- it('should reject package names with terms that do not start with a latin letter', () => {
- return expectPackageNameToBeRejected('un._der.score');
- });
- it('should reject package names containing non-alphanumeric or underscore characters', () => {
- return expectPackageNameToBeRejected('th!$.!$.b@d');
- });
- it('should reject package names that do not contain enough dots', () => {
- return expectPackageNameToBeRejected('therearenodotshere');
- });
- it('should reject package names that end with a dot', () => {
- return expectPackageNameToBeRejected('this.is.a.complete.sentence.');
- });
- });
- });
- describe('validateProjectName helper method', function () {
- describe('happy path (valid project names)', function () {
- var valid = [
- 'mobilespec',
- 'package_name',
- 'PackageName',
- 'CordovaLib'
- ];
- valid.forEach(function (project_name) {
- it('Test#003 : should accept ' + project_name, () => {
- return create.validateProjectName(project_name);
- });
- });
- });
- describe('failure cases (invalid project names)', function () {
- it('should reject empty project names', () => {
- return create.validateProjectName('').then(() => {
- fail('Expected promise to be rejected');
- }, err => {
- expect(err).toEqual(jasmine.any(Error));
- expect(err.message).toContain('Project name cannot be empty');
- });
- });
- it('should reject "CordovaActivity" as a project name', () => {
- return create.validateProjectName('CordovaActivity').then(() => {
- fail('Expected promise to be rejected');
- }, err => {
- expect(err).toEqual(jasmine.any(Error));
- expect(err.message).toContain('Project name cannot be CordovaActivity');
- });
- });
- it('should reject project names that begin with a number', () => {
- return create.validateProjectName('1337').then(() => {
- fail('Expected promise to be rejected');
- }, err => {
- expect(err).toEqual(jasmine.any(Error));
- expect(err.message).toContain('Project name must not begin with a number');
- });
- });
- });
- });
- describe('main method', function () {
- var config_mock;
- var events_mock;
- var Manifest_mock = function () {};
- var revert_manifest_mock;
- var project_path = path.join('some', 'path');
- var app_path = path.join(project_path, 'app', 'src', 'main');
- var default_templates = path.join(__dirname, '..', '..', 'bin', 'templates', 'project');
- var fake_android_target = 'android-1337';
- beforeEach(function () {
- Manifest_mock.prototype = jasmine.createSpyObj('AndroidManifest instance mock', ['setPackageId', 'getActivity', 'setName', 'write']);
- Manifest_mock.prototype.setPackageId.and.returnValue(new Manifest_mock());
- Manifest_mock.prototype.getActivity.and.returnValue(new Manifest_mock());
- Manifest_mock.prototype.setName.and.returnValue(new Manifest_mock());
- spyOn(create, 'validatePackageName').and.returnValue(Q());
- spyOn(create, 'validateProjectName').and.returnValue(Q());
- spyOn(create, 'setShellFatal').and.callFake(function (noop, cb) { cb(); });
- spyOn(create, 'copyJsAndLibrary');
- spyOn(create, 'copyScripts');
- spyOn(create, 'copyBuildRules');
- spyOn(create, 'writeProjectProperties');
- spyOn(create, 'prepBuildFiles');
- revert_manifest_mock = create.__set__('AndroidManifest', Manifest_mock);
- spyOn(fs, 'existsSync').and.returnValue(false);
- spyOn(shell, 'cp');
- spyOn(shell, 'mkdir');
- spyOn(shell, 'sed');
- config_mock = jasmine.createSpyObj('ConfigParser mock instance', ['packageName', 'android_packageName', 'name', 'android_activityName']);
- events_mock = jasmine.createSpyObj('EventEmitter mock instance', ['emit']);
- spyOn(check_reqs, 'get_target').and.returnValue(fake_android_target);
- });
- afterEach(function () {
- revert_manifest_mock();
- });
- describe('parameter values and defaults', function () {
- it('should have a default package name of my.cordova.project', () => {
- config_mock.packageName.and.returnValue(undefined);
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(create.validatePackageName).toHaveBeenCalledWith('my.cordova.project');
- });
- });
- it('should use the ConfigParser-provided package name, if exists', () => {
- config_mock.packageName.and.returnValue('org.apache.cordova');
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(create.validatePackageName).toHaveBeenCalledWith('org.apache.cordova');
- });
- });
- it('should have a default project name of CordovaExample', () => {
- config_mock.name.and.returnValue(undefined);
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(create.validateProjectName).toHaveBeenCalledWith('CordovaExample');
- });
- });
- it('should use the ConfigParser-provided project name, if exists', () => {
- config_mock.name.and.returnValue('MySweetAppName');
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(create.validateProjectName).toHaveBeenCalledWith('MySweetAppName');
- });
- });
- it('should replace any non-word characters (including unicode and spaces) in the ConfigParser-provided project name with underscores', () => {
- config_mock.name.and.returnValue('応応応応 hello 用用用用');
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(create.validateProjectName).toHaveBeenCalledWith('_____hello_____');
- });
- });
- it('should have a default activity name of MainActivity', () => {
- config_mock.android_activityName.and.returnValue(undefined);
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(Manifest_mock.prototype.setName).toHaveBeenCalledWith('MainActivity');
- });
- });
- it('should use the activityName provided via options parameter, if exists', () => {
- config_mock.android_activityName.and.returnValue(undefined);
- return create.create(project_path, config_mock, { activityName: 'AwesomeActivity' }, events_mock).then(() => {
- expect(Manifest_mock.prototype.setName).toHaveBeenCalledWith('AwesomeActivity');
- });
- });
- it('should use the ConfigParser-provided activity name, if exists', () => {
- config_mock.android_activityName.and.returnValue('AmazingActivity');
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(Manifest_mock.prototype.setName).toHaveBeenCalledWith('AmazingActivity');
- });
- });
- });
- describe('failure', function () {
- it('should fail if the target path already exists', () => {
- fs.existsSync.and.returnValue(true);
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- fail('Expected promise to be rejected');
- }, err => {
- expect(err).toEqual(jasmine.any(Error));
- expect(err.message).toContain('Project already exists!');
- });
- });
- it('should fail if validateProjectName rejects', () => {
- const fakeError = new Error();
- create.validateProjectName.and.callFake(() => Promise.reject(fakeError));
-
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- fail('Expected promise to be rejected');
- }, err => {
- expect(err).toBe(fakeError);
- });
-
- });
- });
- describe('happy path', function () {
- it('should copy project templates from a specified custom template', () => {
- return create.create(project_path, config_mock, { customTemplate: '/template/path' }, events_mock).then(() => {
- expect(shell.cp).toHaveBeenCalledWith('-r', path.join('/template/path', 'assets'), app_path);
- expect(shell.cp).toHaveBeenCalledWith('-r', path.join('/template/path', 'res'), app_path);
- expect(shell.cp).toHaveBeenCalledWith(path.join('/template/path', 'gitignore'), path.join(project_path, '.gitignore'));
- });
- });
- it('should copy project templates from the default templates location if no custom template is provided', () => {
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(shell.cp).toHaveBeenCalledWith('-r', path.join(default_templates, 'assets'), app_path);
- expect(shell.cp).toHaveBeenCalledWith('-r', path.join(default_templates, 'res'), app_path);
- expect(shell.cp).toHaveBeenCalledWith(path.join(default_templates, 'gitignore'), path.join(project_path, '.gitignore'));
- });
- });
- it('should copy JS and library assets', () => {
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(create.copyJsAndLibrary).toHaveBeenCalled();
- });
- });
- it('should create a java src directory based on the provided project package name', () => {
- config_mock.packageName.and.returnValue('org.apache.cordova');
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(shell.mkdir).toHaveBeenCalledWith('-p', path.join(app_path, 'java', 'org', 'apache', 'cordova'));
- });
- });
- it('should copy, rename and interpolate the template Activity java class with the project-specific activity name and package name', () => {
- config_mock.packageName.and.returnValue('org.apache.cordova');
- config_mock.android_activityName.and.returnValue('CEEDEEVEE');
- var activity_path = path.join(app_path, 'java', 'org', 'apache', 'cordova', 'CEEDEEVEE.java');
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(shell.cp).toHaveBeenCalledWith('-f', path.join(default_templates, 'Activity.java'), activity_path);
- expect(shell.sed).toHaveBeenCalledWith('-i', /__ACTIVITY__/, 'CEEDEEVEE', activity_path);
- expect(shell.sed).toHaveBeenCalledWith('-i', /__ID__/, 'org.apache.cordova', activity_path);
- });
- });
- it('should interpolate the project name into strings.xml', () => {
- config_mock.name.and.returnValue('IncredibleApp');
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(shell.sed).toHaveBeenCalledWith('-i', /__NAME__/, 'IncredibleApp', path.join(app_path, 'res', 'values', 'strings.xml'));
- });
- });
- it('should copy template scripts into generated project', () => {
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(create.copyScripts).toHaveBeenCalledWith(project_path);
- });
- });
- it('should copy build rules / gradle files into generated project', () => {
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(create.copyBuildRules).toHaveBeenCalledWith(project_path);
- });
- });
- it('should write project.properties file with project details and target API', () => {
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(create.writeProjectProperties).toHaveBeenCalledWith(project_path, fake_android_target);
- });
- });
- it('should prepare build files', () => {
- return create.create(project_path, config_mock, {}, events_mock).then(() => {
- expect(create.prepBuildFiles).toHaveBeenCalledWith(project_path);
- });
- });
- });
- });
- });
|