@regardio/dev 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/LICENSE +9 -0
- package/README.md +416 -0
- package/dist/bin/exec-clean.d.ts +3 -0
- package/dist/bin/exec-clean.d.ts.map +1 -0
- package/dist/bin/exec-clean.js +18 -0
- package/dist/bin/exec-husky.d.ts +3 -0
- package/dist/bin/exec-husky.d.ts.map +1 -0
- package/dist/bin/exec-husky.js +8 -0
- package/dist/bin/exec-p.d.ts +3 -0
- package/dist/bin/exec-p.d.ts.map +1 -0
- package/dist/bin/exec-p.js +8 -0
- package/dist/bin/exec-s.d.ts +3 -0
- package/dist/bin/exec-s.d.ts.map +1 -0
- package/dist/bin/exec-s.js +8 -0
- package/dist/bin/exec-ts.d.ts +3 -0
- package/dist/bin/exec-ts.d.ts.map +1 -0
- package/dist/bin/exec-ts.js +28 -0
- package/dist/bin/exec-tsc.d.ts +3 -0
- package/dist/bin/exec-tsc.d.ts.map +1 -0
- package/dist/bin/exec-tsc.js +8 -0
- package/dist/bin/flow-branch.d.ts +3 -0
- package/dist/bin/flow-branch.d.ts.map +1 -0
- package/dist/bin/flow-branch.js +27 -0
- package/dist/bin/flow-version.d.ts +3 -0
- package/dist/bin/flow-version.d.ts.map +1 -0
- package/dist/bin/flow-version.js +83 -0
- package/dist/bin/lint-biome.d.ts +3 -0
- package/dist/bin/lint-biome.d.ts.map +1 -0
- package/dist/bin/lint-biome.js +8 -0
- package/dist/bin/lint-commit.d.ts +3 -0
- package/dist/bin/lint-commit.d.ts.map +1 -0
- package/dist/bin/lint-commit.js +8 -0
- package/dist/bin/lint-md.d.ts +3 -0
- package/dist/bin/lint-md.d.ts.map +1 -0
- package/dist/bin/lint-md.js +10 -0
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +101 -0
- package/dist/playwright/index.d.ts +10 -0
- package/dist/playwright/index.d.ts.map +1 -0
- package/dist/playwright/index.js +42 -0
- package/dist/playwright/index.test.d.ts +2 -0
- package/dist/playwright/index.test.d.ts.map +1 -0
- package/dist/playwright/index.test.js +55 -0
- package/dist/testing/setup-react.d.ts +2 -0
- package/dist/testing/setup-react.d.ts.map +1 -0
- package/dist/testing/setup-react.js +1 -0
- package/dist/vitest/node.d.ts +3 -0
- package/dist/vitest/node.d.ts.map +1 -0
- package/dist/vitest/node.js +6 -0
- package/dist/vitest/react.d.ts +3 -0
- package/dist/vitest/react.d.ts.map +1 -0
- package/dist/vitest/react.js +7 -0
- package/package.json +104 -0
- package/src/bin/exec-clean.ts +24 -0
- package/src/bin/exec-husky.ts +13 -0
- package/src/bin/exec-p.ts +13 -0
- package/src/bin/exec-s.ts +13 -0
- package/src/bin/exec-ts.ts +39 -0
- package/src/bin/exec-tsc.ts +13 -0
- package/src/bin/lint-biome.ts +13 -0
- package/src/bin/lint-commit.ts +13 -0
- package/src/bin/lint-md.ts +16 -0
- package/src/biome/preset.json +297 -0
- package/src/commitlint/commitlint.cjs +26 -0
- package/src/config.test.ts +129 -0
- package/src/markdownlint/markdownlint.json +9 -0
- package/src/playwright/index.test.ts +73 -0
- package/src/playwright/index.ts +63 -0
- package/src/testing/setup-react.ts +8 -0
- package/src/typescript/base.json +50 -0
- package/src/typescript/build.json +19 -0
- package/src/typescript/react.json +8 -0
- package/src/vitest/node.ts +12 -0
- package/src/vitest/react.ts +15 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* lint-biome: Run Biome (formatter/linter) against the codebase.
|
|
4
|
+
* Usage: lint-biome [biome args...]
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from 'node:child_process';
|
|
7
|
+
import { createRequire } from 'node:module';
|
|
8
|
+
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
const bin = require.resolve('@biomejs/biome/bin/biome');
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
const child = spawn(process.execPath, [bin, ...args], { stdio: 'inherit' });
|
|
13
|
+
child.on('exit', (code) => process.exit(code ?? 0));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* lint-commit: Run commitlint against commit messages.
|
|
4
|
+
* Usage: lint-commit [commitlint args...]
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from 'node:child_process';
|
|
7
|
+
import { createRequire } from 'node:module';
|
|
8
|
+
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
const bin = require.resolve('@commitlint/cli/cli.js');
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
const child = spawn(process.execPath, [bin, ...args], { stdio: 'inherit' });
|
|
13
|
+
child.on('exit', (code) => process.exit(code ?? 0));
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* lint-md: Run markdownlint-cli2 to lint and fix Markdown files.
|
|
4
|
+
* Usage: lint-md [markdownlint-cli2 args...]
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from 'node:child_process';
|
|
7
|
+
import { createRequire } from 'node:module';
|
|
8
|
+
import { dirname, join } from 'node:path';
|
|
9
|
+
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
// Resolve to any exported file to find the package directory
|
|
12
|
+
const packageDir = dirname(require.resolve('markdownlint-cli2'));
|
|
13
|
+
const bin = join(packageDir, 'markdownlint-cli2-bin.mjs');
|
|
14
|
+
const args = process.argv.slice(2);
|
|
15
|
+
const child = spawn(process.execPath, [bin, ...args], { stdio: 'inherit' });
|
|
16
|
+
child.on('exit', (code) => process.exit(code ?? 0));
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/latest/schema.json",
|
|
3
|
+
"assist": {
|
|
4
|
+
"actions": {
|
|
5
|
+
"source": {
|
|
6
|
+
"organizeImports": "on",
|
|
7
|
+
"useSortedAttributes": "on",
|
|
8
|
+
"useSortedKeys": "on",
|
|
9
|
+
"useSortedProperties": "on"
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"css": {
|
|
14
|
+
"assist": {
|
|
15
|
+
"enabled": true
|
|
16
|
+
},
|
|
17
|
+
"formatter": {
|
|
18
|
+
"enabled": true,
|
|
19
|
+
"indentStyle": "space",
|
|
20
|
+
"indentWidth": 2,
|
|
21
|
+
"lineEnding": "lf",
|
|
22
|
+
"lineWidth": 100,
|
|
23
|
+
"quoteStyle": "double"
|
|
24
|
+
},
|
|
25
|
+
"linter": {
|
|
26
|
+
"enabled": true
|
|
27
|
+
},
|
|
28
|
+
"parser": {
|
|
29
|
+
"cssModules": true,
|
|
30
|
+
"tailwindDirectives": true
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"files": {
|
|
34
|
+
"ignoreUnknown": false,
|
|
35
|
+
"maxSize": 1048576
|
|
36
|
+
},
|
|
37
|
+
"formatter": {
|
|
38
|
+
"attributePosition": "multiline",
|
|
39
|
+
"bracketSpacing": true,
|
|
40
|
+
"enabled": true,
|
|
41
|
+
"expand": "auto",
|
|
42
|
+
"formatWithErrors": true,
|
|
43
|
+
"indentStyle": "space",
|
|
44
|
+
"indentWidth": 2,
|
|
45
|
+
"lineEnding": "lf",
|
|
46
|
+
"lineWidth": 100,
|
|
47
|
+
"useEditorconfig": true
|
|
48
|
+
},
|
|
49
|
+
"graphql": {
|
|
50
|
+
"assist": {
|
|
51
|
+
"enabled": true
|
|
52
|
+
},
|
|
53
|
+
"formatter": {
|
|
54
|
+
"enabled": false,
|
|
55
|
+
"indentStyle": "space",
|
|
56
|
+
"indentWidth": 2,
|
|
57
|
+
"lineEnding": "lf",
|
|
58
|
+
"lineWidth": 100,
|
|
59
|
+
"quoteStyle": "double"
|
|
60
|
+
},
|
|
61
|
+
"linter": {
|
|
62
|
+
"enabled": true
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"html": {
|
|
66
|
+
"assist": {
|
|
67
|
+
"enabled": true
|
|
68
|
+
},
|
|
69
|
+
"experimentalFullSupportEnabled": true,
|
|
70
|
+
"formatter": {
|
|
71
|
+
"attributePosition": "multiline",
|
|
72
|
+
"bracketSameLine": false,
|
|
73
|
+
"enabled": true,
|
|
74
|
+
"indentScriptAndStyle": true,
|
|
75
|
+
"indentStyle": "space",
|
|
76
|
+
"indentWidth": 2,
|
|
77
|
+
"lineEnding": "lf",
|
|
78
|
+
"lineWidth": 100
|
|
79
|
+
},
|
|
80
|
+
"linter": {
|
|
81
|
+
"enabled": true
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"javascript": {
|
|
85
|
+
"assist": {
|
|
86
|
+
"enabled": true
|
|
87
|
+
},
|
|
88
|
+
"formatter": {
|
|
89
|
+
"arrowParentheses": "always",
|
|
90
|
+
"attributePosition": "multiline",
|
|
91
|
+
"bracketSameLine": false,
|
|
92
|
+
"bracketSpacing": true,
|
|
93
|
+
"enabled": true,
|
|
94
|
+
"expand": "auto",
|
|
95
|
+
"indentStyle": "space",
|
|
96
|
+
"indentWidth": 2,
|
|
97
|
+
"jsxQuoteStyle": "double",
|
|
98
|
+
"lineEnding": "lf",
|
|
99
|
+
"lineWidth": 100,
|
|
100
|
+
"quoteProperties": "asNeeded",
|
|
101
|
+
"quoteStyle": "single",
|
|
102
|
+
"semicolons": "always",
|
|
103
|
+
"trailingCommas": "all"
|
|
104
|
+
},
|
|
105
|
+
"globals": [],
|
|
106
|
+
"jsxRuntime": "transparent",
|
|
107
|
+
"linter": {
|
|
108
|
+
"enabled": true
|
|
109
|
+
},
|
|
110
|
+
"parser": {
|
|
111
|
+
"jsxEverywhere": true,
|
|
112
|
+
"unsafeParameterDecoratorsEnabled": false
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"json": {
|
|
116
|
+
"assist": {
|
|
117
|
+
"enabled": true
|
|
118
|
+
},
|
|
119
|
+
"formatter": {
|
|
120
|
+
"bracketSpacing": true,
|
|
121
|
+
"enabled": true,
|
|
122
|
+
"expand": "auto",
|
|
123
|
+
"indentStyle": "space",
|
|
124
|
+
"indentWidth": 2,
|
|
125
|
+
"lineEnding": "lf",
|
|
126
|
+
"lineWidth": 100,
|
|
127
|
+
"trailingCommas": "none"
|
|
128
|
+
},
|
|
129
|
+
"linter": {
|
|
130
|
+
"enabled": true
|
|
131
|
+
},
|
|
132
|
+
"parser": {
|
|
133
|
+
"allowComments": true,
|
|
134
|
+
"allowTrailingCommas": true
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
"linter": {
|
|
138
|
+
"enabled": true,
|
|
139
|
+
"rules": {
|
|
140
|
+
"a11y": {
|
|
141
|
+
"noSvgWithoutTitle": "off",
|
|
142
|
+
"recommended": true,
|
|
143
|
+
"useGenericFontNames": "error"
|
|
144
|
+
},
|
|
145
|
+
"complexity": {
|
|
146
|
+
"noArguments": "error",
|
|
147
|
+
"noCommaOperator": "error",
|
|
148
|
+
"recommended": true,
|
|
149
|
+
"useNumericLiterals": "error"
|
|
150
|
+
},
|
|
151
|
+
"correctness": {
|
|
152
|
+
"noInvalidPositionAtImportRule": "off",
|
|
153
|
+
"noUnknownFunction": "off",
|
|
154
|
+
"noUnknownTypeSelector": "off",
|
|
155
|
+
"recommended": true,
|
|
156
|
+
"useUniqueElementIds": {
|
|
157
|
+
"level": "error",
|
|
158
|
+
"options": {
|
|
159
|
+
"excludedComponents": [
|
|
160
|
+
"circle",
|
|
161
|
+
"clipPath",
|
|
162
|
+
"defs",
|
|
163
|
+
"ellipse",
|
|
164
|
+
"filter",
|
|
165
|
+
"g",
|
|
166
|
+
"input",
|
|
167
|
+
"line",
|
|
168
|
+
"linearGradient",
|
|
169
|
+
"mask",
|
|
170
|
+
"path",
|
|
171
|
+
"pattern",
|
|
172
|
+
"polygon",
|
|
173
|
+
"polyline",
|
|
174
|
+
"radialGradient",
|
|
175
|
+
"rect",
|
|
176
|
+
"stop",
|
|
177
|
+
"svg",
|
|
178
|
+
"symbol",
|
|
179
|
+
"Trans"
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
"useValidTypeof": "error"
|
|
184
|
+
},
|
|
185
|
+
"nursery": {
|
|
186
|
+
"recommended": true
|
|
187
|
+
},
|
|
188
|
+
"performance": {
|
|
189
|
+
"noBarrelFile": "error",
|
|
190
|
+
"recommended": true
|
|
191
|
+
},
|
|
192
|
+
"recommended": true,
|
|
193
|
+
"security": {
|
|
194
|
+
"noDangerouslySetInnerHtml": "off",
|
|
195
|
+
"recommended": true
|
|
196
|
+
},
|
|
197
|
+
"style": {
|
|
198
|
+
"noInferrableTypes": "error",
|
|
199
|
+
"noNonNullAssertion": "error",
|
|
200
|
+
"noParameterAssign": "error",
|
|
201
|
+
"noUnusedTemplateLiteral": "error",
|
|
202
|
+
"noUselessElse": "error",
|
|
203
|
+
"recommended": true,
|
|
204
|
+
"useAsConstAssertion": "error",
|
|
205
|
+
"useConst": "error",
|
|
206
|
+
"useDefaultParameterLast": "error",
|
|
207
|
+
"useEnumInitializers": "error",
|
|
208
|
+
"useExponentiationOperator": "error",
|
|
209
|
+
"useExportType": "error",
|
|
210
|
+
"useImportType": "error",
|
|
211
|
+
"useLiteralEnumMembers": "error",
|
|
212
|
+
"useNodejsImportProtocol": "error",
|
|
213
|
+
"useNumberNamespace": "error",
|
|
214
|
+
"useSelfClosingElements": "error",
|
|
215
|
+
"useShorthandFunctionType": "error",
|
|
216
|
+
"useSingleVarDeclarator": "error",
|
|
217
|
+
"useTemplate": "error"
|
|
218
|
+
},
|
|
219
|
+
"suspicious": {
|
|
220
|
+
"noApproximativeNumericConstant": "error",
|
|
221
|
+
"noArrayIndexKey": "error",
|
|
222
|
+
"noAssignInExpressions": "error",
|
|
223
|
+
"noAsyncPromiseExecutor": "error",
|
|
224
|
+
"noCatchAssign": "error",
|
|
225
|
+
"noClassAssign": "error",
|
|
226
|
+
"noCommentText": "error",
|
|
227
|
+
"noCompareNegZero": "error",
|
|
228
|
+
"noConfusingLabels": "error",
|
|
229
|
+
"noConfusingVoidType": "error",
|
|
230
|
+
"noConsole": "off",
|
|
231
|
+
"noConstEnum": "error",
|
|
232
|
+
"noControlCharactersInRegex": "error",
|
|
233
|
+
"noDebugger": "error",
|
|
234
|
+
"noDoubleEquals": "error",
|
|
235
|
+
"noDuplicateAtImportRules": "error",
|
|
236
|
+
"noDuplicateCase": "error",
|
|
237
|
+
"noDuplicateClassMembers": "error",
|
|
238
|
+
"noDuplicateFontNames": "error",
|
|
239
|
+
"noDuplicateJsxProps": "error",
|
|
240
|
+
"noDuplicateObjectKeys": "error",
|
|
241
|
+
"noDuplicateParameters": "error",
|
|
242
|
+
"noDuplicateSelectorsKeyframeBlock": "error",
|
|
243
|
+
"noDuplicateTestHooks": "error",
|
|
244
|
+
"noEmptyBlock": "error",
|
|
245
|
+
"noEmptyBlockStatements": "off",
|
|
246
|
+
"noEmptyInterface": "error",
|
|
247
|
+
"noEvolvingTypes": "error",
|
|
248
|
+
"noExplicitAny": "error",
|
|
249
|
+
"noExportsInTest": "error",
|
|
250
|
+
"noExtraNonNullAssertion": "error",
|
|
251
|
+
"noFallthroughSwitchClause": "error",
|
|
252
|
+
"noFocusedTests": "error",
|
|
253
|
+
"noFunctionAssign": "error",
|
|
254
|
+
"noGlobalAssign": "error",
|
|
255
|
+
"noGlobalIsFinite": "error",
|
|
256
|
+
"noGlobalIsNan": "error",
|
|
257
|
+
"noImplicitAnyLet": "error",
|
|
258
|
+
"noImportAssign": "error",
|
|
259
|
+
"noImportantInKeyframe": "error",
|
|
260
|
+
"noLabelVar": "error",
|
|
261
|
+
"noMisleadingCharacterClass": "error",
|
|
262
|
+
"noMisleadingInstantiator": "error",
|
|
263
|
+
"noMisplacedAssertion": "error",
|
|
264
|
+
"noMisrefactoredShorthandAssign": "error",
|
|
265
|
+
"noPrototypeBuiltins": "error",
|
|
266
|
+
"noReactSpecificProps": "off",
|
|
267
|
+
"noRedeclare": "error",
|
|
268
|
+
"noRedundantUseStrict": "error",
|
|
269
|
+
"noSelfCompare": "error",
|
|
270
|
+
"noShadowRestrictedNames": "error",
|
|
271
|
+
"noShorthandPropertyOverrides": "error",
|
|
272
|
+
"noSkippedTests": "error",
|
|
273
|
+
"noSparseArray": "error",
|
|
274
|
+
"noSuspiciousSemicolonInJsx": "error",
|
|
275
|
+
"noThenProperty": "error",
|
|
276
|
+
"noUnknownAtRules": "off",
|
|
277
|
+
"noUnsafeDeclarationMerging": "error",
|
|
278
|
+
"noUnsafeNegation": "error",
|
|
279
|
+
"recommended": true,
|
|
280
|
+
"useAwait": "error",
|
|
281
|
+
"useDefaultSwitchClauseLast": "error",
|
|
282
|
+
"useErrorMessage": "error",
|
|
283
|
+
"useGetterReturn": "error",
|
|
284
|
+
"useIsArray": "error",
|
|
285
|
+
"useNamespaceKeyword": "error",
|
|
286
|
+
"useNumberToFixedDigitsArgument": "error"
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
"root": true,
|
|
291
|
+
"vcs": {
|
|
292
|
+
"clientKind": "git",
|
|
293
|
+
"defaultBranch": "main",
|
|
294
|
+
"enabled": true,
|
|
295
|
+
"useIgnoreFile": true
|
|
296
|
+
}
|
|
297
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
extends: ['@commitlint/config-conventional'],
|
|
3
|
+
rules: {
|
|
4
|
+
'body-leading-blank': [1, 'always'],
|
|
5
|
+
'footer-leading-blank': [1, 'always'],
|
|
6
|
+
'header-max-length': [2, 'always', 100],
|
|
7
|
+
'type-enum': [
|
|
8
|
+
2,
|
|
9
|
+
'always',
|
|
10
|
+
[
|
|
11
|
+
'BREAKING CHANGE',
|
|
12
|
+
'build',
|
|
13
|
+
'chore',
|
|
14
|
+
'ci',
|
|
15
|
+
'docs',
|
|
16
|
+
'feat',
|
|
17
|
+
'fix',
|
|
18
|
+
'perf',
|
|
19
|
+
'refactor',
|
|
20
|
+
'revert',
|
|
21
|
+
'style',
|
|
22
|
+
'test',
|
|
23
|
+
],
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
|
|
6
|
+
const srcDir = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
|
|
8
|
+
function readJson(filePath: string) {
|
|
9
|
+
// biome-ignore lint/suspicious/noExplicitAny: Test file needs flexible typing for nested config access
|
|
10
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8')) as any;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
describe('Config Structure Validation', () => {
|
|
14
|
+
describe('biome/preset.json', () => {
|
|
15
|
+
const configPath = path.join(srcDir, 'biome/preset.json');
|
|
16
|
+
const config = readJson(configPath);
|
|
17
|
+
|
|
18
|
+
it('has $schema defined', () => {
|
|
19
|
+
expect(config.$schema).toContain('biomejs.dev');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('has linter enabled', () => {
|
|
23
|
+
expect(config.linter?.enabled).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('has formatter enabled', () => {
|
|
27
|
+
expect(config.formatter?.enabled).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('has recommended rules enabled', () => {
|
|
31
|
+
expect(config.linter?.rules?.recommended).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('disallows explicit any', () => {
|
|
35
|
+
expect(config.linter?.rules?.suspicious?.noExplicitAny).toBe('error');
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('typescript/base.json', () => {
|
|
40
|
+
const configPath = path.join(srcDir, 'typescript/base.json');
|
|
41
|
+
const config = readJson(configPath);
|
|
42
|
+
|
|
43
|
+
it('has $schema defined', () => {
|
|
44
|
+
expect(config.$schema).toContain('schemastore.org');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('has strict mode enabled', () => {
|
|
48
|
+
expect(config.compilerOptions?.strict).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('has noUncheckedIndexedAccess enabled', () => {
|
|
52
|
+
expect(config.compilerOptions?.noUncheckedIndexedAccess).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('has strictNullChecks enabled', () => {
|
|
56
|
+
expect(config.compilerOptions?.strictNullChecks).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('has noImplicitAny enabled', () => {
|
|
60
|
+
expect(config.compilerOptions?.noImplicitAny).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('targets ES2022', () => {
|
|
64
|
+
expect(config.compilerOptions?.target).toBe('ES2022');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('uses ESNext module', () => {
|
|
68
|
+
expect(config.compilerOptions?.module).toBe('ESNext');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe('typescript/react.json', () => {
|
|
73
|
+
const configPath = path.join(srcDir, 'typescript/react.json');
|
|
74
|
+
const config = readJson(configPath);
|
|
75
|
+
|
|
76
|
+
it('extends base.json', () => {
|
|
77
|
+
expect(config.extends).toContain('./base.json');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('has jsx set to react-jsx', () => {
|
|
81
|
+
expect(config.compilerOptions?.jsx).toBe('react-jsx');
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('markdownlint/markdownlint.json', () => {
|
|
86
|
+
const configPath = path.join(srcDir, 'markdownlint/markdownlint.json');
|
|
87
|
+
const config = readJson(configPath);
|
|
88
|
+
|
|
89
|
+
it('is a valid JSON object', () => {
|
|
90
|
+
expect(typeof config).toBe('object');
|
|
91
|
+
expect(config).not.toBeNull();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('has MD013 (line-length) rule configured', () => {
|
|
95
|
+
expect(config.MD013).toBeDefined();
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('commitlint/commitlint.cjs', () => {
|
|
100
|
+
const configPath = path.join(srcDir, 'commitlint/commitlint.cjs');
|
|
101
|
+
|
|
102
|
+
it('file exists', () => {
|
|
103
|
+
expect(fs.existsSync(configPath)).toBe(true);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('exports extends with conventional config', () => {
|
|
107
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
108
|
+
expect(content).toContain('@commitlint/config-conventional');
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe('Vitest Configs', () => {
|
|
114
|
+
describe('vitest/node', () => {
|
|
115
|
+
it('exports vitestNodeConfig', async () => {
|
|
116
|
+
const { vitestNodeConfig } = await import('./vitest/node.js');
|
|
117
|
+
expect(vitestNodeConfig).toBeDefined();
|
|
118
|
+
expect(vitestNodeConfig.environment).toBe('node');
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
describe('vitest/react', () => {
|
|
123
|
+
it('exports vitestReactConfig', async () => {
|
|
124
|
+
const { vitestReactConfig } = await import('./vitest/react.js');
|
|
125
|
+
expect(vitestReactConfig).toBeDefined();
|
|
126
|
+
expect(vitestReactConfig.environment).toBe('jsdom');
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { devices } from '@playwright/test';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import type { BuildPlaywrightBaseConfigParams } from './index.js';
|
|
4
|
+
import { buildPlaywrightBaseConfig } from './index.js';
|
|
5
|
+
|
|
6
|
+
describe('buildPlaywrightBaseConfig', () => {
|
|
7
|
+
const validParams: BuildPlaywrightBaseConfigParams = {
|
|
8
|
+
appPort: 3000,
|
|
9
|
+
appUrl: 'http://localhost:3000',
|
|
10
|
+
devices,
|
|
11
|
+
webServerCommand: 'pnpm dev',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
describe('validation', () => {
|
|
15
|
+
it('throws if appUrl is missing', () => {
|
|
16
|
+
expect(() => buildPlaywrightBaseConfig({ ...validParams, appUrl: '' })).toThrow(
|
|
17
|
+
'[playwright] appUrl must be a non-empty string',
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('throws if appPort is not a number', () => {
|
|
22
|
+
expect(() =>
|
|
23
|
+
buildPlaywrightBaseConfig({ ...validParams, appPort: '3000' as unknown as number }),
|
|
24
|
+
).toThrow('[playwright] appPort must be a number');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('throws if devices is missing', () => {
|
|
28
|
+
expect(() =>
|
|
29
|
+
buildPlaywrightBaseConfig({
|
|
30
|
+
...validParams,
|
|
31
|
+
devices: undefined as unknown as typeof devices,
|
|
32
|
+
}),
|
|
33
|
+
).toThrow('[playwright] devices must be provided');
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe('config output', () => {
|
|
38
|
+
it('returns valid Playwright config structure', () => {
|
|
39
|
+
const config = buildPlaywrightBaseConfig(validParams);
|
|
40
|
+
|
|
41
|
+
expect(config).toHaveProperty('projects');
|
|
42
|
+
expect(config).toHaveProperty('testDir', './tests');
|
|
43
|
+
expect(config).toHaveProperty('testMatch', '**/*.e2e.ts');
|
|
44
|
+
expect(config).toHaveProperty('webServer');
|
|
45
|
+
expect(config).toHaveProperty('use.baseURL', 'http://localhost:3000');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('configures 6 browser projects', () => {
|
|
49
|
+
const config = buildPlaywrightBaseConfig(validParams);
|
|
50
|
+
expect(config.projects).toHaveLength(6);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('sets retries to 0 when not in CI', () => {
|
|
54
|
+
const config = buildPlaywrightBaseConfig({ ...validParams, ci: false });
|
|
55
|
+
expect(config.retries).toBe(0);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('sets retries to 2 in CI', () => {
|
|
59
|
+
const config = buildPlaywrightBaseConfig({ ...validParams, ci: true });
|
|
60
|
+
expect(config.retries).toBe(2);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('sets workers to 1 in CI', () => {
|
|
64
|
+
const config = buildPlaywrightBaseConfig({ ...validParams, ci: true });
|
|
65
|
+
expect(config.workers).toBe(1);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('sets forbidOnly to true in CI', () => {
|
|
69
|
+
const config = buildPlaywrightBaseConfig({ ...validParams, ci: true });
|
|
70
|
+
expect(config.forbidOnly).toBe(true);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { PlaywrightTestConfig } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
export interface BuildPlaywrightBaseConfigParams {
|
|
4
|
+
appUrl: string;
|
|
5
|
+
appPort: number;
|
|
6
|
+
devices: typeof import('@playwright/test').devices;
|
|
7
|
+
ci?: boolean;
|
|
8
|
+
webServerCommand: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Build a base Playwright config object with Regardio defaults.
|
|
13
|
+
* Consumers should wrap with defineConfig() in their local playwright.config.ts
|
|
14
|
+
*/
|
|
15
|
+
export function buildPlaywrightBaseConfig({
|
|
16
|
+
appUrl,
|
|
17
|
+
appPort,
|
|
18
|
+
devices,
|
|
19
|
+
ci = !!process.env.CI,
|
|
20
|
+
webServerCommand,
|
|
21
|
+
}: BuildPlaywrightBaseConfigParams): PlaywrightTestConfig {
|
|
22
|
+
if (!appUrl || typeof appUrl !== 'string') {
|
|
23
|
+
throw new Error('[playwright] appUrl must be a non-empty string');
|
|
24
|
+
}
|
|
25
|
+
if (!appPort || typeof appPort !== 'number') {
|
|
26
|
+
throw new Error('[playwright] appPort must be a number');
|
|
27
|
+
}
|
|
28
|
+
if (!devices) {
|
|
29
|
+
throw new Error('[playwright] devices must be provided from "@playwright/test"');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
forbidOnly: ci,
|
|
34
|
+
fullyParallel: true,
|
|
35
|
+
outputDir: './tests/test-results',
|
|
36
|
+
projects: [
|
|
37
|
+
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
|
|
38
|
+
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
|
|
39
|
+
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
|
|
40
|
+
{
|
|
41
|
+
name: 'iPad Pro 11 landscape',
|
|
42
|
+
use: { ...devices['iPad Pro 11 landscape'] },
|
|
43
|
+
},
|
|
44
|
+
{ name: 'iPhone 14 portrait', use: { ...devices['iPhone 14'] } },
|
|
45
|
+
{ name: 'Pixel 7 portrait', use: { ...devices['Pixel 7'] } },
|
|
46
|
+
],
|
|
47
|
+
reporter: [['html', { open: 'never', outputFolder: './tests/playwright-report' }]],
|
|
48
|
+
retries: ci ? 2 : 0,
|
|
49
|
+
testDir: './tests',
|
|
50
|
+
testMatch: '**/*.e2e.ts',
|
|
51
|
+
use: {
|
|
52
|
+
baseURL: appUrl,
|
|
53
|
+
trace: 'on-first-retry',
|
|
54
|
+
},
|
|
55
|
+
webServer: {
|
|
56
|
+
command: webServerCommand,
|
|
57
|
+
ignoreHTTPSErrors: true,
|
|
58
|
+
reuseExistingServer: !ci,
|
|
59
|
+
url: appUrl,
|
|
60
|
+
},
|
|
61
|
+
...(ci ? { workers: 1 } : {}),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test setup file for React packages using Vitest and Testing Library.
|
|
3
|
+
* Import this in your vitest.config.ts setupFiles array.
|
|
4
|
+
*
|
|
5
|
+
* Usage in vitest.config.ts:
|
|
6
|
+
* setupFiles: ['@regardio/dev/testing/setup-react']
|
|
7
|
+
*/
|
|
8
|
+
import '@testing-library/jest-dom/vitest';
|