@zohodesk/codestandard-validator 1.2.4-exp-5 → 1.2.4-exp-7

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.
@@ -6,165 +6,196 @@ const glob = require('glob');
6
6
  const {
7
7
  getRootDirectory
8
8
  } = require('../utils/General/RootDirectoryUtils/getRootDirectory');
9
- class FileResolver {
10
- constructor(options = {}) {
11
- this._rootdir = getRootDirectory();
12
- this._cwd = options.cwd || process.cwd();
13
- this._testSuffixes = options.testSuffixes || ['.test.js', '.test.ts', '.test.jsx', '.test.tsx'];
14
- this._sourceExtensions = options.sourceExtensions || ['.js', '.ts', '.jsx', '.tsx', '.mjs', '.cjs'];
15
- }
16
- findTestForSource(sourceFile) {
17
- const parsed = path.parse(sourceFile);
18
- const dir = parsed.dir;
19
- const name = parsed.name;
20
-
21
- // Strategy 1: Test file alongside source (e.g., src/foo.js -> src/foo.test.js)
22
- for (const suffix of this._testSuffixes) {
23
- const candidate = path.join(dir, `${name}${suffix}`);
24
- if (fs.existsSync(path.resolve(this._rootdir, candidate))) {
25
- return candidate;
26
- }
9
+
10
+ /**
11
+ * FileResolver — resolves source ↔ test file pairs.
12
+ *
13
+ * Uses heuristic strategies (co-located, __tests__/, mirrored dirs)
14
+ * to find a test file for every source file and vice versa.
15
+ *
16
+ * Compatible with Node 16+.
17
+ */
18
+ function FileResolver(options) {
19
+ options = options || {};
20
+ this._rootdir = getRootDirectory();
21
+ this._cwd = options.cwd || process.cwd();
22
+ this._testSuffixes = options.testSuffixes || ['.test.js', '.test.ts', '.test.jsx', '.test.tsx'];
23
+ this._sourceExtensions = options.sourceExtensions || ['.js', '.ts', '.jsx', '.tsx', '.mjs', '.cjs'];
24
+ }
25
+
26
+ /* ------------------------------------------------------------------ */
27
+ /* Source → Test */
28
+ /* ------------------------------------------------------------------ */
29
+
30
+ FileResolver.prototype.findTestForSource = function (sourceFile) {
31
+ var parsed = path.parse(sourceFile);
32
+ var dir = parsed.dir;
33
+ var name = parsed.name;
34
+ var candidate, i, j, k;
35
+
36
+ // Strategy 1: co-located (src/foo.js → src/foo.test.js)
37
+ for (i = 0; i < this._testSuffixes.length; i++) {
38
+ candidate = path.join(dir, name + this._testSuffixes[i]);
39
+ if (fs.existsSync(path.resolve(this._rootdir, candidate))) {
40
+ return candidate;
27
41
  }
42
+ }
28
43
 
29
- // Strategy 2: Test in __tests__ directory (e.g., src/foo.js -> src/__tests__/foo.test.js)
30
- for (const suffix of this._testSuffixes) {
31
- const candidate = path.join(dir, '__tests__', `${name}${suffix}`);
32
- if (fs.existsSync(path.resolve(this._rootdir, candidate))) {
33
- return candidate;
34
- }
44
+ // Strategy 2: __tests__ subdir (src/foo.js src/__tests__/foo.test.js)
45
+ for (i = 0; i < this._testSuffixes.length; i++) {
46
+ candidate = path.join(dir, '__tests__', name + this._testSuffixes[i]);
47
+ if (fs.existsSync(path.resolve(this._rootdir, candidate))) {
48
+ return candidate;
35
49
  }
50
+ }
36
51
 
37
- // Strategy 3: Mirror structure under test/tests directory
38
- const testDirs = ['test', 'tests', '__tests__'];
39
- const srcDirs = ['src', 'lib'];
40
- for (const srcDir of srcDirs) {
41
- if (dir.startsWith(srcDir)) {
42
- const relativePath = dir.substring(srcDir.length);
43
- for (const testDir of testDirs) {
44
- for (const suffix of this._testSuffixes) {
45
- const candidate = path.join(testDir, relativePath, `${name}${suffix}`);
46
- if (fs.existsSync(path.resolve(this._rootdir, candidate))) {
47
- return candidate;
48
- }
52
+ // Strategy 3: mirror structure (src/x/foo.js test/x/foo.test.js)
53
+ var testDirs = ['test', 'tests', '__tests__'];
54
+ var srcDirs = ['src', 'lib'];
55
+ for (i = 0; i < srcDirs.length; i++) {
56
+ if (dir.indexOf(srcDirs[i]) === 0) {
57
+ var relativePath = dir.substring(srcDirs[i].length);
58
+ for (j = 0; j < testDirs.length; j++) {
59
+ for (k = 0; k < this._testSuffixes.length; k++) {
60
+ candidate = path.join(testDirs[j], relativePath, name + this._testSuffixes[k]);
61
+ if (fs.existsSync(path.resolve(this._rootdir, candidate))) {
62
+ return candidate;
49
63
  }
50
64
  }
51
65
  }
52
66
  }
53
- return null;
54
67
  }
55
- findSourceForTest(testFile) {
56
- const parsed = path.parse(testFile);
57
- const dir = parsed.dir;
58
- let name = parsed.name;
59
-
60
- // Remove .test suffix
61
- for (const suffix of ['.test', '.spec']) {
62
- if (name.endsWith(suffix)) {
63
- name = name.slice(0, -suffix.length);
64
- break;
65
- }
68
+ return null;
69
+ };
70
+
71
+ /* ------------------------------------------------------------------ */
72
+ /* Test → Source */
73
+ /* ------------------------------------------------------------------ */
74
+
75
+ FileResolver.prototype.findSourceForTest = function (testFile) {
76
+ var parsed = path.parse(testFile);
77
+ var dir = parsed.dir;
78
+ var name = parsed.name;
79
+ var candidate, i, j, k;
80
+
81
+ // Strip .test / .spec suffix
82
+ var suffixes = ['.test', '.spec'];
83
+ for (i = 0; i < suffixes.length; i++) {
84
+ if (name.slice(-suffixes[i].length) === suffixes[i]) {
85
+ name = name.slice(0, -suffixes[i].length);
86
+ break;
66
87
  }
88
+ }
67
89
 
68
- // Strategy 1: Source file alongside test
69
- for (const ext of this._sourceExtensions) {
70
- const candidate = path.join(dir, `${name}${ext}`);
71
- if (fs.existsSync(path.resolve(this._rootdir, candidate))) {
72
- return candidate;
73
- }
90
+ // Strategy 1: co-located
91
+ for (i = 0; i < this._sourceExtensions.length; i++) {
92
+ candidate = path.join(dir, name + this._sourceExtensions[i]);
93
+ if (fs.existsSync(path.resolve(this._rootdir, candidate))) {
94
+ return candidate;
74
95
  }
96
+ }
75
97
 
76
- // Strategy 2: Source in parent (when test is in __tests__)
77
- if (dir.includes('__tests__')) {
78
- const parentDir = dir.replace(/__tests__\/?/, '');
79
- for (const ext of this._sourceExtensions) {
80
- const candidate = path.join(parentDir, `${name}${ext}`);
81
- if (fs.existsSync(path.resolve(this._rootdir, candidate))) {
82
- return candidate;
83
- }
98
+ // Strategy 2: parent of __tests__
99
+ if (dir.indexOf('__tests__') !== -1) {
100
+ var parentDir = dir.replace(/__tests__\/?/, '');
101
+ for (i = 0; i < this._sourceExtensions.length; i++) {
102
+ candidate = path.join(parentDir, name + this._sourceExtensions[i]);
103
+ if (fs.existsSync(path.resolve(this._rootdir, candidate))) {
104
+ return candidate;
84
105
  }
85
106
  }
107
+ }
86
108
 
87
- // Strategy 3: Mirror test dir structure back to src/lib
88
- const testDirs = ['test', 'tests', '__tests__'];
89
- const srcDirs = ['src', 'lib'];
90
- for (const testDir of testDirs) {
91
- if (dir.startsWith(testDir)) {
92
- const relativePath = dir.substring(testDir.length);
93
- for (const srcDir of srcDirs) {
94
- for (const ext of this._sourceExtensions) {
95
- const candidate = path.join(srcDir, relativePath, `${name}${ext}`);
96
- if (fs.existsSync(path.resolve(this._rootdir, candidate))) {
97
- return candidate;
98
- }
109
+ // Strategy 3: mirror test src/lib
110
+ var testDirs = ['test', 'tests', '__tests__'];
111
+ var srcDirs = ['src', 'lib'];
112
+ for (i = 0; i < testDirs.length; i++) {
113
+ if (dir.indexOf(testDirs[i]) === 0) {
114
+ var relativePath = dir.substring(testDirs[i].length);
115
+ for (j = 0; j < srcDirs.length; j++) {
116
+ for (k = 0; k < this._sourceExtensions.length; k++) {
117
+ candidate = path.join(srcDirs[j], relativePath, name + this._sourceExtensions[k]);
118
+ if (fs.existsSync(path.resolve(this._rootdir, candidate))) {
119
+ return candidate;
99
120
  }
100
121
  }
101
122
  }
102
123
  }
103
- return null;
104
124
  }
105
- resolveSourceTestPairs(sourceFiles, testFiles) {
106
- const pairs = [];
107
- const resolvedSources = new Set();
108
- const resolvedTests = new Set();
109
-
110
- // Map source -> test
111
- for (const source of sourceFiles) {
112
- const normalizedSource = source.replace(/\\/g, '/');
113
- const test = this.findTestForSource(normalizedSource);
114
- if (test) {
115
- const normalizedTest = test.replace(/\\/g, '/');
116
- pairs.push({
117
- source: normalizedSource,
118
- test: normalizedTest
119
- });
120
- resolvedSources.add(normalizedSource);
121
- resolvedTests.add(normalizedTest);
122
- } else {
123
- // Source file with no matching test
124
- pairs.push({
125
- source: normalizedSource,
126
- test: null
127
- });
128
- resolvedSources.add(normalizedSource);
129
- }
130
- }
125
+ return null;
126
+ };
131
127
 
132
- // Map remaining test -> source
133
- for (const test of testFiles) {
134
- const normalizedTest = test.replace(/\\/g, '/');
135
- if (resolvedTests.has(normalizedTest)) continue;
136
- const source = this.findSourceForTest(normalizedTest);
137
- if (source && !resolvedSources.has(source.replace(/\\/g, '/'))) {
138
- pairs.push({
139
- source: source.replace(/\\/g, '/'),
140
- test: normalizedTest
141
- });
142
- resolvedSources.add(source.replace(/\\/g, '/'));
143
- }
144
- resolvedTests.add(normalizedTest);
128
+ /* ------------------------------------------------------------------ */
129
+ /* Pair resolution */
130
+ /* ------------------------------------------------------------------ */
131
+
132
+ FileResolver.prototype.resolveSourceTestPairs = function (sourceFiles, testFiles) {
133
+ var pairs = [];
134
+ var resolvedSources = {};
135
+ var resolvedTests = {};
136
+ var i, normalizedSource, normalizedTest, test, source;
137
+
138
+ // Map source → test
139
+ for (i = 0; i < sourceFiles.length; i++) {
140
+ normalizedSource = sourceFiles[i].replace(/\\/g, '/');
141
+ test = this.findTestForSource(normalizedSource);
142
+ if (test) {
143
+ normalizedTest = test.replace(/\\/g, '/');
144
+ pairs.push({
145
+ source: normalizedSource,
146
+ test: normalizedTest
147
+ });
148
+ resolvedSources[normalizedSource] = true;
149
+ resolvedTests[normalizedTest] = true;
150
+ } else {
151
+ pairs.push({
152
+ source: normalizedSource,
153
+ test: null
154
+ });
155
+ resolvedSources[normalizedSource] = true;
145
156
  }
146
- return pairs;
147
157
  }
148
- collectFiles(directory, pattern) {
149
- const fullPattern = path.join(directory, pattern || '**/*.{js,ts,jsx,tsx}').replace(/\\/g, '/');
150
- try {
151
- const files = glob.sync(fullPattern, {
152
- cwd: this._rootdir,
153
- nodir: true
158
+
159
+ // Map remaining test source
160
+ for (i = 0; i < testFiles.length; i++) {
161
+ normalizedTest = testFiles[i].replace(/\\/g, '/');
162
+ if (resolvedTests[normalizedTest]) continue;
163
+ source = this.findSourceForTest(normalizedTest);
164
+ if (source && !resolvedSources[source.replace(/\\/g, '/')]) {
165
+ pairs.push({
166
+ source: source.replace(/\\/g, '/'),
167
+ test: normalizedTest
154
168
  });
155
- return files;
156
- } catch (err) {
157
- throw new Error(`Failed to collect files from '${directory}': ${err.message}`);
169
+ resolvedSources[source.replace(/\\/g, '/')] = true;
158
170
  }
171
+ resolvedTests[normalizedTest] = true;
159
172
  }
160
- collectSourceFiles(srcDir) {
161
- const allFiles = this.collectFiles(srcDir, '**/*.{js,ts,jsx,tsx,mjs,cjs}');
162
- const testPattern = /\.(test|spec)\.(js|ts|jsx|tsx|mjs|cjs)$/;
163
- return allFiles.filter(f => !testPattern.test(f));
164
- }
165
- collectTestFiles(testDir) {
166
- const allFiles = this.collectFiles(testDir, '**/*.{test,spec}.{js,ts,jsx,tsx}');
167
- return allFiles;
173
+ return pairs;
174
+ };
175
+
176
+ /* ------------------------------------------------------------------ */
177
+ /* File collectors (glob-based) */
178
+ /* ------------------------------------------------------------------ */
179
+
180
+ FileResolver.prototype.collectFiles = function (directory, pattern) {
181
+ var fullPattern = path.join(directory, pattern || '**/*.{js,ts,jsx,tsx}').replace(/\\/g, '/');
182
+ try {
183
+ return glob.sync(fullPattern, {
184
+ cwd: this._rootdir,
185
+ nodir: true
186
+ });
187
+ } catch (err) {
188
+ throw new Error("Failed to collect files from '" + directory + "': " + err.message);
168
189
  }
169
- }
190
+ };
191
+ FileResolver.prototype.collectSourceFiles = function (srcDir) {
192
+ var allFiles = this.collectFiles(srcDir, '**/*.{js,ts,jsx,tsx,mjs,cjs}');
193
+ var testPattern = /\.(test|spec)\.(js|ts|jsx|tsx|mjs|cjs)$/;
194
+ return allFiles.filter(function (f) {
195
+ return !testPattern.test(f);
196
+ });
197
+ };
198
+ FileResolver.prototype.collectTestFiles = function (testDir) {
199
+ return this.collectFiles(testDir, '**/*.{test,spec}.{js,ts,jsx,tsx}');
200
+ };
170
201
  module.exports = FileResolver;
@@ -1,111 +1,173 @@
1
1
  "use strict";
2
2
 
3
- const MutationRunner = require('./mutationRunner');
4
- class MutationCli {
5
- constructor(options = {}) {
6
- this._options = options;
3
+ var MutationRunner = require('./mutationRunner');
4
+ var StrykerConfigBuilder = require('./strykerConfigBuilder');
5
+
6
+ /**
7
+ * MutationCli — CLI argument parser and executor for mutation testing.
8
+ *
9
+ * Two modes:
10
+ * local — pre-commit: staged + branch diff → mutate → JSON report
11
+ * ci — CI pipeline: branch diff → mutate → JSON report
12
+ *
13
+ * Usage (zdcodequality):
14
+ * npx zdcodequality mutate --local [--branch=<branch>] (default branch: release)
15
+ * npx zdcodequality mutate --ci [--branch=<branch>] (default branch: release)
16
+ *
17
+ * Legacy (ZDLintFramework):
18
+ * npx ZDLintFramework mutate --mode=local --release=<branch>
19
+ * npx ZDLintFramework mutate --mode=ci --release=<branch>
20
+ *
21
+ * Optional flags:
22
+ * --outputDir=<dir> (default: reports/mutation)
23
+ * --outputFileName=<name> (default: mutation-report.json)
24
+ * --logLevel=<level> (default: info)
25
+ * --concurrency=<n> (default: cpu count - 1)
26
+ * --timeoutMS=<ms> (default: 60000)
27
+ * --strykerConfig=<path> (external stryker.conf.js)
28
+ *
29
+ * Compatible with Node 16+.
30
+ */
31
+ function MutationCli(options) {
32
+ this._options = options || {};
33
+ }
34
+
35
+ /* ------------------------------------------------------------------ */
36
+ /* Arg parsing */
37
+ /* ------------------------------------------------------------------ */
38
+
39
+ MutationCli.prototype.parseArgs = function (args) {
40
+ var parsed = {
41
+ command: null,
42
+ mode: null,
43
+ release: null,
44
+ outputDir: null,
45
+ outputFileName: null,
46
+ logLevel: 'info',
47
+ concurrency: null,
48
+ timeoutMS: null,
49
+ strykerConfig: null
50
+ };
51
+ for (var i = 0; i < args.length; i++) {
52
+ var arg = args[i];
53
+ if (arg === 'mutate') {
54
+ parsed.command = 'mutate';
55
+ } else if (arg === '--local') {
56
+ parsed.mode = 'local';
57
+ } else if (arg === '--ci') {
58
+ parsed.mode = 'ci';
59
+ } else if (arg.indexOf('--branch=') === 0) {
60
+ parsed.release = arg.split('=')[1];
61
+ } else if (arg.indexOf('--mode=') === 0) {
62
+ parsed.mode = arg.split('=')[1];
63
+ } else if (arg.indexOf('--release=') === 0) {
64
+ parsed.release = arg.split('=')[1];
65
+ } else if (arg.indexOf('--outputDir=') === 0) {
66
+ parsed.outputDir = arg.split('=')[1];
67
+ } else if (arg.indexOf('--outputFileName=') === 0) {
68
+ parsed.outputFileName = arg.split('=')[1];
69
+ } else if (arg.indexOf('--logLevel=') === 0) {
70
+ parsed.logLevel = arg.split('=')[1];
71
+ } else if (arg.indexOf('--concurrency=') === 0) {
72
+ parsed.concurrency = arg.split('=')[1];
73
+ } else if (arg.indexOf('--timeoutMS=') === 0) {
74
+ parsed.timeoutMS = arg.split('=')[1];
75
+ } else if (arg.indexOf('--strykerConfig=') === 0) {
76
+ parsed.strykerConfig = arg.split('=')[1];
77
+ }
78
+ }
79
+ if (parsed.release == null || parsed.release === '') {
80
+ parsed.release = 'release';
7
81
  }
8
- parseArgs(args) {
9
- const parsed = {
10
- command: null,
11
- branch: null,
12
- src: null,
13
- test: null,
14
- useApi: false,
15
- outputDir: null,
16
- outputFileName: null,
17
- logLevel: 'info',
18
- hostname: null
82
+ return parsed;
83
+ };
84
+
85
+ /* ------------------------------------------------------------------ */
86
+ /* Validation */
87
+ /* ------------------------------------------------------------------ */
88
+
89
+ MutationCli.prototype.validate = function (parsed) {
90
+ if (parsed.command !== 'mutate') {
91
+ return {
92
+ valid: false,
93
+ error: 'Unknown command. Expected "mutate".'
19
94
  };
20
- for (const arg of args) {
21
- if (arg === 'mutate') {
22
- parsed.command = 'mutate';
23
- } else if (arg.startsWith('--branch=')) {
24
- parsed.branch = arg.split('=')[1];
25
- } else if (arg.startsWith('--src=')) {
26
- parsed.src = arg.split('=')[1];
27
- } else if (arg.startsWith('--test=')) {
28
- parsed.test = arg.split('=')[1];
29
- } else if (arg === '--useApi') {
30
- parsed.useApi = true;
31
- } else if (arg.startsWith('--outputDir=')) {
32
- parsed.outputDir = arg.split('=')[1];
33
- } else if (arg.startsWith('--outputFileName=')) {
34
- parsed.outputFileName = arg.split('=')[1];
35
- } else if (arg.startsWith('--logLevel=')) {
36
- parsed.logLevel = arg.split('=')[1];
37
- } else if (arg.startsWith('--hostname=')) {
38
- parsed.hostname = arg.split('=')[1];
39
- }
40
- }
41
- return parsed;
42
95
  }
43
- validate(parsed) {
44
- if (parsed.command !== 'mutate') {
45
- return {
46
- valid: false,
47
- error: 'Unknown command. Expected "mutate".'
48
- };
49
- }
50
- const hasBranch = !!parsed.branch;
51
- const hasSrcTest = !!parsed.src && !!parsed.test;
52
- if (!hasBranch && !hasSrcTest) {
53
- return {
54
- valid: false,
55
- error: 'Missing arguments. Usage:\n' + ' npx ZDLintFramework mutate --branch=<branch>\n' + ' npx ZDLintFramework mutate --src=<sourcedir> --test=<testdir>'
56
- };
57
- }
58
- if (hasBranch && hasSrcTest) {
59
- return {
60
- valid: false,
61
- error: 'Cannot use both --branch and --src/--test together. Choose one mode.'
62
- };
63
- }
96
+ if (!parsed.mode || parsed.mode !== 'local' && parsed.mode !== 'ci') {
64
97
  return {
65
- valid: true
98
+ valid: false,
99
+ error: 'Invalid or missing mode. Use --local or --ci.\n' + 'Usage:\n' + ' npx zdcodequality mutate --local [--branch=<branch>]\n' + ' npx zdcodequality mutate --ci [--branch=<branch>]\n' + '(default branch: release)'
66
100
  };
67
101
  }
68
- async execute(args) {
69
- const parsed = this.parseArgs(args);
70
- const validation = this.validate(parsed);
71
- if (!validation.valid) {
72
- return {
73
- success: false,
74
- error: validation.error
75
- };
76
- }
77
- const runner = new MutationRunner({
78
- cwd: this._options.cwd,
79
- api: this._options.api,
80
- patToken: this._options.patToken,
81
- jestConfig: this._options.jestConfig,
82
- outputDir: parsed.outputDir || this._options.outputDir,
83
- outputFileName: parsed.outputFileName || this._options.outputFileName,
84
- logLevel: parsed.logLevel,
85
- concurrency: this._options.concurrency,
86
- timeoutMS: this._options.timeoutMS
102
+ return {
103
+ valid: true
104
+ };
105
+ };
106
+
107
+ /* ------------------------------------------------------------------ */
108
+ /* Build config via builder from parsed + defaults */
109
+ /* ------------------------------------------------------------------ */
110
+
111
+ MutationCli.prototype._buildConfig = function (parsed) {
112
+ var builder = new StrykerConfigBuilder();
113
+ if (parsed.strykerConfig || this._options.strykerConfigpath) {
114
+ builder.fromConfigFile(parsed.strykerConfig || this._options.strykerConfigpath);
115
+ }
116
+ builder.setLogLevel(parsed.logLevel || this._options.logLevel || 'info');
117
+ var concurrency = parsed.concurrency || this._options.concurrency;
118
+ if (concurrency != null) {
119
+ builder.setConcurrency(concurrency);
120
+ }
121
+ var timeoutMS = parsed.timeoutMS || this._options.timeoutMS;
122
+ if (timeoutMS != null) {
123
+ builder.setTimeoutMS(timeoutMS);
124
+ }
125
+ if (this._options.jestConfig) {
126
+ builder.setJest(Object.assign({
127
+ projectType: 'custom',
128
+ enableFindRelatedTests: true
129
+ }, this._options.jestConfig));
130
+ }
131
+ return builder;
132
+ };
133
+
134
+ /* ------------------------------------------------------------------ */
135
+ /* Execution */
136
+ /* ------------------------------------------------------------------ */
137
+
138
+ MutationCli.prototype.execute = function (args) {
139
+ var parsed = this.parseArgs(args);
140
+ var validation = this.validate(parsed);
141
+ if (!validation.valid) {
142
+ return Promise.resolve({
143
+ success: false,
144
+ error: validation.error
87
145
  });
88
- try {
89
- let result;
90
- if (parsed.branch) {
91
- result = await runner.runByBranch(parsed.branch, {
92
- useApi: parsed.useApi,
93
- hostname: this._options.hostname,
94
- projectId: this._options.projectId
95
- });
96
- } else {
97
- result = await runner.runByDirectory(parsed.src, parsed.test);
98
- }
99
- return {
100
- success: true,
101
- ...result
102
- };
103
- } catch (err) {
104
- return {
105
- success: false,
106
- error: err.message
107
- };
108
- }
109
146
  }
110
- }
147
+ var configBuilder = this._buildConfig(parsed);
148
+ var runner = new MutationRunner({
149
+ ...this._options,
150
+ cwd: this._options.cwd,
151
+ configBuilder: configBuilder,
152
+ jestConfig: this._options.jestConfig,
153
+ outputDir: parsed.outputDir || this._options.outputDir,
154
+ outputFileName: parsed.outputFileName || this._options.outputFileName
155
+ });
156
+ var promise;
157
+ if (parsed.mode === 'local') {
158
+ promise = runner.runLocal(parsed.release);
159
+ } else {
160
+ promise = runner.runCI(parsed.release);
161
+ }
162
+ return promise.then(function (result) {
163
+ return Object.assign({
164
+ success: true
165
+ }, result);
166
+ }).catch(function (err) {
167
+ return {
168
+ success: false,
169
+ error: err.message
170
+ };
171
+ });
172
+ };
111
173
  module.exports = MutationCli;