Skip to content

Commit

Permalink
feat(mutators): Remove side effects from mutator plugins (#1352)
Browse files Browse the repository at this point in the history
Use the new plugin system to load the `Mutator` plugins. Remove side effects from importing the existing mutator plugins:

 * `TypescriptMutator`
 * `JavascriptMutator`
 * `VueMutator`
  • Loading branch information
nicojs authored Feb 6, 2019
1 parent 9841799 commit edaf401
Show file tree
Hide file tree
Showing 62 changed files with 637 additions and 578 deletions.
11 changes: 2 additions & 9 deletions packages/stryker-javascript-mutator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,14 @@
"@babel/parser": "~7.3.1",
"@babel/traverse": "~7.2.2",
"lodash": "~4.17.4",
"stryker-api": "^0.23.0",
"tslib": "~1.9.3"
},
"devDependencies": {
"@babel/types": "~7.3.0",
"@stryker-mutator/test-helpers": "^0.0.0",
"@types/babel__generator": "^7.0.0",
"@types/babel__traverse": "^7.0.0",
"stryker-api": "^0.23.0",
"stryker-mutator-specification": "^0.7.0"
},
"peerDependencies": {
"stryker-api": ">=0.18.0 <0.24.0"
},
"initStrykerConfig": {
"mutate": [
"src/**/*.js"
]
}
}
20 changes: 9 additions & 11 deletions packages/stryker-javascript-mutator/src/JavaScriptMutator.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import * as types from '@babel/types';
import { getLogger } from 'stryker-api/logging';
import { Logger } from 'stryker-api/logging';
import { Mutator, Mutant } from 'stryker-api/mutant';
import { File } from 'stryker-api/core';
import { Config } from 'stryker-api/config';
import copy from './helpers/copy';
import NodeMutatorFactory from './NodeMutatorFactory';
import NodeMutator from './mutators/NodeMutator';
import { NodeMutator, NODE_MUTATORS_TOKEN } from './mutators/NodeMutator';
import BabelHelper from './helpers/BabelHelper';
import { tokens, commonTokens } from 'stryker-api/plugin';

function defaultMutators(): NodeMutator[] {
return NodeMutatorFactory.instance().knownNames().map(name => NodeMutatorFactory.instance().create(name, undefined));
}

