@@ -16,6 +16,8 @@ import ErrorsLib = require("../lib/common/errors");
16
16
import ProjectHelperLib = require( "../lib/common/project-helper" ) ;
17
17
import PlatformsDataLib = require( "../lib/platforms-data" ) ;
18
18
import ProjectDataServiceLib = require( "../lib/services/project-data-service" ) ;
19
+ import helpers = require( "../lib/common/helpers" ) ;
20
+ import os = require( "os" ) ;
19
21
20
22
import PluginsServiceLib = require( "../lib/services/plugins-service" ) ;
21
23
import AddPluginCommandLib = require( "../lib/commands/plugin/add-plugin" ) ;
@@ -124,6 +126,30 @@ function addPluginWhenExpectingToFail(testInjector: IInjector, plugin: string, e
124
126
assert . isTrue ( isErrorThrown ) ;
125
127
}
126
128
129
+ function createAndroidManifestFile ( projectFolder : string , fs :IFileSystem ) : void {
130
+ let manifest = '<?xml version="1.0" encoding="UTF-8"?>' +
131
+ '<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.basiccontactables" android:versionCode="1" android:versionName="1.0" >' +
132
+ '<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>' +
133
+ '<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>' +
134
+ '<uses-permission android:name="android.permission.INTERNET"/>' +
135
+ '<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/Theme.Sample" >' +
136
+ '<activity android:name="com.example.android.basiccontactables.MainActivity" android:label="@string/app_name" android:launchMode="singleTop">' +
137
+ '<meta-data android:name="android.app.searchable" android:resource="@xml/searchable" />' +
138
+ '<intent-filter>' +
139
+ '<action android:name="android.intent.action.SEARCH" />' +
140
+ '</intent-filter>' +
141
+ '<intent-filter>' +
142
+ '<action android:name="android.intent.action.MAIN" />' +
143
+ '</intent-filter>' +
144
+ '</activity>' +
145
+ '</application>' +
146
+ '</manifest>' ;
147
+
148
+ fs . createDirectory ( path . join ( projectFolder , "platforms" ) ) . wait ( ) ;
149
+ fs . createDirectory ( path . join ( projectFolder , "platforms" , "android" ) ) . wait ( ) ;
150
+ fs . writeFile ( path . join ( projectFolder , "platforms" , "android" , "AndroidManifest.xml" ) , manifest ) . wait ( ) ;
151
+ }
152
+
127
153
describe ( "Plugins service" , ( ) => {
128
154
let testInjector : IInjector ;
129
155
beforeEach ( ( ) => {
@@ -256,7 +282,7 @@ describe("Plugins service", () => {
256
282
let packageJsonContent = fs . readJson ( path . join ( projectFolder , "package.json" ) ) . wait ( ) ;
257
283
let actualDependencies = packageJsonContent . dependencies ;
258
284
let expectedDependencies = {
259
- "plugin1" : "^1.0.0 "
285
+ "plugin1" : "^1.0.3 "
260
286
} ;
261
287
assert . deepEqual ( actualDependencies , expectedDependencies ) ;
262
288
} ) ;
@@ -419,4 +445,141 @@ describe("Plugins service", () => {
419
445
commandsService . tryExecuteCommand ( "plugin|add" , [ pluginFolderPath ] ) . wait ( ) ;
420
446
} ) ;
421
447
} ) ;
448
+
449
+ describe ( "merge xmls tests" , ( ) => {
450
+ let testInjector : IInjector ;
451
+ beforeEach ( ( ) => {
452
+ testInjector = createTestInjector ( ) ;
453
+ testInjector . registerCommand ( "plugin|add" , AddPluginCommandLib . AddPluginCommand ) ;
454
+ } ) ;
455
+ it ( "fails if the plugin contains incorrect xml" , ( ) => {
456
+ let pluginName = "mySamplePlugin" ;
457
+ let projectFolder = createProjectFile ( testInjector ) ;
458
+ let pluginFolderPath = path . join ( projectFolder , pluginName ) ;
459
+ let pluginJsonData = {
460
+ "name" : pluginName ,
461
+ "version" : "0.0.1" ,
462
+ "nativescript" : {
463
+ "platforms" : {
464
+ "android" : "0.10.0"
465
+ }
466
+ }
467
+ } ;
468
+ let fs = testInjector . resolve ( "fs" ) ;
469
+ fs . writeJson ( path . join ( pluginFolderPath , "package.json" ) , pluginJsonData ) . wait ( ) ;
470
+
471
+ // Adds AndroidManifest.xml file in platforms/android folder
472
+ createAndroidManifestFile ( projectFolder , fs ) ;
473
+
474
+ // Mock plugins service
475
+ let pluginsService = testInjector . resolve ( "pluginsService" ) ;
476
+ pluginsService . getAllInstalledPlugins = ( ) => {
477
+ return ( ( ) => {
478
+ return [ {
479
+ name : ""
480
+ } ] ;
481
+ } ) . future < IPluginData [ ] > ( ) ( ) ;
482
+ }
483
+
484
+ let appDestinationDirectoryPath = path . join ( projectFolder , "platforms" , "android" ) ;
485
+
486
+ // Mock platformsData
487
+ let platformsData = testInjector . resolve ( "platformsData" ) ;
488
+ platformsData . getPlatformData = ( platform : string ) => {
489
+ return {
490
+ appDestinationDirectoryPath : appDestinationDirectoryPath ,
491
+ frameworkPackageName : "tns-android" ,
492
+ configurationFileName : "AndroidManifest.xml"
493
+ }
494
+ }
495
+
496
+ // Ensure the pluginDestinationPath folder exists
497
+ let pluginPlatformsDirPath = path . join ( appDestinationDirectoryPath , "app" , "tns_modules" , pluginName , "platforms" , "android" ) ;
498
+ fs . ensureDirectoryExists ( pluginPlatformsDirPath ) . wait ( ) ;
499
+
500
+ // Creates invalid plugin's AndroidManifest.xml file
501
+ let xml = '<?xml version="1.0" encoding="UTF-8"?>' +
502
+ '<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.basiccontactables" android:versionCode="1" android:versionName="1.0" >' +
503
+ '<uses-permission android:name="android.permission.READ_CONTACTS"/>' ;
504
+ let pluginConfigurationFilePath = path . join ( pluginPlatformsDirPath , "AndroidManifest.xml" ) ;
505
+ fs . writeFile ( pluginConfigurationFilePath , xml ) . wait ( ) ;
506
+
507
+ // Expected error message. The assertion happens in mockBeginCommand
508
+ let expectedErrorMessage = `Exception: Invalid xml file ${ pluginConfigurationFilePath } . Additional technical information: element parse error: Exception: Invalid xml file ` +
509
+ `${ pluginConfigurationFilePath } . Additional technical information: unclosed xml attribute` +
510
+ `\n@#[line:1,col:39].` +
511
+ `\n@#[line:1,col:39].` ;
512
+ mockBeginCommand ( testInjector , expectedErrorMessage ) ;
513
+
514
+ let commandsService = testInjector . resolve ( CommandsServiceLib . CommandsService ) ;
515
+ commandsService . tryExecuteCommand ( "plugin|add" , [ pluginFolderPath ] ) . wait ( ) ;
516
+ } ) ;
517
+ it ( "merges AndroidManifest.xml and produces correct xml" , ( ) => {
518
+ let pluginName = "mySamplePlugin" ;
519
+ let projectFolder = createProjectFile ( testInjector ) ;
520
+ let pluginFolderPath = path . join ( projectFolder , pluginName ) ;
521
+ let pluginJsonData = {
522
+ "name" : pluginName ,
523
+ "version" : "0.0.1" ,
524
+ "nativescript" : {
525
+ "platforms" : {
526
+ "android" : "0.10.0"
527
+ }
528
+ }
529
+ } ;
530
+ let fs = testInjector . resolve ( "fs" ) ;
531
+ fs . writeJson ( path . join ( pluginFolderPath , "package.json" ) , pluginJsonData ) . wait ( ) ;
532
+
533
+ // Adds AndroidManifest.xml file in platforms/android folder
534
+ createAndroidManifestFile ( projectFolder , fs ) ;
535
+
536
+ // Mock plugins service
537
+ let pluginsService = testInjector . resolve ( "pluginsService" ) ;
538
+ pluginsService . getAllInstalledPlugins = ( ) => {
539
+ return ( ( ) => {
540
+ return [ {
541
+ name : ""
542
+ } ] ;
543
+ } ) . future < IPluginData [ ] > ( ) ( ) ;
544
+ }
545
+
546
+ let appDestinationDirectoryPath = path . join ( projectFolder , "platforms" , "android" ) ;
547
+
548
+ // Mock platformsData
549
+ let platformsData = testInjector . resolve ( "platformsData" ) ;
550
+ platformsData . getPlatformData = ( platform : string ) => {
551
+ return {
552
+ appDestinationDirectoryPath : appDestinationDirectoryPath ,
553
+ frameworkPackageName : "tns-android" ,
554
+ configurationFileName : "AndroidManifest.xml" ,
555
+ configurationFilePath : path . join ( appDestinationDirectoryPath , "AndroidManifest.xml" ) ,
556
+ mergeXmlConfig : [ { "nodename" : "manifest" , "attrname" : "*" } ]
557
+ }
558
+ }
559
+
560
+ // Ensure the pluginDestinationPath folder exists
561
+ let pluginPlatformsDirPath = path . join ( appDestinationDirectoryPath , "app" , "tns_modules" , pluginName , "platforms" , "android" ) ;
562
+ fs . ensureDirectoryExists ( pluginPlatformsDirPath ) . wait ( ) ;
563
+
564
+ // Creates valid plugin's AndroidManifest.xml file
565
+ let xml = '<?xml version="1.0" encoding="UTF-8"?>' +
566
+ '<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.basiccontactables" android:versionCode="1" android:versionName="1.0" >' +
567
+ '<uses-permission android:name="android.permission.READ_CONTACTS"/>' +
568
+ '</manifest>' ;
569
+ let pluginConfigurationFilePath = path . join ( pluginPlatformsDirPath , "AndroidManifest.xml" ) ;
570
+ fs . writeFile ( pluginConfigurationFilePath , xml ) . wait ( ) ;
571
+
572
+ pluginsService . add ( pluginFolderPath ) . wait ( ) ;
573
+
574
+ let expectedXml = '<?xmlversion="1.0"encoding="UTF-8"?><manifestxmlns:android="http://schemas.android.com/apk/res/android"package="com.example.android.basiccontactables"android:versionCode="1"android:versionName="1.0"><uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permissionandroid:name="android.permission.INTERNET"/><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/Theme.Sample"><activityandroid:name="com.example.android.basiccontactables.MainActivity"android:label="@string/app_name"android:launchMode="singleTop"><meta-dataandroid:name="android.app.searchable"android:resource="@xml/searchable"/><intent-filter><actionandroid:name="android.intent.action.SEARCH"/></intent-filter><intent-filter><actionandroid:name="android.intent.action.MAIN"/></intent-filter></activity></application><uses-permissionandroid:name="android.permission.READ_CONTACTS"/></manifest>' ;
575
+ expectedXml = helpers . stringReplaceAll ( expectedXml , os . EOL , "" ) ;
576
+ expectedXml = helpers . stringReplaceAll ( expectedXml , " " , "" ) ;
577
+
578
+ let actualXml = fs . readText ( path . join ( appDestinationDirectoryPath , "AndroidManifest.xml" ) ) . wait ( ) ;
579
+ actualXml = helpers . stringReplaceAll ( actualXml , "\n" , "" ) ;
580
+ actualXml = helpers . stringReplaceAll ( actualXml , " " , "" ) ;
581
+
582
+ assert . equal ( expectedXml , actualXml ) ;
583
+ } ) ;
584
+ } ) ;
422
585
} ) ;
0 commit comments