@regressionproof/cli 0.7.4 → 0.9.0
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/build/cli.js +21 -45
- package/build/commands/CommandRunner.d.ts +7 -0
- package/build/commands/CommandRunner.js +15 -0
- package/build/commands/commands.d.ts +7 -0
- package/build/commands/commands.js +118 -0
- package/build/components/Banner.d.ts +2 -0
- package/build/components/Banner.js +13 -0
- package/build/components/Banner.tsx +20 -0
- package/build/components/CommandHeading.d.ts +6 -0
- package/build/components/CommandHeading.js +5 -0
- package/build/components/CommandHeading.tsx +10 -0
- package/build/components/CommandLayout.d.ts +7 -0
- package/build/components/CommandLayout.js +8 -0
- package/build/components/CommandLayout.tsx +17 -0
- package/build/components/Doctor.d.ts +7 -0
- package/build/components/Doctor.js +43 -0
- package/build/components/Doctor.tsx +63 -0
- package/build/components/Init.js +2 -5
- package/build/components/Init.tsx +2 -10
- package/build/doctor/Doctor.d.ts +8 -0
- package/build/doctor/Doctor.js +55 -0
- package/build/doctor/DoctorContext.d.ts +14 -0
- package/build/doctor/DoctorContext.js +48 -0
- package/build/doctor/DoctorOutput.d.ts +6 -0
- package/build/doctor/DoctorOutput.js +32 -0
- package/build/doctor/DoctorResult.d.ts +8 -0
- package/build/doctor/DoctorResult.js +1 -0
- package/build/doctor/DoctorRunner.d.ts +9 -0
- package/build/doctor/DoctorRunner.js +13 -0
- package/build/doctor/checks/ApiReachabilityCheck.d.ts +5 -0
- package/build/doctor/checks/ApiReachabilityCheck.js +41 -0
- package/build/doctor/checks/CredentialsCheck.d.ts +6 -0
- package/build/doctor/checks/CredentialsCheck.js +55 -0
- package/build/doctor/checks/JestReporterCheck.d.ts +5 -0
- package/build/doctor/checks/JestReporterCheck.js +35 -0
- package/build/doctor/checks/LocalConfigCheck.d.ts +5 -0
- package/build/doctor/checks/LocalConfigCheck.js +17 -0
- package/build/doctor/checks/MirrorAccessCheck.d.ts +12 -0
- package/build/doctor/checks/MirrorAccessCheck.js +210 -0
- package/build/esm/cli.js +21 -45
- package/build/esm/commands/CommandRunner.d.ts +7 -0
- package/build/esm/commands/CommandRunner.js +26 -0
- package/build/esm/commands/commands.d.ts +7 -0
- package/build/esm/commands/commands.js +128 -0
- package/build/esm/components/Banner.d.ts +2 -0
- package/build/esm/components/Banner.js +13 -0
- package/build/esm/components/CommandHeading.d.ts +6 -0
- package/build/esm/components/CommandHeading.js +5 -0
- package/build/esm/components/CommandLayout.d.ts +7 -0
- package/build/esm/components/CommandLayout.js +8 -0
- package/build/esm/components/Doctor.d.ts +7 -0
- package/build/esm/components/Doctor.js +43 -0
- package/build/esm/components/Init.js +2 -5
- package/build/esm/doctor/Doctor.d.ts +8 -0
- package/build/esm/doctor/Doctor.js +67 -0
- package/build/esm/doctor/DoctorContext.d.ts +14 -0
- package/build/esm/doctor/DoctorContext.js +43 -0
- package/build/esm/doctor/DoctorOutput.d.ts +6 -0
- package/build/esm/doctor/DoctorOutput.js +32 -0
- package/build/esm/doctor/DoctorResult.d.ts +8 -0
- package/build/esm/doctor/DoctorResult.js +1 -0
- package/build/esm/doctor/DoctorRunner.d.ts +9 -0
- package/build/esm/doctor/DoctorRunner.js +23 -0
- package/build/esm/doctor/checks/ApiReachabilityCheck.d.ts +5 -0
- package/build/esm/doctor/checks/ApiReachabilityCheck.js +52 -0
- package/build/esm/doctor/checks/CredentialsCheck.d.ts +6 -0
- package/build/esm/doctor/checks/CredentialsCheck.js +66 -0
- package/build/esm/doctor/checks/JestReporterCheck.d.ts +5 -0
- package/build/esm/doctor/checks/JestReporterCheck.js +46 -0
- package/build/esm/doctor/checks/LocalConfigCheck.d.ts +5 -0
- package/build/esm/doctor/checks/LocalConfigCheck.js +28 -0
- package/build/esm/doctor/checks/MirrorAccessCheck.d.ts +12 -0
- package/build/esm/doctor/checks/MirrorAccessCheck.js +224 -0
- package/build/esm/jest/JestConfigurator.js +9 -0
- package/build/esm/jest/JestReporterConfigInspector.d.ts +13 -0
- package/build/esm/jest/JestReporterConfigInspector.js +60 -0
- package/build/esm/utilities/renderBanner.d.ts +1 -0
- package/build/esm/utilities/renderBanner.js +7 -0
- package/build/jest/JestConfigurator.js +9 -0
- package/build/jest/JestReporterConfigInspector.d.ts +13 -0
- package/build/jest/JestReporterConfigInspector.js +56 -0
- package/build/utilities/renderBanner.d.ts +1 -0
- package/build/utilities/renderBanner.js +7 -0
- package/package.json +4 -3
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import JestReporterConfigInspector from '../../jest/JestReporterConfigInspector.js.js';
|
|
11
|
+
export default class JestReporterCheck {
|
|
12
|
+
run(context) {
|
|
13
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
14
|
+
const inspector = new JestReporterConfigInspector();
|
|
15
|
+
const inspection = inspector.inspect(context.cwd);
|
|
16
|
+
if (!inspection.hasPackageJson) {
|
|
17
|
+
return {
|
|
18
|
+
name: 'Jest reporter configured',
|
|
19
|
+
status: 'warn',
|
|
20
|
+
details: ['No package.json found in the current directory.'],
|
|
21
|
+
fix: 'Run `npx regressionproof init` from the project root.',
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (inspection.isInstalled && inspection.isConfigured) {
|
|
25
|
+
return {
|
|
26
|
+
name: 'Jest reporter configured',
|
|
27
|
+
status: 'ok',
|
|
28
|
+
details: ['Reporter is installed and configured.'],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const details = [];
|
|
32
|
+
if (!inspection.isInstalled) {
|
|
33
|
+
details.push('Reporter package is not installed.');
|
|
34
|
+
}
|
|
35
|
+
if (!inspection.isConfigured) {
|
|
36
|
+
details.push('Jest config does not include the reporter.');
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
name: 'Jest reporter configured',
|
|
40
|
+
status: 'warn',
|
|
41
|
+
details,
|
|
42
|
+
fix: 'Run `npx regressionproof init` or add the reporter to your Jest config.',
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
export default class LocalConfigCheck {
|
|
11
|
+
run(context) {
|
|
12
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
13
|
+
if (!context.localConfigPath) {
|
|
14
|
+
return {
|
|
15
|
+
name: 'Local project config (.regressionproof.json)',
|
|
16
|
+
status: 'warn',
|
|
17
|
+
details: [`Missing .regressionproof.json in ${context.cwd}.`],
|
|
18
|
+
fix: 'Run `npx regressionproof init` from the project root.',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
name: 'Local project config (.regressionproof.json)',
|
|
23
|
+
status: 'ok',
|
|
24
|
+
details: [`Found at ${context.localConfigPath}.`],
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import DoctorContext from '../DoctorContext.js';
|
|
2
|
+
import type { DoctorResult } from '../DoctorResult.js';
|
|
3
|
+
export default class MirrorAccessCheck {
|
|
4
|
+
run(context: DoctorContext): Promise<DoctorResult>;
|
|
5
|
+
private checkPullAccess;
|
|
6
|
+
private checkPushAccess;
|
|
7
|
+
private isNoCommitsError;
|
|
8
|
+
private isNonFastForwardError;
|
|
9
|
+
private isDivergedBranchError;
|
|
10
|
+
private trySyncMirror;
|
|
11
|
+
private getErrorMessage;
|
|
12
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { execSync } from 'child_process';
|
|
11
|
+
import fs from 'fs';
|
|
12
|
+
import { MirrorSyncer } from '@regressionproof/snapshotter';
|
|
13
|
+
import ConfigManager from '../../config/ConfigManager.js.js';
|
|
14
|
+
export default class MirrorAccessCheck {
|
|
15
|
+
run(context) {
|
|
16
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
var _a, _b, _c, _d;
|
|
18
|
+
if (!context.projectName) {
|
|
19
|
+
return {
|
|
20
|
+
name: 'Mirror directory',
|
|
21
|
+
status: 'warn',
|
|
22
|
+
details: [
|
|
23
|
+
'Unable to resolve project name from .regressionproof.json.',
|
|
24
|
+
],
|
|
25
|
+
fix: 'Run `npx regressionproof init` from the project root.',
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const configManager = new ConfigManager();
|
|
29
|
+
const mirrorPath = context.mirrorPath;
|
|
30
|
+
const credentials = configManager.loadCredentials(context.projectName);
|
|
31
|
+
if (!mirrorPath || !fs.existsSync(mirrorPath)) {
|
|
32
|
+
return {
|
|
33
|
+
name: 'Mirror directory',
|
|
34
|
+
status: 'warn',
|
|
35
|
+
details: [
|
|
36
|
+
`Mirror directory not found at ${mirrorPath !== null && mirrorPath !== void 0 ? mirrorPath : configManager.getConfigDir(context.projectName)}.`,
|
|
37
|
+
'This is normal before the first snapshot is created.',
|
|
38
|
+
],
|
|
39
|
+
fix: 'Run your tests to create the first snapshot.',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
if (!credentials) {
|
|
43
|
+
return {
|
|
44
|
+
name: 'Mirror directory',
|
|
45
|
+
status: 'warn',
|
|
46
|
+
details: ['Credentials not found; remote access not checked.'],
|
|
47
|
+
fix: 'Run `npx regressionproof invite accept <token>` (teammate) or `npx regressionproof init` (owner).',
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const authedUrl = credentials.url.replace('://', `://${credentials.token}@`);
|
|
51
|
+
const pullResult = this.checkPullAccess(authedUrl);
|
|
52
|
+
if (!pullResult.ok) {
|
|
53
|
+
return {
|
|
54
|
+
name: 'Mirror directory',
|
|
55
|
+
status: 'fail',
|
|
56
|
+
details: [
|
|
57
|
+
'Unable to access remote (pull).',
|
|
58
|
+
(_a = pullResult.message) !== null && _a !== void 0 ? _a : 'Unknown error.',
|
|
59
|
+
],
|
|
60
|
+
fix: 'Run `npx regressionproof invite accept <token>` to refresh credentials.',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const pushResult = this.checkPushAccess(mirrorPath, authedUrl);
|
|
64
|
+
if (context.fix && pushResult.status === 'warn') {
|
|
65
|
+
if (pushResult.reason === 'non_fast_forward') {
|
|
66
|
+
const fixResult = yield this.trySyncMirror(mirrorPath);
|
|
67
|
+
if (!fixResult.ok) {
|
|
68
|
+
const message = (_b = fixResult.message) !== null && _b !== void 0 ? _b : 'Unknown error.';
|
|
69
|
+
if (this.isDivergedBranchError(message)) {
|
|
70
|
+
return {
|
|
71
|
+
name: 'Mirror directory',
|
|
72
|
+
status: 'warn',
|
|
73
|
+
details: [
|
|
74
|
+
'Mirror has diverged; manual merge/rebase required.',
|
|
75
|
+
],
|
|
76
|
+
fix: 'Run `git -C <mirror> pull --rebase` (or merge) to resolve divergence.',
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
name: 'Mirror directory',
|
|
81
|
+
status: 'fail',
|
|
82
|
+
details: ['Unable to sync mirror.', message],
|
|
83
|
+
fix: 'Run `npx regressionproof doctor --fix` again or pull the mirror manually.',
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const retryResult = this.checkPushAccess(mirrorPath, authedUrl);
|
|
87
|
+
if (retryResult.status === 'ok') {
|
|
88
|
+
return {
|
|
89
|
+
name: 'Mirror directory',
|
|
90
|
+
status: 'ok',
|
|
91
|
+
details: [
|
|
92
|
+
`Mirror directory exists at ${mirrorPath}.`,
|
|
93
|
+
'Mirror synced successfully.',
|
|
94
|
+
'Remote access confirmed (pull/push).',
|
|
95
|
+
],
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
name: 'Mirror directory',
|
|
100
|
+
status: 'warn',
|
|
101
|
+
details: [
|
|
102
|
+
`Mirror directory exists at ${mirrorPath}.`,
|
|
103
|
+
'Mirror sync completed; recheck push access.',
|
|
104
|
+
],
|
|
105
|
+
fix: 'Re-run `npx regressionproof doctor` to confirm sync results.',
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
throw new Error('Doctor --fix not implemented for this mirror issue.');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (pushResult.status === 'fail') {
|
|
113
|
+
return {
|
|
114
|
+
name: 'Mirror directory',
|
|
115
|
+
status: 'fail',
|
|
116
|
+
details: [
|
|
117
|
+
'Unable to access remote (push).',
|
|
118
|
+
(_c = pushResult.message) !== null && _c !== void 0 ? _c : 'Unknown error.',
|
|
119
|
+
],
|
|
120
|
+
fix: 'Run `npx regressionproof invite accept <token>` to refresh credentials.',
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
if (pushResult.status === 'warn') {
|
|
124
|
+
return {
|
|
125
|
+
name: 'Mirror directory',
|
|
126
|
+
status: 'warn',
|
|
127
|
+
details: [
|
|
128
|
+
'Remote access confirmed (pull).',
|
|
129
|
+
(_d = pushResult.message) !== null && _d !== void 0 ? _d : 'Unknown error.',
|
|
130
|
+
],
|
|
131
|
+
fix: 'Run `npx regressionproof doctor --fix` or pull latest changes in the mirror.',
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
name: 'Mirror directory',
|
|
136
|
+
status: 'ok',
|
|
137
|
+
details: [
|
|
138
|
+
`Mirror directory exists at ${mirrorPath}.`,
|
|
139
|
+
'Remote access confirmed (pull/push).',
|
|
140
|
+
],
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
checkPullAccess(url) {
|
|
145
|
+
try {
|
|
146
|
+
execSync(`git ls-remote "${url}"`, { stdio: 'pipe' });
|
|
147
|
+
return { ok: true };
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
return {
|
|
151
|
+
ok: false,
|
|
152
|
+
message: this.getErrorMessage(err),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
checkPushAccess(mirrorPath, url) {
|
|
157
|
+
try {
|
|
158
|
+
execSync(`git -C "${mirrorPath}" push --dry-run "${url}" HEAD`, {
|
|
159
|
+
stdio: 'pipe',
|
|
160
|
+
});
|
|
161
|
+
return { status: 'ok' };
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
const message = this.getErrorMessage(err);
|
|
165
|
+
if (this.isNoCommitsError(message)) {
|
|
166
|
+
return {
|
|
167
|
+
status: 'warn',
|
|
168
|
+
message: 'No commits in mirror; push check skipped.',
|
|
169
|
+
reason: 'no_commits',
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
if (this.isNonFastForwardError(message)) {
|
|
173
|
+
return {
|
|
174
|
+
status: 'warn',
|
|
175
|
+
message: 'Remote has newer commits; mirror is behind (non-fast-forward).',
|
|
176
|
+
reason: 'non_fast_forward',
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
return { status: 'fail', message, reason: 'other' };
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
isNoCommitsError(message) {
|
|
183
|
+
const normalized = message.toLowerCase();
|
|
184
|
+
return (normalized.includes('src refspec') ||
|
|
185
|
+
normalized.includes('does not match any') ||
|
|
186
|
+
normalized.includes('no commits'));
|
|
187
|
+
}
|
|
188
|
+
isNonFastForwardError(message) {
|
|
189
|
+
const normalized = message.toLowerCase();
|
|
190
|
+
return (normalized.includes('fetch first') ||
|
|
191
|
+
normalized.includes('non-fast-forward') ||
|
|
192
|
+
normalized.includes('failed to push some refs'));
|
|
193
|
+
}
|
|
194
|
+
isDivergedBranchError(message) {
|
|
195
|
+
const normalized = message.toLowerCase();
|
|
196
|
+
return (normalized.includes('diverging branches') ||
|
|
197
|
+
normalized.includes('not possible to fast-forward'));
|
|
198
|
+
}
|
|
199
|
+
trySyncMirror(mirrorPath) {
|
|
200
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
201
|
+
try {
|
|
202
|
+
const syncer = new MirrorSyncer();
|
|
203
|
+
yield syncer.syncBlocking(mirrorPath);
|
|
204
|
+
return { ok: true };
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
return {
|
|
208
|
+
ok: false,
|
|
209
|
+
message: this.getErrorMessage(err),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
getErrorMessage(err) {
|
|
215
|
+
var _a, _b;
|
|
216
|
+
if (err && typeof err === 'object') {
|
|
217
|
+
const error = err;
|
|
218
|
+
return (((_a = error.stderr) === null || _a === void 0 ? void 0 : _a.toString().trim()) ||
|
|
219
|
+
((_b = error.stdout) === null || _b === void 0 ? void 0 : _b.toString().trim()) ||
|
|
220
|
+
error.message);
|
|
221
|
+
}
|
|
222
|
+
return String(err);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import JestReporterConfigInspector from './JestReporterConfigInspector.js.js';
|
|
3
4
|
export default class JestConfigurator {
|
|
4
5
|
constructor(cwd = process.cwd()) {
|
|
5
6
|
this.reporterPackage = '@regressionproof/jest-reporter';
|
|
@@ -7,6 +8,14 @@ export default class JestConfigurator {
|
|
|
7
8
|
}
|
|
8
9
|
configure() {
|
|
9
10
|
var _a, _b, _c;
|
|
11
|
+
const inspector = new JestReporterConfigInspector();
|
|
12
|
+
const inspection = inspector.inspect(this.cwd);
|
|
13
|
+
if (inspection.isConfigured) {
|
|
14
|
+
return {
|
|
15
|
+
configured: true,
|
|
16
|
+
location: inspection.configuredLocations[0],
|
|
17
|
+
};
|
|
18
|
+
}
|
|
10
19
|
return ((_c = (_b = (_a = this.tryConfigurePackageJson()) !== null && _a !== void 0 ? _a : this.tryConfigureJestConfig('jest.config.ts')) !== null && _b !== void 0 ? _b : this.tryConfigureJestConfig('jest.config.js')) !== null && _c !== void 0 ? _c : {
|
|
11
20
|
configured: false,
|
|
12
21
|
location: '',
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export default class JestReporterConfigInspector {
|
|
2
|
+
private reporterPackage;
|
|
3
|
+
inspect(cwd: string): InspectionResult;
|
|
4
|
+
private isConfiguredInPackageJson;
|
|
5
|
+
private isConfiguredInFile;
|
|
6
|
+
private safeReadJson;
|
|
7
|
+
}
|
|
8
|
+
export interface InspectionResult {
|
|
9
|
+
hasPackageJson: boolean;
|
|
10
|
+
isInstalled: boolean;
|
|
11
|
+
configuredLocations: string[];
|
|
12
|
+
isConfigured: boolean;
|
|
13
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
export default class JestReporterConfigInspector {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.reporterPackage = '@regressionproof/jest-reporter';
|
|
6
|
+
}
|
|
7
|
+
inspect(cwd) {
|
|
8
|
+
var _a, _b;
|
|
9
|
+
const packageJsonPath = path.join(cwd, 'package.json');
|
|
10
|
+
const hasPackageJson = fs.existsSync(packageJsonPath);
|
|
11
|
+
const packageJson = hasPackageJson
|
|
12
|
+
? this.safeReadJson(packageJsonPath)
|
|
13
|
+
: null;
|
|
14
|
+
const isInstalled = Boolean((_a = packageJson === null || packageJson === void 0 ? void 0 : packageJson.dependencies) === null || _a === void 0 ? void 0 : _a[this.reporterPackage]) ||
|
|
15
|
+
Boolean((_b = packageJson === null || packageJson === void 0 ? void 0 : packageJson.devDependencies) === null || _b === void 0 ? void 0 : _b[this.reporterPackage]);
|
|
16
|
+
const configuredLocations = [];
|
|
17
|
+
if (this.isConfiguredInPackageJson(packageJson)) {
|
|
18
|
+
configuredLocations.push('package.json');
|
|
19
|
+
}
|
|
20
|
+
if (this.isConfiguredInFile(cwd, 'jest.config.js')) {
|
|
21
|
+
configuredLocations.push('jest.config.js');
|
|
22
|
+
}
|
|
23
|
+
if (this.isConfiguredInFile(cwd, 'jest.config.ts')) {
|
|
24
|
+
configuredLocations.push('jest.config.ts');
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
hasPackageJson,
|
|
28
|
+
isInstalled,
|
|
29
|
+
configuredLocations,
|
|
30
|
+
isConfigured: configuredLocations.length > 0,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
isConfiguredInPackageJson(packageJson) {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
const reporters = (_b = (_a = packageJson === null || packageJson === void 0 ? void 0 : packageJson.jest) === null || _a === void 0 ? void 0 : _a.reporters) !== null && _b !== void 0 ? _b : [];
|
|
36
|
+
const isConfigured = Array.isArray(reporters) && reporters.includes(this.reporterPackage);
|
|
37
|
+
return isConfigured;
|
|
38
|
+
}
|
|
39
|
+
isConfiguredInFile(cwd, filename) {
|
|
40
|
+
const configPath = path.join(cwd, filename);
|
|
41
|
+
if (!fs.existsSync(configPath)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
46
|
+
return content.includes(this.reporterPackage);
|
|
47
|
+
}
|
|
48
|
+
catch (_a) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
safeReadJson(filePath) {
|
|
53
|
+
try {
|
|
54
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
55
|
+
}
|
|
56
|
+
catch (_a) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function renderBanner(): void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import JestReporterConfigInspector from './JestReporterConfigInspector.js';
|
|
3
4
|
export default class JestConfigurator {
|
|
4
5
|
cwd;
|
|
5
6
|
reporterPackage = '@regressionproof/jest-reporter';
|
|
@@ -7,6 +8,14 @@ export default class JestConfigurator {
|
|
|
7
8
|
this.cwd = cwd;
|
|
8
9
|
}
|
|
9
10
|
configure() {
|
|
11
|
+
const inspector = new JestReporterConfigInspector();
|
|
12
|
+
const inspection = inspector.inspect(this.cwd);
|
|
13
|
+
if (inspection.isConfigured) {
|
|
14
|
+
return {
|
|
15
|
+
configured: true,
|
|
16
|
+
location: inspection.configuredLocations[0],
|
|
17
|
+
};
|
|
18
|
+
}
|
|
10
19
|
return (this.tryConfigurePackageJson() ??
|
|
11
20
|
this.tryConfigureJestConfig('jest.config.ts') ??
|
|
12
21
|
this.tryConfigureJestConfig('jest.config.js') ?? {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export default class JestReporterConfigInspector {
|
|
2
|
+
private reporterPackage;
|
|
3
|
+
inspect(cwd: string): InspectionResult;
|
|
4
|
+
private isConfiguredInPackageJson;
|
|
5
|
+
private isConfiguredInFile;
|
|
6
|
+
private safeReadJson;
|
|
7
|
+
}
|
|
8
|
+
export interface InspectionResult {
|
|
9
|
+
hasPackageJson: boolean;
|
|
10
|
+
isInstalled: boolean;
|
|
11
|
+
configuredLocations: string[];
|
|
12
|
+
isConfigured: boolean;
|
|
13
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
export default class JestReporterConfigInspector {
|
|
4
|
+
reporterPackage = '@regressionproof/jest-reporter';
|
|
5
|
+
inspect(cwd) {
|
|
6
|
+
const packageJsonPath = path.join(cwd, 'package.json');
|
|
7
|
+
const hasPackageJson = fs.existsSync(packageJsonPath);
|
|
8
|
+
const packageJson = hasPackageJson
|
|
9
|
+
? this.safeReadJson(packageJsonPath)
|
|
10
|
+
: null;
|
|
11
|
+
const isInstalled = Boolean(packageJson?.dependencies?.[this.reporterPackage]) ||
|
|
12
|
+
Boolean(packageJson?.devDependencies?.[this.reporterPackage]);
|
|
13
|
+
const configuredLocations = [];
|
|
14
|
+
if (this.isConfiguredInPackageJson(packageJson)) {
|
|
15
|
+
configuredLocations.push('package.json');
|
|
16
|
+
}
|
|
17
|
+
if (this.isConfiguredInFile(cwd, 'jest.config.js')) {
|
|
18
|
+
configuredLocations.push('jest.config.js');
|
|
19
|
+
}
|
|
20
|
+
if (this.isConfiguredInFile(cwd, 'jest.config.ts')) {
|
|
21
|
+
configuredLocations.push('jest.config.ts');
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
hasPackageJson,
|
|
25
|
+
isInstalled,
|
|
26
|
+
configuredLocations,
|
|
27
|
+
isConfigured: configuredLocations.length > 0,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
isConfiguredInPackageJson(packageJson) {
|
|
31
|
+
const reporters = packageJson?.jest?.reporters ?? [];
|
|
32
|
+
const isConfigured = Array.isArray(reporters) && reporters.includes(this.reporterPackage);
|
|
33
|
+
return isConfigured;
|
|
34
|
+
}
|
|
35
|
+
isConfiguredInFile(cwd, filename) {
|
|
36
|
+
const configPath = path.join(cwd, filename);
|
|
37
|
+
if (!fs.existsSync(configPath)) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
42
|
+
return content.includes(this.reporterPackage);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
safeReadJson(filePath) {
|
|
49
|
+
try {
|
|
50
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function renderBanner(): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@regressionproof/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"watch.tsc": "tsc -w"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@regressionproof/client": "^0.
|
|
41
|
+
"@regressionproof/client": "^0.9.0",
|
|
42
|
+
"@regressionproof/snapshotter": "^0.9.0",
|
|
42
43
|
"dotenv": "^17.2.3",
|
|
43
44
|
"ink": "^5.1.0",
|
|
44
45
|
"ink-big-text": "^2.0.0",
|
|
@@ -84,5 +85,5 @@
|
|
|
84
85
|
"^#spruce/(.*)$": "<rootDir>/build/.spruce/$1"
|
|
85
86
|
}
|
|
86
87
|
},
|
|
87
|
-
"gitHead": "
|
|
88
|
+
"gitHead": "6f734949b5cd75ead7249cd6d6b4305cf350274e"
|
|
88
89
|
}
|