From 857e4a571bfc792bd3bb1f1c22c4d4898592cd18 Mon Sep 17 00:00:00 2001 From: Simon de Lang Date: Tue, 12 Feb 2019 13:06:26 +0100 Subject: [PATCH] feat(config injection): remove Config from the DI tokens (#1389) BREAKING CHANGE: removed Config object from Dependency Injection (only relevant for plugin creators). --- packages/stryker-api/src/plugin/Contexts.ts | 5 ----- packages/stryker-api/src/plugin/tokens.ts | 4 ---- .../test/unit/plugin/tokens.spec.ts | 1 - .../integration/StrykerJestRunner.it.spec.ts | 13 ++++++----- .../stryker-test-helpers/src/TestInjector.ts | 7 ------ packages/stryker/src/Stryker.ts | 14 +++++------- packages/stryker/src/config/configFactory.ts | 17 -------------- packages/stryker/src/config/index.ts | 2 +- packages/stryker/src/config/readConfig.ts | 9 ++++++++ .../src/di/buildChildProcessInjector.ts | 15 ++++++------- packages/stryker/src/di/buildMainInjector.ts | 3 +-- packages/stryker/src/di/factoryMethods.ts | 10 ++++++--- packages/stryker/test/unit/StrykerSpec.ts | 2 +- .../test/unit/di/buildMainInjector.spec.ts | 22 ++++++++----------- 14 files changed, 48 insertions(+), 76 deletions(-) delete mode 100644 packages/stryker/src/config/configFactory.ts create mode 100644 packages/stryker/src/config/readConfig.ts diff --git a/packages/stryker-api/src/plugin/Contexts.ts b/packages/stryker-api/src/plugin/Contexts.ts index 10e32f9101..b937eb874f 100644 --- a/packages/stryker-api/src/plugin/Contexts.ts +++ b/packages/stryker-api/src/plugin/Contexts.ts @@ -1,7 +1,6 @@ import { LoggerFactoryMethod, Logger } from '../../logging'; import { StrykerOptions } from '../../core'; import { PluginResolver } from './Plugins'; -import { Config } from '../../config'; import { PluginKind } from './PluginKind'; import { commonTokens } from './tokens'; @@ -20,10 +19,6 @@ export interface BaseContext { */ export interface OptionsContext extends BaseContext { [commonTokens.options]: StrykerOptions; - /** - * @deprecated This is just here to migrate between old and new plugins. Don't use this! Use `options` instead - */ - [commonTokens.config]: Config; } /** diff --git a/packages/stryker-api/src/plugin/tokens.ts b/packages/stryker-api/src/plugin/tokens.ts index 75f17ae780..c936a8c005 100644 --- a/packages/stryker-api/src/plugin/tokens.ts +++ b/packages/stryker-api/src/plugin/tokens.ts @@ -14,10 +14,6 @@ const injector: import('typed-inject').InjectorToken = '$injector'; * Common tokens used for dependency injection (see typed-inject readme for more information) */ export const commonTokens = Object.freeze({ - /** - * @deprecated Use 'options' instead. This is just hear to support plugin migration - */ - config: stringLiteral('config'), getLogger: stringLiteral('getLogger'), injector, logger: stringLiteral('logger'), diff --git a/packages/stryker-api/test/unit/plugin/tokens.spec.ts b/packages/stryker-api/test/unit/plugin/tokens.spec.ts index e3ca0a8609..a953919a34 100644 --- a/packages/stryker-api/test/unit/plugin/tokens.spec.ts +++ b/packages/stryker-api/test/unit/plugin/tokens.spec.ts @@ -16,7 +16,6 @@ describe('commonTokens', () => { expect(commonTokens[token]).eq(token); }); } - itShouldProvideToken('config'); itShouldProvideToken('options'); itShouldProvideToken('logger'); itShouldProvideToken('pluginResolver'); diff --git a/packages/stryker-jest-runner/test/integration/StrykerJestRunner.it.spec.ts b/packages/stryker-jest-runner/test/integration/StrykerJestRunner.it.spec.ts index f2bb7573a6..a41abd67ea 100644 --- a/packages/stryker-jest-runner/test/integration/StrykerJestRunner.it.spec.ts +++ b/packages/stryker-jest-runner/test/integration/StrykerJestRunner.it.spec.ts @@ -9,7 +9,7 @@ paths.appTsTestConfig = require.resolve('../../testResources/reactTsProject/tsco import JestConfigEditor from '../../src/JestConfigEditor'; import { jestTestRunnerFactory } from '../../src/JestTestRunner'; -import { testInjector } from '@stryker-mutator/test-helpers'; +import { testInjector, factory } from '@stryker-mutator/test-helpers'; import { commonTokens } from 'stryker-api/plugin'; // Get the actual project root, since we will stub process.cwd later on @@ -38,9 +38,12 @@ describe('Integration test for Strykers Jest runner', () => { processCwdStub = sinon.stub(process, 'cwd'); }); - function createSut() { + function createSut(jestConfig?: any) { const jestConfigEditor = testInjector.injector.injectClass(JestConfigEditor); - const config = testInjector.injector.resolve(commonTokens.config); + const config = factory.config(); + if (jestConfig) { + config.jest = jestConfig; + } jestConfigEditor.edit(config); return testInjector.injector .provideValue(commonTokens.options, config) @@ -49,9 +52,7 @@ describe('Integration test for Strykers Jest runner', () => { it('should run tests on the example React + TypeScript project', async () => { processCwdStub.returns(getProjectRoot('reactTsProject')); - testInjector.options.jest = { projectType: 'react-ts' }; - - const jestTestRunner = createSut(); + const jestTestRunner = createSut({ projectType: 'react-ts' }); const result = await jestTestRunner.run(runOptions); expect(result.status).to.equal(RunStatus.Complete); diff --git a/packages/stryker-test-helpers/src/TestInjector.ts b/packages/stryker-test-helpers/src/TestInjector.ts index c684a00d4d..cb1b291bfd 100644 --- a/packages/stryker-test-helpers/src/TestInjector.ts +++ b/packages/stryker-test-helpers/src/TestInjector.ts @@ -4,7 +4,6 @@ import { Logger } from 'stryker-api/logging'; import * as factory from './factory'; import * as sinon from 'sinon'; import { rootInjector, Injector, Scope } from 'typed-inject'; -import { Config } from 'stryker-api/config'; class TestInjector { @@ -14,11 +13,6 @@ class TestInjector { private readonly provideLogger = (): Logger => { return this.logger; } - private readonly provideConfig = () => { - const config = new Config(); - config.set(this.options); - return config; - } private readonly provideOptions = () => { return this.options; } @@ -30,7 +24,6 @@ class TestInjector { .provideValue(commonTokens.getLogger, this.provideLogger) .provideFactory(commonTokens.logger, this.provideLogger, Scope.Transient) .provideFactory(commonTokens.options, this.provideOptions, Scope.Transient) - .provideFactory(commonTokens.config, this.provideConfig, Scope.Transient) .provideFactory(commonTokens.pluginResolver, this.providePluginResolver, Scope.Transient); public reset() { diff --git a/packages/stryker/src/Stryker.ts b/packages/stryker/src/Stryker.ts index 4854a79269..6ce5cd3463 100644 --- a/packages/stryker/src/Stryker.ts +++ b/packages/stryker/src/Stryker.ts @@ -1,4 +1,3 @@ -import { Config } from 'stryker-api/config'; import { StrykerOptions } from 'stryker-api/core'; import { MutantResult } from 'stryker-api/report'; import { MutantTestMatcher } from './mutants/MutantTestMatcher'; @@ -28,8 +27,8 @@ export default class Stryker { return this.injector.resolve(coreTokens.reporter); } - private get config(): Readonly { - return this.injector.resolve(commonTokens.config); + private get options(): Readonly { + return this.injector.resolve(commonTokens.options); } private get timer() { @@ -46,12 +45,11 @@ export default class Stryker { this.injector = buildMainInjector(cliOptions); this.log = this.injector.resolve(commonTokens.getLogger)(Stryker.name); // Log level may have changed - const options = this.config; - LogConfigurator.configureMainProcess(options.logLevel, options.fileLogLevel, options.allowConsoleColors); + LogConfigurator.configureMainProcess(this.options.logLevel, this.options.fileLogLevel, this.options.allowConsoleColors); } public async runMutationTest(): Promise { - const loggingContext = await LogConfigurator.configureLoggingServer(this.config.logLevel, this.config.fileLogLevel, this.config.allowConsoleColors); + const loggingContext = await LogConfigurator.configureLoggingServer(this.options.logLevel, this.options.fileLogLevel, this.options.allowConsoleColors); this.timer.reset(); const inputFiles = await this.injector.injectClass(InputFileResolver).resolve(); if (inputFiles.files.length) { @@ -60,7 +58,7 @@ export default class Stryker { .provideValue(coreTokens.loggingContext, loggingContext) .provideValue(coreTokens.inputFiles, inputFiles); const initialTestRunProcess = inputFileInjector - .provideValue(commonTokens.produceSourceMaps, this.config.coverageAnalysis !== 'off') + .provideValue(commonTokens.produceSourceMaps, this.options.coverageAnalysis !== 'off') .provideFactory(coreTokens.pluginCreatorTranspiler, PluginCreator.createFactory(PluginKind.Transpiler)) .provideClass(coreTokens.transpiler, TranspilerFacade) .injectClass(InitialTestExecutor); @@ -118,6 +116,6 @@ export default class Stryker { const calculator = this.injector.injectClass(ScoreResultCalculator); const score = calculator.calculate(mutantResults); this.reporter.onScoreCalculated(score); - calculator.determineExitCode(score, this.config.thresholds); + calculator.determineExitCode(score, this.options.thresholds); } } diff --git a/packages/stryker/src/config/configFactory.ts b/packages/stryker/src/config/configFactory.ts deleted file mode 100644 index a6d6d29ef0..0000000000 --- a/packages/stryker/src/config/configFactory.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { ConfigEditorApplier } from './ConfigEditorApplier'; -import ConfigReader from './ConfigReader'; -import { freezeRecursively } from '../utils/objectUtils'; -import { tokens } from 'stryker-api/plugin'; -import { coreTokens } from '../di'; -import { Config } from 'stryker-api/config'; - -export function readConfig(configReader: ConfigReader) { - return configReader.readConfig(); -} -readConfig.inject = tokens(coreTokens.configReader); - -export function configFactory(config: Config, configEditorApplier: ConfigEditorApplier) { - configEditorApplier.edit(config); - return freezeRecursively(config); -} -configFactory.inject = tokens(coreTokens.configReadFromConfigFile, coreTokens.configEditorApplier); diff --git a/packages/stryker/src/config/index.ts b/packages/stryker/src/config/index.ts index 205d110b90..d69d49d445 100644 --- a/packages/stryker/src/config/index.ts +++ b/packages/stryker/src/config/index.ts @@ -1,2 +1,2 @@ export { ConfigEditorApplier } from './ConfigEditorApplier'; -export * from './configFactory'; +export * from './readConfig'; diff --git a/packages/stryker/src/config/readConfig.ts b/packages/stryker/src/config/readConfig.ts new file mode 100644 index 0000000000..acfc82d80d --- /dev/null +++ b/packages/stryker/src/config/readConfig.ts @@ -0,0 +1,9 @@ +import ConfigReader from './ConfigReader'; +import { tokens } from 'stryker-api/plugin'; +import { coreTokens } from '../di'; + +export function readConfig(configReader: ConfigReader) { + return configReader.readConfig(); +} + +readConfig.inject = tokens(coreTokens.configReader); diff --git a/packages/stryker/src/di/buildChildProcessInjector.ts b/packages/stryker/src/di/buildChildProcessInjector.ts index d901395f37..bd23d5f0cd 100644 --- a/packages/stryker/src/di/buildChildProcessInjector.ts +++ b/packages/stryker/src/di/buildChildProcessInjector.ts @@ -1,21 +1,20 @@ -import { Config } from 'stryker-api/config'; import { commonTokens, Scope, Injector, OptionsContext, tokens } from 'stryker-api/plugin'; -import { optionsFactory, pluginResolverFactory, loggerFactory } from './factoryMethods'; +import { pluginResolverFactory, loggerFactory } from './factoryMethods'; import { coreTokens } from '.'; import { getLogger } from 'log4js'; import { rootInjector } from 'typed-inject'; +import { StrykerOptions } from 'stryker-api/core'; -export function buildChildProcessInjector(config: Config): Injector { +export function buildChildProcessInjector(options: StrykerOptions): Injector { return rootInjector - .provideValue(commonTokens.config, config) - .provideFactory(commonTokens.options, optionsFactory) + .provideValue(commonTokens.options, options) .provideValue(commonTokens.getLogger, getLogger) .provideFactory(commonTokens.logger, loggerFactory, Scope.Transient) .provideFactory(coreTokens.pluginDescriptors, pluginDescriptorsFactory) .provideFactory(commonTokens.pluginResolver, pluginResolverFactory); } -function pluginDescriptorsFactory(config: Config): ReadonlyArray { - return config.plugins; +function pluginDescriptorsFactory(options: StrykerOptions): ReadonlyArray { + return options.plugins; } -pluginDescriptorsFactory.inject = tokens(commonTokens.config); +pluginDescriptorsFactory.inject = tokens(commonTokens.options); diff --git a/packages/stryker/src/di/buildMainInjector.ts b/packages/stryker/src/di/buildMainInjector.ts index 0d73563cf5..9a3417cb3b 100644 --- a/packages/stryker/src/di/buildMainInjector.ts +++ b/packages/stryker/src/di/buildMainInjector.ts @@ -6,7 +6,7 @@ import { TestFramework } from 'stryker-api/test_framework'; import { rootInjector } from 'typed-inject'; import { getLogger } from 'log4js'; import { loggerFactory, pluginResolverFactory, optionsFactory, testFrameworkFactory } from './factoryMethods'; -import { ConfigEditorApplier, configFactory, readConfig } from '../config'; +import { ConfigEditorApplier, readConfig } from '../config'; import BroadcastReporter from '../reporters/BroadcastReporter'; import { Config } from 'stryker-api/config'; import ConfigReader from '../config/ConfigReader'; @@ -33,7 +33,6 @@ export function buildMainInjector(cliOptions: Partial): Injector .provideFactory(commonTokens.pluginResolver, pluginResolverFactory) .provideFactory(coreTokens.pluginCreatorConfigEditor, PluginCreator.createFactory(PluginKind.ConfigEditor)) .provideClass(coreTokens.configEditorApplier, ConfigEditorApplier) - .provideFactory(commonTokens.config, configFactory) .provideFactory(commonTokens.options, optionsFactory) .provideFactory(coreTokens.pluginCreatorReporter, PluginCreator.createFactory(PluginKind.Reporter)) .provideFactory(coreTokens.pluginCreatorTestFramework, PluginCreator.createFactory(PluginKind.TestFramework)) diff --git a/packages/stryker/src/di/factoryMethods.ts b/packages/stryker/src/di/factoryMethods.ts index 0d75c53e23..c39c881500 100644 --- a/packages/stryker/src/di/factoryMethods.ts +++ b/packages/stryker/src/di/factoryMethods.ts @@ -2,7 +2,10 @@ import { tokens, commonTokens, OptionsContext, Injector, PluginKind, PluginResol import TestFrameworkOrchestrator from '../TestFrameworkOrchestrator'; import { coreTokens, PluginCreator, PluginLoader } from '.'; import { LoggerFactoryMethod, Logger } from 'stryker-api/logging'; +import { StrykerOptions } from 'stryker-api/core'; import { Config } from 'stryker-api/config'; +import { ConfigEditorApplier } from '../config'; +import { freezeRecursively } from '../utils/objectUtils'; export function pluginResolverFactory(injector: Injector<{ [commonTokens.logger]: Logger, [coreTokens.pluginDescriptors]: ReadonlyArray }>): PluginResolver { const pluginLoader = injector.injectClass(PluginLoader); @@ -21,7 +24,8 @@ export function loggerFactory(getLogger: LoggerFactoryMethod, target: Function | } loggerFactory.inject = tokens(commonTokens.getLogger, commonTokens.target); -export function optionsFactory(config: Config) { - return config; +export function optionsFactory(config: Config, configEditorApplier: ConfigEditorApplier): StrykerOptions { + configEditorApplier.edit(config); + return freezeRecursively(config); } -optionsFactory.inject = tokens(commonTokens.config); +optionsFactory.inject = tokens(coreTokens.configReadFromConfigFile, coreTokens.configEditorApplier); diff --git a/packages/stryker/test/unit/StrykerSpec.ts b/packages/stryker/test/unit/StrykerSpec.ts index a3217e557d..89ab6bbbb3 100644 --- a/packages/stryker/test/unit/StrykerSpec.ts +++ b/packages/stryker/test/unit/StrykerSpec.ts @@ -85,7 +85,7 @@ describe(Stryker.name, () => { .withArgs(MutationTestExecutor).returns(mutationTestExecutorMock) .withArgs(ScoreResultCalculator).returns(scoreResultCalculator); injectorMock.resolve - .withArgs(commonTokens.config).returns(strykerConfig) + .withArgs(commonTokens.options).returns(strykerConfig) .withArgs(di.coreTokens.timer).returns(timerMock) .withArgs(di.coreTokens.reporter).returns(reporterMock) .withArgs(di.coreTokens.testFramework).returns(testFrameworkMock) diff --git a/packages/stryker/test/unit/di/buildMainInjector.spec.ts b/packages/stryker/test/unit/di/buildMainInjector.spec.ts index 970c324f54..d36008684d 100644 --- a/packages/stryker/test/unit/di/buildMainInjector.spec.ts +++ b/packages/stryker/test/unit/di/buildMainInjector.spec.ts @@ -51,43 +51,39 @@ describe(buildMainInjector.name, () => { return stub; } - describe('resolve config', () => { + describe('resolve options', () => { it('should supply readonly stryker options', () => { - const injector = buildMainInjector({}); - const actualConfig = injector.resolve(commonTokens.config); - const actualOptions = injector.resolve(commonTokens.options); - expect(actualConfig).eq(expectedConfig); - expect(actualConfig).frozen; - expect(actualOptions).eq(expectedConfig); + const actualOptions = buildMainInjector({}).resolve(commonTokens.options); + expect(actualOptions).frozen; }); it('should load default plugins', () => { - buildMainInjector({}).resolve(commonTokens.config); + buildMainInjector({}).resolve(commonTokens.options); expect(di.PluginLoader).calledWithNew; expect(di.PluginLoader).calledWith(currentLogMock(), ['stryker-*', require.resolve('../../../src/reporters')]); }); it('should load plugins', () => { - buildMainInjector({}).resolve(commonTokens.config); + buildMainInjector({}).resolve(commonTokens.options); expect(pluginLoaderMock.load).called; }); it('should apply config editors', () => { - buildMainInjector({}).resolve(commonTokens.config); + buildMainInjector({}).resolve(commonTokens.options); expect(configEditorApplierMock.edit).called; }); it('should cache the config', () => { const injector = buildMainInjector({}); - injector.resolve(commonTokens.config); - injector.resolve(commonTokens.config); + injector.resolve(commonTokens.options); + injector.resolve(commonTokens.options); expect(configReaderMock.readConfig).calledOnce; }); it('should inject the `cliOptions` in the config reader', () => { const expectedCliOptions = { foo: 'bar' }; - buildMainInjector(expectedCliOptions).resolve(commonTokens.config); + buildMainInjector(expectedCliOptions).resolve(commonTokens.options); expect(configReaderModule.default).calledWith(expectedCliOptions); }); });