diff --git a/packages/instrumenter/package.json b/packages/instrumenter/package.json index 00a9d7e059..6f6354af33 100644 --- a/packages/instrumenter/package.json +++ b/packages/instrumenter/package.json @@ -40,7 +40,7 @@ "@stryker-mutator/api": "4.5.0", "@stryker-mutator/util": "4.5.0", "angular-html-parser": "~1.7.0", - "weapon-regex": "~0.3.0" + "weapon-regex": "~0.4.1" }, "devDependencies": { "@babel/preset-react": "~7.12.1", diff --git a/packages/instrumenter/src/mutators/regex-mutator.ts b/packages/instrumenter/src/mutators/regex-mutator.ts index 00f1fa5fae..3693568a9c 100644 --- a/packages/instrumenter/src/mutators/regex-mutator.ts +++ b/packages/instrumenter/src/mutators/regex-mutator.ts @@ -22,25 +22,14 @@ function isObviousRegexString(path: NodePath) { } const weaponRegexOptions: weaponRegex.Options = { mutationLevels: [1] }; -function mutatePattern(pattern: string): string[] { - if (pattern.length) { - try { - return weaponRegex.mutate(pattern, weaponRegexOptions).map((mutant) => mutant.pattern); - } catch (err) { - console.error( - `[RegexMutator]: The Regex parser of weapon-regex couldn't parse this regex pattern: "${pattern}". Please report this issue at https://github.com/stryker-mutator/weapon-regex/issues. Inner error: ${err.message}` - ); - } - } - return []; -} - export class RegexMutator implements NodeMutator { public name = 'Regex'; + constructor(private readonly weaponRegexMutateImpl = weaponRegex.mutate) {} + public mutate(path: NodePath): NodeMutation[] { if (path.isRegExpLiteral()) { - return mutatePattern(path.node.pattern).map((replacementPattern) => { + return this.mutatePattern(path.node.pattern).map((replacementPattern) => { const replacement = types.cloneNode(path.node, false); replacement.pattern = replacementPattern; return { @@ -49,7 +38,7 @@ export class RegexMutator implements NodeMutator { }; }); } else if (path.isStringLiteral() && isObviousRegexString(path)) { - return mutatePattern(path.node.value).map((replacementPattern) => { + return this.mutatePattern(path.node.value).map((replacementPattern) => { const replacement = types.cloneNode(path.node, false); replacement.value = replacementPattern; return { @@ -60,4 +49,17 @@ export class RegexMutator implements NodeMutator { } return []; } + + private mutatePattern(pattern: string): string[] { + if (pattern.length) { + try { + return this.weaponRegexMutateImpl(pattern, weaponRegexOptions).map((mutant) => mutant.pattern); + } catch (err) { + console.error( + `[RegexMutator]: The Regex parser of weapon-regex couldn't parse this regex pattern: "${pattern}". Please report this issue at https://github.com/stryker-mutator/weapon-regex/issues. Inner error: ${err.message}` + ); + } + } + return []; + } } diff --git a/packages/instrumenter/test/unit/mutators/regex-mutator.spec.ts b/packages/instrumenter/test/unit/mutators/regex-mutator.spec.ts index 231537ebad..2b97e1876a 100644 --- a/packages/instrumenter/test/unit/mutators/regex-mutator.spec.ts +++ b/packages/instrumenter/test/unit/mutators/regex-mutator.spec.ts @@ -5,36 +5,44 @@ import { RegexMutator } from '../../../src/mutators/regex-mutator'; import { expectJSMutation } from '../../helpers/expect-mutation'; describe(RegexMutator.name, () => { - let sut: RegexMutator; - beforeEach(() => { - sut = new RegexMutator(); - }); - it('should have name "Regex"', () => { + const sut = new RegexMutator(); expect(sut.name).eq('Regex'); }); it('should not mutate normal string literals', () => { + const sut = new RegexMutator(); expectJSMutation(sut, '""'); }); it('should mutate a regex literal', () => { + const sut = new RegexMutator(); expectJSMutation(sut, '/\\d{4}/', '/\\d/', '/\\D{4}/'); }); it("should not crash if a regex couldn't be parsed", () => { + // Arrange + const weaponRegexStub = sinon.stub(); + weaponRegexStub.throws(new Error('[Error] Parser: Position 1:1, found "[[]]"')); + const sut = new RegexMutator(weaponRegexStub); const errorStub = sinon.stub(console, 'error'); + + // Act expectJSMutation(sut, '/[[]]/'); + + // Assert expect(errorStub).calledWith( '[RegexMutator]: The Regex parser of weapon-regex couldn\'t parse this regex pattern: "[[]]". Please report this issue at https://github.com/stryker-mutator/weapon-regex/issues. Inner error: [Error] Parser: Position 1:1, found "[[]]"' ); }); it('should mutate obvious Regex string literals', () => { + const sut = new RegexMutator(); expectJSMutation(sut, 'new RegExp("\\\\d{4}")', 'new RegExp("\\\\d")', 'new RegExp("\\\\D{4}")'); }); it('should not mutate the flags of a new RegExp constructor', () => { + const sut = new RegexMutator(); expectJSMutation(sut, 'new RegExp("", "\\\\d{4}")'); }); }); diff --git a/packages/instrumenter/tsconfig.src.json b/packages/instrumenter/tsconfig.src.json index 0f332194d8..63eb139925 100644 --- a/packages/instrumenter/tsconfig.src.json +++ b/packages/instrumenter/tsconfig.src.json @@ -15,5 +15,5 @@ "path": "../util/tsconfig.src.json" } ], - "include": ["src"] + "include": ["src", "typings"] } diff --git a/packages/instrumenter/tsconfig.test.json b/packages/instrumenter/tsconfig.test.json index 5cf5c49895..f86f43821d 100644 --- a/packages/instrumenter/tsconfig.test.json +++ b/packages/instrumenter/tsconfig.test.json @@ -16,7 +16,5 @@ "path": "../test-helpers/tsconfig.src.json" } ], - "include": [ - "test" - ] + "include": ["test", "typings"] } diff --git a/packages/instrumenter/src/typings/weapon-regex.ts b/packages/instrumenter/typings/weapon-regex.d.ts similarity index 100% rename from packages/instrumenter/src/typings/weapon-regex.ts rename to packages/instrumenter/typings/weapon-regex.d.ts