I am using Stryker with Babel as transpiller and in one of my classess I've got private property #hash. When I try to run Stryker on that class it fails.
Class:
const something = require('something');
const something2 = require('something2');
const something3 = require('something3');
class Example {
#hash = '';
constructor(hash) {
this.#hash = hash;
}
}
Error I am getting:
16:45:00 (12996) ERROR StrykerCli an error occurred SyntaxError: Unexpected character '#' (6:4)
at Object.raise (C:\Users\my_username\PhpstormProjects\my-project-name\node_modules\@babel\parser\lib\index.js:6344:17)
at Object.readToken_numberSign (C:\Users\my_username\PhpstormProjects\my-project-name\node_modules\@babel\parser\lib\index.js:6671:12)
at Object.getTokenFromCode (C:\Users\my_username\PhpstormProjects\my-project-name\node_modules\@babel\parser\lib\index.js:7017:14)
at Object.getTokenFromCode (C:\Users\my_username\PhpstormProjects\my-project-name\node_modules\@babel\parser\lib\index.js:3631:18)
at Object.getTokenFromCode (C:\Users\my_username\PhpstormProjects\my-project-name\node_modules\@babel\parser\lib\index.js:2306:20)
at Object.nextToken (C:\Users\my_username\PhpstormProjects\my-project-name\node_modules\@babel\parser\lib\index.js:6542:12)
at Object.next (C:\Users\my_username\PhpstormProjects\my-project-name\node_modules\@babel\parser\lib\index.js:6482:10)
at Object.eat (C:\Users\my_username\PhpstormProjects\my-project-name\node_modules\@babel\parser\lib\index.js:6487:12)
at Object.expect (C:\Users\my_username\PhpstormProjects\my-project-name\node_modules\@babel\parser\lib\index.js:7645:10)
at Object.parseClassBody (C:\Users\my_username\PhpstormProjects\my-project-name\node_modules\@babel\parser\lib\index.js:10562:10) {
pos: 166,
loc: Position { line: 6, column: 4 }
}
module.exports = function (config) {
config.set({
mutator: 'javascript',
packageManager: 'npm',
reporters: ['html', 'clear-text', 'progress'],
testRunner: 'mocha',
transpilers: ['babel'],
coverageAnalysis: 'off',
babel: {
optionsFile: '.babelrc'
},
mochaOptions: {
spec: ['test/**/*.js'],
}
});
};
+-- @stryker-mutator/[email protected]
| +-- @stryker-mutator/[email protected]
| +-- @stryker-mutator/[email protected]
+-- @stryker-mutator/[email protected]
| +-- @stryker-mutator/[email protected] deduped
| +-- @stryker-mutator/[email protected] deduped
+-- @stryker-mutator/[email protected]
| +-- @stryker-mutator/[email protected] deduped
| +-- @stryker-mutator/[email protected] deduped
+-- @stryker-mutator/[email protected]
| +-- @stryker-mutator/[email protected] deduped
+-- @stryker-mutator/[email protected]
| `-- @stryker-mutator/[email protected] deduped
+-- @stryker-mutator/[email protected]
| +-- @stryker-mutator/[email protected] deduped
+-- mocha ^6.1.4
# Test command
mocha
# .mocharc.js
module.exports = {
recursive: true
};
# .babelrc
{
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-private-methods"
]
}
| software | version(s)
| ---------------- | -------
| node | v12.3.1
| npm | 6.9.0
| Operating System | Windows 10
Have you tried running babel itself? Or do you have some repo we could use to test it?
@simivar Thanks for showing that. It is an issue. After a short investigation, I have found that code is transpiled at first, but then after passing to mutate it, it is not transpiled at all(?) quite strange thing


@nicojs any thoughts?
@simivar I think I have nailed it :)

So...
Problem in stryker is, as i said, missing plugins in stryker/packages/javascript-mutator/src/helpers/BabelHelper.ts
'classPrivateProperties',
'classProperties',
'classPrivateMethods',
These 3 are missing (probably classProperties aren't necessary but still I have included them.
(note, you need to use files option in your stryker config - in this case files = [+(src|test)/classes/*.js]
The second (it is quite breaking issue) is in your code.
you have to add .js in require or somehow everything will crash (at least it crashed on my PC)
(@nicojs you should investigate this crash since it is super strange. I can open an issue if it's necessary. Code to replicate that is already given: https://github.com/simivar/stryker-issue-1614)
(note, you need to use files option in your stryker config - in this case files = [+(src|test)/classes/*.js]
This should never be needed (at least, not when running from inside a git repo).
Indeed @kmdrGroch is correct.
The @stryker-mutator/javascript-mutator right now brings it's own babel and babel plugins. Feel free to add more plugins here in a PR, or (better maybe) allow users to define their own plugins in stryker options. We should be able to add config like this to the mutator object in the stryker config
@nicojs I suggest using babelPlugins with javascript mutator like so: mutator: { name: 'javascript', excludedMutations: ['BooleanSubstitution', 'StringLiteral'], babelPlugins: [] }.
Then we can just extend our default plugins array in BabelHelper.ts by elements given by user
I don't know however what about Typescript.
And yea, these 'files' was my problem since I downloaded repo as zip, not cloned it so I didn't have .git
Wouldn't it be better to use transpillers settings? It seems like this option would be a duplicate.
As I think about it... what are transpilers for? Shouldn't mutations be run on transpiled files? Then that problem would cease to exist.
I guess the problem is in reporting @simivar... Like you get 'your code' in reports not compiled one. If we pass compiled code, you will get reports for ES5(?) babel code
and take a look @simivar that names of babelPlugins are different in these 2 places...
'classPrivateProperties',
'classProperties',
'classPrivateMethods',
vs
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-private-methods"
It looks like that there is a similar issue in the version 4.0.0 with the ts-parser:
export async function parse(text: string, fileName: string): Promise<TSAst> {
const isTSX = fileName.endsWith('x');
const ast = await parseAsync(text, {
filename: fileName,
parserOpts: {
ranges: true,
},
configFile: false,
babelrc: false,
presets: [[require.resolve('@babel/preset-typescript'), { isTSX, allExtensions: true }]],
plugins: [[require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }]],
});
The plugins for ts-parser are fixed and with a set of plugins that do not give support for private properties like #hash
Add @babel/plugin-proposal-class-properties (https://git.io/vb4SL) to the 'plugins' section of your Babel config to enable transformation.
If you want to leave it as-is, add @babel/plugin-syntax-class-properties (https://git.io/vb4yQ) to the 'plugins' section to enable parsing.
at Object._raise (D:\repository\Spider\NS-Netin-Logger-TypeScript\node_modules\@babel\parser\lib\index.js:766:17)
at Object.raiseWithData (D:\repository\Spider\NS-Netin-Logger-TypeScript\node_modules\@babel\parser\lib\index.js:759:17)
at Object.expectOnePlugin (D:\repository\Spider\NS-Netin-Logger-TypeScript\node_modules\@babel\parser\lib\index.js:8981:18)
at Object.parseMaybePrivateName (D:\repository\Spider\NS-Netin-Logger-TypeScript\node_modules\@babel\parser\lib\index.js:10351:12)
at Object.parsePropertyName (D:\repository\Spider\NS-Netin-Logger-TypeScript\node_modules\@babel\parser\lib\index.js:10854:155)
at Object.parseClassElementName (D:\repository\Spider\NS-Netin-Logger-TypeScript\node_modules\@babel\parser\lib\index.js:12401:22)
at Object.parseClassMemberWithIsStatic (D:\repository\Spider\NS-Netin-Logger-TypeScript\node_modules\@babel\parser\lib\index.js:12319:22)
at Object.parseClassMemberWithIsStatic (D:\repository\Spider\NS-Netin-Logger-TypeScript\node_modules\@babel\parser\lib\index.js:6735:11)
at Object.parseClassMember (D:\repository\Spider\NS-Netin-Logger-TypeScript\node_modules\@babel\parser\lib\index.js:12289:10)
at Object.parseClassMember (D:\repository\Spider\NS-Netin-Logger-TypeScript\node_modules\@babel\parser\lib\index.js:6710:11) {
loc: Position { line: 41, column: 2 },
pos: 1635,
missingPlugin: [ 'classPrivateProperties', 'classPrivateMethods' ],
code: 'BABEL_PARSE_ERROR'