@zohodesk/codestandard-validator 1.3.1 → 1.4.1-window-fix
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +3 -2
- package/bin/zdcodequality.js +0 -0
- package/build/ai/ollama-service.js +1 -2
- package/build/chunk/chunk_Restriction.js +3 -4
- package/build/hooks/Precommit/commit.js +3 -2
- package/build/hooks/Precommit/lint.js +4 -3
- package/build/hooks/Precommit/pre-commit-default.js +4 -3
- package/build/hooks/hook.js +9 -4
- package/build/mutation/mutationCli.js +23 -19
- package/build/mutation/mutationRunner.js +4 -27
- package/build/mutation/strykerWrapper.js +97 -62
- package/build/utils/ConfigFileUtils/getEslintExecutablePath.js +9 -3
- package/build/utils/General/getGeneralInfo.js +25 -7
- package/build/utils/General/writeProjectDetailsToJson.js +13 -2
- package/build/utils/PluginsInstallation/checkIfPluginsAreInstalled.js +27 -13
- package/changeLog.md +20 -11
- package/jest.config.js +1 -2
- package/package.json +2 -2
package/.babelrc
CHANGED
package/bin/zdcodequality.js
CHANGED
|
File without changes
|
|
@@ -349,13 +349,12 @@ async function reviewFiles(filePaths, options = {}) {
|
|
|
349
349
|
} : r.value;
|
|
350
350
|
results.push(out);
|
|
351
351
|
} else {
|
|
352
|
-
var _r$reason;
|
|
353
352
|
const fp = r.filePath;
|
|
354
353
|
out = {
|
|
355
354
|
success: false,
|
|
356
355
|
fileName: path.basename(fp),
|
|
357
356
|
filePath: fp,
|
|
358
|
-
error:
|
|
357
|
+
error: r.reason?.message || r.reason || 'Unknown error'
|
|
359
358
|
};
|
|
360
359
|
results.push(out);
|
|
361
360
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var _process;
|
|
4
3
|
const {
|
|
5
4
|
execSync
|
|
6
5
|
} = require('child_process');
|
|
@@ -22,7 +21,7 @@ const {
|
|
|
22
21
|
gitEndPoint: _gitEndPoint
|
|
23
22
|
} = getConfigPath(getConfigPathExecute());
|
|
24
23
|
const gitEndPoint = _gitEndPoint || 'https://zgit.csez.zohocorpin.com';
|
|
25
|
-
const compareBranch =
|
|
24
|
+
const compareBranch = process?.env?.CHUNK_BRANCH || 'release';
|
|
26
25
|
const configPath = path.resolve(process.cwd(), 'lint.config.js');
|
|
27
26
|
function getGitProjectId() {
|
|
28
27
|
try {
|
|
@@ -75,7 +74,7 @@ function createBranchDiffChunk(branchName) {
|
|
|
75
74
|
}
|
|
76
75
|
function parserReleaseDiffRemoteAPI(rawresponse) {
|
|
77
76
|
var formatted = [];
|
|
78
|
-
if (rawresponse
|
|
77
|
+
if (rawresponse?.diffs) {
|
|
79
78
|
formatted = rawresponse.diffs.map(changeset => {
|
|
80
79
|
if (isTestOrUATFile(changeset.new_path)) {
|
|
81
80
|
return null;
|
|
@@ -178,7 +177,7 @@ if (shouldEnable) {
|
|
|
178
177
|
const RESET = '\x1b[0m';
|
|
179
178
|
(async function () {
|
|
180
179
|
Logger.log(`****************************** Calculation Chunk Size *******************************`);
|
|
181
|
-
if (!
|
|
180
|
+
if (!globalThis?.chunkSize) {
|
|
182
181
|
globalThis.chunkSize = {
|
|
183
182
|
$modifieldLines: 0,
|
|
184
183
|
$removedLines: 0
|
|
@@ -35,10 +35,11 @@ async function preCommitHook() {
|
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
const {
|
|
38
|
-
JsFiles
|
|
38
|
+
JsFiles,
|
|
39
|
+
featureFiles
|
|
39
40
|
} = filterFiles(stagedFiles, [".eslintrc.js"], true);
|
|
40
41
|
const branch = await safeGetBranch();
|
|
41
|
-
const shouldAbort = await runLintWorkflow(JsFiles, branch);
|
|
42
|
+
const shouldAbort = await runLintWorkflow([...JsFiles, ...featureFiles], branch);
|
|
42
43
|
if (shouldAbort) {
|
|
43
44
|
Logger.log(Logger.FAILURE_TYPE, "There are linter errors/warnings. Commit aborted 🙁.");
|
|
44
45
|
process.exit(1);
|
|
@@ -45,9 +45,10 @@ async function lintFiles(filePath) {
|
|
|
45
45
|
return [];
|
|
46
46
|
}
|
|
47
47
|
async function findEslintErrors(file) {
|
|
48
|
-
const nodeModulesPath = getNodeModulesPath();
|
|
48
|
+
const nodeModulesPath = path.resolve(getNodeModulesPath());
|
|
49
49
|
const eslintPath = getEslintExecutablePath();
|
|
50
|
-
const eslintConfig =
|
|
50
|
+
const eslintConfig = path.join(nodeModulesPath, '.eslintrc.js');
|
|
51
|
+
const resolvePluginsPath = path.join(nodeModulesPath, 'node_modules');
|
|
51
52
|
if (!fs.existsSync(nodeModulesPath)) {
|
|
52
53
|
Logger.log(Logger.INFO_TYPE, 'node_modules not found');
|
|
53
54
|
return [];
|
|
@@ -56,7 +57,7 @@ async function findEslintErrors(file) {
|
|
|
56
57
|
Logger.log(Logger.INFO_TYPE, 'Eslint executable not found. Make sure eslint plugin is installed');
|
|
57
58
|
return [];
|
|
58
59
|
}
|
|
59
|
-
return execSync(`npx --ignore-existing "${eslintPath}" --config "${eslintConfig}" --no-inline-config --resolve-plugins-relative-to="${
|
|
60
|
+
return execSync(`npx --ignore-existing "${eslintPath}" --config "${eslintConfig}" --no-inline-config --resolve-plugins-relative-to="${resolvePluginsPath}" ${path.resolve(getRootDirectory(), file)}`).then(({
|
|
60
61
|
stderr
|
|
61
62
|
}) => stderr ? stderr.toString().trim().split('\n') : []).catch(err => {
|
|
62
63
|
Logger.log(Logger.FAILURE_TYPE, err);
|
|
@@ -113,15 +113,16 @@ async function lintFiles(filePath) {
|
|
|
113
113
|
*/
|
|
114
114
|
|
|
115
115
|
function findEslintErrors(file) {
|
|
116
|
-
let nodeModulesPathOfProject =
|
|
116
|
+
let nodeModulesPathOfProject = path.resolve(getNodeModulesPath());
|
|
117
117
|
let eslintExecutablePath = getEslintExecutablePath();
|
|
118
|
-
let eslintConfigurationFilePath =
|
|
118
|
+
let eslintConfigurationFilePath = path.join(nodeModulesPathOfProject, '.eslintrc.js');
|
|
119
|
+
let resolvePluginsPath = path.join(nodeModulesPathOfProject, 'node_modules');
|
|
119
120
|
let isEslintExecutablePresent = fs.existsSync(eslintExecutablePath) ? true : false;
|
|
120
121
|
let isNodeModulesPresent = fs.existsSync(nodeModulesPathOfProject);
|
|
121
122
|
if (isNodeModulesPresent) {
|
|
122
123
|
if (isEslintExecutablePresent) {
|
|
123
124
|
return new Promise((resolve, reject) => {
|
|
124
|
-
exec(`npx --ignore-existing "${eslintExecutablePath}" --config "${eslintConfigurationFilePath}" --no-inline-config --resolve-plugins-relative-to="${
|
|
125
|
+
exec(`npx --ignore-existing "${eslintExecutablePath}" --config "${eslintConfigurationFilePath}" --no-inline-config --resolve-plugins-relative-to="${resolvePluginsPath}" ${path.resolve(getRootDirectory(), file)}`, (error, stderr, stdout) => {
|
|
125
126
|
if (stderr) {
|
|
126
127
|
resolve(stderr.trim().split('\n'));
|
|
127
128
|
} else if (error) {
|
package/build/hooks/hook.js
CHANGED
|
@@ -54,8 +54,13 @@ async function hooks() {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
(async function () {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
try {
|
|
58
|
+
await initConfig(getConfigPathExecute());
|
|
59
|
+
await Promise.resolve(postInstallExecution());
|
|
60
|
+
require("../chunk/chunk_Restriction");
|
|
61
|
+
await hooks();
|
|
62
|
+
} catch (error) {
|
|
63
|
+
Logger.log(Logger.FAILURE_TYPE, `Pre-commit initialization failed: ${error.message}`);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
61
66
|
})();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var MutationRunner = require('./mutationRunner');
|
|
4
|
-
var
|
|
4
|
+
var path = require('path');
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* MutationCli — CLI argument parser and executor for mutation testing.
|
|
@@ -25,6 +25,7 @@ var StrykerConfigBuilder = require('./strykerConfigBuilder');
|
|
|
25
25
|
* --concurrency=<n> (default: cpu count - 1)
|
|
26
26
|
* --timeoutMS=<ms> (default: 60000)
|
|
27
27
|
* --strykerConfig=<path> (external stryker.conf.js)
|
|
28
|
+
* --jestConfig=<path> (external jest.config.js)
|
|
28
29
|
*
|
|
29
30
|
* Compatible with Node 16+.
|
|
30
31
|
*/
|
|
@@ -46,7 +47,8 @@ MutationCli.prototype.parseArgs = function (args) {
|
|
|
46
47
|
logLevel: 'info',
|
|
47
48
|
concurrency: null,
|
|
48
49
|
timeoutMS: null,
|
|
49
|
-
strykerConfig: null
|
|
50
|
+
strykerConfig: null,
|
|
51
|
+
jestConfig: null
|
|
50
52
|
};
|
|
51
53
|
for (var i = 0; i < args.length; i++) {
|
|
52
54
|
var arg = args[i];
|
|
@@ -72,8 +74,10 @@ MutationCli.prototype.parseArgs = function (args) {
|
|
|
72
74
|
parsed.concurrency = arg.split('=')[1];
|
|
73
75
|
} else if (arg.indexOf('--timeoutMS=') === 0) {
|
|
74
76
|
parsed.timeoutMS = arg.split('=')[1];
|
|
75
|
-
} else if (arg.indexOf('--
|
|
77
|
+
} else if (arg.indexOf('--mutationConfigPath=') === 0) {
|
|
76
78
|
parsed.strykerConfig = arg.split('=')[1];
|
|
79
|
+
} else if (arg.indexOf('--jestConfigPath=') === 0) {
|
|
80
|
+
parsed.jestConfig = arg.split('=')[1];
|
|
77
81
|
}
|
|
78
82
|
}
|
|
79
83
|
if (parsed.release == null || parsed.release === '') {
|
|
@@ -109,26 +113,26 @@ MutationCli.prototype.validate = function (parsed) {
|
|
|
109
113
|
/* ------------------------------------------------------------------ */
|
|
110
114
|
|
|
111
115
|
MutationCli.prototype._buildConfig = function (parsed) {
|
|
112
|
-
var
|
|
113
|
-
|
|
114
|
-
|
|
116
|
+
var config = {};
|
|
117
|
+
|
|
118
|
+
// Load config from file if specified
|
|
119
|
+
var configPath = parsed.strykerConfig || this._options.mutationConfigPath;
|
|
120
|
+
if (configPath) {
|
|
121
|
+
var resolved = path.resolve(configPath);
|
|
122
|
+
config = Object.assign({}, require(resolved));
|
|
115
123
|
}
|
|
116
|
-
|
|
124
|
+
|
|
125
|
+
// Apply CLI overrides
|
|
126
|
+
config.logLevel = parsed.logLevel || this._options.logLevel || 'info';
|
|
117
127
|
var concurrency = parsed.concurrency || this._options.concurrency;
|
|
118
128
|
if (concurrency != null) {
|
|
119
|
-
|
|
129
|
+
config.concurrency = Number(concurrency);
|
|
120
130
|
}
|
|
121
131
|
var timeoutMS = parsed.timeoutMS || this._options.timeoutMS;
|
|
122
132
|
if (timeoutMS != null) {
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
if (this._options.jestConfig) {
|
|
126
|
-
builder.setJest(Object.assign({
|
|
127
|
-
projectType: 'custom',
|
|
128
|
-
enableFindRelatedTests: true
|
|
129
|
-
}, this._options.jestConfig));
|
|
133
|
+
config.timeoutMS = Number(timeoutMS);
|
|
130
134
|
}
|
|
131
|
-
return
|
|
135
|
+
return config;
|
|
132
136
|
};
|
|
133
137
|
|
|
134
138
|
/* ------------------------------------------------------------------ */
|
|
@@ -144,12 +148,12 @@ MutationCli.prototype.execute = function (args) {
|
|
|
144
148
|
error: validation.error
|
|
145
149
|
});
|
|
146
150
|
}
|
|
147
|
-
var
|
|
151
|
+
var mutationConfig = this._buildConfig(parsed);
|
|
148
152
|
var runner = new MutationRunner({
|
|
149
153
|
...this._options,
|
|
150
154
|
cwd: this._options.cwd,
|
|
151
|
-
|
|
152
|
-
|
|
155
|
+
mutationConfig: mutationConfig,
|
|
156
|
+
jestConfigPath: parsed.jestConfig || this._options.jestConfig || null,
|
|
153
157
|
outputDir: parsed.outputDir || this._options.outputDir,
|
|
154
158
|
outputFileName: parsed.outputFileName || this._options.outputFileName
|
|
155
159
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var StrykerWrapper = require('./strykerWrapper');
|
|
4
|
-
var StrykerConfigBuilder = require('./strykerConfigBuilder');
|
|
5
4
|
var BranchDiff = require('./branchDiff');
|
|
6
5
|
var FileResolver = require('./fileResolver');
|
|
7
6
|
var ReportGenerator = require('./reportGenerator');
|
|
@@ -30,24 +29,8 @@ var path = require('path');
|
|
|
30
29
|
function MutationRunner(options) {
|
|
31
30
|
options = options || {};
|
|
32
31
|
this._cwd = options.cwd || process.cwd();
|
|
33
|
-
var
|
|
34
|
-
|
|
35
|
-
configBuilder = new StrykerConfigBuilder();
|
|
36
|
-
if (options.strykerConfigpath) {
|
|
37
|
-
configBuilder.fromConfigFile(options.strykerConfigpath);
|
|
38
|
-
}
|
|
39
|
-
if (options.concurrency != null) configBuilder.setConcurrency(options.concurrency);
|
|
40
|
-
if (options.timeoutMS != null) configBuilder.setTimeoutMS(options.timeoutMS);
|
|
41
|
-
if (options.logLevel) configBuilder.setLogLevel(options.logLevel);
|
|
42
|
-
if (options.reportPath) {
|
|
43
|
-
configBuilder.setHtmlReporter({
|
|
44
|
-
fileName: options.reportPath
|
|
45
|
-
}).setJsonReporter({
|
|
46
|
-
fileName: options.reportPath
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
this._stryker = new StrykerWrapper(configBuilder);
|
|
32
|
+
var mutationConfig = options.mutationConfig || {};
|
|
33
|
+
this._stryker = new StrykerWrapper(mutationConfig);
|
|
51
34
|
this._branchDiff = new BranchDiff({
|
|
52
35
|
cwd: this._cwd,
|
|
53
36
|
token: options.token,
|
|
@@ -64,7 +47,7 @@ function MutationRunner(options) {
|
|
|
64
47
|
outputDir: options.outputDir || 'reports/mutation',
|
|
65
48
|
outputFileName: options.outputFileName || 'mutation-report.json'
|
|
66
49
|
});
|
|
67
|
-
this.
|
|
50
|
+
this._jestConfigPath = options.jestConfigPath || null;
|
|
68
51
|
}
|
|
69
52
|
|
|
70
53
|
/* ------------------------------------------------------------------ */
|
|
@@ -187,13 +170,7 @@ MutationRunner.prototype._runMutation = function (sourceFiles, testFiles, ctx) {
|
|
|
187
170
|
var strykerOpts = {
|
|
188
171
|
rootDirectory: this._branchDiff.getRootDirectory(),
|
|
189
172
|
testFiles: testsToRun,
|
|
190
|
-
|
|
191
|
-
config: {
|
|
192
|
-
testMatch: testsToRun,
|
|
193
|
-
reporters: ['json']
|
|
194
|
-
},
|
|
195
|
-
enableFindRelatedTests: true
|
|
196
|
-
})
|
|
173
|
+
jestConfigPath: this._jestConfigPath
|
|
197
174
|
};
|
|
198
175
|
return self._stryker.run(sourcesToMutate, strykerOpts).then(function (mutationResult) {
|
|
199
176
|
var out3 = self._reportGenerator.generateAndWrite(mutationResult, {
|
|
@@ -1,49 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
4
3
|
var path = require('path');
|
|
4
|
+
var os = require('os');
|
|
5
5
|
var patternConfig = require('./mutatePattern.json');
|
|
6
|
-
var StrykerConfigBuilder = require('./strykerConfigBuilder');
|
|
7
6
|
var DEFAULT_MUTATE_PATTERN = patternConfig.defaultPattern;
|
|
7
|
+
var DEFAULTS = {
|
|
8
|
+
packageManager: 'npm',
|
|
9
|
+
testRunner: 'jest',
|
|
10
|
+
coverageAnalysis: 'perTest',
|
|
11
|
+
reporters: ['html', 'json'],
|
|
12
|
+
logLevel: 'info',
|
|
13
|
+
timeoutMS: 60000,
|
|
14
|
+
timeoutFactor: 1.5,
|
|
15
|
+
cleanTempDir: true,
|
|
16
|
+
allowEmpty: true,
|
|
17
|
+
thresholds: {
|
|
18
|
+
high: 80,
|
|
19
|
+
low: 60,
|
|
20
|
+
break: null
|
|
21
|
+
}
|
|
22
|
+
};
|
|
8
23
|
|
|
9
24
|
/**
|
|
10
|
-
* StrykerWrapper — thin wrapper around @stryker-mutator/core
|
|
25
|
+
* StrykerWrapper — thin wrapper around @stryker-mutator/core.
|
|
11
26
|
*
|
|
12
|
-
* Accepts a
|
|
13
|
-
*
|
|
14
|
-
* and normalizes results.
|
|
27
|
+
* Accepts a plain config object (loaded from a config file or defaults),
|
|
28
|
+
* merges with DEFAULTS, runs mutation testing, and normalizes results.
|
|
15
29
|
*
|
|
16
30
|
* Compatible with Node 16+.
|
|
17
31
|
*/
|
|
18
|
-
function StrykerWrapper(
|
|
19
|
-
options = options || {};
|
|
32
|
+
function StrykerWrapper(config) {
|
|
20
33
|
this._strykerModule = null;
|
|
21
|
-
|
|
22
|
-
this._configBuilder = options;
|
|
23
|
-
} else if (options.strykerConfigpath) {
|
|
24
|
-
this._configBuilder = new StrykerConfigBuilder().fromConfigFile(options.strykerConfigpath);
|
|
25
|
-
} else {
|
|
26
|
-
this._configBuilder = new StrykerConfigBuilder().setTestRunner('jest').setCoverageAnalysis('perTest').setAllowEmpty(true).setReporters(['html', 'json']).setCleanTempDir(true);
|
|
27
|
-
if (options.reportPath) {
|
|
28
|
-
this._configBuilder.setHtmlReporter({
|
|
29
|
-
fileName: options.reportPath
|
|
30
|
-
}).setJsonReporter({
|
|
31
|
-
fileName: options.reportPath
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
if (options.concurrency != null) {
|
|
35
|
-
this._configBuilder.setConcurrency(options.concurrency);
|
|
36
|
-
}
|
|
37
|
-
if (options.timeoutMS != null) {
|
|
38
|
-
this._configBuilder.setTimeoutMS(options.timeoutMS);
|
|
39
|
-
}
|
|
40
|
-
if (options.timeoutFactor != null) {
|
|
41
|
-
this._configBuilder.setTimeoutFactor(options.timeoutFactor);
|
|
42
|
-
}
|
|
43
|
-
if (options.logLevel) {
|
|
44
|
-
this._configBuilder.setLogLevel(options.logLevel);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
34
|
+
this._baseConfig = config && typeof config === 'object' ? Object.assign({}, config) : {};
|
|
47
35
|
}
|
|
48
36
|
|
|
49
37
|
/* ------------------------------------------------------------------ */
|
|
@@ -56,13 +44,13 @@ StrykerWrapper.prototype._loadStryker = async function () {
|
|
|
56
44
|
return Promise.resolve(self._strykerModule);
|
|
57
45
|
}
|
|
58
46
|
try {
|
|
59
|
-
self._strykerModule = await
|
|
47
|
+
self._strykerModule = await import('@stryker-mutator/core');
|
|
60
48
|
return Promise.resolve(self._strykerModule);
|
|
61
49
|
} catch (err) {
|
|
62
50
|
return Promise.reject(new Error('Failed to load @stryker-mutator/core. Install it:\n' + ' npm i --save-dev @stryker-mutator/core@5 @stryker-mutator/jest-runner@5\n' + err.message));
|
|
63
51
|
}
|
|
64
52
|
};
|
|
65
|
-
StrykerWrapper.prototype.
|
|
53
|
+
StrykerWrapper.prototype._buildSourceToRun = function (sourceFiles, options) {
|
|
66
54
|
if (!sourceFiles || sourceFiles.length === 0) {
|
|
67
55
|
return [DEFAULT_MUTATE_PATTERN];
|
|
68
56
|
}
|
|
@@ -75,45 +63,88 @@ StrykerWrapper.prototype._buildMutatePatterns = function (sourceFiles, options)
|
|
|
75
63
|
};
|
|
76
64
|
|
|
77
65
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
66
|
+
* Load a jest config file (JS or JSON). Handles both object and
|
|
67
|
+
* function exports (jest supports `module.exports = async (cfg) => ({...})`).
|
|
68
|
+
*
|
|
69
|
+
* Returns null if filePath is falsy or the file cannot be loaded.
|
|
70
|
+
*/
|
|
71
|
+
StrykerWrapper.prototype._loadJestConfigFile = function (filePath) {
|
|
72
|
+
if (!filePath) return null;
|
|
73
|
+
try {
|
|
74
|
+
var resolved = path.resolve(filePath);
|
|
75
|
+
var exported = require(resolved);
|
|
76
|
+
if (typeof exported === 'function') {
|
|
77
|
+
exported = exported();
|
|
78
|
+
}
|
|
79
|
+
return exported && typeof exported === 'object' ? exported : null;
|
|
80
|
+
} catch (err) {
|
|
81
|
+
throw new Error('Failed to load jest config from "' + filePath + '": ' + err.message);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Build the final Stryker config by merging DEFAULTS, base config,
|
|
87
|
+
* and per-run overrides.
|
|
88
|
+
*
|
|
89
|
+
* Jest config resolution (highest → lowest precedence inside Stryker):
|
|
90
|
+
* configFromFile (loaded via Jest's native pipeline — handles preset, <rootDir>, transform)
|
|
91
|
+
* ↓ merged with
|
|
92
|
+
* jest.config (inline override object — safe for testMatch, reporters, etc.)
|
|
93
|
+
* ↓ merged with
|
|
94
|
+
* JEST_OVERRIDE_OPTIONS (Stryker's own forced keys — always wins)
|
|
80
95
|
*/
|
|
81
96
|
StrykerWrapper.prototype._buildStrykerConfig = function (sourceFiles, options) {
|
|
82
97
|
options = options || {};
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}).join('|');
|
|
91
|
-
var cdCmd = options.rootDirectory ? 'cd ' + options.rootDirectory + ' && ' : '';
|
|
92
|
-
builder.setCommandRunner({
|
|
93
|
-
command: 'npx ZDTestingFramework unit-test'
|
|
94
|
-
});
|
|
98
|
+
|
|
99
|
+
// 1. Start with defaults, overlay base config
|
|
100
|
+
var config = Object.assign({}, DEFAULTS, this._baseConfig);
|
|
101
|
+
|
|
102
|
+
// 2. Compute concurrency if not set
|
|
103
|
+
if (config.concurrency == null) {
|
|
104
|
+
config.concurrency = Math.max(1, os.cpus().length - 1);
|
|
95
105
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
106
|
+
|
|
107
|
+
// 3. Set mutate = resolved source files (sourceToRun)
|
|
108
|
+
config.mutate = this._buildSourceToRun(sourceFiles, options);
|
|
109
|
+
|
|
110
|
+
// 4. Build jest section
|
|
111
|
+
var jestSection = {
|
|
112
|
+
projectType: 'custom',
|
|
113
|
+
enableFindRelatedTests: false
|
|
114
|
+
};
|
|
115
|
+
if (options.jestConfigPath) {
|
|
116
|
+
jestSection.configFile = options.jestConfigPath;
|
|
117
|
+
}
|
|
118
|
+
if (options.testFiles && options.testFiles.length > 0) {
|
|
119
|
+
// Convert absolute test paths to <rootDir>-relative paths
|
|
120
|
+
var rootDir = options.rootDirectory || process.cwd();
|
|
121
|
+
var rootDirRelativeTests = options.testFiles.map(function (f) {
|
|
122
|
+
var absPath = path.isAbsolute(f) ? f : path.resolve(rootDir, f);
|
|
123
|
+
var relativePath = path.relative(rootDir, absPath);
|
|
124
|
+
return '<rootDir>/' + relativePath.replace(/\\/g, '/');
|
|
125
|
+
});
|
|
126
|
+
jestSection.config = Object.assign({}, this._loadJestConfigFile(options.jestConfigPath), {
|
|
127
|
+
testMatch: rootDirRelativeTests
|
|
128
|
+
});
|
|
101
129
|
}
|
|
130
|
+
config.jest = jestSection;
|
|
131
|
+
|
|
132
|
+
// 5. Per-run overrides
|
|
102
133
|
if (options.configFile) {
|
|
103
|
-
|
|
134
|
+
config.configFile = options.configFile;
|
|
104
135
|
}
|
|
105
136
|
if (options.reportPath) {
|
|
106
|
-
|
|
137
|
+
config.jsonReporter = {
|
|
107
138
|
fileName: options.reportPath
|
|
108
|
-
}
|
|
139
|
+
};
|
|
109
140
|
}
|
|
110
141
|
if (options.tempDirName) {
|
|
111
|
-
|
|
142
|
+
config.tempDirName = options.tempDirName;
|
|
112
143
|
}
|
|
113
144
|
if (options.thresholds) {
|
|
114
|
-
|
|
145
|
+
config.thresholds = options.thresholds;
|
|
115
146
|
}
|
|
116
|
-
return
|
|
147
|
+
return config;
|
|
117
148
|
};
|
|
118
149
|
|
|
119
150
|
/* ------------------------------------------------------------------ */
|
|
@@ -230,7 +261,11 @@ StrykerWrapper.prototype._emptyNormalizedResult = function () {
|
|
|
230
261
|
};
|
|
231
262
|
};
|
|
232
263
|
StrykerWrapper.prototype.getDefaultConfig = function () {
|
|
233
|
-
|
|
264
|
+
var config = Object.assign({}, DEFAULTS, this._baseConfig);
|
|
265
|
+
if (config.concurrency == null) {
|
|
266
|
+
config.concurrency = Math.max(1, os.cpus().length - 1);
|
|
267
|
+
}
|
|
268
|
+
return config;
|
|
234
269
|
};
|
|
235
270
|
module.exports = StrykerWrapper;
|
|
236
271
|
module.exports.DEFAULT_MUTATE_PATTERN = DEFAULT_MUTATE_PATTERN;
|
|
@@ -13,12 +13,18 @@ const {
|
|
|
13
13
|
const {
|
|
14
14
|
getLibraryInstalledLocation
|
|
15
15
|
} = require('../General/getLibraryInstalledLocation');
|
|
16
|
+
function getProjectNodeModulesPath(projectPath) {
|
|
17
|
+
const normalizedPath = path.resolve(projectPath);
|
|
18
|
+
return path.basename(normalizedPath) === 'node_modules' ? normalizedPath : path.join(normalizedPath, 'node_modules');
|
|
19
|
+
}
|
|
16
20
|
function getEslintExecutablePath() {
|
|
17
21
|
let eslintLibraryName = 'eslint';
|
|
18
|
-
let
|
|
22
|
+
let nodeModulesPath = getProjectNodeModulesPath(getNodeModulesPath());
|
|
23
|
+
let librariesInNodeModulesOfProject = executeSynchronizedCommands(readdirSync, [nodeModulesPath], '', 'Unable to get the plugins inside node_modules', true, false);
|
|
19
24
|
let isEslintInstalledinProject = librariesInNodeModulesOfProject.some(library => library === eslintLibraryName);
|
|
20
|
-
return isEslintInstalledinProject ? path.join(
|
|
25
|
+
return isEslintInstalledinProject ? path.join(nodeModulesPath, eslintLibraryName, 'bin', 'eslint.js') : path.join(getLibraryInstalledLocation(), 'node_modules', eslintLibraryName, 'bin', 'eslint.js');
|
|
21
26
|
}
|
|
22
27
|
module.exports = {
|
|
23
|
-
getEslintExecutablePath
|
|
28
|
+
getEslintExecutablePath,
|
|
29
|
+
getProjectNodeModulesPath
|
|
24
30
|
};
|
|
@@ -70,13 +70,26 @@ function getSupportedLanguage() {
|
|
|
70
70
|
_language.push('.tsx');
|
|
71
71
|
_language.push('.css');
|
|
72
72
|
_language.push('.scss');
|
|
73
|
+
_language.push('.feature');
|
|
73
74
|
return [...new Set(_language)];
|
|
74
75
|
}
|
|
75
76
|
function getRunningEnv() {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
if (process.env.npm_config_lint_env) {
|
|
78
|
+
return String(process.env.npm_config_lint_env).trim();
|
|
79
|
+
}
|
|
80
|
+
if (process.env.LINT_ENV) {
|
|
81
|
+
return String(process.env.LINT_ENV).trim();
|
|
82
|
+
}
|
|
83
|
+
if (process.env.CI === "true" || process.env.CI === "1") {
|
|
84
|
+
return "CI";
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
return execSync("npm config get lint_env", {
|
|
88
|
+
shell: true
|
|
89
|
+
}).toString().trim();
|
|
90
|
+
} catch {
|
|
91
|
+
return "";
|
|
92
|
+
}
|
|
80
93
|
}
|
|
81
94
|
|
|
82
95
|
/**
|
|
@@ -89,9 +102,12 @@ function getRunningEnv() {
|
|
|
89
102
|
|
|
90
103
|
function getLastCommitHash() {
|
|
91
104
|
try {
|
|
92
|
-
var _JSON$parse$;
|
|
93
105
|
const cmd = `curl --header "PRIVATE-TOKEN: ${process.env.TOOL_TOKEN}" --url ${commitHashEndPoint}`;
|
|
94
|
-
|
|
106
|
+
const response = execSync(cmd, {
|
|
107
|
+
encoding: 'utf-8',
|
|
108
|
+
timeout: 10000
|
|
109
|
+
});
|
|
110
|
+
return JSON.parse(response)[0]?.id;
|
|
95
111
|
} catch (err) {
|
|
96
112
|
Logger.log(Logger.FAILURE_TYPE, err);
|
|
97
113
|
return null;
|
|
@@ -117,7 +133,9 @@ function updateJsonFile(filePath, modifier) {
|
|
|
117
133
|
const rawData = fs.readFileSync(absolutePath, "utf-8");
|
|
118
134
|
const jsonData = JSON.parse(rawData);
|
|
119
135
|
const updatedData = modifier(jsonData);
|
|
120
|
-
|
|
136
|
+
const tempPath = `${absolutePath}.${process.pid}.${Date.now()}.tmp`;
|
|
137
|
+
fs.writeFileSync(tempPath, JSON.stringify(updatedData, null, 2), "utf-8");
|
|
138
|
+
fs.renameSync(tempPath, absolutePath);
|
|
121
139
|
} catch (error) {
|
|
122
140
|
Logger.log(Logger.FAILURE_TYPE, "Error updating JSON file");
|
|
123
141
|
}
|
|
@@ -10,13 +10,24 @@ const {
|
|
|
10
10
|
const {
|
|
11
11
|
getLastCommitHash
|
|
12
12
|
} = require('./getGeneralInfo');
|
|
13
|
+
function getProjectRootFromInstallPath(currentPath) {
|
|
14
|
+
const isWindowsAbsolutePath = /^[A-Za-z]:[\\/]/.test(String(currentPath));
|
|
15
|
+
const normalizedPath = (isWindowsAbsolutePath ? String(currentPath) : path.resolve(currentPath)).replace(/\\/g, '/');
|
|
16
|
+
const packageSuffix = '/node_modules/@zohodesk/codestandard-validator';
|
|
17
|
+
const suffixIndex = normalizedPath.lastIndexOf(packageSuffix);
|
|
18
|
+
if (suffixIndex !== -1) {
|
|
19
|
+
return path.normalize(normalizedPath.slice(0, suffixIndex));
|
|
20
|
+
}
|
|
21
|
+
return path.resolve(currentPath, '..', '..', '..');
|
|
22
|
+
}
|
|
13
23
|
function writeFsPaths() {
|
|
14
24
|
var fileContent = {
|
|
15
|
-
nodeModulesPath:
|
|
25
|
+
nodeModulesPath: getProjectRootFromInstallPath(process.cwd()),
|
|
16
26
|
commitHash: getLastCommitHash()
|
|
17
27
|
};
|
|
18
28
|
return executeSynchronizedCommands(writeFileSync, [path.join(process.cwd(), 'jsonUtils', 'fsUtils.json'), JSON.stringify(fileContent), 'utf-8'], 'node_modules path updated in json file', 'Unable to write node_modules path to json file', false, true);
|
|
19
29
|
}
|
|
20
30
|
module.exports = {
|
|
21
|
-
writeFsPaths
|
|
31
|
+
writeFsPaths,
|
|
32
|
+
getProjectRootFromInstallPath
|
|
22
33
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
|
-
existsSync
|
|
4
|
+
existsSync,
|
|
5
|
+
readFileSync
|
|
5
6
|
} = require('fs');
|
|
6
7
|
const path = require('path');
|
|
7
8
|
const {
|
|
@@ -59,7 +60,8 @@ function checkIfPluginsAreInstalled() {
|
|
|
59
60
|
isPluginPresent,
|
|
60
61
|
pluginPath
|
|
61
62
|
} = checkPluginsPresentInNodemodules(packageName); // circular installation loop so comment out
|
|
62
|
-
|
|
63
|
+
// checkPluginHasProperVersion(packageName,pluginPath,version) remove version check due to unnecess
|
|
64
|
+
if (isPluginPresent) {
|
|
63
65
|
return false;
|
|
64
66
|
}
|
|
65
67
|
return `${packageName}@${version}`;
|
|
@@ -110,7 +112,7 @@ function getPluginsToInstall() {
|
|
|
110
112
|
* @returns {string} - which represents exactPluginVersion
|
|
111
113
|
*/
|
|
112
114
|
function returnExactPluginVersion(pluginVersion) {
|
|
113
|
-
return pluginVersion.replace(/[\^~]/, '');
|
|
115
|
+
return String(pluginVersion || '').replace(/[\^~]/, '');
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
/**
|
|
@@ -120,16 +122,24 @@ function returnExactPluginVersion(pluginVersion) {
|
|
|
120
122
|
*/
|
|
121
123
|
function checkPluginsPresentInNodemodules(rulePluginName) {
|
|
122
124
|
try {
|
|
123
|
-
const pluginPath = require.resolve(rulePluginName.toString());
|
|
125
|
+
const pluginPath = require.resolve(path.join(rulePluginName.toString(), 'package.json'));
|
|
124
126
|
return {
|
|
125
127
|
pluginPath: pluginPath,
|
|
126
128
|
isPluginPresent: existsSync(pluginPath)
|
|
127
129
|
};
|
|
128
130
|
} catch (error) {
|
|
129
|
-
|
|
130
|
-
pluginPath
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
try {
|
|
132
|
+
const pluginPath = require.resolve(rulePluginName.toString());
|
|
133
|
+
return {
|
|
134
|
+
pluginPath: path.join(path.dirname(pluginPath), 'package.json'),
|
|
135
|
+
isPluginPresent: existsSync(pluginPath)
|
|
136
|
+
};
|
|
137
|
+
} catch (_innerError) {
|
|
138
|
+
return {
|
|
139
|
+
pluginPath: "",
|
|
140
|
+
isPluginPresent: false
|
|
141
|
+
};
|
|
142
|
+
}
|
|
133
143
|
}
|
|
134
144
|
}
|
|
135
145
|
|
|
@@ -142,11 +152,15 @@ function checkPluginsPresentInNodemodules(rulePluginName) {
|
|
|
142
152
|
*/
|
|
143
153
|
|
|
144
154
|
function checkPluginHasProperVersion(rulePluginName, installationPath, remotePluginVersion) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
155
|
+
try {
|
|
156
|
+
const rulePluginPackageJSONPath = installationPath || require.resolve(path.join(rulePluginName.toString(), 'package.json'));
|
|
157
|
+
const remotePluginExactVersion = returnExactPluginVersion(remotePluginVersion);
|
|
158
|
+
const packageJsonPluginExactVersion = returnExactPluginVersion(JSON.parse(readFileSync(rulePluginPackageJSONPath, 'utf-8')).version);
|
|
159
|
+
return remotePluginExactVersion === packageJsonPluginExactVersion;
|
|
160
|
+
} catch (error) {
|
|
161
|
+
Logger.log(Logger.FAILURE_TYPE, `Unable to check plugin version for ${rulePluginName}`);
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
150
164
|
}
|
|
151
165
|
module.exports = {
|
|
152
166
|
getPluginsToInstall,
|
package/changeLog.md
CHANGED
|
@@ -37,29 +37,38 @@
|
|
|
37
37
|
|
|
38
38
|
# 1.1.0 - SonarQube Enable
|
|
39
39
|
|
|
40
|
-
1. Enable sonarqube with flag with backward compactibility
|
|
40
|
+
1. Enable sonarqube with flag with backward compactibility
|
|
41
41
|
|
|
42
42
|
# 1.1.3 - SonarQube Enable
|
|
43
43
|
|
|
44
|
-
1. Remote Installtion flow moved to before and handled process.exit removed
|
|
44
|
+
1. Remote Installtion flow moved to before and handled process.exit removed
|
|
45
45
|
|
|
46
46
|
# 1.1.4 - Minor Bug Fixes
|
|
47
47
|
|
|
48
|
-
1. ProjectId api revamp
|
|
49
|
-
2. code standard analytics bin bind to code standard validator bin
|
|
48
|
+
1. ProjectId api revamp
|
|
49
|
+
2. code standard analytics bin bind to code standard validator bin
|
|
50
50
|
|
|
51
51
|
# 1.2.4
|
|
52
52
|
|
|
53
|
-
1. Refactor configuration loading and linting process, update mandatory rules handling, and improve pre-commit hook functionality
|
|
53
|
+
1. Refactor configuration loading and linting process, update mandatory rules handling, and improve pre-commit hook functionality
|
|
54
54
|
|
|
55
55
|
# 1.3.4
|
|
56
56
|
|
|
57
|
-
1. Fix typo in environment variable name: `MANDARORY_RULES` corrected to `MANDATORY_RULES`
|
|
58
|
-
2. Fix typo in Config.js: `intialize` corrected to `initialize` for post-install execution
|
|
59
|
-
3. Remove unused `jest.setup.js` placeholder file
|
|
60
|
-
4. Version bump from `1.2.4-exp-7` to `1.2.4-exp-9`
|
|
57
|
+
1. Fix typo in environment variable name: `MANDARORY_RULES` corrected to `MANDATORY_RULES`
|
|
58
|
+
2. Fix typo in Config.js: `intialize` corrected to `initialize` for post-install execution
|
|
59
|
+
3. Remove unused `jest.setup.js` placeholder file
|
|
60
|
+
4. Version bump from `1.2.4-exp-7` to `1.2.4-exp-9`
|
|
61
61
|
|
|
62
62
|
# 1.3.1 - Bug Fixes
|
|
63
63
|
|
|
64
|
-
1. Replace asynchronous `fs.rm` with synchronous `fs.rmSync` in folder cleanup utility to align with synchronized command execution.
|
|
65
|
-
2. Update package version from `1.3.0` to `1.3.1`.
|
|
64
|
+
1. Replace asynchronous `fs.rm` with synchronous `fs.rmSync` in folder cleanup utility to align with synchronized command execution.
|
|
65
|
+
2. Update package version from `1.3.0` to `1.3.1`.
|
|
66
|
+
|
|
67
|
+
# 1.4.0 - Mutation Refactor & Environment Detection
|
|
68
|
+
|
|
69
|
+
1. Remove `StrykerConfigBuilder` class and simplify Stryker configuration to use a plain defaults object in `strykerWrapper.js`
|
|
70
|
+
2. Refactor `mutationCli.js` and `mutationRunner.js` to work without the config builder abstraction
|
|
71
|
+
3. Improve `getRunningEnv()` to read environment from `npm_config_lint_env`, `LINT_ENV`, and `CI` env vars before falling back to `npm config get`
|
|
72
|
+
4. Add `.feature` file support in `getSupportedLanguage()` and include feature files in pre-commit hook linting
|
|
73
|
+
5. Update `@zohodesk/codestandard-analytics` dependency to `1.1.6-node-18`
|
|
74
|
+
6. Update unit tests for mutation modules to match refactored API
|
package/jest.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zohodesk/codestandard-validator",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1-window-fix",
|
|
4
4
|
"description": "library to enforce code standard using eslint",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"@stryker-mutator/jest-runner": "8.7.1",
|
|
22
22
|
"@stryker-mutator/typescript-checker": "8.7.1",
|
|
23
23
|
"@zohodesk-private/client_deployment_tool": "0.0.5",
|
|
24
|
-
"@zohodesk/codestandard-analytics": "1.
|
|
24
|
+
"@zohodesk/codestandard-analytics": "1.2.0",
|
|
25
25
|
"eslint": "8.26.0",
|
|
26
26
|
"glob": "8.1.0",
|
|
27
27
|
"jest": "29.7.0",
|