Skip to content

Commit dbf06cd

Browse files
Fatme HavaluovaFatme Havaluova
Fatme Havaluova
authored and
Fatme Havaluova
committed
Add unit tests
1 parent 77f2aee commit dbf06cd

File tree

11 files changed

+249
-37
lines changed

11 files changed

+249
-37
lines changed

lib/definitions/plugins.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ interface IPluginsService {
44
prepare(pluginData: IDependencyData): IFuture<void>;
55
getAllInstalledPlugins(): IFuture<IPluginData[]>;
66
ensureAllDependenciesAreInstalled(): IFuture<void>;
7+
afterPrepareAllPlugins(): IFuture<void>;
78
}
89

910
interface IPluginData extends INodeModuleData {

lib/definitions/project.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ interface IPlatformProjectService {
4040
updatePlatform(currentVersion: string, newVersion: string): IFuture<void>;
4141
preparePluginNativeCode(pluginData: IPluginData): IFuture<void>;
4242
removePluginNativeCode(pluginData: IPluginData): IFuture<void>;
43+
afterPrepareAllPlugins(): IFuture<void>;
4344
}
4445

4546
interface IAndroidProjectPropertiesManager {

lib/services/android-project-service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,10 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
296296
}).future<void>()();
297297
}
298298

299+
public afterPrepareAllPlugins(): IFuture<void> {
300+
return Future.fromResult();
301+
}
302+
299303
private getLibraryRelativePath(basePath: string, libraryPath: string): string {
300304
return path.relative(basePath, libraryPath).split("\\").join("/");
301305
}

lib/services/ios-project-service.ts

Lines changed: 73 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ import Future = require("fibers/future");
55
import path = require("path");
66
import shell = require("shelljs");
77
import util = require("util");
8+
import os = require("os");
89
import xcode = require("xcode");
910
import constants = require("./../constants");
1011
import helpers = require("./../common/helpers");
1112
import projectServiceBaseLib = require("./platform-project-service-base");
1213

13-
class IOSProjectService extends projectServiceBaseLib.PlatformProjectServiceBase implements IPlatformProjectService {
14+
export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServiceBase implements IPlatformProjectService {
1415
private static XCODE_PROJECT_EXT_NAME = ".xcodeproj";
1516
private static XCODEBUILD_MIN_VERSION = "6.0";
1617
private static IOS_PROJECT_NAME_PLACEHOLDER = "__PROJECT_NAME__";
@@ -261,14 +262,6 @@ class IOSProjectService extends projectServiceBaseLib.PlatformProjectServiceBase
261262

262263
this.savePbxProj(project).wait();
263264
}
264-
265-
if(this.$fs.exists(this.projectPodFilePath).wait() && this.$fs.getFsStats(this.projectPodFilePath).wait().mtime < this.$fs.getFsStats(this.$projectData.projectFilePath).wait().mtime) {
266-
try {
267-
this.$childProcess.exec("pod install", { cwd: this.platformData.projectRoot }).wait();
268-
} catch(e) {
269-
this.$errors.failWithoutHelp("CocoaPods are not installed. Run `sudo gem install cocoapods` and try again.");
270-
}
271-
}
272265
}).future<void>()();
273266
}
274267

@@ -313,35 +306,31 @@ class IOSProjectService extends projectServiceBaseLib.PlatformProjectServiceBase
313306
public preparePluginNativeCode(pluginData: IPluginData): IFuture<void> {
314307
return (() => {
315308
let pluginPlatformsFolderPath = pluginData.pluginPlatformsFolderPath(IOSProjectService.IOS_PLATFORM_NAME);
316-
_.each(this.getAllDynamicFrameworksForPlugin(pluginData).wait(), fileName => this.addLibrary(path.join(pluginPlatformsFolderPath, fileName)).wait());
317-
318-
let pluginPodFilePath = path.join(pluginPlatformsFolderPath, "Podfile");
319-
if(this.$fs.exists(pluginPodFilePath).wait()) {
320-
let pluginPodFileContent = this.$fs.readText(pluginPodFilePath).wait();
321-
this.$fs.appendFile(this.projectPodFilePath, pluginPodFileContent).wait();
322-
}
309+
this.prepareDynamicFrameworks(pluginPlatformsFolderPath, pluginData).wait();
310+
this.prepareCocoapods(pluginPlatformsFolderPath).wait();
323311
}).future<void>()();
324312
}
325313

