Skip to content

Merge release in master pre 1.5.0 (third time) #1222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Nov 20, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
ec1b2c6
Use fork instead of spawn for startTestRunner
rosen-vladimirov Nov 17, 2015
720477a
Add help for dev-test-* commands
rosen-vladimirov Nov 17, 2015
6925a14
Make sure all dependencies are installed before starting karma
rosen-vladimirov Nov 18, 2015
35446fc
Merge pull request #1207 from NativeScript/vladimirov/fix-unit-test-r…
rosen-vladimirov Nov 18, 2015
ab555e0
Release the console after `tns run ios` command
Nov 18, 2015
1960b03
Merge pull request #1209 from NativeScript/fatme/release-console-afte…
Nov 18, 2015
ac639c7
Fix ENOENT error when livesyncing deleted .xml or .css file
Nov 18, 2015
8023ed3
Bump ios-sim version
Nov 19, 2015
1d40bb1
Merge pull request #1211 from NativeScript/fatme/fix-enoent-error
Nov 19, 2015
a8caa28
Create configurations and src folders only for plugins that have nati…
Nov 19, 2015
54d8f44
Merge pull request #1217 from NativeScript/fatme/fix-long-path-on-win…
Nov 19, 2015
4d8c36a
Merge pull request #1216 from NativeScript/fatme/bump-ios-sim-version
Nov 19, 2015
9507f18
Silent shelljs by default
rosen-vladimirov Nov 19, 2015
441f927
Merge pull request #1220 from NativeScript/vladimirov/update-shelljs-…
rosen-vladimirov Nov 20, 2015
d81817a
Show application output from livesync command
Nov 19, 2015
980ee5e
Merge pull request #1219 from NativeScript/fatme/show-app-output-by-l…
rosen-vladimirov Nov 20, 2015
368044e
Merge release in master pre 1.5.0 (third time)
rosen-vladimirov Nov 20, 2015
bb4b54e
Update to latest common lib
rosen-vladimirov Nov 20, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions docs/man_pages/project/testing/dev-test-android.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
test android
==========

Usage | Synopsis
------|-------
Run tests on all connected devices | `$ tns test android [--watch] [--debug-brk]`
Run tests on a selected device | `$ tns test android --device <Device ID> [--watch] [--debug-brk]`

Runs the tests in your project on connected Android devices and running native emulators.<% if(isConsole) { %> Your project must already be configured for unit testing by running `$ tns test init`.<% } %>

### Options
* `--watch` - If set, when you save changes to the project, changes are automatically synchronized to the connected device and tests are re-run.
* `--device` - Specifies the serial number or the index of the connected device on which to run the tests. To list all connected devices, grouped by platform, run `$ tns device`
* `--debug-brk` - Runs the tests under the debugger. The debugger will break just before your tests are executed, so you have a chance to place breakpoints.

### Attributes
* `<Device ID>` is the device index or identifier as listed by `$ tns device`

