Skip to content

Commit 2e8728f

Browse files
committed
test init and test run commands for running unit tests
* install and serve testing framework dependencies * jasmine and mocha support * respect --watch option in tns test * pass $config.DEBUG to karma server * support for ios simulator * exclude tests/ folder from release builds * documentation for test commands * pass log level and --path if specified to karma * pass path to node executable and path to nativescript cli entry point to karma * '--framework' option for `tns test init` * deploy unit test runner as tns plugin * option to debug socket.io in unit test runner
1 parent 0472887 commit 2e8728f

24 files changed

+484
-8
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
!/*.js
55
!bin/nativescript.js
66
!vendor/*.js
7+
!resources/**
78
*.js.map
89

910
coverage

docs/man_pages/index.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ Command | Description
2929
[deploy `<Platform>`](project/testing/deploy.html) | Deploys the project to a connected physical or virtual device.
3030
[emulate `<Platform>`](project/testing/emulate.html) | Deploys the project in the native emulator for the selected target platform.
3131
[run `<Platform>`](project/testing/run.html) | Runs your project on a connected device or in the native emulator, if configured.
32-
[debug `<Platform>`](project/testing/debug.html) | Debugs your project on a connected device.
32+
[debug `<Platform>`](project/testing/debug.html) | Debugs your project on a connected physical or virtual device.
33+
[test init](project/testing/test-init.html) | Adds support for unit testing to your project.
34+
[test `<Platform>`](project/testing/test.html) | Runs the unit tests in your project on a connected physical or virtual device.
3335
[install](project/configuration/install.html) | Installs all platforms and dependencies described in the `package.json` file in the current directory.
3436
[plugin](lib-management/plugin.html) | Lets you manage the plugins for your project.
3537
[livesync](project/testing/livesync.html) | Synchronizes the latest changes in your project to devices.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
test android
2+
==========
3+
4+
Usage | Synopsis
5+
------|-------
6+
General | `$ tns test android [--watch] [--device <Device ID>]`
7+
8+
Runs the tests in your project on connected Android devices and emulators.
9+
10+
### Options
11+
* `--watch` - If set, when you save changes to the project, changes are automatically synchronized to the connected device and tests are re-run.
12+
* `--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`
13+
14+
### Attributes
15+
* `<Device ID>` is the device index or identifier as listed by `$ tns device`
16+
17+
<% if(isHtml) { %>
18+
### Related commands
19+
Command | Description
20+
--------|------------
21+
[test init](test-init.html) | Creates a test project in an existing NativeScript project
22+
<% } %>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
test init
2+
===========
3+
4+
Usage | Synopsis
5+
------|-------
6+
General | `$ tns test init [--framework <Framework>]`
7+
8+
Adds support for unit testing in an existing project.
9+
10+
### Options
11+
* `--framework <Framework>` - Specify the unit testing framework to install. Available frameworks are <%= formatListOfNames(constants.TESTING_FRAMEWORKS, 'and') %>.
12+
13+
<% if(isHtml) { %>
14+
### Related commands
15+
Command | Description
16+
--------|------------
17+
[test](test.html) | Run tests
18+
<% } %>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
test ios
2+
==========
3+
4+
Usage | Synopsis
5+
------|-------
6+
Run tests on all connected devices | `$ tns test ios [--watch]`
7+
Run tests on a selected device | `$ tns test ios --device <Device ID> [--watch]`
8+
Run tests in the iOS Simulator | `$ tns test ios --emulator [--watch]`
9+
10+
Runs the tests in your project on connected iOS devices or the iOS Simulator.
11+
12+
### Options
13+
* `--watch` - If set, when you save changes to the project, changes are automatically synchronized to the connected device and tests are re-ran.
14+
* `--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.
15+
* `--emulator` - Runs tests on the iOS Simulator. You cannot set `--device` and `--emulator` simultaneously.
16+
17+
<% if(isHtml) { %>
18+
### Related commands
19+
Command | Description
20+
--------|------------
21+
[test init](test-init.html) | Creates a test project in an existing NativeScript project
22+
<% } %>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
test
2+
===========
3+
4+
Usage | Synopsis
5+
------|-------
6+
General | `$ tns test <Platform>`
7+
8+
Run unit tests.
9+
10+
### Attributes
11+
`<Platform>` is the target mobile platform on which you want to run the tests. You can set the following target platforms:
12+
* `android` - Runs the tests in your project on connected Android devices.
13+
* `ios` - Runs the tests in your project on connected iOS devices.
14+
15+
16+
<% if(isHtml) { %>
17+
### Related commands
18+
Command | Description
19+
--------|------------
20+
[test init](test-init.html) | Creates a test project in an existing NativeScript project
21+
[test android](test-android.html) | Runs the tests in your project on Android devices.
22+
[test ios](test-ios.html) | Runs the tests in your project on iOS devices or the iOS Simulator.
23+
<% } %>

lib/bootstrap.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ $injector.requireCommand("deploy", "./commands/deploy");
4646
$injector.requireCommand("emulate|android", "./commands/emulate");
4747
$injector.requireCommand("emulate|ios", "./commands/emulate");
4848

49+
$injector.require("testExecutionService", "./services/test-execution-service");
50+
$injector.requireCommand("dev-test|android", "./commands/test");
51+
$injector.requireCommand("dev-test|ios", "./commands/test");
52+
$injector.requireCommand("test|android", "./commands/test");
53+
$injector.requireCommand("test|ios", "./commands/test");
54+
$injector.requireCommand("test|init", "./commands/test-init");
55+
4956
$injector.require("npm", "./node-package-manager");
5057
$injector.require("npmInstallationManager", "./npm-installation-manager");
5158
$injector.require("lockfile", "./lockfile");
@@ -74,3 +81,6 @@ $injector.requireCommand("init", "./commands/init");
7481
$injector.require("projectFilesManager", "./services/project-files-manager");
7582
$injector.requireCommand("livesync", "./commands/livesync");
7683
$injector.require("androidToolsInfo", "./android-tools-info");
84+
85+
$injector.require("iosUsbLiveSyncServiceLocator", "./services/usb-livesync-service");
86+
$injector.require("androidUsbLiveSyncServiceLocator", "./services/usb-livesync-service");

lib/commands/test-init.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
///<reference path="../.d.ts"/>
2+
3+
"use strict";
4+
5+
import * as path from 'path';
6+
import * as util from 'util';
7+
import {TESTING_FRAMEWORKS} from '../constants';
8+
9+
class TestInitCommand implements ICommand {
10+
constructor(private $npm: INodePackageManager,
11+
private $projectData: IProjectData,
12+
private $errors: IErrors,
13+
private $options: IOptions,
14+
private $prompter: IPrompter,
15+
private $fs: IFileSystem,
16+
private $resources: IResourceLoader,
17+
private $pluginsService: IPluginsService,
18+
private $logger: ILogger) {
19+
}
20+
21+
private frameworkDependencies:IDictionary<string[]> = {
22+
jasmine: [],
23+
mocha: ['chai'],
24+
};
25+
26+
public execute(args: string[]) : IFuture<void> {
27+
return (() => {
28+
let projectDir = this.$projectData.projectDir;
29+
30+
let frameworkToInstall = this.$options.framework
31+
|| this.$prompter.promptForChoice('Select testing framework:', TESTING_FRAMEWORKS).wait();
32+
if (TESTING_FRAMEWORKS.indexOf(frameworkToInstall) === -1) {
33+
this.$errors.fail(`Unknown or unsupported unit testing framework: ${frameworkToInstall}`);
34+
}
35+
36+
['karma', 'karma-' + frameworkToInstall, 'karma-nativescript-launcher']
37+
.concat(this.frameworkDependencies[frameworkToInstall].map(f => 'karma-' + f))
38+
.forEach(mod => {
39+
this.$npm.install(mod, projectDir, {
40+
'save-dev': true,
41+
optional: false,
42+
}).wait();
43+
});
44+
45+
this.$pluginsService.add('nativescript-unit-test-runner').wait();
46+
47+
let testsDir = path.join(projectDir, 'app/tests');
48+
let shouldCreateSampleTests = true;
49+
if (this.$fs.exists(testsDir).wait()) {
50+
this.$logger.info('app/tests/ directory already exists, will not create an example test project.');
51+
shouldCreateSampleTests = false;
52+
}
53+
54+
this.$fs.ensureDirectoryExists(testsDir).wait();
55+
56+
let karmaConfTemplate = this.$resources.readText('test/karma.conf.js').wait();
57+
let karmaConf = _.template(karmaConfTemplate)({
58+
frameworks: [frameworkToInstall].concat(this.frameworkDependencies[frameworkToInstall])
59+
.map(fw => `'${fw}'`)
60+
.join(', ')
61+
});
62+
63+
this.$fs.writeFile(path.join(projectDir, 'karma.conf.js'), karmaConf).wait();
64+
65+
let exampleFilePath = this.$resources.resolvePath(util.format('test/example.%s.js', frameworkToInstall));
66+
67+
if (shouldCreateSampleTests && this.$fs.exists(exampleFilePath).wait()) {
68+
this.$fs.copyFile(exampleFilePath, path.join(testsDir, 'example.js')).wait();
69+
this.$logger.info('\nExample test file created in app/tests/'.yellow);
70+
} else {
71+
this.$logger.info('\nPlace your test files under app/tests/'.yellow);
72+
}
73+
74+
this.$logger.info('Run your tests using the "$ tns test <platform>" command.'.yellow);
75+
}).future<void>()();
76+
}
77+
78+
allowedParameters: ICommandParameter[] = [];
79+
}
80+
$injector.registerCommand("test|init", TestInitCommand);

lib/commands/test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
///<reference path="../.d.ts"/>
2+
3+
"use strict";
4+
5+
function RunTestCommandFactory(platform: string) {
6+
return function RunTestCommand($testExecutionService: ITestExecutionService) {
7+
this.execute = (args: string[]): IFuture<void> => $testExecutionService.startTestRunner(platform);
8+
this.allowedParameters = [];
9+
};
10+
}
11+
12+
$injector.registerCommand("dev-test|android", RunTestCommandFactory('android'));
13+
$injector.registerCommand("dev-test|ios", RunTestCommandFactory('ios'));
14+
15+
function RunKarmaTestCommandFactory(platform: string) {
16+
return function RunKarmaTestCommand($testExecutionService: ITestExecutionService) {
17+
this.execute = (args: string[]): IFuture<void> => $testExecutionService.startKarmaServer(platform);
18+
this.allowedParameters = [];
19+
};
20+
}
21+
22+
$injector.registerCommand("test|android", RunKarmaTestCommandFactory('android'));
23+
$injector.registerCommand("test|ios", RunKarmaTestCommandFactory('ios'));

0 commit comments

Comments
 (0)