326314
public removePluginNativeCode(pluginData: IPluginData): IFuture<void> {
327315
return (() => {
328316
let pluginPlatformsFolderPath = pluginData.pluginPlatformsFolderPath(IOSProjectService.IOS_PLATFORM_NAME);
329-
let project = this.createPbxProj();
330-
331-
_.each(this.getAllDynamicFrameworksForPlugin(pluginData).wait(), fileName => {
332-
let fullFrameworkPath = path.join(pluginPlatformsFolderPath, fileName);
333-
let relativeFrameworkPath = this.getFrameworkRelativePath(fullFrameworkPath);
334-
project.removeFramework(relativeFrameworkPath, { customFramework: true, embed: true })
335-
});
336-
337-
this.savePbxProj(project).wait();
338-
339-
let pluginPodFilePath = path.join(pluginPlatformsFolderPath, "Podfile");
340-
if(this.$fs.exists(pluginPodFilePath).wait()) {
341-
let pluginPodFileContent = this.$fs.readText(pluginPodFilePath).wait();
342-
let projectPodFileContent = this.$fs.readText(this.projectPodFilePath).wait();
343-
projectPodFileContent = helpers.stringReplaceAll(projectPodFileContent, pluginPodFileContent, "");
344-
this.$fs.writeFile(this.projectPodFilePath, projectPodFileContent).wait();
317+
this.removeDynamicFrameworks(pluginPlatformsFolderPath, pluginData).wait();
318+
this.removeCocoapods(pluginPlatformsFolderPath).wait();
319+
}).future<void>()();
320+
}
321+
322+
public afterPrepareAllPlugins(): IFuture<void> {
323+
return (() => {
324+
if(this.$fs.exists(this.projectPodFilePath).wait()) {
325+
// Check availability
326+
try {
327+
this.$childProcess.exec("gem which cocoapods").wait();
328+
} catch(e) {
329+
this.$errors.failWithoutHelp("CocoaPods are not installed. Run `sudo gem install cocoapods` and try again.");
330+
}
331+
332+
this.$logger.info("Installing pods...");
333+
this.$childProcess.exec("pod install", { cwd: this.platformData.projectRoot }).wait();
345334
}
346335
}).future<void>()();
347336
}
@@ -403,5 +392,57 @@ class IOSProjectService extends projectServiceBaseLib.PlatformProjectServiceBase
403392
this.$fs.rename(path.join(fileRootLocation, oldFileName), path.join(fileRootLocation, newFileName)).wait();
404393
}).future<void>()();
405394
}
395+
396+
private prepareDynamicFrameworks(pluginPlatformsFolderPath: string, pluginData: IPluginData): IFuture<void> {
397+
return (() => {
398+
_.each(this.getAllDynamicFrameworksForPlugin(pluginData).wait(), fileName => this.addLibrary(path.join(pluginPlatformsFolderPath, fileName)).wait());
399+
}).future<void>()();
400+
}
401+
402+
private prepareCocoapods(pluginPlatformsFolderPath: string): IFuture<void> {
403+
return (() => {
404+
let pluginPodFilePath = path.join(pluginPlatformsFolderPath, "Podfile");
405+
if(this.$fs.exists(pluginPodFilePath).wait()) {
406+
let pluginPodFileContent = this.$fs.readText(pluginPodFilePath).wait();
407+
let contentToWrite = this.buildPodfileContent(pluginPodFilePath, pluginPodFileContent);
408+
this.$fs.appendFile(this.projectPodFilePath, contentToWrite).wait();
409+
}
410+
}).future<void>()();
411+
}
412+
413+
private removeDynamicFrameworks(pluginPlatformsFolderPath: string, pluginData: IPluginData): IFuture<void> {
414+
return (() => {
415+
let project = this.createPbxProj();
416+
417+
_.each(this.getAllDynamicFrameworksForPlugin(pluginData).wait(), fileName => {
418+
let fullFrameworkPath = path.join(pluginPlatformsFolderPath, fileName);
419+
let relativeFrameworkPath = this.getFrameworkRelativePath(fullFrameworkPath);
420+
project.removeFramework(relativeFrameworkPath, { customFramework: true, embed: true })
421+
});
422+
423+
this.savePbxProj(project).wait();
424+
}).future<void>()();
425+
}
426+
427+
private removeCocoapods(pluginPlatformsFolderPath: string): IFuture<void> {
428+
return (() => {
429+
let pluginPodFilePath = path.join(pluginPlatformsFolderPath, "Podfile");
430+
if(this.$fs.exists(pluginPodFilePath).wait()) {
431+
let pluginPodFileContent = this.$fs.readText(pluginPodFilePath).wait();
432+
let projectPodFileContent = this.$fs.readText(this.projectPodFilePath).wait();
433+
let contentToRemove= this.buildPodfileContent(pluginPodFilePath, pluginPodFileContent);
434+
projectPodFileContent = helpers.stringReplaceAll(projectPodFileContent, contentToRemove, "");
435+
if(_.isEmpty(projectPodFileContent)) {
436+
this.$fs.deleteFile(this.projectPodFilePath).wait();
437+
} else {
438+
this.$fs.writeFile(this.projectPodFilePath, projectPodFileContent).wait();
439+
}
440+
}
441+
}).future<void>()();
442+
}
443+
444+
private buildPodfileContent(pluginPodFilePath: string, pluginPodFileContent: string): string {
445+
return `# Begin Podfile - ${pluginPodFilePath} ${os.EOL} ${pluginPodFileContent} ${os.EOL} # End Podfile ${os.EOL}`;
446+
}
406447
}
407448
$injector.register("iOSProjectService", IOSProjectService);

