",
9 | "funding": {
10 | "type": "github-sponsors",
11 | "url": "https://github.com/sponsors/keplersj"
12 | },
13 | "license": "MIT",
14 | "private": false,
15 | "scripts": {
16 | "build": "tsc",
17 | "test": "npm run build; node --experimental-vm-modules node_modules/jest/bin/jest.js",
18 | "prepack": "npm run build",
19 | "prepare": "husky install"
20 | },
21 | "lint-staged": {
22 | "*": "node --experimental-vm-modules node_modules/jest/bin/jest.js --bail --findRelatedTests"
23 | },
24 | "release": {
25 | "verifyConditions": "@semantic-release/github"
26 | },
27 | "dependencies": {
28 | "create-lite-jest-runner": "^1.0.2",
29 | "emphasize": "^5.0.0",
30 | "jest-diff": "^29.0.0"
31 | },
32 | "peerDependencies": {
33 | "jest": ">= 27.0.0",
34 | "prettier": ">= 1.8"
35 | },
36 | "devDependencies": {
37 | "@commitlint/cli": "17.2.0",
38 | "@commitlint/config-conventional": "17.2.0",
39 | "@types/jest": "29.2.2",
40 | "@types/node": "18.11.9",
41 | "eslint": "8.27.0",
42 | "eslint-config-starstuff": "1.5.14",
43 | "husky": "8.0.3",
44 | "jest": "29.3.1",
45 | "jest-runner-eslint": "1.1.0",
46 | "lint-staged": "13.0.3",
47 | "prettier": "2.7.1",
48 | "ts-jest": "29.0.3",
49 | "typescript": "4.8.4"
50 | },
51 | "eslintConfig": {
52 | "extends": "starstuff/auto",
53 | "env": {
54 | "node": true
55 | }
56 | },
57 | "commitlint": {
58 | "extends": [
59 | "@commitlint/config-conventional"
60 | ]
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["starstuff"]
3 | }
4 |
--------------------------------------------------------------------------------
/src/__fixtures__/bad.json:
--------------------------------------------------------------------------------
1 | {"ohMyGodLongArray": ["prettyLongValue", "decentlyLongValue",
2 | "prettyDecentlyLongValue", "wowWowWowWhatALongValue"], "woahThisObjectIsDisapperingOffTheScreen": {"foo": "bar",
3 | "bar": "foo", "faz": false}, "truthy": true, "aNumber": 123, "aString": "hi"
4 | }
--------------------------------------------------------------------------------
/src/__fixtures__/bad.jsx:
--------------------------------------------------------------------------------
1 | function HelloWorld({greeting = "hello", greeted = '"World"', silent = false, onMouseOver,}) {
2 |
3 | if(!greeting){return null};
4 |
5 | // TODO: Don't use random in render
6 | let num = Math.floor (Math.random() * 1E+7).toString().replace(/\.\d+/ig, "")
7 |
8 | return
9 |
10 | { greeting.slice( 0, 1 ).toUpperCase() + greeting.slice(1).toLowerCase() }
11 | {greeting.endsWith(",") ? " " : ", " }
12 |
13 | { greeted }
14 |
15 | { (silent)
16 | ? "."
17 | : "!"}
18 |
19 |
;
20 |
21 | }
--------------------------------------------------------------------------------
/src/__fixtures__/good.json:
--------------------------------------------------------------------------------
1 | {
2 | "ohMyGodLongArray": [
3 | "prettyLongValue",
4 | "decentlyLongValue",
5 | "prettyDecentlyLongValue",
6 | "wowWowWowWhatALongValue"
7 | ],
8 | "woahThisObjectIsDisapperingOffTheScreen": {
9 | "foo": "bar",
10 | "bar": "foo",
11 | "faz": false
12 | },
13 | "truthy": true,
14 | "aNumber": 123,
15 | "aString": "hi"
16 | }
17 |
--------------------------------------------------------------------------------
/src/__fixtures__/good.jsx:
--------------------------------------------------------------------------------
1 | function HelloWorld({
2 | greeting = "hello",
3 | greeted = '"World"',
4 | silent = false,
5 | onMouseOver,
6 | }) {
7 | if (!greeting) {
8 | return null;
9 | }
10 |
11 | // TODO: Don't use random in render
12 | let num = Math.floor(Math.random() * 1e7)
13 | .toString()
14 | .replace(/\.\d+/gi, "");
15 |
16 | return (
17 |
22 |
23 | {greeting.slice(0, 1).toUpperCase() + greeting.slice(1).toLowerCase()}
24 |
25 | {greeting.endsWith(",") ? (
26 | " "
27 | ) : (
28 | ", "
29 | )}
30 | {greeted}
31 | {silent ? "." : "!"}
32 |
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/src/__snapshots__/run.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`jest-runner-prettier JSON bad fixture matches snapshot 1`] = `
4 | Object {
5 | "console": undefined,
6 | "coverage": undefined,
7 | "displayName": undefined,
8 | "failureMessage": "[32m- Expected[39m
9 | [31m+ Received[39m
10 |
11 | [32m- {[39m
12 | [32m- [33m\\"ohMyGodLongArray\\"[39m[32m: [[39m
13 | [32m- [36m\\"prettyLongValue\\"[39m[32m,[39m
14 | [32m- [36m\\"decentlyLongValue\\"[39m[32m,[39m
15 | [32m- [36m\\"prettyDecentlyLongValue\\"[39m[32m,[39m
16 | [32m- [36m\\"wowWowWowWhatALongValue\\"[39m[32m[39m
17 | [32m- ],[39m
18 | [32m- [33m\\"woahThisObjectIsDisapperingOffTheScreen\\"[39m[32m: {[39m
19 | [32m- [33m\\"foo\\"[39m[32m: [36m\\"bar\\"[39m[32m,[39m
20 | [32m- [33m\\"bar\\"[39m[32m: [36m\\"foo\\"[39m[32m,[39m
21 | [32m- [33m\\"faz\\"[39m[32m: [32mfalse[39m[32m[39m
22 | [32m- },[39m
23 | [32m- [33m\\"truthy\\"[39m[32m: [32mtrue[39m[32m,[39m
24 | [32m- [33m\\"aNumber\\"[39m[32m: [36m123[39m[32m,[39m
25 | [32m- [33m\\"aString\\"[39m[32m: [36m\\"hi\\"[39m[32m[39m
26 | [32m- }[39m
27 | [32m-[39m
28 | [31m+ {[33m\\"ohMyGodLongArray\\"[39m[31m: [[36m\\"prettyLongValue\\"[39m[31m, [36m\\"decentlyLongValue\\"[39m[31m,[39m
29 | [31m+ [36m\\"prettyDecentlyLongValue\\"[39m[31m, [36m\\"wowWowWowWhatALongValue\\"[39m[31m], [33m\\"woahThisObjectIsDisapperingOffTheScreen\\"[39m[31m: {[33m\\"foo\\"[39m[31m: [36m\\"bar\\"[39m[31m,[39m
30 | [31m+ [33m\\"bar\\"[39m[31m: [36m\\"foo\\"[39m[31m, [33m\\"faz\\"[39m[31m: [32mfalse[39m[31m}, [33m\\"truthy\\"[39m[31m: [32mtrue[39m[31m, [33m\\"aNumber\\"[39m[31m: [36m123[39m[31m, [33m\\"aString\\"[39m[31m: [36m\\"hi\\"[39m[31m[39m
31 | [31m+ }[39m",
32 | "leaks": false,
33 | "memoryUsage": undefined,
34 | "numFailingTests": 1,
35 | "numPassingTests": 0,
36 | "numPendingTests": 0,
37 | "numTodoTests": 0,
38 | "openHandles": Array [],
39 | "skipped": false,
40 | "snapshot": Object {
41 | "added": 0,
42 | "fileDeleted": false,
43 | "matched": 0,
44 | "unchecked": 0,
45 | "uncheckedKeys": Array [],
46 | "unmatched": 0,
47 | "updated": 0,
48 | },
49 | "testExecError": undefined,
50 | "testResults": Array [
51 | Object {
52 | "ancestorTitles": Array [],
53 | "failureDetails": Array [],
54 | "failureMessages": Array [
55 | "[32m- Expected[39m
56 | [31m+ Received[39m
57 |
58 | [32m- {[39m
59 | [32m- [33m\\"ohMyGodLongArray\\"[39m[32m: [[39m
60 | [32m- [36m\\"prettyLongValue\\"[39m[32m,[39m
61 | [32m- [36m\\"decentlyLongValue\\"[39m[32m,[39m
62 | [32m- [36m\\"prettyDecentlyLongValue\\"[39m[32m,[39m
63 | [32m- [36m\\"wowWowWowWhatALongValue\\"[39m[32m[39m
64 | [32m- ],[39m
65 | [32m- [33m\\"woahThisObjectIsDisapperingOffTheScreen\\"[39m[32m: {[39m
66 | [32m- [33m\\"foo\\"[39m[32m: [36m\\"bar\\"[39m[32m,[39m
67 | [32m- [33m\\"bar\\"[39m[32m: [36m\\"foo\\"[39m[32m,[39m
68 | [32m- [33m\\"faz\\"[39m[32m: [32mfalse[39m[32m[39m
69 | [32m- },[39m
70 | [32m- [33m\\"truthy\\"[39m[32m: [32mtrue[39m[32m,[39m
71 | [32m- [33m\\"aNumber\\"[39m[32m: [36m123[39m[32m,[39m
72 | [32m- [33m\\"aString\\"[39m[32m: [36m\\"hi\\"[39m[32m[39m
73 | [32m- }[39m
74 | [32m-[39m
75 | [31m+ {[33m\\"ohMyGodLongArray\\"[39m[31m: [[36m\\"prettyLongValue\\"[39m[31m, [36m\\"decentlyLongValue\\"[39m[31m,[39m
76 | [31m+ [36m\\"prettyDecentlyLongValue\\"[39m[31m, [36m\\"wowWowWowWhatALongValue\\"[39m[31m], [33m\\"woahThisObjectIsDisapperingOffTheScreen\\"[39m[31m: {[33m\\"foo\\"[39m[31m: [36m\\"bar\\"[39m[31m,[39m
77 | [31m+ [33m\\"bar\\"[39m[31m: [36m\\"foo\\"[39m[31m, [33m\\"faz\\"[39m[31m: [32mfalse[39m[31m}, [33m\\"truthy\\"[39m[31m: [32mtrue[39m[31m, [33m\\"aNumber\\"[39m[31m: [36m123[39m[31m, [33m\\"aString\\"[39m[31m: [36m\\"hi\\"[39m[31m[39m
78 | [31m+ }[39m",
79 | ],
80 | "fullName": "",
81 | "numPassingAsserts": 0,
82 | "status": "failed",
83 | "title": "",
84 | },
85 | ],
86 | "v8Coverage": undefined,
87 | }
88 | `;
89 |
90 | exports[`jest-runner-prettier JSON good fixture matches snapshot 1`] = `
91 | Object {
92 | "console": undefined,
93 | "coverage": undefined,
94 | "displayName": undefined,
95 | "failureMessage": undefined,
96 | "leaks": false,
97 | "memoryUsage": undefined,
98 | "numFailingTests": 0,
99 | "numPassingTests": 1,
100 | "numPendingTests": 0,
101 | "numTodoTests": 0,
102 | "openHandles": Array [],
103 | "skipped": false,
104 | "snapshot": Object {
105 | "added": 0,
106 | "fileDeleted": false,
107 | "matched": 0,
108 | "unchecked": 0,
109 | "uncheckedKeys": Array [],
110 | "unmatched": 0,
111 | "updated": 0,
112 | },
113 | "testExecError": undefined,
114 | "testResults": Array [
115 | Object {
116 | "ancestorTitles": Array [],
117 | "failureDetails": Array [],
118 | "failureMessages": Array [],
119 | "fullName": "",
120 | "numPassingAsserts": 1,
121 | "status": "passed",
122 | "title": "",
123 | },
124 | ],
125 | "v8Coverage": undefined,
126 | }
127 | `;
128 |
129 | exports[`jest-runner-prettier JSX bad fixture matches snapshot 1`] = `
130 | Object {
131 | "console": undefined,
132 | "coverage": undefined,
133 | "displayName": undefined,
134 | "failureMessage": "[32m- Expected[39m
135 | [31m+ Received[39m
136 |
137 | [32m- [32mfunction[39m[32m [34mHelloWorld[39m[32m({[39m
138 | [32m- greeting = [36m\\"hello\\"[39m[32m,[39m
139 | [32m- greeted = [36m'\\"World\\"'[39m[32m,[39m
140 | [32m- silent = [36mfalse[39m[32m,[39m
141 | [32m- onMouseOver,[39m
142 | [32m- }) {[39m
143 | [32m- [32mif[39m[32m (!greeting) {[39m
144 | [32m- [32mreturn[39m[32m [36mnull[39m[32m;[39m
145 | [32m- }[39m
146 | [31m+ [32mfunction[39m[31m [34mHelloWorld[39m[31m({greeting = [36m\\"hello\\"[39m[31m, greeted = [36m'\\"World\\"'[39m[31m, silent = [36mfalse[39m[31m, onMouseOver,}) {[39m
147 | [31m+[39m
148 | [31m+ [32mif[39m[31m(!greeting){[32mreturn[39m[31m [36mnull[39m[31m};[39m
149 | [31m+[39m
150 | [31m+ [90m// [36mTODO:[39m[31m[90m Don't use random in render[39m[31m[39m
151 | [31m+ [32mlet[39m[31m num = [34mMath[39m[31m.floor ([34mMath[39m[31m.[34mrandom[39m[31m() * [36m1E+7[39m[31m).[34mtoString[39m[31m().[34mreplace[39m[31m([36m/\\\\.\\\\d+/ig[39m[31m, [36m\\"\\"[39m[31m)[39m
152 | [31m+[39m
153 | [31m+ [32mreturn[39m[31m <[34mdiv[39m[31m [33mclassName[39m[31m=[36m'HelloWorld'[39m[31m [33mtitle[39m[31m=[36m{[39m[31m\`[33mYou[39m[31m [33mare[39m[31m [33mvisitor[39m[31m [33mnumber[39m[31m \${ [33mnum[39m[31m }\`} [33monMouseOver[39m[31m=[36m{onMouseOver}[39m[31m>[39m
154 | [31m+[39m
155 | [31m+ <[34mstrong[39m[31m>{ greeting.slice( 0, 1 ).toUpperCase() + greeting.slice(1).toLowerCase() }[34mstrong[39m[31m>[39m
156 | [31m+ {greeting.endsWith(\\",\\") ? \\" \\" : <[34mspan[39m[31m [33mstyle[39m[31m=[36m{{color:[39m[31m '\\\\[33mgrey[39m[31m'}}>\\", \\"[34mspan[39m[31m> }[39m
157 | [31m+ <[34mem[39m[31m>[39m
158 | [31m+ { greeted }[39m
159 | [31m+ [34mem[39m[31m>[39m
160 | [31m+ { (silent)[39m
161 | [31m+ ? \\".\\"[39m
162 | [31m+ : \\"!\\"}[39m
163 |
164 | [32m- [90m// [36mTODO:[39m[32m[90m Don't use random in render[39m[32m[39m
165 | [32m- [32mlet[39m[32m num = [34mMath[39m[32m.[34mfloor[39m[32m([34mMath[39m[32m.[34mrandom[39m[32m() * [36m1e7[39m[32m)[39m
166 | [32m- .[34mtoString[39m[32m()[39m
167 | [32m- .[34mreplace[39m[32m([36m/\\\\.\\\\d+/gi[39m[32m, [36m\\"\\"[39m[32m);[39m
168 | [31m+ [34mdiv[39m[31m>;[39m
169 |
170 | [32m- [32mreturn[39m[32m ([39m
171 | [32m- <[34mdiv[39m[32m[39m
172 | [32m- [33mclassName[39m[32m=[36m\\"HelloWorld\\"[39m[32m[39m
173 | [32m- [33mtitle[39m[32m=[36m{[39m[32m\`[33mYou[39m[32m [33mare[39m[32m [33mvisitor[39m[32m [33mnumber[39m[32m \${[33mnum[39m[32m}\`}[39m
174 | [32m- [33monMouseOver[39m[32m=[36m{onMouseOver}[39m[32m[39m
175 | [32m- >[39m
176 | [32m- <[34mstrong[39m[32m>[39m
177 | [32m- {greeting.slice(0, 1).toUpperCase() + greeting.slice(1).toLowerCase()}[39m
178 | [32m- [34mstrong[39m[32m>[39m
179 | [32m- {greeting.endsWith(\\",\\") ? ([39m
180 | [32m- \\" \\"[39m
181 | [32m- ) : ([39m
182 | [32m- <[34mspan[39m[32m [33mstyle[39m[32m=[36m{{[39m[32m [33mcolor:[39m[32m \\"[33mgrey[39m[32m\\" }}>\\", \\"[34mspan[39m[32m>[39m
183 | [32m- )}[39m
184 | [32m- <[34mem[39m[32m>{greeted}[34mem[39m[32m>[39m
185 | [32m- {silent ? \\".\\" : \\"!\\"}[39m
186 | [32m- [34mdiv[39m[32m>[39m
187 | [32m- );[39m
188 | [2m }[22m
189 | [32m-[39m",
190 | "leaks": false,
191 | "memoryUsage": undefined,
192 | "numFailingTests": 1,
193 | "numPassingTests": 0,
194 | "numPendingTests": 0,
195 | "numTodoTests": 0,
196 | "openHandles": Array [],
197 | "skipped": false,
198 | "snapshot": Object {
199 | "added": 0,
200 | "fileDeleted": false,
201 | "matched": 0,
202 | "unchecked": 0,
203 | "uncheckedKeys": Array [],
204 | "unmatched": 0,
205 | "updated": 0,
206 | },
207 | "testExecError": undefined,
208 | "testResults": Array [
209 | Object {
210 | "ancestorTitles": Array [],
211 | "failureDetails": Array [],
212 | "failureMessages": Array [
213 | "[32m- Expected[39m
214 | [31m+ Received[39m
215 |
216 | [32m- [32mfunction[39m[32m [34mHelloWorld[39m[32m({[39m
217 | [32m- greeting = [36m\\"hello\\"[39m[32m,[39m
218 | [32m- greeted = [36m'\\"World\\"'[39m[32m,[39m
219 | [32m- silent = [36mfalse[39m[32m,[39m
220 | [32m- onMouseOver,[39m
221 | [32m- }) {[39m
222 | [32m- [32mif[39m[32m (!greeting) {[39m
223 | [32m- [32mreturn[39m[32m [36mnull[39m[32m;[39m
224 | [32m- }[39m
225 | [31m+ [32mfunction[39m[31m [34mHelloWorld[39m[31m({greeting = [36m\\"hello\\"[39m[31m, greeted = [36m'\\"World\\"'[39m[31m, silent = [36mfalse[39m[31m, onMouseOver,}) {[39m
226 | [31m+[39m
227 | [31m+ [32mif[39m[31m(!greeting){[32mreturn[39m[31m [36mnull[39m[31m};[39m
228 | [31m+[39m
229 | [31m+ [90m// [36mTODO:[39m[31m[90m Don't use random in render[39m[31m[39m
230 | [31m+ [32mlet[39m[31m num = [34mMath[39m[31m.floor ([34mMath[39m[31m.[34mrandom[39m[31m() * [36m1E+7[39m[31m).[34mtoString[39m[31m().[34mreplace[39m[31m([36m/\\\\.\\\\d+/ig[39m[31m, [36m\\"\\"[39m[31m)[39m
231 | [31m+[39m
232 | [31m+ [32mreturn[39m[31m <[34mdiv[39m[31m [33mclassName[39m[31m=[36m'HelloWorld'[39m[31m [33mtitle[39m[31m=[36m{[39m[31m\`[33mYou[39m[31m [33mare[39m[31m [33mvisitor[39m[31m [33mnumber[39m[31m \${ [33mnum[39m[31m }\`} [33monMouseOver[39m[31m=[36m{onMouseOver}[39m[31m>[39m
233 | [31m+[39m
234 | [31m+ <[34mstrong[39m[31m>{ greeting.slice( 0, 1 ).toUpperCase() + greeting.slice(1).toLowerCase() }[34mstrong[39m[31m>[39m
235 | [31m+ {greeting.endsWith(\\",\\") ? \\" \\" : <[34mspan[39m[31m [33mstyle[39m[31m=[36m{{color:[39m[31m '\\\\[33mgrey[39m[31m'}}>\\", \\"[34mspan[39m[31m> }[39m
236 | [31m+ <[34mem[39m[31m>[39m
237 | [31m+ { greeted }[39m
238 | [31m+ [34mem[39m[31m>[39m
239 | [31m+ { (silent)[39m
240 | [31m+ ? \\".\\"[39m
241 | [31m+ : \\"!\\"}[39m
242 |
243 | [32m- [90m// [36mTODO:[39m[32m[90m Don't use random in render[39m[32m[39m
244 | [32m- [32mlet[39m[32m num = [34mMath[39m[32m.[34mfloor[39m[32m([34mMath[39m[32m.[34mrandom[39m[32m() * [36m1e7[39m[32m)[39m
245 | [32m- .[34mtoString[39m[32m()[39m
246 | [32m- .[34mreplace[39m[32m([36m/\\\\.\\\\d+/gi[39m[32m, [36m\\"\\"[39m[32m);[39m
247 | [31m+ [34mdiv[39m[31m>;[39m
248 |
249 | [32m- [32mreturn[39m[32m ([39m
250 | [32m- <[34mdiv[39m[32m[39m
251 | [32m- [33mclassName[39m[32m=[36m\\"HelloWorld\\"[39m[32m[39m
252 | [32m- [33mtitle[39m[32m=[36m{[39m[32m\`[33mYou[39m[32m [33mare[39m[32m [33mvisitor[39m[32m [33mnumber[39m[32m \${[33mnum[39m[32m}\`}[39m
253 | [32m- [33monMouseOver[39m[32m=[36m{onMouseOver}[39m[32m[39m
254 | [32m- >[39m
255 | [32m- <[34mstrong[39m[32m>[39m
256 | [32m- {greeting.slice(0, 1).toUpperCase() + greeting.slice(1).toLowerCase()}[39m
257 | [32m- [34mstrong[39m[32m>[39m
258 | [32m- {greeting.endsWith(\\",\\") ? ([39m
259 | [32m- \\" \\"[39m
260 | [32m- ) : ([39m
261 | [32m- <[34mspan[39m[32m [33mstyle[39m[32m=[36m{{[39m[32m [33mcolor:[39m[32m \\"[33mgrey[39m[32m\\" }}>\\", \\"[34mspan[39m[32m>[39m
262 | [32m- )}[39m
263 | [32m- <[34mem[39m[32m>{greeted}[34mem[39m[32m>[39m
264 | [32m- {silent ? \\".\\" : \\"!\\"}[39m
265 | [32m- [34mdiv[39m[32m>[39m
266 | [32m- );[39m
267 | [2m }[22m
268 | [32m-[39m",
269 | ],
270 | "fullName": "",
271 | "numPassingAsserts": 0,
272 | "status": "failed",
273 | "title": "",
274 | },
275 | ],
276 | "v8Coverage": undefined,
277 | }
278 | `;
279 |
280 | exports[`jest-runner-prettier JSX good fixture matches snapshot 1`] = `
281 | Object {
282 | "console": undefined,
283 | "coverage": undefined,
284 | "displayName": undefined,
285 | "failureMessage": undefined,
286 | "leaks": false,
287 | "memoryUsage": undefined,
288 | "numFailingTests": 0,
289 | "numPassingTests": 1,
290 | "numPendingTests": 0,
291 | "numTodoTests": 0,
292 | "openHandles": Array [],
293 | "skipped": false,
294 | "snapshot": Object {
295 | "added": 0,
296 | "fileDeleted": false,
297 | "matched": 0,
298 | "unchecked": 0,
299 | "uncheckedKeys": Array [],
300 | "unmatched": 0,
301 | "updated": 0,
302 | },
303 | "testExecError": undefined,
304 | "testResults": Array [
305 | Object {
306 | "ancestorTitles": Array [],
307 | "failureDetails": Array [],
308 | "failureMessages": Array [],
309 | "fullName": "",
310 | "numPassingAsserts": 1,
311 | "status": "passed",
312 | "title": "",
313 | },
314 | ],
315 | "v8Coverage": undefined,
316 | }
317 | `;
318 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import createJestRunner from "create-lite-jest-runner";
2 | import run from "./run.js";
3 |
4 | export default createJestRunner(run);
5 |
--------------------------------------------------------------------------------
/src/run.test.ts:
--------------------------------------------------------------------------------
1 | import path from "node:path";
2 | import run from "./run";
3 | import { fileURLToPath } from "node:url";
4 |
5 | const __filename = fileURLToPath(import.meta.url);
6 | const __dirname = path.dirname(__filename);
7 |
8 | // Remove undeterministic data from test reports
9 | expect.addSnapshotSerializer({
10 | print: (value: any, serialize) => {
11 | delete value.perfStats;
12 | delete value.testFilePath;
13 | for (const result of value.testResults) {
14 | delete result.duration;
15 | }
16 | return serialize(value);
17 | },
18 | test: (value) =>
19 | value && value.perfStats && value.testFilePath && value.testResults,
20 | });
21 |
22 | describe("jest-runner-prettier", () => {
23 | describe("JSON", () => {
24 | describe("good fixture", () => {
25 | it("matches snapshot", () => {
26 | return run({
27 | testPath: path.join(__dirname, "__fixtures__", `good.json`),
28 | }).then((result) => expect(result).toMatchSnapshot());
29 | });
30 | });
31 |
32 | describe("bad fixture", () => {
33 | it("matches snapshot", () => {
34 | return run({
35 | testPath: path.join(__dirname, "__fixtures__", `bad.json`),
36 | }).then((result) => expect(result).toMatchSnapshot());
37 | });
38 | });
39 | });
40 |
41 | describe("JSX", () => {
42 | describe("good fixture", () => {
43 | it("matches snapshot", () => {
44 | return run({
45 | testPath: path.join(__dirname, "__fixtures__", `good.jsx`),
46 | }).then((result) => expect(result).toMatchSnapshot());
47 | });
48 | });
49 |
50 | describe("bad fixture", () => {
51 | it("matches snapshot", () => {
52 | return run({
53 | testPath: path.join(__dirname, "__fixtures__", `bad.jsx`),
54 | }).then((result) => expect(result).toMatchSnapshot());
55 | });
56 | });
57 | });
58 | });
59 |
--------------------------------------------------------------------------------
/src/run.ts:
--------------------------------------------------------------------------------
1 | import { TestResult } from "@jest/test-result";
2 | import { emphasize } from "emphasize";
3 | import { pass, fail } from "create-lite-jest-runner";
4 | import * as fs from "node:fs/promises";
5 | import { diff } from "jest-diff";
6 | import prettier from "prettier";
7 |
8 | interface Parameters {
9 | testPath: string;
10 | }
11 |
12 | export default async ({ testPath }: Parameters): Promise => {
13 | const start = Date.now();
14 | const contents = await fs.readFile(testPath, "utf8");
15 | const config = await prettier.resolveConfig(testPath);
16 |
17 | const prettierConfig = {
18 | ...config,
19 | filepath: testPath,
20 | };
21 |
22 | const isPretty = prettier.check(contents, prettierConfig);
23 | if (isPretty) {
24 | return pass({
25 | start,
26 | end: Date.now(),
27 | test: { path: testPath },
28 | });
29 | }
30 |
31 | const formatted = prettier.format(contents, prettierConfig);
32 |
33 | return fail({
34 | start,
35 | end: Date.now(),
36 | test: {
37 | path: testPath,
38 | errorMessage: diff(
39 | emphasize.highlightAuto(formatted).value,
40 | emphasize.highlightAuto(contents).value,
41 | {
42 | expand: false,
43 | }
44 | ) as string | undefined,
45 | },
46 | });
47 | };
48 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */
4 |
5 | /* Projects */
6 | // "incremental": true, /* Enable incremental compilation */
7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
8 | // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12 |
13 | /* Language and Environment */
14 | "target": "esnext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16 | // "jsx": "preserve", /* Specify what JSX code is generated. */
17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
22 | // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
25 |
26 | /* Modules */
27 | "module": "esnext" /* Specify what module code is generated. */,
28 | // "rootDir": "./", /* Specify the root folder within your source files. */
29 | "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
30 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
31 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
32 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
33 | // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
34 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */
35 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
36 | // "resolveJsonModule": true, /* Enable importing .json files */
37 | // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */
38 |
39 | /* JavaScript Support */
40 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
41 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
42 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
43 |
44 | /* Emit */
45 | "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
46 | "declarationMap": true /* Create sourcemaps for d.ts files. */,
47 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
48 | "sourceMap": true /* Create source map files for emitted JavaScript files. */,
49 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
50 | "outDir": "./dist/" /* Specify an output folder for all emitted files. */,
51 | // "removeComments": true, /* Disable emitting comments. */
52 | // "noEmit": true, /* Disable emitting files from a compilation. */
53 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
54 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
55 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
56 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
58 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
59 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
60 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
61 | // "newLine": "crlf", /* Set the newline character for emitting files. */
62 | // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
63 | // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
64 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
65 | // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
66 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
67 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
68 |
69 | /* Interop Constraints */
70 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
71 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
72 | "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
73 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
74 | "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
75 |
76 | /* Type Checking */
77 | "strict": true /* Enable all strict type-checking options. */,
78 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
79 | // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
80 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
81 | // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
82 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
83 | // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
84 | // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
85 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
86 | // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
87 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
88 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
89 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
90 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
91 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
92 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
93 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
94 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
95 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
96 |
97 | /* Completeness */
98 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
99 | "skipLibCheck": true /* Skip type checking all .d.ts files. */
100 | }
101 | }
102 |
--------------------------------------------------------------------------------