CB-12517 : pkgjson displayname should equal config's name and pkgjson.name should...
[cordova-create.git] / spec / create.spec.js
1 /**
2 Licensed to the Apache Software Foundation (ASF) under one
3 or more contributor license agreements. See the NOTICE file
4 distributed with this work for additional information
5 regarding copyright ownership. The ASF licenses this file
6 to you under the Apache License, Version 2.0 (the
7 "License"); you may not use this file except in compliance
8 with the License. You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing,
13 software distributed under the License is distributed on an
14 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 KIND, either express or implied. See the License for the
16 specific language governing permissions and limitations
17 under the License.
18 */
19
20 var helpers = require('./helpers'),
21 path = require('path'),
22 shell = require('shelljs'),
23 events = require('cordova-common').events,
24 ConfigParser = require('cordova-common').ConfigParser,
25 create = require('../index'),
26 fs = require('fs'),
27 CordovaLogger = require('cordova-common').CordovaLogger.get().setLevel('error');
28
29 var tmpDir = helpers.tmpDir('create_test');
30 var appName = 'TestBase';
31 var appId = 'org.testing';
32 var project = path.join(tmpDir, appName);
33
34 var configSubDirPkgJson = {
35 lib: {
36 www: {
37 template: true,
38 url: path.join(__dirname, 'templates', 'withsubdirectory_package_json'),
39 version: ''
40 }
41 }
42 };
43
44 var configConfigInWww = {
45 lib: {
46 www: {
47 template: true,
48 url: path.join(__dirname, 'templates', 'config_in_www'),
49 version: ''
50 }
51 }
52 };
53
54 var configGit = {
55 lib: {
56 www: {
57 url: 'https://github.com/apache/cordova-app-hello-world',
58 template: true,
59 version: 'not_versioned'
60 }
61 }
62 };
63
64 var configNPM = {
65 lib: {
66 www: {
67 template: true,
68 url: 'cordova-app-hello-world',
69 version: ''
70 }
71 }
72 };
73
74 describe('cordova create checks for valid-identifier', function() {
75 it('should reject reserved words from start of id', function(done) {
76 create('projectPath', 'int.bob', 'appName', {}, events)
77 .fail(function(err) {
78 expect(err.message).toBe('App id contains a reserved word, or is not a valid identifier.');
79 })
80 .fin(done);
81 }, 60000);
82
83 it('should reject reserved words from end of id', function(done) {
84 create('projectPath', 'bob.class', 'appName', {}, events)
85 .fail(function(err) {
86 expect(err.message).toBe('App id contains a reserved word, or is not a valid identifier.');
87 })
88 .fin(done);
89 }, 60000);
90 });
91
92
93 describe('create end-to-end', function() {
94 //this.timeout(240000);
95
96 beforeEach(function() {
97 shell.rm('-rf', project);
98 shell.mkdir('-p', tmpDir);
99 });
100
101
102 afterEach(function() {
103 process.chdir(path.join(__dirname, '..')); // Needed to rm the dir on Windows.
104 shell.rm('-rf', tmpDir);
105 });
106
107 function checkProject() {
108 // Check if top level dirs exist.
109 var dirs = ['hooks', 'platforms', 'plugins', 'www'];
110 dirs.forEach(function(d) {
111 expect(path.join(project, d)).toExist();
112 });
113
114 expect(path.join(project, 'hooks', 'README.md')).toExist();
115
116 // Check if www files exist.
117 expect(path.join(project, 'www', 'index.html')).toExist();
118
119 // Check that config.xml was updated.
120 var configXml = new ConfigParser(path.join(project, 'config.xml'));
121 expect(configXml.packageName()).toEqual(appId);
122
123 // TODO (kamrik): check somehow that we got the right config.xml from the fixture and not some place else.
124 // expect(configXml.name()).toEqual('TestBase');
125 }
126
127 function checkConfigXml() {
128 // Check if top level dirs exist.
129 var dirs = ['hooks', 'platforms', 'plugins', 'www'];
130 dirs.forEach(function(d) {
131 expect(path.join(project, d)).toExist();
132 });
133 expect(path.join(project, 'hooks', 'README.md')).toExist();
134
135 //index.js and template subdir folder should not exist (inner files should be copied to the project folder)
136 expect(path.join(project, 'index.js')).not.toExist();
137 expect(path.join(project, 'template')).not.toExist();
138
139 // Check if www files exist.
140 expect(path.join(project, 'www', 'index.html')).toExist();
141 var configXml = new ConfigParser(path.join(project, 'config.xml'));
142 expect(configXml.packageName()).toEqual(appId);
143 expect(configXml.version()).toEqual('1.0.0');
144
145 // Check that config.xml does not exist inside of www
146 expect(path.join(project, 'www', 'config.xml')).not.toExist();
147
148 // Check that we got no package.json
149 expect(path.join(project, 'package.json')).not.toExist();
150
151 // Check that we got the right config.xml from the template and not stock
152 expect(configXml.description()).toEqual('this is the correct config.xml');
153 }
154
155 function checkSubDir() {
156 // Check if top level dirs exist.
157 var dirs = ['hooks', 'platforms', 'plugins', 'www'];
158 dirs.forEach(function(d) {
159 expect(path.join(project, d)).toExist();
160 });
161 expect(path.join(project, 'hooks', 'README.md')).toExist();
162
163 //index.js and template subdir folder should not exist (inner files should be copied to the project folder)
164 expect(path.join(project, 'index.js')).not.toExist();
165 expect(path.join(project, 'template')).not.toExist();
166
167 // Check if config files exist.
168 expect(path.join(project, 'www', 'index.html')).toExist();
169
170 // Check that config.xml was updated.
171 var configXml = new ConfigParser(path.join(project, 'config.xml'));
172 expect(configXml.packageName()).toEqual(appId);
173 expect(configXml.version()).toEqual('1.0.0');
174
175
176 // Check that we got package.json (the correct one)
177 var pkjson = require(path.join(project, 'package.json'));
178 // Pkjson.displayName should equal config's name.
179 expect(pkjson.displayName).toEqual(appName);
180 expect(pkjson.valid).toEqual('true');
181
182 // Check that we got the right config.xml
183 expect(configXml.description()).toEqual('this is the correct config.xml');
184 }
185
186 var results;
187 events.on('results', function(res) { results = res; });
188
189 it('should successfully run with Git URL', function(done) {
190 // Call cordova create with no args, should return help.)
191 // Create a real project
192 return create(project, appId, appName, configGit, events)
193 .then(checkProject)
194 .fail(function(err) {
195 console.log(err && err.stack);
196 expect(err).toBeUndefined();
197 })
198 .fin(done);
199 }, 60000);
200
201 // it('should successfully run with NPM package', function(done) {
202 // // Call cordova create with no args, should return help.
203
204 // // Create a real project
205 // return create(project, appId, appName, configNPM)
206 // .then(checkProject)
207 // .fail(function(err) {
208 // console.log(err && err.stack);
209 // expect(err).toBeUndefined();
210 // })
211 // .fin(done);
212 // }, 60000);
213
214 it('should successfully run with template not having a package.json at toplevel', function(done) {
215 // Call cordova create with no args, should return help.
216 var config = {
217 lib: {
218 www: {
219 template: true,
220 url: path.join(__dirname, 'templates', 'nopackage_json'),
221 version: ''
222 }
223 }
224 };
225 // Create a real project
226 return create(project, appId, appName, config, events)
227 .then(checkProject)
228 .then(function(){
229 // Check that we got the right config.xml
230 var configXml = new ConfigParser(path.join(project, 'config.xml'));
231 expect(configXml.description()).toEqual('this is the very correct config.xml');
232 })
233 .fail(function(err) {
234 console.log(err && err.stack);
235 expect(err).toBeUndefined();
236 })
237 .fin(done);
238 }, 60000);
239
240 it('should successfully run with template having package.json and no sub directory', function(done) {
241 // Call cordova create with no args, should return help.
242 var config = {
243 lib: {
244 www: {
245 template: true,
246 url: path.join(__dirname, 'templates', 'withpackage_json'),
247 version: ''
248 }
249 }
250 };
251 // Create a real project
252 return create(project, appId, appName, config, events)
253 .then(checkProject)
254 .fail(function(err) {
255 console.log(err && err.stack);
256 expect(err).toBeUndefined();
257 })
258 .fin(done);
259 }, 60000);
260
261 it('should successfully run with template having package.json, and subdirectory, and no package.json in subdirectory', function(done) {
262 // Call cordova create with no args, should return help.
263 var config = {
264 lib: {
265 www: {
266 template: true,
267 url: path.join(__dirname, 'templates', 'withsubdirectory'),
268 version: ''
269 }
270 }
271 };
272
273 // Create a real project
274 return create(project, appId, appName, config, events)
275 .then(checkProject)
276 .fail(function(err) {
277 console.log(err && err.stack);
278 expect(err).toBeUndefined();
279 })
280 .fin(done);
281 }, 60000);
282
283
284 it('should successfully run with template having package.json, and subdirectory, and package.json in subdirectory', function(done) {
285 // Call cordova create with no args, should return help.
286 var config = configSubDirPkgJson;
287 return create(project, appId, appName, config, events)
288 .then(checkSubDir)
289 .fail(function(err) {
290 console.log(err && err.stack);
291 expect(err).toBeUndefined();
292 })
293 .fin(done);
294 }, 60000);
295
296 it('should successfully run config.xml in the www folder and move it outside', function(done) {
297 // Call cordova create with no args, should return help.
298 var config = configConfigInWww;
299 // Create a real project
300 return create(project, appId, appName, config, events)
301 .then(checkConfigXml)
302 .fail(function(err) {
303 console.log(err && err.stack);
304 expect(err).toBeUndefined();
305 })
306 .fin(done);
307 }, 60000);
308
309 it('should successfully run with www folder as the template', function(done) {
310 var config = {
311 lib: {
312 www: {
313 template: true,
314 url: path.join(__dirname, 'templates', 'config_in_www', 'www'),
315 version: ''
316 }
317 }
318 };
319 return create(project, appId, appName, config, events)
320 .then(checkConfigXml)
321 .fail(function(err) {
322 console.log(err && err.stack);
323 expect(err).toBeUndefined();
324 })
325 .fin(done);
326 }, 60000);
327
328 describe('when --link-to is provided', function() {
329 it('when passed www folder should not move www/config.xml, only copy and update', function(done) {
330 function checkSymWWW() {
331 // Check if top level dirs exist.
332 var dirs = ['hooks', 'platforms', 'plugins', 'www'];
333 dirs.forEach(function(d) {
334 expect(path.join(project, d)).toExist();
335 });
336 expect(path.join(project, 'hooks', 'README.md')).toExist();
337
338 // Check if www files exist.
339 expect(path.join(project, 'www', 'index.html')).toExist();
340
341 // Check www/config exists
342 expect(path.join(project, 'www', 'config.xml')).toExist();
343 // Check www/config.xml was not updated.
344 var configXml = new ConfigParser(path.join(project, 'www', 'config.xml'));
345 expect(configXml.packageName()).toEqual('io.cordova.hellocordova');
346 expect(configXml.version()).toEqual('0.0.1');
347 expect(configXml.description()).toEqual('this is the correct config.xml');
348
349 // Check that config.xml was copied to project/config.xml
350 expect(path.join(project, 'config.xml')).toExist();
351 configXml = new ConfigParser(path.join(project, 'config.xml'));
352 expect(configXml.description()).toEqual('this is the correct config.xml');
353 // Check project/config.xml was updated.
354 expect(configXml.packageName()).toEqual(appId);
355 expect(configXml.version()).toEqual('1.0.0');
356
357 // Check that we got no package.json
358 expect(path.join(project, 'package.json')).not.toExist();
359
360 // Check that www is really a symlink,
361 // and project/config.xml , hooks and merges are not
362 expect(fs.lstatSync(path.join(project, 'www')).isSymbolicLink()).toBe(true);
363 expect(fs.lstatSync(path.join(project, 'hooks')).isSymbolicLink()).not.toBe(true);
364 expect(fs.lstatSync(path.join(project, 'config.xml')).isSymbolicLink()).not.toBe(true);
365 }
366 var config = {
367 lib: {
368 www: {
369 template: true,
370 url: path.join(__dirname, 'templates', 'config_in_www', 'www'),
371 version: '',
372 link: true
373 }
374 }
375 };
376 return create(project, appId, appName, config, events)
377 .then(checkSymWWW)
378 .fail(function(err) {
379 if(process.platform.slice(0, 3) == 'win') {
380 // Allow symlink error if not in admin mode
381 expect(err.message).toBe('Symlinks on Windows require Administrator privileges');
382 } else {
383 if (err) {
384 console.log(err.stack);
385 }
386 expect(err).toBeUndefined();
387 }
388 })
389 .fin(done);
390 }, 60000);
391
392 it('with subdirectory should not update symlinked project/config.xml', function(done) {
393 function checkSymSubDir() {
394 // Check if top level dirs exist.
395 var dirs = ['hooks', 'platforms', 'plugins', 'www'];
396 dirs.forEach(function(d) {
397 expect(path.join(project, d)).toExist();
398 });
399 expect(path.join(project, 'hooks', 'README.md')).toExist();
400
401 //index.js and template subdir folder should not exist (inner files should be copied to the project folder)
402 expect(path.join(project, 'index.js')).not.toExist();
403 expect(path.join(project, 'template')).not.toExist();
404
405 // Check if www files exist.
406 expect(path.join(project, 'www', 'index.html')).toExist();
407
408 // Check that www, and config.xml is really a symlink
409 expect(fs.lstatSync(path.join(project, 'www')).isSymbolicLink()).toBe(true);
410 expect(fs.lstatSync(path.join(project, 'config.xml')).isSymbolicLink()).toBe(true);
411
412 // Check that config.xml was not updated. (symlinked config does not get updated!)
413 var configXml = new ConfigParser(path.join(project, 'config.xml'));
414 expect(configXml.packageName()).toEqual('io.cordova.hellocordova');
415 expect(configXml.version()).toEqual('0.0.1');
416
417 // Check that we got the right config.xml
418 expect(configXml.description()).toEqual('this is the correct config.xml');
419
420 // Check that we got package.json (the correct one) and it was changed
421 var pkjson = require(path.join(project, 'package.json'));
422 // Pkjson.name should equal config's id.
423 expect(pkjson.name).toEqual(appId.toLowerCase());
424 expect(pkjson.valid).toEqual('true');
425 }
426 var config = {
427 lib: {
428 www: {
429 template: true,
430 url: path.join(__dirname, 'templates', 'withsubdirectory_package_json'),
431 version: '',
432 link: true
433 }
434 }
435 };
436 return create(project, appId, appName, config, events)
437 .then(checkSymSubDir)
438 .fail(function(err) {
439 if(process.platform.slice(0, 3) == 'win') {
440 // Allow symlink error if not in admin mode
441 expect(err.message).toBe('Symlinks on Windows require Administrator privileges');
442 } else {
443 if (err) {
444 console.log(err.stack);
445 }
446 expect(err).toBeUndefined();
447 }
448 })
449 .fin(done);
450 }, 60000);
451
452 it('with no config should create one and update it', function(done) {
453 function checkSymNoConfig() {
454 // Check if top level dirs exist.
455 var dirs = ['hooks', 'platforms', 'plugins', 'www'];
456 dirs.forEach(function(d) {
457 expect(path.join(project, d)).toExist();
458 });
459 expect(path.join(project, 'hooks', 'hooks.file')).toExist();
460 expect(path.join(project, 'merges', 'merges.file')).toExist();
461
462 // Check if www files exist.
463 expect(path.join(project, 'www', 'index.html')).toExist();
464
465 // Check that config.xml was updated.
466 var configXml = new ConfigParser(path.join(project, 'config.xml'));
467 expect(configXml.packageName()).toEqual(appId);
468
469 // Check that www, hooks, merges are really a symlink; config is not
470 expect(fs.lstatSync(path.join(project, 'www')).isSymbolicLink()).toBe(true);
471 expect(fs.lstatSync(path.join(project, 'hooks')).isSymbolicLink()).toBe(true);
472 expect(fs.lstatSync(path.join(project, 'merges')).isSymbolicLink()).toBe(true);
473 expect(fs.lstatSync(path.join(project, 'config.xml')).isSymbolicLink()).not.toBe(true);
474 }
475
476 var config = {
477 lib: {
478 www: {
479 template: true,
480 url: path.join(__dirname, 'templates', 'noconfig'),
481 version: '',
482 link: true
483 }
484 }
485 };
486 return create(project, appId, appName, config, events)
487 .then(checkSymNoConfig)
488 .fail(function(err) {
489 if(process.platform.slice(0, 3) == 'win') {
490 // Allow symlink error if not in admin mode
491 expect(err.message).toBe('Symlinks on Windows require Administrator privileges');
492 } else {
493 if (err) {
494 console.log(err.stack);
495 }
496 expect(err).toBeUndefined();
497 }
498 })
499 .fin(done);
500 }, 60000);
501
502 });
503
504
505
506
507
508 });