lib/services/plugins-service.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,14 @@ export class PluginsService implements IPluginsService {
144144
}).future<IPluginData[]>()();
145145
}
146146

147+
public afterPrepareAllPlugins(): IFuture<void> {
148+
let action = (pluginDestinationPath: string, platform: string, platformData: IPlatformData) => {
149+
return platformData.platformProjectService.afterPrepareAllPlugins();
150+
};
151+
152+
return this.executeForAllInstalledPlatforms(action);
153+
}
154+
147155
private get nodeModulesPath(): string {
148156
return path.join(this.$projectData.projectDir, "node_modules");
149157
}

lib/tools/broccoli/node-modules-dest-copy.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ export class DestCopy implements IBroccoliPlugin {
7676
this.$pluginsService.prepare(dependency).wait();
7777
}
7878
});
79+
80+
if(_.keys(this.dependencies).length > 0) {
81+
this.$pluginsService.afterPrepareAllPlugins().wait();
82+
}
7983
}
8084

8185
public rebuild(treeDiff: IDiffResult): void {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
},
1111
"main": "./lib/nativescript-cli.js",
1212
"scripts": {
13-
"test": "node_modules\\.bin\\_mocha --ui mocha-fibers --recursive --reporter spec --require test/test-bootstrap.js --timeout 60000 test/ lib/common/test/unit-tests",
13+
"test": "node_modules\\.bin\\_mocha --ui mocha-fibers --recursive --reporter spec --require test/test-bootstrap.js --timeout 60000 test/ios-project-service",
1414
"postinstall": "node postinstall.js",
1515
"preuninstall": "node preuninstall.js"
1616
},

