From f4605e929522bb639fc33886fd7dbecc97a24aca Mon Sep 17 00:00:00 2001 From: fatme Date: Wed, 6 Mar 2019 19:14:43 +0200 Subject: [PATCH 1/9] fix: skip not needed prepare when bundle is passed --- lib/services/test-execution-service.ts | 47 +++++++++++++++----------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/lib/services/test-execution-service.ts b/lib/services/test-execution-service.ts index d2f5d9a72c..347feb3fb2 100644 --- a/lib/services/test-execution-service.ts +++ b/lib/services/test-execution-service.ts @@ -59,25 +59,7 @@ export class TestExecutionService implements ITestExecutionService { this.$fs.writeFile(path.join(projectDir, TestExecutionService.CONFIG_FILE_NAME), configJs); } - const appFilesUpdaterOptions: IAppFilesUpdaterOptions = { - bundle: !!this.$options.bundle, - release: this.$options.release, - useHotModuleReload: this.$options.hmr - }; - const preparePlatformInfo: IPreparePlatformInfo = { - platform, - appFilesUpdaterOptions, - platformTemplate: this.$options.platformTemplate, - projectData, - config: this.$options, - env: this.$options.env - }; - - // Prepare the project AFTER the TestExecutionService.CONFIG_FILE_NAME file is created in node_modules - // so it will be sent to device. - if (!await this.$platformService.preparePlatform(preparePlatformInfo)) { - this.$errors.failWithoutHelp("Verify that listed files are well-formed and try again the operation."); - } + await this.preparePlatform(projectData, platform); let devices = []; if (this.$options.debugBrk) { @@ -230,5 +212,32 @@ export class TestExecutionService implements ITestExecutionService { return karmaConfig; } + + private async preparePlatform(projectData: IProjectData, platform: string): Promise { + if (this.$options.bundle) { + return; + } + + const appFilesUpdaterOptions: IAppFilesUpdaterOptions = { + bundle: !!this.$options.bundle, + release: this.$options.release, + useHotModuleReload: this.$options.hmr + }; + const preparePlatformInfo: IPreparePlatformInfo = { + platform, + appFilesUpdaterOptions, + platformTemplate: this.$options.platformTemplate, + projectData, + config: this.$options, + env: this.$options.env + }; + + // Prepare the project AFTER the TestExecutionService.CONFIG_FILE_NAME file is created in node_modules + // so it will be sent to device. + const isPlatformPrepared = await this.$platformService.preparePlatform(preparePlatformInfo); + if (!isPlatformPrepared) { + this.$errors.failWithoutHelp("Verify that listed files are well-formed and try again the operation."); + } + } } $injector.register('testExecutionService', TestExecutionService); From 8ee2bed102c44a64e51b6cffa5111ef3bdaa1e32 Mon Sep 17 00:00:00 2001 From: fatme Date: Wed, 6 Mar 2019 22:05:01 +0200 Subject: [PATCH 2/9] feat: add webpack support for karma.conf.js --- lib/services/test-execution-service.ts | 2 ++ resources/test/karma.conf.js | 32 ++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/lib/services/test-execution-service.ts b/lib/services/test-execution-service.ts index 347feb3fb2..c5ccc35408 100644 --- a/lib/services/test-execution-service.ts +++ b/lib/services/test-execution-service.ts @@ -208,6 +208,8 @@ export class TestExecutionService implements ITestExecutionService { } karmaConfig.projectDir = projectData.projectDir; + karmaConfig.bundle = this.$options.bundle; + karmaConfig.platform = platform.toLowerCase(); this.$logger.debug(JSON.stringify(karmaConfig, null, 4)); return karmaConfig; diff --git a/resources/test/karma.conf.js b/resources/test/karma.conf.js index 5fc70a7fb1..9c478afc36 100644 --- a/resources/test/karma.conf.js +++ b/resources/test/karma.conf.js @@ -1,5 +1,5 @@ module.exports = function(config) { - config.set({ + const options = { // base path that will be used to resolve all patterns (eg. files, exclude) basePath: '', @@ -73,5 +73,33 @@ module.exports = function(config) { // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits singleRun: false - }) + }; + + setWebpackPreprocessor(config, options); + setWebpack(config, options); + + config.set(options); +} + +function setWebpackPreprocessor(config, options) { + if (config && config.bundle) { + if (!options.preprocessors) { + options.preprocessors = {}; + } + + options.files.forEach(file => { + if (!options.preprocessors[file]) { + options.preprocessors[file] = []; + } + options.preprocessors[file].push('webpack'); + }); + } +} + +function setWebpack(config, options) { + if (config && config.bundle) { + const env = {}; + env[config.platform] = true; + options.webpack = require('./webpack.config')(env); + } } From 0bbbf7124036ebc3dedc11061cee426b283331df Mon Sep 17 00:00:00 2001 From: fatme Date: Wed, 6 Mar 2019 22:14:28 +0200 Subject: [PATCH 3/9] feat: add unitTesting env variable to webpack process --- lib/services/test-execution-service.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/services/test-execution-service.ts b/lib/services/test-execution-service.ts index c5ccc35408..2b7ae9666c 100644 --- a/lib/services/test-execution-service.ts +++ b/lib/services/test-execution-service.ts @@ -107,13 +107,16 @@ export class TestExecutionService implements ITestExecutionService { return info; }); + const env = this.$options.env || {}; + env.unitTesting = !!this.$options.bundle; + const liveSyncInfo: ILiveSyncInfo = { projectDir: projectData.projectDir, skipWatcher: !this.$options.watch || this.$options.justlaunch, watchAllFiles: this.$options.syncAllFiles, bundle: !!this.$options.bundle, release: this.$options.release, - env: this.$options.env, + env, timeout: this.$options.timeout, useHotModuleReload: this.$options.hmr }; From 359059b8cfd571ad200e73a512f5a26e2320ee65 Mon Sep 17 00:00:00 2001 From: fatme Date: Fri, 15 Mar 2019 09:05:37 +0200 Subject: [PATCH 4/9] fix: remove not needed prepare --- lib/services/test-execution-service.ts | 31 ++------------------------ 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/lib/services/test-execution-service.ts b/lib/services/test-execution-service.ts index 2b7ae9666c..bdb72fb4bd 100644 --- a/lib/services/test-execution-service.ts +++ b/lib/services/test-execution-service.ts @@ -19,7 +19,6 @@ export class TestExecutionService implements ITestExecutionService { private $fs: IFileSystem, private $options: IOptions, private $pluginsService: IPluginsService, - private $errors: IErrors, private $devicesService: Mobile.IDevicesService, private $childProcess: IChildProcess) { } @@ -59,7 +58,8 @@ export class TestExecutionService implements ITestExecutionService { this.$fs.writeFile(path.join(projectDir, TestExecutionService.CONFIG_FILE_NAME), configJs); } - await this.preparePlatform(projectData, platform); + // Prepare the project AFTER the TestExecutionService.CONFIG_FILE_NAME file is created in node_modules + // so it will be sent to device. let devices = []; if (this.$options.debugBrk) { @@ -217,32 +217,5 @@ export class TestExecutionService implements ITestExecutionService { return karmaConfig; } - - private async preparePlatform(projectData: IProjectData, platform: string): Promise { - if (this.$options.bundle) { - return; - } - - const appFilesUpdaterOptions: IAppFilesUpdaterOptions = { - bundle: !!this.$options.bundle, - release: this.$options.release, - useHotModuleReload: this.$options.hmr - }; - const preparePlatformInfo: IPreparePlatformInfo = { - platform, - appFilesUpdaterOptions, - platformTemplate: this.$options.platformTemplate, - projectData, - config: this.$options, - env: this.$options.env - }; - - // Prepare the project AFTER the TestExecutionService.CONFIG_FILE_NAME file is created in node_modules - // so it will be sent to device. - const isPlatformPrepared = await this.$platformService.preparePlatform(preparePlatformInfo); - if (!isPlatformPrepared) { - this.$errors.failWithoutHelp("Verify that listed files are well-formed and try again the operation."); - } - } } $injector.register('testExecutionService', TestExecutionService); From 3e053c761357ed309d52c07b9ef89c93f1b655a1 Mon Sep 17 00:00:00 2001 From: fatme Date: Fri, 15 Mar 2019 09:06:46 +0200 Subject: [PATCH 5/9] fix: start tests execution only when the appropriate message is received --- lib/services/test-execution-service.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/services/test-execution-service.ts b/lib/services/test-execution-service.ts index bdb72fb4bd..50f1bee5d1 100644 --- a/lib/services/test-execution-service.ts +++ b/lib/services/test-execution-service.ts @@ -124,7 +124,12 @@ export class TestExecutionService implements ITestExecutionService { await this.$liveSyncService.liveSync(deviceDescriptors, liveSyncInfo); }; - karmaRunner.on("message", (karmaData: any) => { + karmaRunner.on("message", (karmaData: any) => { + this.$logger.trace(`The received message from karma is: `, karmaData); + if (!karmaData.launcherConfig && !karmaData.url) { + return; + } + launchKarmaTests(karmaData) .catch((result) => { this.$logger.error(result); From 293573df21c46950e124e136558558b486ec93d2 Mon Sep 17 00:00:00 2001 From: fatme Date: Fri, 15 Mar 2019 09:07:52 +0200 Subject: [PATCH 6/9] fix: exclude webpack from karma-webpack's peer dependencies --- lib/commands/test-init.ts | 6 ++++++ lib/common/declarations.d.ts | 1 + 2 files changed, 7 insertions(+) diff --git a/lib/commands/test-init.ts b/lib/commands/test-init.ts index fcc80bf75d..74d57ddcee 100644 --- a/lib/commands/test-init.ts +++ b/lib/commands/test-init.ts @@ -41,6 +41,7 @@ class TestInitCommand implements ICommand { this.$errors.failWithoutHelp(`'${dependency}' is not a registered dependency.`); } + return { name: dependency, version: dependencyVersion }; }); } catch (err) { @@ -66,6 +67,11 @@ class TestInitCommand implements ICommand { const modulePeerDependencies = modulePackageJsonContent.peerDependencies || {}; for (const peerDependency in modulePeerDependencies) { + const isPeerDependencyExcluded = _.includes(mod.excludedPeerDependencies, peerDependency); + if (isPeerDependencyExcluded) { + continue; + } + const dependencyVersion = modulePeerDependencies[peerDependency] || "*"; // catch errors when a peerDependency is already installed diff --git a/lib/common/declarations.d.ts b/lib/common/declarations.d.ts index 3a83d4b6c8..aa1369441a 100644 --- a/lib/common/declarations.d.ts +++ b/lib/common/declarations.d.ts @@ -1466,6 +1466,7 @@ interface IProcessService { interface IDependencyInformation { name: string; version?: string; + excludedPeerDependencies?: string[]; } /** From 1d7d27d91a52ae88ccea74e53ebc4f792aa58475 Mon Sep 17 00:00:00 2001 From: fatme Date: Fri, 15 Mar 2019 09:08:19 +0200 Subject: [PATCH 7/9] fix: pass bundle option to karma config --- lib/services/test-execution-service.ts | 1 + resources/test/karma.conf.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/lib/services/test-execution-service.ts b/lib/services/test-execution-service.ts index 50f1bee5d1..04f6590be2 100644 --- a/lib/services/test-execution-service.ts +++ b/lib/services/test-execution-service.ts @@ -197,6 +197,7 @@ export class TestExecutionService implements ITestExecutionService { debugTransport: this.$options.debugTransport, debugBrk: this.$options.debugBrk, watch: !!this.$options.watch, + bundle: !!this.$options.bundle, appDirectoryRelativePath: projectData.getAppDirectoryRelativePath() } }, diff --git a/resources/test/karma.conf.js b/resources/test/karma.conf.js index 9c478afc36..1cc877d6e4 100644 --- a/resources/test/karma.conf.js +++ b/resources/test/karma.conf.js @@ -101,5 +101,7 @@ function setWebpack(config, options) { const env = {}; env[config.platform] = true; options.webpack = require('./webpack.config')(env); + delete options.webpack.entry; + delete options.webpack.output.libraryTarget; } } From ca3c0e23fddc9ef17eaf9a729b569f309fbcd99e Mon Sep 17 00:00:00 2001 From: fatme Date: Fri, 15 Mar 2019 16:00:24 +0200 Subject: [PATCH 8/9] fix: integrate the logic with excludedPeerDependencies with the new testInitialization service --- config/test-dependencies.json | 4 ++++ lib/commands/test-init.ts | 8 +++----- lib/definitions/project.d.ts | 2 +- lib/services/test-initialization-service.ts | 7 +++---- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/config/test-dependencies.json b/config/test-dependencies.json index be15545e40..7a4868e2fb 100644 --- a/config/test-dependencies.json +++ b/config/test-dependencies.json @@ -5,6 +5,10 @@ { "name": "karma-nativescript-launcher" }, + { + "name": "karma-webpack", + "excludedPeerDependencies": ["webpack"] + }, { "name": "mocha", "framework": "mocha" diff --git a/lib/commands/test-init.ts b/lib/commands/test-init.ts index 74d57ddcee..86b7098611 100644 --- a/lib/commands/test-init.ts +++ b/lib/commands/test-init.ts @@ -36,13 +36,11 @@ class TestInitCommand implements ICommand { const dependencies = this.$testInitializationService.getDependencies(frameworkToInstall); const dependenciesVersions = this.$testInitializationService.getDependenciesVersions(); modulesToInstall = dependencies.map(dependency => { - const dependencyVersion = dependenciesVersions[dependency]; - if (!dependencyVersion) { + dependency.version = dependenciesVersions[dependency.name]; + if (!dependency.version) { this.$errors.failWithoutHelp(`'${dependency}' is not a registered dependency.`); } - - - return { name: dependency, version: dependencyVersion }; + return dependency; }); } catch (err) { this.$errors.failWithoutHelp(`Unable to install the unit testing dependencies. Error: '${err.message}'`); diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index 5110e56e8d..959c344c05 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -482,7 +482,7 @@ interface ITestExecutionService { } interface ITestInitializationService { - getDependencies(framework: string): string[]; + getDependencies(framework: string): IDependencyInformation[]; getDependenciesVersions(): IDictionary; } diff --git a/lib/services/test-initialization-service.ts b/lib/services/test-initialization-service.ts index df0a081059..de97264e9c 100644 --- a/lib/services/test-initialization-service.ts +++ b/lib/services/test-initialization-service.ts @@ -7,12 +7,11 @@ export class TestInitializationService implements ITestInitializationService { constructor(private $fs: IFileSystem) { } @cache() - public getDependencies(selectedFramework: string): string[] { + public getDependencies(selectedFramework: string): IDependencyInformation[] { 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); + const targetFrameworkDependencies: IDependencyInformation[] = allDependencies + .filter(dependency => !dependency.framework || dependency.framework === selectedFramework); return targetFrameworkDependencies; } From aaac12f42fb63cd48ae246c74accda6e4dfe082a Mon Sep 17 00:00:00 2001 From: fatme Date: Mon, 18 Mar 2019 08:58:48 +0200 Subject: [PATCH 9/9] fix: remove getDependenciesVersions method from test-initialization-service --- lib/commands/test-init.ts | 10 +-------- lib/definitions/project.d.ts | 1 - lib/services/test-initialization-service.ts | 24 ++++++++++++--------- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/lib/commands/test-init.ts b/lib/commands/test-init.ts index 86b7098611..5a17fb42f8 100644 --- a/lib/commands/test-init.ts +++ b/lib/commands/test-init.ts @@ -33,15 +33,7 @@ class TestInitCommand implements ICommand { let modulesToInstall: IDependencyInformation[] = []; try { - const dependencies = this.$testInitializationService.getDependencies(frameworkToInstall); - const dependenciesVersions = this.$testInitializationService.getDependenciesVersions(); - modulesToInstall = dependencies.map(dependency => { - dependency.version = dependenciesVersions[dependency.name]; - if (!dependency.version) { - this.$errors.failWithoutHelp(`'${dependency}' is not a registered dependency.`); - } - return dependency; - }); + modulesToInstall = this.$testInitializationService.getDependencies(frameworkToInstall); } catch (err) { this.$errors.failWithoutHelp(`Unable to install the unit testing dependencies. Error: '${err.message}'`); } diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index 959c344c05..d4ec9135a8 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -483,7 +483,6 @@ interface ITestExecutionService { interface ITestInitializationService { getDependencies(framework: string): IDependencyInformation[]; - getDependenciesVersions(): IDictionary; } /** diff --git a/lib/services/test-initialization-service.ts b/lib/services/test-initialization-service.ts index de97264e9c..226cd3fc22 100644 --- a/lib/services/test-initialization-service.ts +++ b/lib/services/test-initialization-service.ts @@ -4,24 +4,28 @@ import { cache } from "../common/decorators"; export class TestInitializationService implements ITestInitializationService { private configsPath = path.join(__dirname, "..", "..", "config"); - constructor(private $fs: IFileSystem) { } + constructor(private $errors: IErrors, + private $fs: IFileSystem) { } @cache() public getDependencies(selectedFramework: string): IDependencyInformation[] { const dependenciesPath = path.join(this.configsPath, "test-dependencies.json"); - const allDependencies: { name: string, framework: string }[] = this.$fs.readJson(dependenciesPath); - const targetFrameworkDependencies: IDependencyInformation[] = allDependencies - .filter(dependency => !dependency.framework || dependency.framework === selectedFramework); - - return targetFrameworkDependencies; - } + const allDependencies: { name: string, framework?: string, excludedPeerDependencies?: string[] }[] = this.$fs.readJson(dependenciesPath); - @cache() - public getDependenciesVersions(): IDictionary { const dependenciesVersionsPath = path.join(this.configsPath, "test-deps-versions-generated.json"); const dependenciesVersions = this.$fs.readJson(dependenciesVersionsPath); - return dependenciesVersions; + const targetFrameworkDependencies: IDependencyInformation[] = allDependencies + .filter(dependency => !dependency.framework || dependency.framework === selectedFramework) + .map(dependency => { + const dependencyVersion = dependenciesVersions[dependency.name]; + if (!dependencyVersion) { + this.$errors.failWithoutHelp(`'${dependency}' is not a registered dependency.`); + } + return { ...dependency, version: dependencyVersion }; + }); + + return targetFrameworkDependencies; } }