@zohodesk/codestandard-validator 1.1.4 → 1.2.4-exp-2
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/bin/cliCI.js +0 -0
- package/build/ai/config.example.json +10 -0
- package/build/ai/ollama-service.js +403 -0
- package/build/ai/prompts/CODE_REVIEW_PROMPT.md +72 -0
- package/build/ai/prompts/PROMPT1.MD +70 -0
- package/build/ai/prompts/PROMPT2.md +159 -0
- package/build/ai/prompts/PROMPT3.md +64 -0
- package/build/ai/prompts/PROMPT4.md +64 -0
- package/build/ai/provider-factory.js +19 -0
- package/build/ai/providers/OllamaProvider.js +106 -0
- package/build/ai/render.js +157 -0
- package/build/ai/run-review.js +50 -0
- package/build/chunk/chunk_Restriction.js +202 -0
- package/build/hooks/Precommit/pre-commit-default.js +158 -140
- package/build/hooks/hook.js +6 -5
- package/build/lib/postinstall.js +6 -10
- package/build/mutation/branchDiff.js +178 -0
- package/build/mutation/fileResolver.js +170 -0
- package/build/mutation/index.js +16 -0
- package/build/mutation/mutatePattern.json +3 -0
- package/build/mutation/mutationCli.js +111 -0
- package/build/mutation/mutationRunner.js +208 -0
- package/build/mutation/reportGenerator.js +72 -0
- package/build/mutation/strykerWrapper.js +180 -0
- package/build/utils/FileAndFolderOperations/filterFiles.js +8 -6
- package/build/utils/FileAndFolderOperations/removeFolder.js +2 -2
- package/build/utils/General/Config.js +25 -0
- package/build/utils/General/SonarQubeUtil.js +1 -1
- package/jest.config.js +1 -1
- package/package.json +4 -1
- package/samples/sample-branch-mode.js +34 -0
- package/samples/sample-cli-entry.js +34 -0
- package/samples/sample-components.js +63 -0
- package/samples/sample-directory-mode.js +30 -0
- package/samples/sample-runner-direct.js +32 -0
- package/samples/sample-with-api.js +44 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
class ReportGenerator {
|
|
6
|
+
constructor(options = {}) {
|
|
7
|
+
this._outputDir = options.outputDir || 'reports/mutation';
|
|
8
|
+
this._outputFileName = options.outputFileName || 'mutation-report.json';
|
|
9
|
+
this._cwd = options.cwd || process.cwd();
|
|
10
|
+
}
|
|
11
|
+
generate(mutationResult, context = {}) {
|
|
12
|
+
const report = {
|
|
13
|
+
schemaVersion: '1.0',
|
|
14
|
+
timestamp: new Date().toISOString(),
|
|
15
|
+
projectRoot: this._cwd,
|
|
16
|
+
command: context.command || 'unknown',
|
|
17
|
+
configuration: {
|
|
18
|
+
branch: context.branch || null,
|
|
19
|
+
srcDir: context.srcDir || null,
|
|
20
|
+
testDir: context.testDir || null
|
|
21
|
+
},
|
|
22
|
+
filePairs: context.filePairs || [],
|
|
23
|
+
summary: mutationResult.summary || this._buildEmptySummary(),
|
|
24
|
+
files: mutationResult.files || {},
|
|
25
|
+
mutants: (mutationResult.mutants || []).map(m => ({
|
|
26
|
+
id: m.id,
|
|
27
|
+
mutatorName: m.mutatorName,
|
|
28
|
+
replacement: m.replacement,
|
|
29
|
+
fileName: m.fileName || m.sourceFile,
|
|
30
|
+
status: m.status,
|
|
31
|
+
location: m.location || null,
|
|
32
|
+
killedBy: m.killedBy || [],
|
|
33
|
+
coveredBy: m.coveredBy || [],
|
|
34
|
+
description: m.description || ''
|
|
35
|
+
}))
|
|
36
|
+
};
|
|
37
|
+
return report;
|
|
38
|
+
}
|
|
39
|
+
_buildEmptySummary() {
|
|
40
|
+
return {
|
|
41
|
+
totalMutants: 0,
|
|
42
|
+
killed: 0,
|
|
43
|
+
survived: 0,
|
|
44
|
+
timeout: 0,
|
|
45
|
+
noCoverage: 0,
|
|
46
|
+
ignored: 0,
|
|
47
|
+
runtimeErrors: 0,
|
|
48
|
+
compileErrors: 0,
|
|
49
|
+
mutationScore: 0
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
write(report) {
|
|
53
|
+
const outputPath = path.resolve(this._cwd, this._outputDir);
|
|
54
|
+
if (!fs.existsSync(outputPath)) {
|
|
55
|
+
fs.mkdirSync(outputPath, {
|
|
56
|
+
recursive: true
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
const filePath = path.join(outputPath, this._outputFileName);
|
|
60
|
+
fs.writeFileSync(filePath, JSON.stringify(report, null, 2), 'utf-8');
|
|
61
|
+
return filePath;
|
|
62
|
+
}
|
|
63
|
+
generateAndWrite(mutationResult, context = {}) {
|
|
64
|
+
const report = this.generate(mutationResult, context);
|
|
65
|
+
const filePath = this.write(report);
|
|
66
|
+
return {
|
|
67
|
+
report,
|
|
68
|
+
filePath
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
module.exports = ReportGenerator;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
4
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
5
|
+
var path = require('path');
|
|
6
|
+
var patternConfig = require('./mutatePattern.json');
|
|
7
|
+
var DEFAULT_MUTATE_PATTERN = patternConfig.defaultPattern;
|
|
8
|
+
function StrykerWrapper(options) {
|
|
9
|
+
options = options || {};
|
|
10
|
+
this._strykerModule = null;
|
|
11
|
+
this._defaultOptions = {
|
|
12
|
+
testRunner: 'jest',
|
|
13
|
+
coverageAnalysis: 'perTest',
|
|
14
|
+
reporters: ['json', 'clear-text'],
|
|
15
|
+
jsonReporter: {
|
|
16
|
+
fileName: options.reportPath || 'reports/mutation/mutation.json'
|
|
17
|
+
},
|
|
18
|
+
cleanTempDir: true,
|
|
19
|
+
concurrency: options.concurrency || Math.max(1, require('os').cpus().length - 1),
|
|
20
|
+
timeoutMS: options.timeoutMS || 60000,
|
|
21
|
+
timeoutFactor: options.timeoutFactor || 1.5,
|
|
22
|
+
logLevel: options.logLevel || 'info',
|
|
23
|
+
allowEmpty: true
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
StrykerWrapper.prototype._loadStryker = async function () {
|
|
27
|
+
if (!this._strykerModule) {
|
|
28
|
+
try {
|
|
29
|
+
this._strykerModule = await Promise.resolve().then(() => _interopRequireWildcard(require('@stryker-mutator/core')));
|
|
30
|
+
} catch (err) {
|
|
31
|
+
throw new Error('Failed to load @stryker-mutator/core. Install it: ' + 'npm i --save-dev @stryker-mutator/core @stryker-mutator/jest-runner\n' + err.message);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return this._strykerModule;
|
|
35
|
+
};
|
|
36
|
+
StrykerWrapper.prototype._buildMutatePatterns = function (sourceFiles) {
|
|
37
|
+
if (!sourceFiles || sourceFiles.length === 0) {
|
|
38
|
+
return [DEFAULT_MUTATE_PATTERN];
|
|
39
|
+
}
|
|
40
|
+
return sourceFiles.map(function (f) {
|
|
41
|
+
return f.replace(/\\/g, '/');
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
StrykerWrapper.prototype._buildStrykerConfig = function (sourceFiles, options) {
|
|
45
|
+
options = options || {};
|
|
46
|
+
var mutatePatterns = this._buildMutatePatterns(sourceFiles);
|
|
47
|
+
var config = Object.assign({}, this._defaultOptions, {
|
|
48
|
+
mutate: mutatePatterns
|
|
49
|
+
});
|
|
50
|
+
if (options.testFiles && options.testFiles.length > 0) {
|
|
51
|
+
config.testFiles = options.testFiles.map(function (f) {
|
|
52
|
+
return f.replace(/\\/g, '/');
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (options.jest) {
|
|
56
|
+
config.jest = Object.assign({
|
|
57
|
+
projectType: 'custom',
|
|
58
|
+
enableFindRelatedTests: true
|
|
59
|
+
}, options.jest);
|
|
60
|
+
}
|
|
61
|
+
if (options.configFile) {
|
|
62
|
+
config.configFile = options.configFile;
|
|
63
|
+
}
|
|
64
|
+
if (options.reportPath) {
|
|
65
|
+
config.jsonReporter = {
|
|
66
|
+
fileName: options.reportPath
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (options.tempDirName) {
|
|
70
|
+
config.tempDirName = options.tempDirName;
|
|
71
|
+
}
|
|
72
|
+
if (options.thresholds) {
|
|
73
|
+
config.thresholds = options.thresholds;
|
|
74
|
+
}
|
|
75
|
+
return config;
|
|
76
|
+
};
|
|
77
|
+
StrykerWrapper.prototype.run = async function (sourceFiles, options) {
|
|
78
|
+
options = options || {};
|
|
79
|
+
var strykerModule = await this._loadStryker();
|
|
80
|
+
var Stryker = strykerModule.Stryker || strykerModule.default || strykerModule;
|
|
81
|
+
var config = this._buildStrykerConfig(sourceFiles, options);
|
|
82
|
+
try {
|
|
83
|
+
var instance = new Stryker(config);
|
|
84
|
+
var result = await instance.runMutationTest();
|
|
85
|
+
return this._normalizeResult(result);
|
|
86
|
+
} catch (err) {
|
|
87
|
+
throw new Error('Stryker mutation test failed: ' + err.message);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
StrykerWrapper.prototype._normalizeResult = function (rawResult) {
|
|
91
|
+
if (!rawResult) {
|
|
92
|
+
return this._emptyNormalizedResult();
|
|
93
|
+
}
|
|
94
|
+
var mutants = Array.isArray(rawResult) ? rawResult : rawResult.mutants || [];
|
|
95
|
+
var summary = this._buildSummary(mutants);
|
|
96
|
+
var fileMap = this._buildFileMap(mutants);
|
|
97
|
+
return {
|
|
98
|
+
files: fileMap,
|
|
99
|
+
schemaVersion: '1',
|
|
100
|
+
thresholds: {
|
|
101
|
+
high: 80,
|
|
102
|
+
low: 60,
|
|
103
|
+
break: null
|
|
104
|
+
},
|
|
105
|
+
projectRoot: process.cwd(),
|
|
106
|
+
mutants: mutants,
|
|
107
|
+
summary: summary
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
StrykerWrapper.prototype._buildSummary = function (mutants) {
|
|
111
|
+
var summary = {
|
|
112
|
+
totalMutants: mutants.length,
|
|
113
|
+
killed: 0,
|
|
114
|
+
survived: 0,
|
|
115
|
+
timeout: 0,
|
|
116
|
+
noCoverage: 0,
|
|
117
|
+
ignored: 0,
|
|
118
|
+
runtimeErrors: 0,
|
|
119
|
+
compileErrors: 0,
|
|
120
|
+
mutationScore: 0
|
|
121
|
+
};
|
|
122
|
+
for (var i = 0; i < mutants.length; i++) {
|
|
123
|
+
var status = (mutants[i].status || '').toLowerCase();
|
|
124
|
+
if (status === 'killed') summary.killed++;else if (status === 'survived') summary.survived++;else if (status === 'timeout') summary.timeout++;else if (status === 'nocoverage') summary.noCoverage++;else if (status === 'ignored') summary.ignored++;else if (status === 'runtimeerror') summary.runtimeErrors++;else if (status === 'compileerror') summary.compileErrors++;
|
|
125
|
+
}
|
|
126
|
+
var detected = summary.killed + summary.timeout;
|
|
127
|
+
var totalValid = summary.totalMutants - summary.ignored - summary.compileErrors - summary.runtimeErrors;
|
|
128
|
+
summary.mutationScore = totalValid > 0 ? parseFloat((detected / totalValid * 100).toFixed(2)) : 0;
|
|
129
|
+
return summary;
|
|
130
|
+
};
|
|
131
|
+
StrykerWrapper.prototype._buildFileMap = function (mutants) {
|
|
132
|
+
var fileMap = {};
|
|
133
|
+
for (var i = 0; i < mutants.length; i++) {
|
|
134
|
+
var mutant = mutants[i];
|
|
135
|
+
var fileName = mutant.fileName || mutant.sourceFile || 'unknown';
|
|
136
|
+
if (!fileMap[fileName]) {
|
|
137
|
+
fileMap[fileName] = [];
|
|
138
|
+
}
|
|
139
|
+
fileMap[fileName].push({
|
|
140
|
+
id: mutant.id,
|
|
141
|
+
mutatorName: mutant.mutatorName,
|
|
142
|
+
replacement: mutant.replacement,
|
|
143
|
+
status: mutant.status,
|
|
144
|
+
location: mutant.location,
|
|
145
|
+
killedBy: mutant.killedBy || [],
|
|
146
|
+
coveredBy: mutant.coveredBy || [],
|
|
147
|
+
description: mutant.description || ''
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return fileMap;
|
|
151
|
+
};
|
|
152
|
+
StrykerWrapper.prototype._emptyNormalizedResult = function () {
|
|
153
|
+
return {
|
|
154
|
+
files: {},
|
|
155
|
+
schemaVersion: '1',
|
|
156
|
+
thresholds: {
|
|
157
|
+
high: 80,
|
|
158
|
+
low: 60,
|
|
159
|
+
break: null
|
|
160
|
+
},
|
|
161
|
+
projectRoot: process.cwd(),
|
|
162
|
+
mutants: [],
|
|
163
|
+
summary: {
|
|
164
|
+
totalMutants: 0,
|
|
165
|
+
killed: 0,
|
|
166
|
+
survived: 0,
|
|
167
|
+
timeout: 0,
|
|
168
|
+
noCoverage: 0,
|
|
169
|
+
ignored: 0,
|
|
170
|
+
runtimeErrors: 0,
|
|
171
|
+
compileErrors: 0,
|
|
172
|
+
mutationScore: 0
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
StrykerWrapper.prototype.getDefaultConfig = function () {
|
|
177
|
+
return Object.assign({}, this._defaultOptions);
|
|
178
|
+
};
|
|
179
|
+
module.exports = StrykerWrapper;
|
|
180
|
+
module.exports.DEFAULT_MUTATE_PATTERN = DEFAULT_MUTATE_PATTERN;
|
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
const {
|
|
4
4
|
Logger
|
|
5
5
|
} = require('../Logger/Logger');
|
|
6
|
-
const
|
|
7
|
-
existsSync
|
|
8
|
-
} = require("fs");
|
|
6
|
+
const path = require('path');
|
|
9
7
|
/**
|
|
10
8
|
* @function filterFiles - removes certain files from set of source files
|
|
11
9
|
* @param {Array} arrayOfFilesToBeFiltered - array of files which must be filtered
|
|
@@ -20,14 +18,18 @@ function filterFiles(arrayOfFilesToBeFiltered, filesToBeRemoved, isConfigFileNee
|
|
|
20
18
|
* @returns {Array<String>}
|
|
21
19
|
* */
|
|
22
20
|
function filterFilesByExtension(lintFiles) {
|
|
21
|
+
const ext = file => path.extname(file).toLowerCase();
|
|
23
22
|
return lintFiles.reduce((files, currentFile) => {
|
|
24
|
-
if (
|
|
23
|
+
// if (!existsSync(currentFile)) return files;
|
|
24
|
+
|
|
25
|
+
const e = ext(currentFile);
|
|
26
|
+
if (e === '.feature') {
|
|
25
27
|
files.featureFiles.push(currentFile);
|
|
26
28
|
}
|
|
27
|
-
if (
|
|
29
|
+
if (['.js', '.ts', '.tsx', '.jsx', '.properties'].includes(e)) {
|
|
28
30
|
files.JsFiles.push(currentFile);
|
|
29
31
|
}
|
|
30
|
-
if (
|
|
32
|
+
if (e === '.css') {
|
|
31
33
|
files.CssFiles.push(currentFile);
|
|
32
34
|
}
|
|
33
35
|
return files;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
4
|
existsSync,
|
|
5
|
-
|
|
5
|
+
rm
|
|
6
6
|
} = require('fs');
|
|
7
7
|
const {
|
|
8
8
|
Logger
|
|
@@ -20,7 +20,7 @@ function removeFolder(folderPath) {
|
|
|
20
20
|
try {
|
|
21
21
|
let isCommonConfigFolderPresent = existsSync(folderPath);
|
|
22
22
|
if (isCommonConfigFolderPresent) {
|
|
23
|
-
executeSynchronizedCommands(
|
|
23
|
+
executeSynchronizedCommands(rm, [folderPath, {
|
|
24
24
|
recursive: true,
|
|
25
25
|
force: true
|
|
26
26
|
}], 'common linter configuration folder removed successfully', 'Unable to remove the common linter configuration folder', false, false);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
function initConfig(actualConfigPath) {
|
|
5
|
+
const config = getConfigObject(actualConfigPath);
|
|
6
|
+
process.env.SONARQUBE_EXTERNAL = config.metric_token;
|
|
7
|
+
process.env.SONARQUBE = config.meticHandler_api_token;
|
|
8
|
+
process.env.ZGIT_TOKEN = config.token;
|
|
9
|
+
process.env.TOOL_TOKEN = config.toolToken;
|
|
10
|
+
}
|
|
11
|
+
function getConfigPathPostInstall() {
|
|
12
|
+
return path.resolve(process.cwd(), '..', '..', '..');
|
|
13
|
+
}
|
|
14
|
+
function getConfigPathExecute() {
|
|
15
|
+
return path.resolve(process.cwd());
|
|
16
|
+
}
|
|
17
|
+
function getConfigObject(actualConfigPath) {
|
|
18
|
+
return require(path.join(actualConfigPath, 'lint.config.js'));
|
|
19
|
+
}
|
|
20
|
+
module.exports = {
|
|
21
|
+
initConfig,
|
|
22
|
+
getConfigPathExecute,
|
|
23
|
+
getConfigPathPostInstall,
|
|
24
|
+
getConfigObject
|
|
25
|
+
};
|
|
@@ -78,7 +78,7 @@ async function fetchProjectIssuesViaCurl(componentKey) {
|
|
|
78
78
|
_Logger.Logger.log(_Logger.Logger.INFO_TYPE, `\n Fetching issues (curl) for component: ${componentKey}`);
|
|
79
79
|
const url = buildIssuesSearchUrl(componentKey);
|
|
80
80
|
try {
|
|
81
|
-
const token = process.env.SONARQUBE;
|
|
81
|
+
const token = process.env.SONARQUBE;
|
|
82
82
|
const command = `curl --tlsv1.2 -s -u "${token}:" "${url}"`;
|
|
83
83
|
const output = execSync(command).toString();
|
|
84
84
|
const json = JSON.parse(output.toString());
|
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.2.4-exp-2",
|
|
4
4
|
"description": "library to enforce code standard using eslint",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -18,7 +18,10 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@zohodesk-private/client_deployment_tool": "0.0.5",
|
|
20
20
|
"@zohodesk/codestandard-analytics": "1.1.4-exp-2",
|
|
21
|
+
"@stryker-mutator/core": "5.0.0",
|
|
21
22
|
"eslint": "8.26.0",
|
|
23
|
+
"marked": "9.1.6",
|
|
24
|
+
"marked-terminal": "6.2.0",
|
|
22
25
|
"stylelint": "16.23.0"
|
|
23
26
|
},
|
|
24
27
|
"devDependencies": {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Usage: node samples/sample-branch-mode.js
|
|
2
|
+
|
|
3
|
+
var MutationCli = require('../src/mutation').MutationCli;
|
|
4
|
+
|
|
5
|
+
var cli = new MutationCli({ cwd: process.cwd() });
|
|
6
|
+
|
|
7
|
+
console.log('Running mutation testing in branch diff mode...');
|
|
8
|
+
console.log('Diffing current branch against: main');
|
|
9
|
+
console.log('');
|
|
10
|
+
|
|
11
|
+
cli.execute(['mutate', '--branch=main']).then(function (result) {
|
|
12
|
+
if (result.success) {
|
|
13
|
+
console.log('=== SUCCESS ===');
|
|
14
|
+
console.log('Report file: ', result.filePath);
|
|
15
|
+
console.log('Score: ', result.report.summary.mutationScore + '%');
|
|
16
|
+
console.log('Total: ', result.report.summary.totalMutants);
|
|
17
|
+
console.log('Killed: ', result.report.summary.killed);
|
|
18
|
+
console.log('Survived: ', result.report.summary.survived);
|
|
19
|
+
console.log('No Coverage: ', result.report.summary.noCoverage);
|
|
20
|
+
if (result.message) {
|
|
21
|
+
console.log('Note: ', result.message);
|
|
22
|
+
}
|
|
23
|
+
console.log('');
|
|
24
|
+
console.log('File pairs tested:');
|
|
25
|
+
result.report.filePairs.forEach(function (pair) {
|
|
26
|
+
console.log(' Source: ' + pair.source + ' -> Test: ' + (pair.test || 'NONE'));
|
|
27
|
+
});
|
|
28
|
+
} else {
|
|
29
|
+
console.error('=== FAILED ===');
|
|
30
|
+
console.error('Error:', result.error);
|
|
31
|
+
}
|
|
32
|
+
}).catch(function (err) {
|
|
33
|
+
console.error('Unexpected error:', err);
|
|
34
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Usage: node samples/sample-cli-entry.js
|
|
2
|
+
// Tests CLI argument parsing and validation only (no Stryker run)
|
|
3
|
+
|
|
4
|
+
var MutationCli = require('../src/mutation').MutationCli;
|
|
5
|
+
|
|
6
|
+
var testCases = [
|
|
7
|
+
{ name: 'Directory mode', args: ['mutate', '--src=src', '--test=test'] },
|
|
8
|
+
{ name: 'Branch mode', args: ['mutate', '--branch=main'] },
|
|
9
|
+
{ name: 'Missing args (should fail)', args: ['mutate'] },
|
|
10
|
+
{ name: 'Both modes (should fail)', args: ['mutate', '--branch=main', '--src=src', '--test=test'] },
|
|
11
|
+
{ name: 'Unknown command (should fail)', args: ['lint'] },
|
|
12
|
+
{ name: 'With optional flags', args: ['mutate', '--src=src', '--test=test', '--outputDir=custom-reports', '--logLevel=debug'] },
|
|
13
|
+
{ name: 'Branch with useApi', args: ['mutate', '--branch=develop', '--useApi'] },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
var cli = new MutationCli({ cwd: process.cwd() });
|
|
17
|
+
|
|
18
|
+
console.log('=== CLI Argument Parsing Tests ===');
|
|
19
|
+
console.log('');
|
|
20
|
+
|
|
21
|
+
testCases.forEach(function (tc) {
|
|
22
|
+
console.log('Test: ' + tc.name);
|
|
23
|
+
console.log(' Args: ' + tc.args.join(' '));
|
|
24
|
+
|
|
25
|
+
var parsed = cli.parseArgs(tc.args);
|
|
26
|
+
console.log(' Parsed:', JSON.stringify(parsed));
|
|
27
|
+
|
|
28
|
+
var validation = cli.validate(parsed);
|
|
29
|
+
console.log(' Valid:', validation.valid);
|
|
30
|
+
if (!validation.valid) {
|
|
31
|
+
console.log(' Error:', validation.error.split('\n')[0]);
|
|
32
|
+
}
|
|
33
|
+
console.log('');
|
|
34
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// Usage: node samples/sample-components.js
|
|
2
|
+
|
|
3
|
+
var mutation = require('../src/mutation');
|
|
4
|
+
|
|
5
|
+
console.log('=== 1. Testing BranchDiff ===');
|
|
6
|
+
var branchDiff = new mutation.BranchDiff({ cwd: process.cwd() });
|
|
7
|
+
|
|
8
|
+
branchDiff.getChangedFiles('main').then(function (changed) {
|
|
9
|
+
console.log('Source files changed:', changed.sourceFiles);
|
|
10
|
+
console.log('Test files changed:', changed.testFiles);
|
|
11
|
+
console.log('');
|
|
12
|
+
|
|
13
|
+
console.log('=== 2. Testing FileResolver ===');
|
|
14
|
+
var resolver = new mutation.FileResolver({ cwd: process.cwd() });
|
|
15
|
+
var pairs = resolver.resolveSourceTestPairs(changed.sourceFiles, changed.testFiles);
|
|
16
|
+
console.log('Resolved pairs:');
|
|
17
|
+
pairs.forEach(function (pair) {
|
|
18
|
+
console.log(' ' + pair.source + ' -> ' + (pair.test || 'NO TEST'));
|
|
19
|
+
});
|
|
20
|
+
console.log('');
|
|
21
|
+
|
|
22
|
+
console.log('=== 3. Testing StrykerWrapper config ===');
|
|
23
|
+
var stryker = new mutation.StrykerWrapper({
|
|
24
|
+
reportPath: 'reports/mutation/sample-report.json',
|
|
25
|
+
});
|
|
26
|
+
var config = stryker.getDefaultConfig();
|
|
27
|
+
console.log('Default config:');
|
|
28
|
+
console.log(' testRunner:', config.testRunner);
|
|
29
|
+
console.log(' coverageAnalysis:', config.coverageAnalysis);
|
|
30
|
+
console.log('');
|
|
31
|
+
|
|
32
|
+
console.log('=== 4. Testing ReportGenerator ===');
|
|
33
|
+
var reporter = new mutation.ReportGenerator({
|
|
34
|
+
cwd: process.cwd(),
|
|
35
|
+
outputDir: 'reports/mutation',
|
|
36
|
+
outputFileName: 'sample-component-report.json',
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
var fakeResult = {
|
|
40
|
+
summary: {
|
|
41
|
+
totalMutants: 5, killed: 3, survived: 1, timeout: 0,
|
|
42
|
+
noCoverage: 1, ignored: 0, runtimeErrors: 0, compileErrors: 0,
|
|
43
|
+
mutationScore: 60,
|
|
44
|
+
},
|
|
45
|
+
files: {},
|
|
46
|
+
mutants: [
|
|
47
|
+
{ id: '1', status: 'Killed', fileName: 'src/app.js', mutatorName: 'StringLiteral' },
|
|
48
|
+
{ id: '2', status: 'Survived', fileName: 'src/app.js', mutatorName: 'BooleanLiteral' },
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
var output = reporter.generateAndWrite(fakeResult, {
|
|
53
|
+
command: 'sample-components test',
|
|
54
|
+
branch: 'main',
|
|
55
|
+
filePairs: pairs,
|
|
56
|
+
});
|
|
57
|
+
console.log('Report written to:', output.filePath);
|
|
58
|
+
console.log('Report summary:', output.report.summary);
|
|
59
|
+
console.log('');
|
|
60
|
+
console.log('=== All component tests complete ===');
|
|
61
|
+
}).catch(function (err) {
|
|
62
|
+
console.error('Error:', err.message);
|
|
63
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Usage: node samples/sample-directory-mode.js
|
|
2
|
+
|
|
3
|
+
var MutationCli = require('../src/mutation').MutationCli;
|
|
4
|
+
|
|
5
|
+
var cli = new MutationCli({ cwd: process.cwd() });
|
|
6
|
+
|
|
7
|
+
console.log('Running mutation testing in directory mode...');
|
|
8
|
+
console.log('Source dir: src');
|
|
9
|
+
console.log('Test dir: test');
|
|
10
|
+
console.log('');
|
|
11
|
+
|
|
12
|
+
cli.execute(['mutate', '--src=src', '--test=test']).then(function (result) {
|
|
13
|
+
if (result.success) {
|
|
14
|
+
console.log('=== SUCCESS ===');
|
|
15
|
+
console.log('Report file: ', result.filePath);
|
|
16
|
+
console.log('Score: ', result.report.summary.mutationScore + '%');
|
|
17
|
+
console.log('Total: ', result.report.summary.totalMutants);
|
|
18
|
+
console.log('Killed: ', result.report.summary.killed);
|
|
19
|
+
console.log('Survived: ', result.report.summary.survived);
|
|
20
|
+
console.log('No Coverage: ', result.report.summary.noCoverage);
|
|
21
|
+
if (result.message) {
|
|
22
|
+
console.log('Note: ', result.message);
|
|
23
|
+
}
|
|
24
|
+
} else {
|
|
25
|
+
console.error('=== FAILED ===');
|
|
26
|
+
console.error('Error:', result.error);
|
|
27
|
+
}
|
|
28
|
+
}).catch(function (err) {
|
|
29
|
+
console.error('Unexpected error:', err);
|
|
30
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Usage: node samples/sample-runner-direct.js
|
|
2
|
+
|
|
3
|
+
var MutationRunner = require('../src/mutation').MutationRunner;
|
|
4
|
+
|
|
5
|
+
var runner = new MutationRunner({
|
|
6
|
+
cwd: process.cwd(),
|
|
7
|
+
outputDir: 'reports/mutation',
|
|
8
|
+
outputFileName: 'direct-runner-report.json',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
console.log('=== Testing runByBranch ===');
|
|
12
|
+
runner.runByBranch('main').then(function (result) {
|
|
13
|
+
console.log('Branch mode result:');
|
|
14
|
+
console.log(' Report:', result.filePath);
|
|
15
|
+
console.log(' Score:', result.report.summary.mutationScore + '%');
|
|
16
|
+
if (result.message) {
|
|
17
|
+
console.log(' Note:', result.message);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
console.log('');
|
|
21
|
+
console.log('=== Testing runByDirectory ===');
|
|
22
|
+
return runner.runByDirectory('src', 'test');
|
|
23
|
+
}).then(function (result) {
|
|
24
|
+
console.log('Directory mode result:');
|
|
25
|
+
console.log(' Report:', result.filePath);
|
|
26
|
+
console.log(' Score:', result.report.summary.mutationScore + '%');
|
|
27
|
+
if (result.message) {
|
|
28
|
+
console.log(' Note:', result.message);
|
|
29
|
+
}
|
|
30
|
+
}).catch(function (err) {
|
|
31
|
+
console.error('Error:', err.message);
|
|
32
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Usage: PAT_TOKEN=your_token node samples/sample-with-api.js
|
|
2
|
+
|
|
3
|
+
var MutationCli = require('../src/mutation').MutationCli;
|
|
4
|
+
|
|
5
|
+
var myApi = {
|
|
6
|
+
getChangedFiles: function (targetBranch, patToken) {
|
|
7
|
+
console.log('API called with branch:', targetBranch);
|
|
8
|
+
console.log('PAT token provided:', patToken ? 'yes' : 'no');
|
|
9
|
+
return Promise.resolve([
|
|
10
|
+
'src/services/auth.js',
|
|
11
|
+
'src/services/auth.test.js',
|
|
12
|
+
'src/utils/format.js',
|
|
13
|
+
'src/utils/format.test.js',
|
|
14
|
+
'src/config.js',
|
|
15
|
+
]);
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
var cli = new MutationCli({
|
|
20
|
+
cwd: process.cwd(),
|
|
21
|
+
api: myApi,
|
|
22
|
+
patToken: process.env.PAT_TOKEN || 'mock-token',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
console.log('Running mutation testing with API-based branch diff...');
|
|
26
|
+
console.log('');
|
|
27
|
+
|
|
28
|
+
cli.execute(['mutate', '--branch=main', '--useApi']).then(function (result) {
|
|
29
|
+
if (result.success) {
|
|
30
|
+
console.log('=== SUCCESS ===');
|
|
31
|
+
console.log('Report:', result.filePath);
|
|
32
|
+
console.log('Score:', result.report.summary.mutationScore + '%');
|
|
33
|
+
console.log('');
|
|
34
|
+
console.log('File pairs:');
|
|
35
|
+
result.report.filePairs.forEach(function (pair) {
|
|
36
|
+
console.log(' ' + pair.source + ' -> ' + (pair.test || 'NO TEST'));
|
|
37
|
+
});
|
|
38
|
+
} else {
|
|
39
|
+
console.error('=== FAILED ===');
|
|
40
|
+
console.error('Error:', result.error);
|
|
41
|
+
}
|
|
42
|
+
}).catch(function (err) {
|
|
43
|
+
console.error('Unexpected error:', err);
|
|
44
|
+
});
|