test/ios-project-service.ts

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/// <reference path=".d.ts" />
2+
"use strict";
3+
4+
import Future = require("fibers/future");
5+
import path = require("path");
6+
import temp = require("temp");
7+
8+
import ChildProcessLib = require("../lib/common/child-process");
9+
import ConfigLib = require("../lib/config");
10+
import ErrorsLib = require("../lib/common/errors");
11+
import FileSystemLib = require("../lib/common/file-system");
12+
import HostInfoLib = require("../lib/common/host-info");
13+
import iOSProjectServiceLib = require("../lib/services/ios-project-service");
14+
import LoggerLib = require("../lib/common/logger");
15+
import OptionsLib = require("../lib/options");
16+
import ProjectDataLib = require("../lib/project-data");
17+
18+
import yok = require("../lib/common/yok");
19+
20+
let assert = require("chai").assert;
21+
22+
function createTestInjector(projectPath: string, projectName: string): IInjector {
23+
let testInjector = new yok.Yok();
24+
testInjector.register("childProcess", ChildProcessLib.ChildProcess);
25+
testInjector.register("config", ConfigLib.Configuration);
26+
testInjector.register("errors", ErrorsLib.Errors);
27+
testInjector.register("fs", FileSystemLib.FileSystem);
28+
testInjector.register("hostInfo", HostInfoLib.HostInfo);
29+
testInjector.register("injector", testInjector);
30+
testInjector.register("iOSEmulatorServices", {});
31+
testInjector.register("iOSProjectService", iOSProjectServiceLib.IOSProjectService);
32+
testInjector.register("logger", LoggerLib.Logger);
33+
testInjector.register("options", OptionsLib.Options);
34+
testInjector.register("projectData", {
35+
platformsDir: projectPath,
36+
projectName: projectName
37+
});
38+
testInjector.register("projectHelper", {});
39+
testInjector.register("staticConfig", ConfigLib.StaticConfig);
40+
41+
return testInjector;
42+
}
43+
44+
describe("Cocoapods support", () => {
45+
it("adds plugin with Podfile", () => {
46+
let projectName = "projectDirectory";
47+
let projectPath = temp.mkdirSync(projectName);
48+
49+
let testInjector = createTestInjector(projectPath, projectName);
50+
let fs: IFileSystem = testInjector.resolve("fs");
51+
52+
let packageJsonData = {
53+
"name": "myProject",
54+
"version": "0.1.0",
55+
"nativescript": {
56+
"id": "org.nativescript.myProject",
57+
"tns-android": {
58+
"version": "1.0.0"
59+
}
60+
}
61+
};
62+
fs.writeJson(path.join(projectPath, "package.json"), packageJsonData).wait();
63+
64+
let platformsFolderPath = path.join(projectPath, "ios");
65+
fs.createDirectory(platformsFolderPath).wait();
66+
67+
let iOSProjectService = testInjector.resolve("iOSProjectService");
68+
iOSProjectService.prepareDynamicFrameworks = (pluginPlatformsFolderPath: string, pluginData: IPluginData): IFuture<void> => {
69+
return Future.fromResult();
70+
};
71+
72+
let pluginPath = temp.mkdirSync("pluginDirectory");
73+
let pluginPlatformsFolderPath = path.join(pluginPath, "platforms", "ios");
74+
let pluginPodfilePath = path.join(pluginPlatformsFolderPath, "Podfile");
75+
let pluginPodfileContent = ["source 'https://github.com/CocoaPods/Specs.git'", "platform :ios, '8.1'", "pod 'GoogleMaps'"].join("\n");
76+
fs.writeFile(pluginPodfilePath, pluginPodfileContent).wait();
77+
78+
let pluginData = {
79+
pluginPlatformsFolderPath(platform: string): string {
80+
return pluginPlatformsFolderPath;
81+
}
82+
};
83+
84+
iOSProjectService.preparePluginNativeCode(pluginData).wait();
85+
86+
let projectPodfilePath = path.join(platformsFolderPath, "Podfile");
87+
assert.isTrue(fs.exists(projectPodfilePath).wait());
88+
89+
let actualProjectPodfileContent = fs.readText(projectPodfilePath).wait();
90+
let expectedProjectPodfileContent = [`# Begin Podfile - ${pluginPodfilePath} `, ` ${pluginPodfileContent} `, " # End Podfile \n"].join("\n");
91+
assert.equal(actualProjectPodfileContent, expectedProjectPodfileContent);
92+
});
93+
it("adds and removes plugin with Podfile", () => {
94+
let projectName = "projectDirectory2";
95+
let projectPath = temp.mkdirSync(projectName);
96+
97+
let testInjector = createTestInjector(projectPath, projectName);
98+
let fs: IFileSystem = testInjector.resolve("fs");
99+
100+
let packageJsonData = {
101+
"name": "myProject2",
102+
"version": "0.1.0",
103+
"nativescript": {
104+
"id": "org.nativescript.myProject2",
105+
"tns-android": {
106+
"version": "1.0.0"
107+
}
108+
}
109+
};
110+
fs.writeJson(path.join(projectPath, "package.json"), packageJsonData).wait();
111+
112+
let platformsFolderPath = path.join(projectPath, "ios");
113+
fs.createDirectory(platformsFolderPath).wait();
114+
115+
let iOSProjectService = testInjector.resolve("iOSProjectService");
116+
iOSProjectService.prepareDynamicFrameworks = (pluginPlatformsFolderPath: string, pluginData: IPluginData): IFuture<void> => {
117+
return Future.fromResult();
118+
};
119+
iOSProjectService.removeDynamicFrameworks = (pluginPlatformsFolderPath: string, pluginData: IPluginData): IFuture<void> => {
120+
return Future.fromResult();
121+
}
122+
123+
let pluginPath = temp.mkdirSync("pluginDirectory");
124+
let pluginPlatformsFolderPath = path.join(pluginPath, "platforms", "ios");
125+
let pluginPodfilePath = path.join(pluginPlatformsFolderPath, "Podfile");
126+
let pluginPodfileContent = ["source 'https://github.com/CocoaPods/Specs.git'", "platform :ios, '8.1'", "pod 'GoogleMaps'"].join("\n");
127+
fs.writeFile(pluginPodfilePath, pluginPodfileContent).wait();
128+
129+
let pluginData = {
130+
pluginPlatformsFolderPath(platform: string): string {
131+
return pluginPlatformsFolderPath;
132+
}
133+
};
134+
135+
iOSProjectService.preparePluginNativeCode(pluginData).wait();
136+
137+
let projectPodfilePath = path.join(platformsFolderPath, "Podfile");
138+
assert.isTrue(fs.exists(projectPodfilePath).wait());
139+
140+
let actualProjectPodfileContent = fs.readText(projectPodfilePath).wait();
141+
let expectedProjectPodfileContent = [`# Begin Podfile - ${pluginPodfilePath} `, ` ${pluginPodfileContent} `, " # End Podfile \n"].join("\n");
142+
assert.equal(actualProjectPodfileContent, expectedProjectPodfileContent);
143+
144+
iOSProjectService.removePluginNativeCode(pluginData).wait();
145+
146+
assert.isFalse(fs.exists(projectPodfilePath).wait());
147+
});
148+
});

