Skip to content

feat: keep the unit testing dependencies up-to-date and stable #4418

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 3 commits into from
Mar 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,4 @@ lib/common/xunit.xml
lib/common/test-reports.xml
!lib/common/test-scripts/**
!lib/common/scripts/**
config/test-deps-versions-generated.json
33 changes: 32 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const childProcess = require("child_process");
const EOL = require("os").EOL;
const path = require("path");
const now = new Date().toISOString();
const latestVersion = require('latest-version');

const ENVIRONMENTS = {
live: "live",
Expand Down Expand Up @@ -205,9 +207,14 @@ module.exports = function (grunt) {
});

grunt.registerTask("test", ["ts:devall", "shell:npm_test"]);

registerTestingDependenciesTasks(grunt);

grunt.registerTask("prepare", [
"clean",
"ts:release_build",
"generate_unit_testing_dependencies",
"verify_unit_testing_dependencies",
"shell:npm_test",

"set_live_ga_id",
Expand All @@ -230,6 +237,30 @@ module.exports = function (grunt) {
grunt.registerTask("lint", ["tslint:build"]);
grunt.registerTask("all", ["clean", "test", "lint"]);
grunt.registerTask("rebuild", ["clean", "ts:devlib"]);
grunt.registerTask("default", "ts:devlib");
grunt.registerTask("default", ["ts:devlib", "generate_unit_testing_dependencies"]);
grunt.registerTask("docs-jekyll", ['template']);
};

function registerTestingDependenciesTasks(grunt) {
const configsBasePath = path.join(__dirname, "config");
const generatedVersionFilePath = path.join(configsBasePath, "test-deps-versions-generated.json");

grunt.registerTask("generate_unit_testing_dependencies", async function () {
var done = this.async();
const dependenciesVersions = {};
const testDependencies = grunt.file.readJSON(path.join(configsBasePath, "test-dependencies.json"));
for (var dependency of testDependencies) {
const dependencyVersion = dependency.version || await latestVersion(dependency.name);
dependenciesVersions[dependency.name] = dependencyVersion;
}
grunt.file.write(generatedVersionFilePath, JSON.stringify(dependenciesVersions));
done();
});

grunt.registerTask("verify_unit_testing_dependencies", function () {
if (!grunt.file.exists(generatedVersionFilePath)) {
throw new Error("Unit testing dependencies are not configured.");
}
});
}

28 changes: 28 additions & 0 deletions config/test-dependencies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[
{
"name": "karma"
},
{
"name": "karma-nativescript-launcher"
},
{
"name": "mocha",
"framework": "mocha"
},
{
"name": "karma-mocha",
"framework": "mocha"
},
{
"name": "karma-chai",
"framework": "mocha"
},
{
"name": "karma-jasmine",
"framework": "jasmine"
},
{
"name": "karma-qunit",
"framework": "qunit"
}
]
1 change: 1 addition & 0 deletions lib/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,5 +187,6 @@ $injector.require("hmrStatusService", "./services/hmr-status-service");

$injector.require("pacoteService", "./services/pacote-service");
$injector.require("qrCodeTerminalService", "./services/qr-code-terminal-service");
$injector.require("testInitializationService", "./services/test-initialization-service");

$injector.require("networkConnectivityValidator", "./helpers/network-connectivity-validator");
40 changes: 17 additions & 23 deletions lib/commands/test-init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import { fromWindowsRelativePathToUnix } from '../common/helpers';
class TestInitCommand implements ICommand {
public allowedParameters: ICommandParameter[] = [];

private frameworkDependencies: IDictionary<string[]> = {
mocha: ['karma-chai', 'mocha'],
};

private karmaConfigAdditionalFrameworks: IDictionary<string[]> = {
mocha: ['chai']
};
Expand All @@ -21,7 +17,8 @@ class TestInitCommand implements ICommand {
private $fs: IFileSystem,
private $resources: IResourceLoader,
private $pluginsService: IPluginsService,
private $logger: ILogger) {
private $logger: ILogger,
private $testInitializationService: ITestInitializationService) {
this.$projectData.initializeProjectData();
}

Expand All @@ -34,28 +31,25 @@ class TestInitCommand implements ICommand {
this.$errors.fail(`Unknown or unsupported unit testing framework: ${frameworkToInstall}`);
}

const dependencies = this.frameworkDependencies[frameworkToInstall] || [];
const modulesToInstall: IDependencyInformation[] = [
{
name: 'karma',
// Hardcode the version unitl https://github.com/karma-runner/karma/issues/3052 is fixed
version: "2.0.2"
},
{
name: `karma-${frameworkToInstall}`
},
{
name: 'karma-nativescript-launcher'
}
];
let modulesToInstall: IDependencyInformation[] = [];
try {
const dependencies = this.$testInitializationService.getDependencies(frameworkToInstall);
const dependenciesVersions = this.$testInitializationService.getDependenciesVersions();
modulesToInstall = dependencies.map(dependency => {
const dependencyVersion = dependenciesVersions[dependency];
if (!dependencyVersion) {
this.$errors.failWithoutHelp(`'${dependency}' is not a registered dependency.`);
}

modulesToInstall.push(...dependencies.map(f => ({ name: f })));
return { name: dependency, version: dependencyVersion };
});
} catch (err) {
this.$errors.failWithoutHelp(`Unable to install the unit testing dependencies. Error: '${err.message}'`);
}

for (const mod of modulesToInstall) {
let moduleToInstall = mod.name;
if (mod.version) {
moduleToInstall += `@${mod.version}`;
}
moduleToInstall += `@${mod.version}`;
await this.$packageManager.install(moduleToInstall, projectDir, {
'save-dev': true,
'save-exact': true,
Expand Down
5 changes: 5 additions & 0 deletions lib/definitions/project.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,11 @@ interface ITestExecutionService {
canStartKarmaServer(projectData: IProjectData): Promise<boolean>;
}

interface ITestInitializationService {
getDependencies(framework: string): string[];
getDependenciesVersions(): IDictionary<string>;
}

/**
* Describes a service used to facilitate communication with CocoaPods
*/
Expand Down
29 changes: 29 additions & 0 deletions lib/services/test-initialization-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as path from "path";
import { cache } from "../common/decorators";

export class TestInitializationService implements ITestInitializationService {
private configsPath = path.join(__dirname, "..", "..", "config");

constructor(private $fs: IFileSystem) { }

@cache()
public getDependencies(selectedFramework: string): string[] {
const dependenciesPath = path.join(this.configsPath, "test-dependencies.json");
const allDependencies: { name: string, framework: string }[] = this.$fs.readJson(dependenciesPath);
const targetFrameworkDependencies: string[] = allDependencies
.filter(dependency => !dependency.framework || dependency.framework === selectedFramework)
.map(dependency => dependency.name);

return targetFrameworkDependencies;
}

@cache()
public getDependenciesVersions(): IDictionary<string> {
const dependenciesVersionsPath = path.join(this.configsPath, "test-deps-versions-generated.json");
const dependenciesVersions = this.$fs.readJson(dependenciesVersionsPath);

return dependenciesVersions;
}
}

$injector.register("testInitializationService", TestInitializationService);
Loading