export default class JavaScriptMutator implements Mutator {
private readonly log = getLogger(JavaScriptMutator.name);
export class JavaScriptMutator implements Mutator {

constructor(_: Config, private readonly mutators: NodeMutator[] = defaultMutators()) { }
public static inject = tokens(commonTokens.logger, NODE_MUTATORS_TOKEN) ;
constructor(
private readonly log: Logger,
private readonly mutators: ReadonlyArray<NodeMutator>
) { }

public mutate(inputFiles: File[]): Mutant[] {
const mutants: Mutant[] = [];
Expand Down
23 changes: 0 additions & 23 deletions packages/stryker-javascript-mutator/src/NodeMutatorFactory.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as types from '@babel/types';

export default class NodeGenerator {
export class NodeGenerator {
public static createBooleanLiteralNode(originalNode: types.Node, value: boolean): types.BooleanLiteral {
return {
end: originalNode.end,
Expand Down
18 changes: 14 additions & 4 deletions packages/stryker-javascript-mutator/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import { MutatorFactory } from 'stryker-api/mutant';
import JavaScriptMutator from './JavaScriptMutator';
require('./mutators');
import { JavaScriptMutator } from './JavaScriptMutator';
import { PluginKind, declareFactoryPlugin, commonTokens, tokens, Injector, OptionsContext } from 'stryker-api/plugin';
import { NODE_MUTATORS_TOKEN } from './mutators/NodeMutator';
import { nodeMutators } from './mutators';

MutatorFactory.instance().register('javascript', JavaScriptMutator);
export const strykerPlugins = [
declareFactoryPlugin(PluginKind.Mutator, 'javascript', javaScriptMutatorFactory)
];

function javaScriptMutatorFactory(injector: Injector<OptionsContext>): JavaScriptMutator {
return injector
.provideValue(NODE_MUTATORS_TOKEN, nodeMutators)
.injectClass(JavaScriptMutator);
}
javaScriptMutatorFactory.inject = tokens(commonTokens.injector);
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import { NodeMutator } from './NodeMutator';

/**
* Represents a mutator which can remove the content of an array's elements.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import { NodeMutator } from './NodeMutator';

/**
* Represents a mutator which can remove the content of an array's elements.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import { NodeMutator } from './NodeMutator';

export default class BinaryExpressionMutator implements NodeMutator {
private readonly operators: { [targetedOperator: string]: string | string[] } = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import { NodeMutator } from './NodeMutator';

/**
* Represents a mutator which can remove the content of a Block.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import { NodeMutator } from './NodeMutator';

export default class BooleanSubstitutionMutator implements NodeMutator {
public name = 'BooleanSubstitution';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import NodeGenerator from '../helpers/NodeGenerator';
import { NodeMutator } from './NodeMutator';
import { NodeGenerator } from '../helpers/NodeGenerator';
import { NodeWithParent } from '../helpers/ParentNode';

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import NodeGenerator from '../helpers/NodeGenerator';
import { NodeMutator } from './NodeMutator';
import { NodeGenerator } from '../helpers/NodeGenerator';

/**
* Represents a mutator which can remove the conditional clause from statements.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import NodeGenerator from '../helpers/NodeGenerator';
import { NodeMutator } from './NodeMutator';
import { NodeGenerator } from '../helpers/NodeGenerator';

/**
* Represents a mutator which can remove the conditional clause from statements.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import NodeGenerator from '../helpers/NodeGenerator';
import { NodeMutator } from './NodeMutator';
import { NodeGenerator } from '../helpers/NodeGenerator';

/**
* Represents a mutator which can remove the conditional clause from statements.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import * as types from '@babel/types';
import { NodeWithParent } from '../helpers/ParentNode';

export const NODE_MUTATORS_TOKEN = 'NodeMutators';

/**
* Represents a class which can mutate parts of an Abstract Syntax Tree.
*/
export default interface NodeMutator {
export interface NodeMutator {
/**
* The name of the Mutator which may be used by reporters.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import { NodeMutator } from './NodeMutator';

/**
* Represents a mutator which can remove the content of a Object.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import { NodeMutator } from './NodeMutator';

export default class PostfixUnaryExpressionMutator implements NodeMutator {
public name = 'PostfixUnaryExpression';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import { NodeMutator } from './NodeMutator';

export default class PrefixUnaryExpressionMutator implements NodeMutator {
public name = 'PrefixUnaryExpression';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import { NodeMutator } from './NodeMutator';
import { NodeWithParent } from '../helpers/ParentNode';

export default class StringLiteralMutator implements NodeMutator {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import { NodeMutator } from './NodeMutator';
import { NodeWithParent } from '../helpers/ParentNode';

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as types from '@babel/types';
import NodeMutator from './NodeMutator';
import NodeGenerator from '../helpers/NodeGenerator';
import { NodeMutator } from './NodeMutator';
import { NodeGenerator } from '../helpers/NodeGenerator';

/**
* Represents a mutator which can remove the conditional clause from statements.
Expand Down
34 changes: 17 additions & 17 deletions packages/stryker-javascript-mutator/src/mutators/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import NodeMutatorFactory from '../NodeMutatorFactory';
import ArrayLiteralMutator from './ArrayLiteralMutator';
import ArrayNewExpressionMutator from './ArrayNewExpressionMutator';
import BinaryExpressionMutator from './BinaryExpressionMutator';
Expand All @@ -15,19 +14,20 @@ import StringLiteralMutator from './StringLiteralMutator';
import SwitchCaseMutator from './SwitchCaseMutator';
import WhileStatementMutator from './WhileStatementMutator';

const factory = NodeMutatorFactory.instance();
factory.register(ArrayLiteralMutator.name, ArrayLiteralMutator);
factory.register(ArrayNewExpressionMutator.name, ArrayNewExpressionMutator);
factory.register(BinaryExpressionMutator.name, BinaryExpressionMutator);
factory.register(BlockMutator.name, BlockMutator);
factory.register(BooleanSubstitutionMutator.name, BooleanSubstitutionMutator);
factory.register(ConditionalExpressionMutator.name, ConditionalExpressionMutator);
factory.register(DoStatementMutator.name, DoStatementMutator);
factory.register(ForStatementMutator.name, ForStatementMutator);
factory.register(IfStatementMutator.name, IfStatementMutator);
factory.register(ObjectLiteralMutator.name, ObjectLiteralMutator);
factory.register(PostfixUnaryExpressionMutator.name, PostfixUnaryExpressionMutator);
factory.register(PrefixUnaryExpressionMutator.name, PrefixUnaryExpressionMutator);
factory.register(StringLiteralMutator.name, StringLiteralMutator);
factory.register(SwitchCaseMutator.name, SwitchCaseMutator);
factory.register(WhileStatementMutator.name, WhileStatementMutator);
export const nodeMutators = Object.freeze([
new ArrayLiteralMutator(),
new ArrayNewExpressionMutator(),
new BinaryExpressionMutator(),
new BlockMutator(),
new BooleanSubstitutionMutator(),
new ConditionalExpressionMutator(),
new DoStatementMutator(),
new ForStatementMutator(),
new IfStatementMutator(),
new ObjectLiteralMutator(),
new PostfixUnaryExpressionMutator(),
new PrefixUnaryExpressionMutator(),
new StringLiteralMutator(),
new SwitchCaseMutator(),
new WhileStatementMutator()
]);
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { expect } from 'chai';
import { File } from 'stryker-api/core';
import { Mutant } from 'stryker-api/mutant';
import { Config } from 'stryker-api/config';
import JavaScriptMutator from '../../src/JavaScriptMutator';
import NodeMutator from '../../src/mutators/NodeMutator';
import { JavaScriptMutator } from '../../src/JavaScriptMutator';
import { NodeMutator } from '../../src/mutators/NodeMutator';
import ExpectMutation from 'stryker-mutator-specification/src/ExpectMutation';
import { testInjector } from '@stryker-mutator/test-helpers';

type MutatorConstructor = new() => NodeMutator;

Expand All @@ -13,7 +13,7 @@ export function verifySpecification(specification: (name: string, expectMutation
}

export function expectMutation(mutator: NodeMutator, sourceText: string, ...expectedTexts: string[]) {
const javaScriptMutator = new JavaScriptMutator(new Config(), [mutator]);
const javaScriptMutator = new JavaScriptMutator(testInjector.logger, [mutator]);
const sourceFile = new File('file.js', sourceText);
const mutants = javaScriptMutator.mutate([sourceFile]);
expect(mutants).lengthOf(expectedTexts.length);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import { expect } from 'chai';
import { File } from 'stryker-api/core';
import JavaScriptMutator from '../../src/JavaScriptMutator';
import '../../src/index';
import { Config } from 'stryker-api/config';
import { JavaScriptMutator } from '../../src/JavaScriptMutator';
import { testInjector } from '@stryker-mutator/test-helpers';
import { NodeMutator, NODE_MUTATORS_TOKEN } from '../../src/mutators/NodeMutator';
import { nodeMutators } from '../../src/mutators';

describe('JavaScriptMutator', () => {

let selectedMutators: ReadonlyArray<NodeMutator>;

beforeEach(() => {
selectedMutators = nodeMutators;
});

function createSut() {
return testInjector.injector
.provideValue(NODE_MUTATORS_TOKEN, selectedMutators)
.injectClass(JavaScriptMutator);
}

it('should generate a correct mutant', () => {
const mutator = new JavaScriptMutator(new Config());
const mutator = createSut();
const files: File[] = [new File('testFile.js', '"use strict"; var a = 1 + 2;')];

const mutants = mutator.mutate(files);
Expand All @@ -22,7 +35,7 @@ describe('JavaScriptMutator', () => {
});

it('should generate mutant a correct mutant for jsx code', () => {
const mutator = new JavaScriptMutator(new Config());
const mutator = createSut();
const files: File[] = [new File('testFile.jsx', `
"use strict";
import React from 'react'
Expand Down Expand Up @@ -52,7 +65,7 @@ describe('JavaScriptMutator', () => {
});

it('should not mutate unknown extensions', () => {
const mutator = new JavaScriptMutator(new Config());
const mutator = createSut();
const files: File[] = [new File('testFile.html', `
<html>
<head>
Expand All @@ -69,7 +82,7 @@ describe('JavaScriptMutator', () => {
});

it('should generate mutants for flow code', () => {
const mutator = new JavaScriptMutator(new Config());
const mutator = createSut();
const files: File[] = [new File('testFile.js', `
// @flow
import React from 'react'
Expand Down Expand Up @@ -105,7 +118,7 @@ describe('JavaScriptMutator', () => {
});

it('should generate mutants for js vnext code', () => {
const sut = new JavaScriptMutator(new Config());
const sut = createSut();
const files: File[] = [new File('testFile.js', `
function objectRestSpread(input) {
return {
Expand All @@ -131,7 +144,7 @@ describe('JavaScriptMutator', () => {
});

it('should generate mutants for multiple files', () => {
const mutator = new JavaScriptMutator(new Config());
const mutator = createSut();
const file: File = new File('testFile.js', '"use strict"; var a = 1 + 2;');
const file2: File = new File('testFile2.js', '"use strict"; var a = 1 + 2;');
const mutants = mutator.mutate([file, file2]);
Expand Down
11 changes: 11 additions & 0 deletions packages/stryker-javascript-mutator/test/unit/helpers/initSinon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as chai from 'chai';
import * as chaiAsPromised from 'chai-as-promised';
import * as sinon from 'sinon';
import * as sinonChai from 'sinon-chai';
import { testInjector } from '@stryker-mutator/test-helpers';
chai.use(chaiAsPromised);
chai.use(sinonChai);
afterEach(() => {
sinon.restore();
testInjector.reset();
});
3 changes: 0 additions & 3 deletions packages/stryker-javascript-mutator/tsconfig.src.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
"references": [
{
"path": "../stryker-api/tsconfig.src.json",
},
{
"path": "../stryker-mutator-specification/tsconfig.src.json"
}
]
}
Loading

0 comments on commit edaf401

Please sign in to comment.