test/npm-support.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ function setupProject(): IFuture<any> {
119119
normalizedPlatformName: "Android",
120120
platformProjectService: {
121121
prepareProject: () => Future.fromResult(),
122-
prepareAppResources: () => Future.fromResult()
122+
prepareAppResources: () => Future.fromResult(),
123+
afterPrepareAllPlugins: () => Future.fromResult()
123124
}
124125
}
125126
};

test/stubs.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ export class PlatformsDataStub implements IPlatformsData {
250250
appDestinationDirectoryPath: "",
251251
appResourcesDestinationDirectoryPath: "",
252252
preparePluginNativeCode: () => Future.fromResult(),
253-
removePluginNativeCode: () => Future.fromResult()
253+
removePluginNativeCode: () => Future.fromResult(),
254+
afterPrepareAllPlugins: () => Future.fromResult()
254255
};
255256
}
256257

@@ -271,7 +272,7 @@ export class PlatformProjectServiceStub implements IPlatformProjectService {
271272
validPackageNamesForDevice: [],
272273
frameworkFilesExtensions: [],
273274
appDestinationDirectoryPath: "",
274-
appResourcesDestinationDirectoryPath: ""
275+
appResourcesDestinationDirectoryPath: "",
275276
};
276277
}
277278
validate(): IFuture<void> {
@@ -316,6 +317,9 @@ export class PlatformProjectServiceStub implements IPlatformProjectService {
316317
removePluginNativeCode(pluginData: IPluginData): IFuture<void> {
317318
return Future.fromResult();
318319
}
320+
afterPrepareAllPlugins(): IFuture<void> {
321+
return Future.fromResult();
322+
}
319323
}
320324

321325
export class ProjectDataService implements IProjectDataService {

0 commit comments

Comments
 (0)