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 fcc80bf75d..5a17fb42f8 100644 --- a/lib/commands/test-init.ts +++ b/lib/commands/test-init.ts @@ -33,16 +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 => { - const dependencyVersion = dependenciesVersions[dependency]; - if (!dependencyVersion) { - this.$errors.failWithoutHelp(`'${dependency}' is not a registered dependency.`); - } - - return { name: dependency, version: dependencyVersion }; - }); + modulesToInstall = this.$testInitializationService.getDependencies(frameworkToInstall); } catch (err) { this.$errors.failWithoutHelp(`Unable to install the unit testing dependencies. Error: '${err.message}'`); } @@ -66,6 +57,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[]; } /** diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index 5110e56e8d..d4ec9135a8 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -482,8 +482,7 @@ interface ITestExecutionService { } interface ITestInitializationService { - getDependencies(framework: string): string[]; - getDependenciesVersions(): IDictionary; + getDependencies(framework: string): IDependencyInformation[]; } /** diff --git a/lib/services/test-execution-service.ts b/lib/services/test-execution-service.ts index d2f5d9a72c..04f6590be2 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,25 +58,8 @@ 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."); - } let devices = []; if (this.$options.debugBrk) { @@ -125,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 }; @@ -139,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); @@ -207,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() } }, @@ -226,6 +217,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/lib/services/test-initialization-service.ts b/lib/services/test-initialization-service.ts index df0a081059..226cd3fc22 100644 --- a/lib/services/test-initialization-service.ts +++ b/lib/services/test-initialization-service.ts @@ -4,25 +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): 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); - - 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; } } diff --git a/resources/test/karma.conf.js b/resources/test/karma.conf.js index 5fc70a7fb1..1cc877d6e4 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,35 @@ 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); + delete options.webpack.entry; + delete options.webpack.output.libraryTarget; + } }