@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.
Files changed (36) hide show
  1. package/bin/cliCI.js +0 -0
  2. package/build/ai/config.example.json +10 -0
  3. package/build/ai/ollama-service.js +403 -0
  4. package/build/ai/prompts/CODE_REVIEW_PROMPT.md +72 -0
  5. package/build/ai/prompts/PROMPT1.MD +70 -0
  6. package/build/ai/prompts/PROMPT2.md +159 -0
  7. package/build/ai/prompts/PROMPT3.md +64 -0
  8. package/build/ai/prompts/PROMPT4.md +64 -0
  9. package/build/ai/provider-factory.js +19 -0
  10. package/build/ai/providers/OllamaProvider.js +106 -0
  11. package/build/ai/render.js +157 -0
  12. package/build/ai/run-review.js +50 -0
  13. package/build/chunk/chunk_Restriction.js +202 -0
  14. package/build/hooks/Precommit/pre-commit-default.js +158 -140
  15. package/build/hooks/hook.js +6 -5
  16. package/build/lib/postinstall.js +6 -10
  17. package/build/mutation/branchDiff.js +178 -0
  18. package/build/mutation/fileResolver.js +170 -0
  19. package/build/mutation/index.js +16 -0
  20. package/build/mutation/mutatePattern.json +3 -0
  21. package/build/mutation/mutationCli.js +111 -0
  22. package/build/mutation/mutationRunner.js +208 -0
  23. package/build/mutation/reportGenerator.js +72 -0
  24. package/build/mutation/strykerWrapper.js +180 -0
  25. package/build/utils/FileAndFolderOperations/filterFiles.js +8 -6
  26. package/build/utils/FileAndFolderOperations/removeFolder.js +2 -2
  27. package/build/utils/General/Config.js +25 -0
  28. package/build/utils/General/SonarQubeUtil.js +1 -1
  29. package/jest.config.js +1 -1
  30. package/package.json +4 -1
  31. package/samples/sample-branch-mode.js +34 -0
  32. package/samples/sample-cli-entry.js +34 -0
  33. package/samples/sample-components.js +63 -0
  34. package/samples/sample-directory-mode.js +30 -0
  35. package/samples/sample-runner-direct.js +32 -0
  36. 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 (currentFile.includes('.feature') && existsSync(currentFile)) {
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 (currentFile.includes('.js') || currentFile.includes('.ts') || currentFile.includes('.tsx') || currentFile.includes('.jsx') || currentFile.includes('.properties') && existsSync(currentFile)) {
29
+ if (['.js', '.ts', '.tsx', '.jsx', '.properties'].includes(e)) {
28
30
  files.JsFiles.push(currentFile);
29
31
  }
30
- if (currentFile.includes('.css') && existsSync(currentFile)) {
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
- rmSync
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(rmSync, [folderPath, {
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; //'sqa_1f6675c05f63c4784dc741ce751efa0066d2693c' || decrypt(getAPIToken(), ); // 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
@@ -1,5 +1,5 @@
1
1
  module.exports = {
2
2
  testEnvironment: 'node',
3
3
  clearMocks: true,
4
- setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
4
+ setupFilesAfterEnv: ['<rootDir>/jest.setup.js']
5
5
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zohodesk/codestandard-validator",
3
- "version": "1.1.4",
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
+ });