<% if(isHtml) { %>
### Prerequisites

* Verify that [you have configured your project for unit testing](test-init.html).
* Verify that [you have stored your unit tests in `app` &#8594; `tests`](http://docs.nativescript.org/testing).
* Verify that [you have configured your system and devices properly](http://docs.nativescript.org/testing).

### Related Commands
Command | Description
--------|------------
[test init](test-init.html) | Configures your project for unit testing with a selected framework.
[test ios](test-ios.html) | Runs the tests in your project on iOS devices or the iOS Simulator.
<% } %>
36 changes: 36 additions & 0 deletions docs/man_pages/project/testing/dev-test-ios.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
test ios
==========

Usage | Synopsis
------|-------
Run tests on all connected devices | `$ tns test ios [--watch] [--debug-brk]`
Run tests on a selected device | `$ tns test ios --device <Device ID> [--watch] [--debug-brk]`
Run tests in the iOS Simulator | `$ tns test ios --emulator [--watch] [--debug-brk]`

Runs the tests in your project on connected iOS devices or the iOS Simulator.<% if(isConsole && isMacOS) { %> Your project must already be configured for unit testing by running `$ tns test init`.<% } %>

<% if(isConsole && (isLinux || isWindows)) { %>WARNING: You can run this command only on OS X systems. To view the complete help for this command, run `$ tns help test ios`<% } %>

<% if((isConsole && isMacOS) || isHtml) { %>
### Options
* `--watch` - If set, when you save changes to the project, changes are automatically synchronized to the connected device and tests are re-ran.
* `--device` - Specifies the serial number or the index of the connected device on which you want to run tests. To list all connected devices, grouped by platform, run `$ tns device`. You cannot set `--device` and `--emulator` simultaneously.
* `--emulator` - Runs tests on the iOS Simulator. You cannot set `--device` and `--emulator` simultaneously.
* `--debug-brk` - Runs the tests under the debugger. The debugger will break just before your tests are executed, so you have a chance to place breakpoints.

### Attributes
* `<Device ID>` is the device index or identifier as listed by `$ tns device`<% } %>

<% if(isHtml) { %>
### Prerequisites

* Verify that [you have configured your project for unit testing](test-init.html).
* Verify that [you have stored your unit tests in `app` &#8594; `tests`](http://docs.nativescript.org/testing).
* Verify that [you have configured your system and devices properly](http://docs.nativescript.org/testing).

### Related Commands
Command | Description
--------|------------
[test init](test-init.html) | Configures your project for unit testing with a selected framework.
[test android](test-android.html) | Runs the tests in your project on Android devices or native emulators.
<% } %>
1 change: 0 additions & 1 deletion lib/commands/livesync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export class LivesyncCommand implements ICommand {
private $errors: IErrors) { }

public execute(args: string[]): IFuture<void> {
this.$options.justlaunch = true;
return this.$usbLiveSyncService.liveSync(args[0]);
}

Expand Down
2 changes: 2 additions & 0 deletions lib/nativescript-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ require("./common/verify-node-version").verifyNodeVersion(require("../package.js
require("./bootstrap");
import * as fiber from "fibers";
import Future = require("fibers/future");
import * as shelljs from "shelljs";
shelljs.config.silent = true;
import {installUncaughtExceptionListener} from "./common/errors";
installUncaughtExceptionListener(process.exit);

Expand Down
34 changes: 31 additions & 3 deletions lib/providers/device-log-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,38 @@
"use strict";

export class DeviceLogProvider implements Mobile.IDeviceLogProvider {
constructor(private $logger: ILogger) { }
//sample line is "I/Web Console( 4438): Received Event: deviceready at file:///storage/emulated/0/Icenium/com.telerik.TestApp/js/index.js:48"
private static LINE_REGEX = /.\/(.+?)\s*\(\s*(\d+?)\): (.*)/;

public logData(line: string, platform: string, deviceIdentifier: string): void {
this.$logger.out(line);
constructor(private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants,
private $logger: ILogger) { }

public logData(lineText: string, platform: string, deviceIdentifier: string): void {
if (!platform || platform.toLowerCase() === this.$devicePlatformsConstants.iOS.toLowerCase()) {
this.$logger.out(lineText);
} else if (platform === this.$devicePlatformsConstants.Android) {
let log = this.getConsoleLogFromLine(lineText);
if (log) {
if (log.tag) {
this.$logger.out(`${log.tag}: ${log.message}`);
} else {
this.$logger.out(log.message);
}
}
}
}

private getConsoleLogFromLine(lineText: String): any {
let acceptedTags = ["chromium", "Web Console", "JS"];
let match = lineText.match(DeviceLogProvider.LINE_REGEX);
if (match) {
if(acceptedTags.indexOf(match[1]) !== -1) {
return {tag: match[1], message: match[3]};
}
} else if (_.any(acceptedTags, (tag: string) => { return lineText.indexOf(tag) !== -1; })) {
return {message: match[3]};
}
return null;
}
}
$injector.register("deviceLogProvider", DeviceLogProvider);
14 changes: 8 additions & 6 deletions lib/services/android-project-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,18 +296,20 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
this.$fs.ensureDirectoryExists(configurationsDirectoryPath).wait();

let pluginConfigurationDirectoryPath = path.join(configurationsDirectoryPath, pluginName);
this.$fs.ensureDirectoryExists(pluginConfigurationDirectoryPath).wait();
if (this.$fs.exists(pluginPlatformsFolderPath).wait()) {
this.$fs.ensureDirectoryExists(pluginConfigurationDirectoryPath).wait();

// Copy all resources from plugin
let resourcesDestinationDirectoryPath = path.join(this.platformData.projectRoot, "src", pluginName);
this.$fs.ensureDirectoryExists(resourcesDestinationDirectoryPath).wait();
shell.cp("-Rf", path.join(pluginPlatformsFolderPath, "*"), resourcesDestinationDirectoryPath);
}

// Copy include.gradle file
let includeGradleFilePath = path.join(pluginPlatformsFolderPath, "include.gradle");
if(this.$fs.exists(includeGradleFilePath).wait()) {
shell.cp("-f", includeGradleFilePath, pluginConfigurationDirectoryPath);
}

// Copy all resources from plugin
let resourcesDestinationDirectoryPath = path.join(this.platformData.projectRoot, "src", pluginName);
this.$fs.ensureDirectoryExists(resourcesDestinationDirectoryPath).wait();
shell.cp("-Rf", path.join(pluginPlatformsFolderPath, "*"), resourcesDestinationDirectoryPath);
}).future<void>()();
}

Expand Down
4 changes: 0 additions & 4 deletions lib/services/platform-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,10 +353,6 @@ export class PlatformService implements IPlatformService {
return (() => {
platformData.platformProjectService.deploy(device.deviceInfo.identifier).wait();
device.deploy(packageFile, this.$projectData.projectId).wait();

if (!this.$options.justlaunch) {
device.openDeviceLogStream();
}
}).future<void>()();
};
this.$devicesService.execute(action).wait();
Expand Down
167 changes: 92 additions & 75 deletions lib/services/test-execution-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as constants from "../constants";
import * as path from 'path';
import Future = require('fibers/future');
import * as os from 'os';
import * as fiberBootstrap from "../common/fiber-bootstrap";

interface IKarmaConfigOptions {
debugBrk: boolean;
Expand All @@ -31,93 +32,109 @@ class TestExecutionService implements ITestExecutionService {
private $config: IConfiguration,
private $logger: ILogger,
private $fs: IFileSystem,
private $options: IOptions) {
private $options: IOptions,
private $pluginsService: IPluginsService) {
}

public startTestRunner(platform: string) : IFuture<void> {
return (() => {
this.$options.justlaunch = true;
let blockingOperationFuture = new Future<void>();
process.on('message', (launcherConfig: any) => {
fiberBootstrap.run(() => {
try {
let platformData = this.$platformsData.getPlatformData(platform.toLowerCase());
let projectDir = this.$projectData.projectDir;

let projectFilesPath = path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME);

let configOptions: IKarmaConfigOptions = JSON.parse(launcherConfig);
this.$options.debugBrk = configOptions.debugBrk;
this.$options.debugTransport = configOptions.debugTransport;
let configJs = this.generateConfig(configOptions);
this.$fs.writeFile(path.join(projectDir, TestExecutionService.CONFIG_FILE_NAME), configJs).wait();

let socketIoJsUrl = `http://localhost:${this.$options.port}/socket.io/socket.io.js`;
let socketIoJs = this.$httpClient.httpRequest(socketIoJsUrl).wait().body;
this.$fs.writeFile(path.join(projectDir, TestExecutionService.SOCKETIO_JS_FILE_NAME), socketIoJs).wait();

this.$platformService.preparePlatform(platform).wait();
this.detourEntryPoint(projectFilesPath).wait();

let watchGlob = path.join(projectDir, constants.APP_FOLDER_NAME);

let platformSpecificLiveSyncServices: IDictionary<any> = {
android: (_device: Mobile.IDevice, $injector: IInjector): IPlatformSpecificLiveSyncService => {
return $injector.resolve(this.$androidUsbLiveSyncServiceLocator.factory, {_device: _device});
},
ios: (_device: Mobile.IDevice, $injector: IInjector) => {
return $injector.resolve(this.$iosUsbLiveSyncServiceLocator.factory, {_device: _device});
}
};

let notInstalledAppOnDeviceAction = (device: Mobile.IDevice): IFuture<void> => {
return (() => {
this.$platformService.installOnDevice(platform).wait();
this.detourEntryPoint(projectFilesPath).wait();
}).future<void>()();
};

let notRunningiOSSimulatorAction = (): IFuture<void> => {
return (() => {
this.$platformService.deployOnEmulator(this.$devicePlatformsConstants.iOS.toLowerCase()).wait();
this.detourEntryPoint(projectFilesPath).wait();
}).future<void>()();
};

let beforeBatchLiveSyncAction = (filePath: string): IFuture<string> => {
return (() => {
this.$platformService.preparePlatform(platform).wait();
return path.join(projectFilesPath, path.relative(path.join(this.$projectData.projectDir, constants.APP_FOLDER_NAME), filePath));
}).future<string>()();
};

let localProjectRootPath = platform.toLowerCase() === "ios" ? platformData.appDestinationDirectoryPath : null;

let liveSyncData = {
platform: platform,
appIdentifier: this.$projectData.projectId,
projectFilesPath: projectFilesPath,
excludedProjectDirsAndFiles: constants.LIVESYNC_EXCLUDED_DIRECTORIES,
watchGlob: watchGlob,
platformSpecificLiveSyncServices: platformSpecificLiveSyncServices,
notInstalledAppOnDeviceAction: notInstalledAppOnDeviceAction,
notRunningiOSSimulatorAction: notRunningiOSSimulatorAction,
localProjectRootPath: localProjectRootPath,
beforeBatchLiveSyncAction: beforeBatchLiveSyncAction,
shouldRestartApplication: (localToDevicePaths: Mobile.ILocalToDevicePathData[]) => Future.fromResult(!this.$options.debugBrk),
canExecuteFastLiveSync: (filePath: string) => false,
};

this.$usbLiveSyncServiceBase.sync(liveSyncData).wait();

if (this.$options.debugBrk) {
this.$logger.info('Starting debugger...');
let debugService: IDebugService = this.$injector.resolve(`${platform}DebugService`);
debugService.debugStart().wait();
}
blockingOperationFuture.return();
} catch(err) {
// send the error to the real future
blockingOperationFuture.throw(err);
}
});
});

let platformData = this.$platformsData.getPlatformData(platform.toLowerCase());
let projectDir = this.$projectData.projectDir;

let projectFilesPath = path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME);

let configOptions: IKarmaConfigOptions = JSON.parse(this.$fs.readStdin().wait());
this.$options.debugBrk = configOptions.debugBrk;
this.$options.debugTransport = configOptions.debugTransport;
let configJs = this.generateConfig(configOptions);
this.$fs.writeFile(path.join(projectDir, TestExecutionService.CONFIG_FILE_NAME), configJs).wait();

let socketIoJsUrl = `http://localhost:${this.$options.port}/socket.io/socket.io.js`;
let socketIoJs = this.$httpClient.httpRequest(socketIoJsUrl).wait().body;
this.$fs.writeFile(path.join(projectDir, TestExecutionService.SOCKETIO_JS_FILE_NAME), socketIoJs).wait();

this.$platformService.preparePlatform(platform).wait();
this.detourEntryPoint(projectFilesPath).wait();

let watchGlob = path.join(projectDir, constants.APP_FOLDER_NAME);

let platformSpecificLiveSyncServices: IDictionary<any> = {
android: (_device: Mobile.IDevice, $injector: IInjector): IPlatformSpecificLiveSyncService => {
return $injector.resolve(this.$androidUsbLiveSyncServiceLocator.factory, {_device: _device});
},
ios: (_device: Mobile.IDevice, $injector: IInjector) => {
return $injector.resolve(this.$iosUsbLiveSyncServiceLocator.factory, {_device: _device});
}
};

let notInstalledAppOnDeviceAction = (device: Mobile.IDevice): IFuture<void> => {
return (() => {
this.$platformService.installOnDevice(platform).wait();
this.detourEntryPoint(projectFilesPath).wait();
}).future<void>()();
};

let notRunningiOSSimulatorAction = (): IFuture<void> => {
return (() => {
this.$platformService.deployOnEmulator(this.$devicePlatformsConstants.iOS.toLowerCase()).wait();
this.detourEntryPoint(projectFilesPath).wait();
}).future<void>()();
};

let beforeBatchLiveSyncAction = (filePath: string): IFuture<string> => {
return (() => {
this.$platformService.preparePlatform(platform).wait();
return path.join(projectFilesPath, path.relative(path.join(this.$projectData.projectDir, constants.APP_FOLDER_NAME), filePath));
}).future<string>()();
};

let localProjectRootPath = platform.toLowerCase() === "ios" ? platformData.appDestinationDirectoryPath : null;

let liveSyncData = {
platform: platform,
appIdentifier: this.$projectData.projectId,
projectFilesPath: projectFilesPath,
excludedProjectDirsAndFiles: constants.LIVESYNC_EXCLUDED_DIRECTORIES,
watchGlob: watchGlob,
platformSpecificLiveSyncServices: platformSpecificLiveSyncServices,
notInstalledAppOnDeviceAction: notInstalledAppOnDeviceAction,
notRunningiOSSimulatorAction: notRunningiOSSimulatorAction,
localProjectRootPath: localProjectRootPath,
beforeBatchLiveSyncAction: beforeBatchLiveSyncAction,
shouldRestartApplication: (localToDevicePaths: Mobile.ILocalToDevicePathData[]) => Future.fromResult(!this.$options.debugBrk),
canExecuteFastLiveSync: (filePath: string) => false,
};

this.$usbLiveSyncServiceBase.sync(liveSyncData).wait();

if (this.$options.debugBrk) {
this.$logger.info('Starting debugger...');
let debugService: IDebugService = this.$injector.resolve(`${platform}DebugService`);
debugService.debugStart().wait();
}
// Tell the parent that we are ready to receive the data.
process.send("ready");
blockingOperationFuture.wait();
}).future<void>()();
}

public startKarmaServer(platform: string): IFuture<void> {
return (() => {
platform = platform.toLowerCase();
this.$pluginsService.ensureAllDependenciesAreInstalled().wait();
let pathToKarma = path.join(this.$projectData.projectDir, 'node_modules/karma');
let KarmaServer = require(path.join(pathToKarma, 'lib/server'));
if (platform === 'ios' && this.$options.emulator) {
Expand Down
4 changes: 3 additions & 1 deletion lib/services/usb-livesync-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ export class UsbLiveSyncService extends usbLivesyncServiceBaseLib.UsbLiveSyncSer

let devices = this.$devicesService.getDeviceInstances();
_.each(devices, (device: Mobile.IDevice) => {
this.transferFiles(device, deviceAppData, localToDevicePaths, projectFilesPath, true).wait();
if (this.$fs.exists(filePath).wait()) {
this.transferFiles(device, deviceAppData, localToDevicePaths, projectFilesPath, true).wait();
}
let platformSpecificUsbLiveSyncService = this.resolvePlatformSpecificLiveSyncService(platform || this.$devicesService.platform, device, platformSpecificLiveSyncServices);
return platformSpecificUsbLiveSyncService.sendPageReloadMessageToDevice(deviceAppData).wait();
});
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"gulp": "3.9.0",
"iconv-lite": "0.4.11",
"inquirer": "0.9.0",
"ios-sim-portable": "1.0.13-delta",
"ios-sim-portable": "1.0.13-epsilon",
"lockfile": "1.0.1",
"lodash": "3.10.0",
"log4js": "0.6.26",
Expand Down