vitest-tiny-reporter 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -7,12 +7,19 @@
|
|
|
7
7
|
[](https://github.com/manbearwiz/vitest-tiny-reporter/issues)
|
|
8
8
|
[](https://github.com/semantic-release/semantic-release)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
A minimal reporter for [Vitest](https://github.com/vitest-dev/vitest) that provides only the essential information about test runs. Perfect for CI/CD pipelines, git hooks, and AI agent contexts where concise output is crucial.
|
|
11
|
+
|
|
12
|
+
## Why?
|
|
13
|
+
|
|
14
|
+
- **Cleaner output** in tools like lefthook that run multiple checks in parallel
|
|
15
|
+
- **Fewer tokens** when using AI agents to analyze test results (~90% reduction)
|
|
16
|
+
- **Faster to read** for humans scanning multiple test outputs
|
|
17
|
+
- **Essential info only** - no verbose timing breakdowns or file paths
|
|
11
18
|
|
|
12
19
|
## Installation
|
|
13
20
|
|
|
14
21
|
```sh
|
|
15
|
-
npm install --save vitest-tiny-reporter
|
|
22
|
+
npm install --save-dev vitest-tiny-reporter
|
|
16
23
|
```
|
|
17
24
|
|
|
18
25
|
## Usage
|
|
@@ -20,8 +27,8 @@ npm install --save vitest-tiny-reporter
|
|
|
20
27
|
You can specify the reporter in your `vitest.config.ts`:
|
|
21
28
|
|
|
22
29
|
```ts
|
|
23
|
-
import type { UserConfig } from
|
|
24
|
-
import TinyReporter from
|
|
30
|
+
import type { UserConfig } from "vitest/config";
|
|
31
|
+
import TinyReporter from "vitest-tiny-reporter";
|
|
25
32
|
|
|
26
33
|
export default {
|
|
27
34
|
test: {
|
|
@@ -52,25 +59,92 @@ pre-commit:
|
|
|
52
59
|
|
|
53
60
|
## Output
|
|
54
61
|
|
|
55
|
-
###
|
|
62
|
+
### With vitest-tiny-reporter
|
|
56
63
|
|
|
57
|
-
|
|
64
|
+
<img width="272" alt="image" src="https://github.com/user-attachments/assets/312c4f5d-e56f-4662-bf2b-d395339031ce">
|
|
58
65
|
|
|
59
66
|
```sh
|
|
60
|
-
$ vitest
|
|
67
|
+
$ npx vitest run --reporter=vitest-tiny-reporter
|
|
61
68
|
✖ FAIL 1 test failed
|
|
62
69
|
Test Files 1 failed (1)
|
|
63
|
-
Tests 1 failed |
|
|
70
|
+
Tests 1 failed | 17 passed (18)
|
|
64
71
|
```
|
|
65
72
|
|
|
66
|
-
###
|
|
73
|
+
### With default reporter
|
|
74
|
+
|
|
75
|
+
<img width="272" alt="image" src="https://github.com/user-attachments/assets/b68d930d-05f8-4281-8b14-9f8843e7dfb4">
|
|
67
76
|
|
|
68
|
-
|
|
77
|
+
```sh
|
|
78
|
+
$ npx vitest run --reporter=default
|
|
69
79
|
|
|
70
|
-
|
|
80
|
+
RUN v3.2.4 /Users/username/project
|
|
71
81
|
|
|
72
|
-
|
|
82
|
+
❯ src/example.test.ts (18 tests | 1 failed) 19ms
|
|
83
|
+
✓ test-suite > should throw error when not initialized 1ms
|
|
84
|
+
✓ test-suite > when no key > initialize > should not initialize client 1ms
|
|
85
|
+
✓ test-suite > when authenticated > initialize > should use user context 2ms
|
|
86
|
+
✓ test-suite > when authenticated > get > should return true when true 1ms
|
|
87
|
+
✓ test-suite > when authenticated > get > should return false when false 0ms
|
|
88
|
+
✓ test-suite > when authenticated > get > should return default value when undefined 0ms
|
|
89
|
+
✓ test-suite > when authenticated > get > should return default value on string values 0ms
|
|
90
|
+
✓ test-suite > when authenticated > get > should return details 5ms
|
|
91
|
+
✓ test-suite > when authenticated > changeUser > should change user when valid 1ms
|
|
92
|
+
✓ test-suite > when authenticated > changeUser > should reject when user is invalid 1ms
|
|
93
|
+
✓ test-suite > when authenticated > changeUser > should call changeUser with tenant slug 0ms
|
|
94
|
+
✓ test-suite > when authenticated > changeUser > should call changeUser with tenant object 0ms
|
|
95
|
+
× test-suite > when authenticated > should call close 1ms
|
|
96
|
+
→ expected "spy" to not be called at all, but actually been called 2 times
|
|
73
97
|
|
|
74
|
-
|
|
98
|
+
Received:
|
|
75
99
|
|
|
76
|
-
|
|
100
|
+
1st spy call:
|
|
101
|
+
|
|
102
|
+
Array []
|
|
103
|
+
|
|
104
|
+
2nd spy call:
|
|
105
|
+
|
|
106
|
+
Array []
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
Number of calls: 2
|
|
110
|
+
|
|
111
|
+
✓ test-suite > when authenticated > should log an error when calling track 0ms
|
|
112
|
+
✓ test-suite > when authenticated > should call onUpdate 1ms
|
|
113
|
+
✓ test-suite > when anonymous > initialize > should use anonymous context 0ms
|
|
114
|
+
✓ test-suite > when anonymous > get > should return value 3ms
|
|
115
|
+
✓ test-suite > when standalone > get > should return value 0ms
|
|
116
|
+
|
|
117
|
+
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
|
|
118
|
+
|
|
119
|
+
FAIL src/example.test.ts > test-suite > when authenticated > should call close
|
|
120
|
+
AssertionError: expected "spy" to not be called at all, but actually been called 2 times
|
|
121
|
+
|
|
122
|
+
Received:
|
|
123
|
+
|
|
124
|
+
1st spy call:
|
|
125
|
+
|
|
126
|
+
Array []
|
|
127
|
+
|
|
128
|
+
2nd spy call:
|
|
129
|
+
|
|
130
|
+
Array []
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
Number of calls: 2
|
|
134
|
+
|
|
135
|
+
❯ src/example.test.ts:209:36
|
|
136
|
+
207| it('should call close', async () => {
|
|
137
|
+
208| await flags.close();
|
|
138
|
+
209| expect(mockClient.close).not.toHaveBeenCalled();
|
|
139
|
+
| ^
|
|
140
|
+
210| });
|
|
141
|
+
211|
|
|
142
|
+
|
|
143
|
+
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
Test Files 1 failed (1)
|
|
147
|
+
Tests 1 failed | 17 passed (18)
|
|
148
|
+
Start at 22:06:43
|
|
149
|
+
Duration 439ms (transform 44ms, setup 0ms, collect 101ms, tests 19ms, environment 103ms, prepare 51ms)
|
|
150
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RunnerTask } from 'vitest';
|
|
2
|
+
import type { Vitest } from 'vitest/node';
|
|
3
|
+
import type { Reporter } from 'vitest/reporters';
|
|
4
|
+
export default class TinyReporter implements Reporter {
|
|
5
|
+
ctx: Vitest;
|
|
6
|
+
protected verbose: boolean;
|
|
7
|
+
onInit(ctx: Vitest): void;
|
|
8
|
+
onFinished(files?: import("vitest").RunnerTestFile[], errors?: unknown[]): void;
|
|
9
|
+
padTitle: (str: string) => string;
|
|
10
|
+
getStateString(tasks: RunnerTask[], name?: string): string;
|
|
11
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest-tiny-reporter.js","sources":["../node_modules/@vitest/utils/dist/helpers.js","../node_modules/@vitest/runner/dist/chunk-tasks.js","../src/index.ts"],"sourcesContent":["import { VALID_ID_PREFIX, NULL_BYTE_PLACEHOLDER } from './constants.js';\n\n// port from nanoid\n// https://github.com/ai/nanoid\nconst urlAlphabet = \"useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict\";\nfunction nanoid(size = 21) {\n\tlet id = \"\";\n\tlet i = size;\n\twhile (i--) {\n\t\tid += urlAlphabet[Math.random() * 64 | 0];\n\t}\n\treturn id;\n}\n\nconst RealDate = Date;\nfunction random(seed) {\n\tconst x = Math.sin(seed++) * 1e4;\n\treturn x - Math.floor(x);\n}\nfunction shuffle(array, seed = RealDate.now()) {\n\tlet length = array.length;\n\twhile (length) {\n\t\tconst index = Math.floor(random(seed) * length--);\n\t\tconst previous = array[length];\n\t\tarray[length] = array[index];\n\t\tarray[index] = previous;\n\t\t++seed;\n\t}\n\treturn array;\n}\n\n/**\n* Get original stacktrace without source map support the most performant way.\n* - Create only 1 stack frame.\n* - Rewrite prepareStackTrace to bypass \"support-stack-trace\" (usually takes ~250ms).\n*/\nfunction createSimpleStackTrace(options) {\n\tconst { message = \"$$stack trace error\", stackTraceLimit = 1 } = options || {};\n\tconst limit = Error.stackTraceLimit;\n\tconst prepareStackTrace = Error.prepareStackTrace;\n\tError.stackTraceLimit = stackTraceLimit;\n\tError.prepareStackTrace = (e) => e.stack;\n\tconst err = new Error(message);\n\tconst stackTrace = err.stack || \"\";\n\tError.prepareStackTrace = prepareStackTrace;\n\tError.stackTraceLimit = limit;\n\treturn stackTrace;\n}\nfunction notNullish(v) {\n\treturn v != null;\n}\nfunction assertTypes(value, name, types) {\n\tconst receivedType = typeof value;\n\tconst pass = types.includes(receivedType);\n\tif (!pass) {\n\t\tthrow new TypeError(`${name} value must be ${types.join(\" or \")}, received \"${receivedType}\"`);\n\t}\n}\nfunction isPrimitive(value) {\n\treturn value === null || typeof value !== \"function\" && typeof value !== \"object\";\n}\nfunction slash(path) {\n\treturn path.replace(/\\\\/g, \"/\");\n}\nconst postfixRE = /[?#].*$/;\nfunction cleanUrl(url) {\n\treturn url.replace(postfixRE, \"\");\n}\nconst externalRE = /^(?:[a-z]+:)?\\/\\//;\nconst isExternalUrl = (url) => externalRE.test(url);\n/**\n* Prepend `/@id/` and replace null byte so the id is URL-safe.\n* This is prepended to resolved ids that are not valid browser\n* import specifiers by the importAnalysis plugin.\n*/\nfunction wrapId(id) {\n\treturn id.startsWith(VALID_ID_PREFIX) ? id : VALID_ID_PREFIX + id.replace(\"\\0\", NULL_BYTE_PLACEHOLDER);\n}\n/**\n* Undo {@link wrapId}'s `/@id/` and null byte replacements.\n*/\nfunction unwrapId(id) {\n\treturn id.startsWith(VALID_ID_PREFIX) ? id.slice(VALID_ID_PREFIX.length).replace(NULL_BYTE_PLACEHOLDER, \"\\0\") : id;\n}\nfunction withTrailingSlash(path) {\n\tif (path.at(-1) !== \"/\") {\n\t\treturn `${path}/`;\n\t}\n\treturn path;\n}\nconst bareImportRE = /^(?![a-z]:)[\\w@](?!.*:\\/\\/)/i;\nfunction isBareImport(id) {\n\treturn bareImportRE.test(id);\n}\nfunction toArray(array) {\n\tif (array === null || array === undefined) {\n\t\tarray = [];\n\t}\n\tif (Array.isArray(array)) {\n\t\treturn array;\n\t}\n\treturn [array];\n}\nfunction isObject(item) {\n\treturn item != null && typeof item === \"object\" && !Array.isArray(item);\n}\nfunction isFinalObj(obj) {\n\treturn obj === Object.prototype || obj === Function.prototype || obj === RegExp.prototype;\n}\nfunction getType(value) {\n\treturn Object.prototype.toString.apply(value).slice(8, -1);\n}\nfunction collectOwnProperties(obj, collector) {\n\tconst collect = typeof collector === \"function\" ? collector : (key) => collector.add(key);\n\tObject.getOwnPropertyNames(obj).forEach(collect);\n\tObject.getOwnPropertySymbols(obj).forEach(collect);\n}\nfunction getOwnProperties(obj) {\n\tconst ownProps = new Set();\n\tif (isFinalObj(obj)) {\n\t\treturn [];\n\t}\n\tcollectOwnProperties(obj, ownProps);\n\treturn Array.from(ownProps);\n}\nconst defaultCloneOptions = { forceWritable: false };\nfunction deepClone(val, options = defaultCloneOptions) {\n\tconst seen = new WeakMap();\n\treturn clone(val, seen, options);\n}\nfunction clone(val, seen, options = defaultCloneOptions) {\n\tlet k, out;\n\tif (seen.has(val)) {\n\t\treturn seen.get(val);\n\t}\n\tif (Array.isArray(val)) {\n\t\tout = Array.from({ length: k = val.length });\n\t\tseen.set(val, out);\n\t\twhile (k--) {\n\t\t\tout[k] = clone(val[k], seen, options);\n\t\t}\n\t\treturn out;\n\t}\n\tif (Object.prototype.toString.call(val) === \"[object Object]\") {\n\t\tout = Object.create(Object.getPrototypeOf(val));\n\t\tseen.set(val, out);\n\t\t// we don't need properties from prototype\n\t\tconst props = getOwnProperties(val);\n\t\tfor (const k of props) {\n\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(val, k);\n\t\t\tif (!descriptor) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst cloned = clone(val[k], seen, options);\n\t\t\tif (options.forceWritable) {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\tenumerable: descriptor.enumerable,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: cloned\n\t\t\t\t});\n\t\t\t} else if (\"get\" in descriptor) {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\t...descriptor,\n\t\t\t\t\tget() {\n\t\t\t\t\t\treturn cloned;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\t...descriptor,\n\t\t\t\t\tvalue: cloned\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn out;\n\t}\n\treturn val;\n}\nfunction noop() {}\nfunction objectAttr(source, path, defaultValue = undefined) {\n\t// a[3].b -> a.3.b\n\tconst paths = path.replace(/\\[(\\d+)\\]/g, \".$1\").split(\".\");\n\tlet result = source;\n\tfor (const p of paths) {\n\t\tresult = new Object(result)[p];\n\t\tif (result === undefined) {\n\t\t\treturn defaultValue;\n\t\t}\n\t}\n\treturn result;\n}\nfunction createDefer() {\n\tlet resolve = null;\n\tlet reject = null;\n\tconst p = new Promise((_resolve, _reject) => {\n\t\tresolve = _resolve;\n\t\treject = _reject;\n\t});\n\tp.resolve = resolve;\n\tp.reject = reject;\n\treturn p;\n}\n/**\n* If code starts with a function call, will return its last index, respecting arguments.\n* This will return 25 - last ending character of toMatch \")\"\n* Also works with callbacks\n* ```\n* toMatch({ test: '123' });\n* toBeAliased('123')\n* ```\n*/\nfunction getCallLastIndex(code) {\n\tlet charIndex = -1;\n\tlet inString = null;\n\tlet startedBracers = 0;\n\tlet endedBracers = 0;\n\tlet beforeChar = null;\n\twhile (charIndex <= code.length) {\n\t\tbeforeChar = code[charIndex];\n\t\tcharIndex++;\n\t\tconst char = code[charIndex];\n\t\tconst isCharString = char === \"\\\"\" || char === \"'\" || char === \"`\";\n\t\tif (isCharString && beforeChar !== \"\\\\\") {\n\t\t\tif (inString === char) {\n\t\t\t\tinString = null;\n\t\t\t} else if (!inString) {\n\t\t\t\tinString = char;\n\t\t\t}\n\t\t}\n\t\tif (!inString) {\n\t\t\tif (char === \"(\") {\n\t\t\t\tstartedBracers++;\n\t\t\t}\n\t\t\tif (char === \")\") {\n\t\t\t\tendedBracers++;\n\t\t\t}\n\t\t}\n\t\tif (startedBracers && endedBracers && startedBracers === endedBracers) {\n\t\t\treturn charIndex;\n\t\t}\n\t}\n\treturn null;\n}\nfunction isNegativeNaN(val) {\n\tif (!Number.isNaN(val)) {\n\t\treturn false;\n\t}\n\tconst f64 = new Float64Array(1);\n\tf64[0] = val;\n\tconst u32 = new Uint32Array(f64.buffer);\n\tconst isNegative = u32[1] >>> 31 === 1;\n\treturn isNegative;\n}\nfunction toString(v) {\n\treturn Object.prototype.toString.call(v);\n}\nfunction isPlainObject(val) {\n\treturn toString(val) === \"[object Object]\" && (!val.constructor || val.constructor.name === \"Object\");\n}\nfunction isMergeableObject(item) {\n\treturn isPlainObject(item) && !Array.isArray(item);\n}\n/**\n* Deep merge :P\n*\n* Will merge objects only if they are plain\n*\n* Do not merge types - it is very expensive and usually it's better to case a type here\n*/\nfunction deepMerge(target, ...sources) {\n\tif (!sources.length) {\n\t\treturn target;\n\t}\n\tconst source = sources.shift();\n\tif (source === undefined) {\n\t\treturn target;\n\t}\n\tif (isMergeableObject(target) && isMergeableObject(source)) {\n\t\tObject.keys(source).forEach((key) => {\n\t\t\tconst _source = source;\n\t\t\tif (isMergeableObject(_source[key])) {\n\t\t\t\tif (!target[key]) {\n\t\t\t\t\ttarget[key] = {};\n\t\t\t\t}\n\t\t\t\tdeepMerge(target[key], _source[key]);\n\t\t\t} else {\n\t\t\t\ttarget[key] = _source[key];\n\t\t\t}\n\t\t});\n\t}\n\treturn deepMerge(target, ...sources);\n}\n\nexport { assertTypes, cleanUrl, clone, createDefer, createSimpleStackTrace, deepClone, deepMerge, getCallLastIndex, getOwnProperties, getType, isBareImport, isExternalUrl, isNegativeNaN, isObject, isPrimitive, nanoid, noop, notNullish, objectAttr, shuffle, slash, toArray, unwrapId, withTrailingSlash, wrapId };\n","import { processError } from '@vitest/utils/error';\nimport { parseSingleStack } from '@vitest/utils/source-map';\nimport { relative } from 'pathe';\nimport { toArray } from '@vitest/utils/helpers';\n\nfunction createChainable(keys, fn) {\n\tfunction create(context) {\n\t\tconst chain = function(...args) {\n\t\t\treturn fn.apply(context, args);\n\t\t};\n\t\tObject.assign(chain, fn);\n\t\tchain.withContext = () => chain.bind(context);\n\t\tchain.setContext = (key, value) => {\n\t\t\tcontext[key] = value;\n\t\t};\n\t\tchain.mergeContext = (ctx) => {\n\t\t\tObject.assign(context, ctx);\n\t\t};\n\t\tfor (const key of keys) {\n\t\t\tObject.defineProperty(chain, key, { get() {\n\t\t\t\treturn create({\n\t\t\t\t\t...context,\n\t\t\t\t\t[key]: true\n\t\t\t\t});\n\t\t\t} });\n\t\t}\n\t\treturn chain;\n\t}\n\tconst chain = create({});\n\tchain.fn = fn;\n\treturn chain;\n}\n\n/**\n* If any tasks been marked as `only`, mark all other tasks as `skip`.\n*/\nfunction interpretTaskModes(file, namePattern, testLocations, onlyMode, parentIsOnly, allowOnly) {\n\tconst matchedLocations = [];\n\tconst traverseSuite = (suite, parentIsOnly, parentMatchedWithLocation) => {\n\t\tconst suiteIsOnly = parentIsOnly || suite.mode === \"only\";\n\t\tsuite.tasks.forEach((t) => {\n\t\t\t// Check if either the parent suite or the task itself are marked as included\n\t\t\tconst includeTask = suiteIsOnly || t.mode === \"only\";\n\t\t\tif (onlyMode) {\n\t\t\t\tif (t.type === \"suite\" && (includeTask || someTasksAreOnly(t))) {\n\t\t\t\t\t// Don't skip this suite\n\t\t\t\t\tif (t.mode === \"only\") {\n\t\t\t\t\t\tcheckAllowOnly(t, allowOnly);\n\t\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t\t}\n\t\t\t\t} else if (t.mode === \"run\" && !includeTask) {\n\t\t\t\t\tt.mode = \"skip\";\n\t\t\t\t} else if (t.mode === \"only\") {\n\t\t\t\t\tcheckAllowOnly(t, allowOnly);\n\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet hasLocationMatch = parentMatchedWithLocation;\n\t\t\t// Match test location against provided locations, only run if present\n\t\t\t// in `testLocations`. Note: if `includeTaskLocations` is not enabled,\n\t\t\t// all test will be skipped.\n\t\t\tif (testLocations !== undefined && testLocations.length !== 0) {\n\t\t\t\tif (t.location && (testLocations === null || testLocations === void 0 ? void 0 : testLocations.includes(t.location.line))) {\n\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t\tmatchedLocations.push(t.location.line);\n\t\t\t\t\thasLocationMatch = true;\n\t\t\t\t} else if (parentMatchedWithLocation) {\n\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t} else if (t.type === \"test\") {\n\t\t\t\t\tt.mode = \"skip\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (t.type === \"test\") {\n\t\t\t\tif (namePattern && !getTaskFullName(t).match(namePattern)) {\n\t\t\t\t\tt.mode = \"skip\";\n\t\t\t\t}\n\t\t\t} else if (t.type === \"suite\") {\n\t\t\t\tif (t.mode === \"skip\") {\n\t\t\t\t\tskipAllTasks(t);\n\t\t\t\t} else if (t.mode === \"todo\") {\n\t\t\t\t\ttodoAllTasks(t);\n\t\t\t\t} else {\n\t\t\t\t\ttraverseSuite(t, includeTask, hasLocationMatch);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t// if all subtasks are skipped, mark as skip\n\t\tif (suite.mode === \"run\" || suite.mode === \"queued\") {\n\t\t\tif (suite.tasks.length && suite.tasks.every((i) => i.mode !== \"run\" && i.mode !== \"queued\")) {\n\t\t\t\tsuite.mode = \"skip\";\n\t\t\t}\n\t\t}\n\t};\n\ttraverseSuite(file, parentIsOnly, false);\n\tconst nonMatching = testLocations === null || testLocations === void 0 ? void 0 : testLocations.filter((loc) => !matchedLocations.includes(loc));\n\tif (nonMatching && nonMatching.length !== 0) {\n\t\tconst message = nonMatching.length === 1 ? `line ${nonMatching[0]}` : `lines ${nonMatching.join(\", \")}`;\n\t\tif (file.result === undefined) {\n\t\t\tfile.result = {\n\t\t\t\tstate: \"fail\",\n\t\t\t\terrors: []\n\t\t\t};\n\t\t}\n\t\tif (file.result.errors === undefined) {\n\t\t\tfile.result.errors = [];\n\t\t}\n\t\tfile.result.errors.push(processError(new Error(`No test found in ${file.name} in ${message}`)));\n\t}\n}\nfunction getTaskFullName(task) {\n\treturn `${task.suite ? `${getTaskFullName(task.suite)} ` : \"\"}${task.name}`;\n}\nfunction someTasksAreOnly(suite) {\n\treturn suite.tasks.some((t) => t.mode === \"only\" || t.type === \"suite\" && someTasksAreOnly(t));\n}\nfunction skipAllTasks(suite) {\n\tsuite.tasks.forEach((t) => {\n\t\tif (t.mode === \"run\" || t.mode === \"queued\") {\n\t\t\tt.mode = \"skip\";\n\t\t\tif (t.type === \"suite\") {\n\t\t\t\tskipAllTasks(t);\n\t\t\t}\n\t\t}\n\t});\n}\nfunction todoAllTasks(suite) {\n\tsuite.tasks.forEach((t) => {\n\t\tif (t.mode === \"run\" || t.mode === \"queued\") {\n\t\t\tt.mode = \"todo\";\n\t\t\tif (t.type === \"suite\") {\n\t\t\t\ttodoAllTasks(t);\n\t\t\t}\n\t\t}\n\t});\n}\nfunction checkAllowOnly(task, allowOnly) {\n\tif (allowOnly) {\n\t\treturn;\n\t}\n\tconst error = processError(new Error(\"[Vitest] Unexpected .only modifier. Remove it or pass --allowOnly argument to bypass this error\"));\n\ttask.result = {\n\t\tstate: \"fail\",\n\t\terrors: [error]\n\t};\n}\n/* @__NO_SIDE_EFFECTS__ */\nfunction generateHash(str) {\n\tlet hash = 0;\n\tif (str.length === 0) {\n\t\treturn `${hash}`;\n\t}\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst char = str.charCodeAt(i);\n\t\thash = (hash << 5) - hash + char;\n\t\thash = hash & hash;\n\t}\n\treturn `${hash}`;\n}\nfunction calculateSuiteHash(parent) {\n\tparent.tasks.forEach((t, idx) => {\n\t\tt.id = `${parent.id}_${idx}`;\n\t\tif (t.type === \"suite\") {\n\t\t\tcalculateSuiteHash(t);\n\t\t}\n\t});\n}\nfunction createFileTask(filepath, root, projectName, pool) {\n\tconst path = relative(root, filepath);\n\tconst file = {\n\t\tid: generateFileHash(path, projectName),\n\t\tname: path,\n\t\ttype: \"suite\",\n\t\tmode: \"queued\",\n\t\tfilepath,\n\t\ttasks: [],\n\t\tmeta: Object.create(null),\n\t\tprojectName,\n\t\tfile: undefined,\n\t\tpool\n\t};\n\tfile.file = file;\n\treturn file;\n}\n/**\n* Generate a unique ID for a file based on its path and project name\n* @param file File relative to the root of the project to keep ID the same between different machines\n* @param projectName The name of the test project\n*/\n/* @__NO_SIDE_EFFECTS__ */\nfunction generateFileHash(file, projectName) {\n\treturn /* @__PURE__ */ generateHash(`${file}${projectName || \"\"}`);\n}\nfunction findTestFileStackTrace(testFilePath, error) {\n\t// first line is the error message\n\tconst lines = error.split(\"\\n\").slice(1);\n\tfor (const line of lines) {\n\t\tconst stack = parseSingleStack(line);\n\t\tif (stack && stack.file === testFilePath) {\n\t\t\treturn stack;\n\t\t}\n\t}\n}\n\n/**\n* Return a function for running multiple async operations with limited concurrency.\n*/\nfunction limitConcurrency(concurrency = Infinity) {\n\t// The number of currently active + pending tasks.\n\tlet count = 0;\n\t// The head and tail of the pending task queue, built using a singly linked list.\n\t// Both head and tail are initially undefined, signifying an empty queue.\n\t// They both become undefined again whenever there are no pending tasks.\n\tlet head;\n\tlet tail;\n\t// A bookkeeping function executed whenever a task has been run to completion.\n\tconst finish = () => {\n\t\tcount--;\n\t\t// Check if there are further pending tasks in the queue.\n\t\tif (head) {\n\t\t\t// Allow the next pending task to run and pop it from the queue.\n\t\t\thead[0]();\n\t\t\thead = head[1];\n\t\t\t// The head may now be undefined if there are no further pending tasks.\n\t\t\t// In that case, set tail to undefined as well.\n\t\t\ttail = head && tail;\n\t\t}\n\t};\n\treturn (func, ...args) => {\n\t\t// Create a promise chain that:\n\t\t// 1. Waits for its turn in the task queue (if necessary).\n\t\t// 2. Runs the task.\n\t\t// 3. Allows the next pending task (if any) to run.\n\t\treturn new Promise((resolve) => {\n\t\t\tif (count++ < concurrency) {\n\t\t\t\t// No need to queue if fewer than maxConcurrency tasks are running.\n\t\t\t\tresolve();\n\t\t\t} else if (tail) {\n\t\t\t\t// There are pending tasks, so append to the queue.\n\t\t\t\ttail = tail[1] = [resolve];\n\t\t\t} else {\n\t\t\t\t// No other pending tasks, initialize the queue with a new tail and head.\n\t\t\t\thead = tail = [resolve];\n\t\t\t}\n\t\t}).then(() => {\n\t\t\t// Running func here ensures that even a non-thenable result or an\n\t\t\t// immediately thrown error gets wrapped into a Promise.\n\t\t\treturn func(...args);\n\t\t}).finally(finish);\n\t};\n}\n\n/**\n* Partition in tasks groups by consecutive concurrent\n*/\nfunction partitionSuiteChildren(suite) {\n\tlet tasksGroup = [];\n\tconst tasksGroups = [];\n\tfor (const c of suite.tasks) {\n\t\tif (tasksGroup.length === 0 || c.concurrent === tasksGroup[0].concurrent) {\n\t\t\ttasksGroup.push(c);\n\t\t} else {\n\t\t\ttasksGroups.push(tasksGroup);\n\t\t\ttasksGroup = [c];\n\t\t}\n\t}\n\tif (tasksGroup.length > 0) {\n\t\ttasksGroups.push(tasksGroup);\n\t}\n\treturn tasksGroups;\n}\n\nfunction isTestCase(s) {\n\treturn s.type === \"test\";\n}\nfunction getTests(suite) {\n\tconst tests = [];\n\tconst arraySuites = toArray(suite);\n\tfor (const s of arraySuites) {\n\t\tif (isTestCase(s)) {\n\t\t\ttests.push(s);\n\t\t} else {\n\t\t\tfor (const task of s.tasks) {\n\t\t\t\tif (isTestCase(task)) {\n\t\t\t\t\ttests.push(task);\n\t\t\t\t} else {\n\t\t\t\t\tconst taskTests = getTests(task);\n\t\t\t\t\tfor (const test of taskTests) {\n\t\t\t\t\t\ttests.push(test);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn tests;\n}\nfunction getTasks(tasks = []) {\n\treturn toArray(tasks).flatMap((s) => isTestCase(s) ? [s] : [s, ...getTasks(s.tasks)]);\n}\nfunction getSuites(suite) {\n\treturn toArray(suite).flatMap((s) => s.type === \"suite\" ? [s, ...getSuites(s.tasks)] : []);\n}\nfunction hasTests(suite) {\n\treturn toArray(suite).some((s) => s.tasks.some((c) => isTestCase(c) || hasTests(c)));\n}\nfunction hasFailed(suite) {\n\treturn toArray(suite).some((s) => {\n\t\tvar _s$result;\n\t\treturn ((_s$result = s.result) === null || _s$result === void 0 ? void 0 : _s$result.state) === \"fail\" || s.type === \"suite\" && hasFailed(s.tasks);\n\t});\n}\nfunction getNames(task) {\n\tconst names = [task.name];\n\tlet current = task;\n\twhile (current === null || current === void 0 ? void 0 : current.suite) {\n\t\tcurrent = current.suite;\n\t\tif (current === null || current === void 0 ? void 0 : current.name) {\n\t\t\tnames.unshift(current.name);\n\t\t}\n\t}\n\tif (current !== task.file) {\n\t\tnames.unshift(task.file.name);\n\t}\n\treturn names;\n}\nfunction getFullName(task, separator = \" > \") {\n\treturn getNames(task).join(separator);\n}\nfunction getTestName(task, separator = \" > \") {\n\treturn getNames(task).slice(1).join(separator);\n}\n\nexport { calculateSuiteHash as a, createFileTask as b, createChainable as c, generateHash as d, getFullName as e, findTestFileStackTrace as f, generateFileHash as g, getNames as h, interpretTaskModes as i, getSuites as j, getTasks as k, limitConcurrency as l, getTestName as m, getTests as n, hasFailed as o, partitionSuiteChildren as p, hasTests as q, isTestCase as r, someTasksAreOnly as s };\n","import { getTests } from '@vitest/runner/utils';\nimport c from 'tinyrainbow';\nimport type { RunnerTask } from 'vitest';\nimport type { Vitest } from 'vitest/node';\nimport type { Reporter } from 'vitest/reporters';\n\nexport default class TinyReporter implements Reporter {\n // biome-ignore lint/style/noNonNullAssertion: Non-null assertion is allowed here because the onInit method is called before any other method\n ctx: Vitest = undefined!;\n protected verbose = false;\n\n onInit(ctx: Vitest) {\n this.ctx = ctx;\n }\n\n onFinished(\n files = this.ctx.state.getFiles(),\n errors = this.ctx.state.getUnhandledErrors(),\n ) {\n const { logger } = this.ctx;\n const tests = getTests(files);\n const failedTests = tests.filter((i) => i.result?.state === 'fail').length;\n\n const passed = !(failedTests + errors.length);\n const status = passed ? '\\u2714 PASS' : '\\u2716 FAIL';\n const statusColor = passed ? c.green : c.red;\n\n logger.log(\n `${statusColor(c.bold(c.inverse(` ${status} `)))} ${statusColor(\n passed\n ? 'All tests passed'\n : `${failedTests} test${failedTests > 1 ? 's' : ''} failed`,\n )}`,\n );\n logger.log(this.padTitle('Test Files'), this.getStateString(files));\n logger.log(this.padTitle('Tests'), this.getStateString(tests));\n\n if (errors.length) {\n logger.log(\n this.padTitle('Errors'),\n c.bold(c.red(`${errors.length} error${errors.length > 1 ? 's' : ''}`)),\n );\n }\n\n if (!passed) {\n process.exitCode = 1;\n }\n }\n\n padTitle = (str: string) => c.dim(`${str.padStart(11)} `);\n\n getStateString(tasks: RunnerTask[], name = 'tests') {\n if (!tasks.length) {\n return c.dim(`no ${name}`);\n }\n\n const passed = tasks.filter((i) => i.result?.state === 'pass').length;\n const failed = tasks.filter((i) => i.result?.state === 'fail').length;\n const skipped = tasks.filter((i) => i.mode === 'skip').length;\n const todo = tasks.filter((i) => i.mode === 'todo').length;\n\n return (\n [\n failed && c.bold(c.red(`${failed} failed`)),\n passed && c.bold(c.green(`${passed} passed`)),\n skipped && c.yellow(`${skipped} skipped`),\n todo && c.gray(`${todo} todo`),\n ]\n .filter(Boolean)\n .join(c.dim(' | ')) + c.gray(` (${tasks.length})`)\n );\n }\n}\n"],"names":["toArray","array","isTestCase","getTests","suite","tests","arraySuites","s","task","taskTests","test","TinyReporter","ctx","files","errors","logger","failedTests","i","passed","status","statusColor","c","str","tasks","name","failed","skipped","todo"],"mappings":";AA8FA,SAASA,EAAQC,GAAO;AAIvB,SAHIA,KAAU,SACbA,IAAQ,CAAA,IAEL,MAAM,QAAQA,CAAK,IACfA,IAED,CAACA,CAAK;AACd;ACyKA,SAASC,EAAW,GAAG;AACtB,SAAO,EAAE,SAAS;AACnB;AACA,SAASC,EAASC,GAAO;AACxB,QAAMC,IAAQ,CAAA,GACRC,IAAcN,EAAQI,CAAK;AACjC,aAAWG,KAAKD;AACf,QAAIJ,EAAWK,CAAC;AACf,MAAAF,EAAM,KAAKE,CAAC;AAAA;AAEZ,iBAAWC,KAAQD,EAAE;AACpB,YAAIL,EAAWM,CAAI;AAClB,UAAAH,EAAM,KAAKG,CAAI;AAAA,aACT;AACN,gBAAMC,IAAYN,EAASK,CAAI;AAC/B,qBAAWE,KAAQD;AAClB,YAAAJ,EAAM,KAAKK,CAAI;AAAA,QAEjB;AAIH,SAAOL;AACR;AChSA,MAAqBM,EAAiC;AAAA;AAAA,EAEpD,MAAc;AAAA,EACJ,UAAU;AAAA,EAEpB,OAAOC,GAAa;AAClB,SAAK,MAAMA;AAAA,EACb;AAAA,EAEA,WACEC,IAAQ,KAAK,IAAI,MAAM,YACvBC,IAAS,KAAK,IAAI,MAAM,mBAAA,GACxB;AACA,UAAM,EAAE,QAAAC,MAAW,KAAK,KAClBV,IAAQF,EAASU,CAAK,GACtBG,IAAcX,EAAM,OAAO,CAACY,MAAMA,EAAE,QAAQ,UAAU,MAAM,EAAE,QAE9DC,IAAS,EAAEF,IAAcF,EAAO,SAChCK,IAASD,IAAS,WAAgB,UAClCE,IAAcF,IAASG,EAAE,QAAQA,EAAE;AAEzC,IAAAN,EAAO;AAAA,MACL,GAAGK,EAAYC,EAAE,KAAKA,EAAE,QAAQ,IAAIF,CAAM,GAAG,CAAC,CAAC,CAAC,IAAIC;AAAA,QAClDF,IACI,qBACA,GAAGF,CAAW,QAAQA,IAAc,IAAI,MAAM,EAAE;AAAA,MAAA,CACrD;AAAA,IAAA,GAEHD,EAAO,IAAI,KAAK,SAAS,YAAY,GAAG,KAAK,eAAeF,CAAK,CAAC,GAClEE,EAAO,IAAI,KAAK,SAAS,OAAO,GAAG,KAAK,eAAeV,CAAK,CAAC,GAEzDS,EAAO,UACTC,EAAO;AAAA,MACL,KAAK,SAAS,QAAQ;AAAA,MACtBM,EAAE,KAAKA,EAAE,IAAI,GAAGP,EAAO,MAAM,SAASA,EAAO,SAAS,IAAI,MAAM,EAAE,EAAE,CAAC;AAAA,IAAA,GAIpEI,MACH,QAAQ,WAAW;AAAA,EAEvB;AAAA,EAEA,WAAW,CAACI,MAAgBD,EAAE,IAAI,GAAGC,EAAI,SAAS,EAAE,CAAC,GAAG;AAAA,EAExD,eAAeC,GAAqBC,IAAO,SAAS;AAClD,QAAI,CAACD,EAAM;AACT,aAAOF,EAAE,IAAI,MAAMG,CAAI,EAAE;AAG3B,UAAMN,IAASK,EAAM,OAAO,CAACN,MAAMA,EAAE,QAAQ,UAAU,MAAM,EAAE,QACzDQ,IAASF,EAAM,OAAO,CAACN,MAAMA,EAAE,QAAQ,UAAU,MAAM,EAAE,QACzDS,IAAUH,EAAM,OAAO,CAACN,MAAMA,EAAE,SAAS,MAAM,EAAE,QACjDU,IAAOJ,EAAM,OAAO,CAACN,MAAMA,EAAE,SAAS,MAAM,EAAE;AAEpD,WACE;AAAA,MACEQ,KAAUJ,EAAE,KAAKA,EAAE,IAAI,GAAGI,CAAM,SAAS,CAAC;AAAA,MAC1CP,KAAUG,EAAE,KAAKA,EAAE,MAAM,GAAGH,CAAM,SAAS,CAAC;AAAA,MAC5CQ,KAAWL,EAAE,OAAO,GAAGK,CAAO,UAAU;AAAA,MACxCC,KAAQN,EAAE,KAAK,GAAGM,CAAI,OAAO;AAAA,IAAA,EAE5B,OAAO,OAAO,EACd,KAAKN,EAAE,IAAI,KAAK,CAAC,IAAIA,EAAE,KAAK,KAAKE,EAAM,MAAM,GAAG;AAAA,EAEvD;AACF;","x_google_ignoreList":[0,1]}
|
|
1
|
+
{"version":3,"file":"vitest-tiny-reporter.js","sources":["../node_modules/@vitest/utils/dist/helpers.js","../node_modules/@vitest/runner/dist/chunk-tasks.js","../src/index.ts"],"sourcesContent":["import { VALID_ID_PREFIX, NULL_BYTE_PLACEHOLDER } from './constants.js';\n\n// port from nanoid\n// https://github.com/ai/nanoid\nconst urlAlphabet = \"useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict\";\nfunction nanoid(size = 21) {\n\tlet id = \"\";\n\tlet i = size;\n\twhile (i--) {\n\t\tid += urlAlphabet[Math.random() * 64 | 0];\n\t}\n\treturn id;\n}\n\nconst RealDate = Date;\nfunction random(seed) {\n\tconst x = Math.sin(seed++) * 1e4;\n\treturn x - Math.floor(x);\n}\nfunction shuffle(array, seed = RealDate.now()) {\n\tlet length = array.length;\n\twhile (length) {\n\t\tconst index = Math.floor(random(seed) * length--);\n\t\tconst previous = array[length];\n\t\tarray[length] = array[index];\n\t\tarray[index] = previous;\n\t\t++seed;\n\t}\n\treturn array;\n}\n\n/**\n* Get original stacktrace without source map support the most performant way.\n* - Create only 1 stack frame.\n* - Rewrite prepareStackTrace to bypass \"support-stack-trace\" (usually takes ~250ms).\n*/\nfunction createSimpleStackTrace(options) {\n\tconst { message = \"$$stack trace error\", stackTraceLimit = 1 } = options || {};\n\tconst limit = Error.stackTraceLimit;\n\tconst prepareStackTrace = Error.prepareStackTrace;\n\tError.stackTraceLimit = stackTraceLimit;\n\tError.prepareStackTrace = (e) => e.stack;\n\tconst err = new Error(message);\n\tconst stackTrace = err.stack || \"\";\n\tError.prepareStackTrace = prepareStackTrace;\n\tError.stackTraceLimit = limit;\n\treturn stackTrace;\n}\nfunction notNullish(v) {\n\treturn v != null;\n}\nfunction assertTypes(value, name, types) {\n\tconst receivedType = typeof value;\n\tconst pass = types.includes(receivedType);\n\tif (!pass) {\n\t\tthrow new TypeError(`${name} value must be ${types.join(\" or \")}, received \"${receivedType}\"`);\n\t}\n}\nfunction isPrimitive(value) {\n\treturn value === null || typeof value !== \"function\" && typeof value !== \"object\";\n}\nfunction slash(path) {\n\treturn path.replace(/\\\\/g, \"/\");\n}\nconst postfixRE = /[?#].*$/;\nfunction cleanUrl(url) {\n\treturn url.replace(postfixRE, \"\");\n}\nconst externalRE = /^(?:[a-z]+:)?\\/\\//;\nconst isExternalUrl = (url) => externalRE.test(url);\n/**\n* Prepend `/@id/` and replace null byte so the id is URL-safe.\n* This is prepended to resolved ids that are not valid browser\n* import specifiers by the importAnalysis plugin.\n*/\nfunction wrapId(id) {\n\treturn id.startsWith(VALID_ID_PREFIX) ? id : VALID_ID_PREFIX + id.replace(\"\\0\", NULL_BYTE_PLACEHOLDER);\n}\n/**\n* Undo {@link wrapId}'s `/@id/` and null byte replacements.\n*/\nfunction unwrapId(id) {\n\treturn id.startsWith(VALID_ID_PREFIX) ? id.slice(VALID_ID_PREFIX.length).replace(NULL_BYTE_PLACEHOLDER, \"\\0\") : id;\n}\nfunction withTrailingSlash(path) {\n\tif (path.at(-1) !== \"/\") {\n\t\treturn `${path}/`;\n\t}\n\treturn path;\n}\nconst bareImportRE = /^(?![a-z]:)[\\w@](?!.*:\\/\\/)/i;\nfunction isBareImport(id) {\n\treturn bareImportRE.test(id);\n}\nfunction toArray(array) {\n\tif (array === null || array === undefined) {\n\t\tarray = [];\n\t}\n\tif (Array.isArray(array)) {\n\t\treturn array;\n\t}\n\treturn [array];\n}\nfunction isObject(item) {\n\treturn item != null && typeof item === \"object\" && !Array.isArray(item);\n}\nfunction isFinalObj(obj) {\n\treturn obj === Object.prototype || obj === Function.prototype || obj === RegExp.prototype;\n}\nfunction getType(value) {\n\treturn Object.prototype.toString.apply(value).slice(8, -1);\n}\nfunction collectOwnProperties(obj, collector) {\n\tconst collect = typeof collector === \"function\" ? collector : (key) => collector.add(key);\n\tObject.getOwnPropertyNames(obj).forEach(collect);\n\tObject.getOwnPropertySymbols(obj).forEach(collect);\n}\nfunction getOwnProperties(obj) {\n\tconst ownProps = new Set();\n\tif (isFinalObj(obj)) {\n\t\treturn [];\n\t}\n\tcollectOwnProperties(obj, ownProps);\n\treturn Array.from(ownProps);\n}\nconst defaultCloneOptions = { forceWritable: false };\nfunction deepClone(val, options = defaultCloneOptions) {\n\tconst seen = new WeakMap();\n\treturn clone(val, seen, options);\n}\nfunction clone(val, seen, options = defaultCloneOptions) {\n\tlet k, out;\n\tif (seen.has(val)) {\n\t\treturn seen.get(val);\n\t}\n\tif (Array.isArray(val)) {\n\t\tout = Array.from({ length: k = val.length });\n\t\tseen.set(val, out);\n\t\twhile (k--) {\n\t\t\tout[k] = clone(val[k], seen, options);\n\t\t}\n\t\treturn out;\n\t}\n\tif (Object.prototype.toString.call(val) === \"[object Object]\") {\n\t\tout = Object.create(Object.getPrototypeOf(val));\n\t\tseen.set(val, out);\n\t\t// we don't need properties from prototype\n\t\tconst props = getOwnProperties(val);\n\t\tfor (const k of props) {\n\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(val, k);\n\t\t\tif (!descriptor) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst cloned = clone(val[k], seen, options);\n\t\t\tif (options.forceWritable) {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\tenumerable: descriptor.enumerable,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: cloned\n\t\t\t\t});\n\t\t\t} else if (\"get\" in descriptor) {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\t...descriptor,\n\t\t\t\t\tget() {\n\t\t\t\t\t\treturn cloned;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\t...descriptor,\n\t\t\t\t\tvalue: cloned\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn out;\n\t}\n\treturn val;\n}\nfunction noop() {}\nfunction objectAttr(source, path, defaultValue = undefined) {\n\t// a[3].b -> a.3.b\n\tconst paths = path.replace(/\\[(\\d+)\\]/g, \".$1\").split(\".\");\n\tlet result = source;\n\tfor (const p of paths) {\n\t\tresult = new Object(result)[p];\n\t\tif (result === undefined) {\n\t\t\treturn defaultValue;\n\t\t}\n\t}\n\treturn result;\n}\nfunction createDefer() {\n\tlet resolve = null;\n\tlet reject = null;\n\tconst p = new Promise((_resolve, _reject) => {\n\t\tresolve = _resolve;\n\t\treject = _reject;\n\t});\n\tp.resolve = resolve;\n\tp.reject = reject;\n\treturn p;\n}\n/**\n* If code starts with a function call, will return its last index, respecting arguments.\n* This will return 25 - last ending character of toMatch \")\"\n* Also works with callbacks\n* ```\n* toMatch({ test: '123' });\n* toBeAliased('123')\n* ```\n*/\nfunction getCallLastIndex(code) {\n\tlet charIndex = -1;\n\tlet inString = null;\n\tlet startedBracers = 0;\n\tlet endedBracers = 0;\n\tlet beforeChar = null;\n\twhile (charIndex <= code.length) {\n\t\tbeforeChar = code[charIndex];\n\t\tcharIndex++;\n\t\tconst char = code[charIndex];\n\t\tconst isCharString = char === \"\\\"\" || char === \"'\" || char === \"`\";\n\t\tif (isCharString && beforeChar !== \"\\\\\") {\n\t\t\tif (inString === char) {\n\t\t\t\tinString = null;\n\t\t\t} else if (!inString) {\n\t\t\t\tinString = char;\n\t\t\t}\n\t\t}\n\t\tif (!inString) {\n\t\t\tif (char === \"(\") {\n\t\t\t\tstartedBracers++;\n\t\t\t}\n\t\t\tif (char === \")\") {\n\t\t\t\tendedBracers++;\n\t\t\t}\n\t\t}\n\t\tif (startedBracers && endedBracers && startedBracers === endedBracers) {\n\t\t\treturn charIndex;\n\t\t}\n\t}\n\treturn null;\n}\nfunction isNegativeNaN(val) {\n\tif (!Number.isNaN(val)) {\n\t\treturn false;\n\t}\n\tconst f64 = new Float64Array(1);\n\tf64[0] = val;\n\tconst u32 = new Uint32Array(f64.buffer);\n\tconst isNegative = u32[1] >>> 31 === 1;\n\treturn isNegative;\n}\nfunction toString(v) {\n\treturn Object.prototype.toString.call(v);\n}\nfunction isPlainObject(val) {\n\treturn toString(val) === \"[object Object]\" && (!val.constructor || val.constructor.name === \"Object\");\n}\nfunction isMergeableObject(item) {\n\treturn isPlainObject(item) && !Array.isArray(item);\n}\n/**\n* Deep merge :P\n*\n* Will merge objects only if they are plain\n*\n* Do not merge types - it is very expensive and usually it's better to case a type here\n*/\nfunction deepMerge(target, ...sources) {\n\tif (!sources.length) {\n\t\treturn target;\n\t}\n\tconst source = sources.shift();\n\tif (source === undefined) {\n\t\treturn target;\n\t}\n\tif (isMergeableObject(target) && isMergeableObject(source)) {\n\t\tObject.keys(source).forEach((key) => {\n\t\t\tconst _source = source;\n\t\t\tif (isMergeableObject(_source[key])) {\n\t\t\t\tif (!target[key]) {\n\t\t\t\t\ttarget[key] = {};\n\t\t\t\t}\n\t\t\t\tdeepMerge(target[key], _source[key]);\n\t\t\t} else {\n\t\t\t\ttarget[key] = _source[key];\n\t\t\t}\n\t\t});\n\t}\n\treturn deepMerge(target, ...sources);\n}\n\nexport { assertTypes, cleanUrl, clone, createDefer, createSimpleStackTrace, deepClone, deepMerge, getCallLastIndex, getOwnProperties, getType, isBareImport, isExternalUrl, isNegativeNaN, isObject, isPrimitive, nanoid, noop, notNullish, objectAttr, shuffle, slash, toArray, unwrapId, withTrailingSlash, wrapId };\n","import { processError } from '@vitest/utils/error';\nimport { parseSingleStack } from '@vitest/utils/source-map';\nimport { relative } from 'pathe';\nimport { toArray } from '@vitest/utils/helpers';\n\nfunction createChainable(keys, fn) {\n\tfunction create(context) {\n\t\tconst chain = function(...args) {\n\t\t\treturn fn.apply(context, args);\n\t\t};\n\t\tObject.assign(chain, fn);\n\t\tchain.withContext = () => chain.bind(context);\n\t\tchain.setContext = (key, value) => {\n\t\t\tcontext[key] = value;\n\t\t};\n\t\tchain.mergeContext = (ctx) => {\n\t\t\tObject.assign(context, ctx);\n\t\t};\n\t\tfor (const key of keys) {\n\t\t\tObject.defineProperty(chain, key, { get() {\n\t\t\t\treturn create({\n\t\t\t\t\t...context,\n\t\t\t\t\t[key]: true\n\t\t\t\t});\n\t\t\t} });\n\t\t}\n\t\treturn chain;\n\t}\n\tconst chain = create({});\n\tchain.fn = fn;\n\treturn chain;\n}\n\n/**\n* If any tasks been marked as `only`, mark all other tasks as `skip`.\n*/\nfunction interpretTaskModes(file, namePattern, testLocations, onlyMode, parentIsOnly, allowOnly) {\n\tconst matchedLocations = [];\n\tconst traverseSuite = (suite, parentIsOnly, parentMatchedWithLocation) => {\n\t\tconst suiteIsOnly = parentIsOnly || suite.mode === \"only\";\n\t\tsuite.tasks.forEach((t) => {\n\t\t\t// Check if either the parent suite or the task itself are marked as included\n\t\t\tconst includeTask = suiteIsOnly || t.mode === \"only\";\n\t\t\tif (onlyMode) {\n\t\t\t\tif (t.type === \"suite\" && (includeTask || someTasksAreOnly(t))) {\n\t\t\t\t\t// Don't skip this suite\n\t\t\t\t\tif (t.mode === \"only\") {\n\t\t\t\t\t\tcheckAllowOnly(t, allowOnly);\n\t\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t\t}\n\t\t\t\t} else if (t.mode === \"run\" && !includeTask) {\n\t\t\t\t\tt.mode = \"skip\";\n\t\t\t\t} else if (t.mode === \"only\") {\n\t\t\t\t\tcheckAllowOnly(t, allowOnly);\n\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet hasLocationMatch = parentMatchedWithLocation;\n\t\t\t// Match test location against provided locations, only run if present\n\t\t\t// in `testLocations`. Note: if `includeTaskLocations` is not enabled,\n\t\t\t// all test will be skipped.\n\t\t\tif (testLocations !== undefined && testLocations.length !== 0) {\n\t\t\t\tif (t.location && (testLocations === null || testLocations === void 0 ? void 0 : testLocations.includes(t.location.line))) {\n\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t\tmatchedLocations.push(t.location.line);\n\t\t\t\t\thasLocationMatch = true;\n\t\t\t\t} else if (parentMatchedWithLocation) {\n\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t} else if (t.type === \"test\") {\n\t\t\t\t\tt.mode = \"skip\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (t.type === \"test\") {\n\t\t\t\tif (namePattern && !getTaskFullName(t).match(namePattern)) {\n\t\t\t\t\tt.mode = \"skip\";\n\t\t\t\t}\n\t\t\t} else if (t.type === \"suite\") {\n\t\t\t\tif (t.mode === \"skip\") {\n\t\t\t\t\tskipAllTasks(t);\n\t\t\t\t} else if (t.mode === \"todo\") {\n\t\t\t\t\ttodoAllTasks(t);\n\t\t\t\t} else {\n\t\t\t\t\ttraverseSuite(t, includeTask, hasLocationMatch);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t// if all subtasks are skipped, mark as skip\n\t\tif (suite.mode === \"run\" || suite.mode === \"queued\") {\n\t\t\tif (suite.tasks.length && suite.tasks.every((i) => i.mode !== \"run\" && i.mode !== \"queued\")) {\n\t\t\t\tsuite.mode = \"skip\";\n\t\t\t}\n\t\t}\n\t};\n\ttraverseSuite(file, parentIsOnly, false);\n\tconst nonMatching = testLocations === null || testLocations === void 0 ? void 0 : testLocations.filter((loc) => !matchedLocations.includes(loc));\n\tif (nonMatching && nonMatching.length !== 0) {\n\t\tconst message = nonMatching.length === 1 ? `line ${nonMatching[0]}` : `lines ${nonMatching.join(\", \")}`;\n\t\tif (file.result === undefined) {\n\t\t\tfile.result = {\n\t\t\t\tstate: \"fail\",\n\t\t\t\terrors: []\n\t\t\t};\n\t\t}\n\t\tif (file.result.errors === undefined) {\n\t\t\tfile.result.errors = [];\n\t\t}\n\t\tfile.result.errors.push(processError(new Error(`No test found in ${file.name} in ${message}`)));\n\t}\n}\nfunction getTaskFullName(task) {\n\treturn `${task.suite ? `${getTaskFullName(task.suite)} ` : \"\"}${task.name}`;\n}\nfunction someTasksAreOnly(suite) {\n\treturn suite.tasks.some((t) => t.mode === \"only\" || t.type === \"suite\" && someTasksAreOnly(t));\n}\nfunction skipAllTasks(suite) {\n\tsuite.tasks.forEach((t) => {\n\t\tif (t.mode === \"run\" || t.mode === \"queued\") {\n\t\t\tt.mode = \"skip\";\n\t\t\tif (t.type === \"suite\") {\n\t\t\t\tskipAllTasks(t);\n\t\t\t}\n\t\t}\n\t});\n}\nfunction todoAllTasks(suite) {\n\tsuite.tasks.forEach((t) => {\n\t\tif (t.mode === \"run\" || t.mode === \"queued\") {\n\t\t\tt.mode = \"todo\";\n\t\t\tif (t.type === \"suite\") {\n\t\t\t\ttodoAllTasks(t);\n\t\t\t}\n\t\t}\n\t});\n}\nfunction checkAllowOnly(task, allowOnly) {\n\tif (allowOnly) {\n\t\treturn;\n\t}\n\tconst error = processError(new Error(\"[Vitest] Unexpected .only modifier. Remove it or pass --allowOnly argument to bypass this error\"));\n\ttask.result = {\n\t\tstate: \"fail\",\n\t\terrors: [error]\n\t};\n}\n/* @__NO_SIDE_EFFECTS__ */\nfunction generateHash(str) {\n\tlet hash = 0;\n\tif (str.length === 0) {\n\t\treturn `${hash}`;\n\t}\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst char = str.charCodeAt(i);\n\t\thash = (hash << 5) - hash + char;\n\t\thash = hash & hash;\n\t}\n\treturn `${hash}`;\n}\nfunction calculateSuiteHash(parent) {\n\tparent.tasks.forEach((t, idx) => {\n\t\tt.id = `${parent.id}_${idx}`;\n\t\tif (t.type === \"suite\") {\n\t\t\tcalculateSuiteHash(t);\n\t\t}\n\t});\n}\nfunction createFileTask(filepath, root, projectName, pool, viteEnvironment) {\n\tconst path = relative(root, filepath);\n\tconst file = {\n\t\tid: generateFileHash(path, projectName),\n\t\tname: path,\n\t\tfullName: path,\n\t\ttype: \"suite\",\n\t\tmode: \"queued\",\n\t\tfilepath,\n\t\ttasks: [],\n\t\tmeta: Object.create(null),\n\t\tprojectName,\n\t\tfile: undefined,\n\t\tpool,\n\t\tviteEnvironment\n\t};\n\tfile.file = file;\n\treturn file;\n}\n/**\n* Generate a unique ID for a file based on its path and project name\n* @param file File relative to the root of the project to keep ID the same between different machines\n* @param projectName The name of the test project\n*/\n/* @__NO_SIDE_EFFECTS__ */\nfunction generateFileHash(file, projectName) {\n\treturn /* @__PURE__ */ generateHash(`${file}${projectName || \"\"}`);\n}\nfunction findTestFileStackTrace(testFilePath, error) {\n\t// first line is the error message\n\tconst lines = error.split(\"\\n\").slice(1);\n\tfor (const line of lines) {\n\t\tconst stack = parseSingleStack(line);\n\t\tif (stack && stack.file === testFilePath) {\n\t\t\treturn stack;\n\t\t}\n\t}\n}\n\n/**\n* Return a function for running multiple async operations with limited concurrency.\n*/\nfunction limitConcurrency(concurrency = Infinity) {\n\t// The number of currently active + pending tasks.\n\tlet count = 0;\n\t// The head and tail of the pending task queue, built using a singly linked list.\n\t// Both head and tail are initially undefined, signifying an empty queue.\n\t// They both become undefined again whenever there are no pending tasks.\n\tlet head;\n\tlet tail;\n\t// A bookkeeping function executed whenever a task has been run to completion.\n\tconst finish = () => {\n\t\tcount--;\n\t\t// Check if there are further pending tasks in the queue.\n\t\tif (head) {\n\t\t\t// Allow the next pending task to run and pop it from the queue.\n\t\t\thead[0]();\n\t\t\thead = head[1];\n\t\t\t// The head may now be undefined if there are no further pending tasks.\n\t\t\t// In that case, set tail to undefined as well.\n\t\t\ttail = head && tail;\n\t\t}\n\t};\n\treturn (func, ...args) => {\n\t\t// Create a promise chain that:\n\t\t// 1. Waits for its turn in the task queue (if necessary).\n\t\t// 2. Runs the task.\n\t\t// 3. Allows the next pending task (if any) to run.\n\t\treturn new Promise((resolve) => {\n\t\t\tif (count++ < concurrency) {\n\t\t\t\t// No need to queue if fewer than maxConcurrency tasks are running.\n\t\t\t\tresolve();\n\t\t\t} else if (tail) {\n\t\t\t\t// There are pending tasks, so append to the queue.\n\t\t\t\ttail = tail[1] = [resolve];\n\t\t\t} else {\n\t\t\t\t// No other pending tasks, initialize the queue with a new tail and head.\n\t\t\t\thead = tail = [resolve];\n\t\t\t}\n\t\t}).then(() => {\n\t\t\t// Running func here ensures that even a non-thenable result or an\n\t\t\t// immediately thrown error gets wrapped into a Promise.\n\t\t\treturn func(...args);\n\t\t}).finally(finish);\n\t};\n}\n\n/**\n* Partition in tasks groups by consecutive concurrent\n*/\nfunction partitionSuiteChildren(suite) {\n\tlet tasksGroup = [];\n\tconst tasksGroups = [];\n\tfor (const c of suite.tasks) {\n\t\tif (tasksGroup.length === 0 || c.concurrent === tasksGroup[0].concurrent) {\n\t\t\ttasksGroup.push(c);\n\t\t} else {\n\t\t\ttasksGroups.push(tasksGroup);\n\t\t\ttasksGroup = [c];\n\t\t}\n\t}\n\tif (tasksGroup.length > 0) {\n\t\ttasksGroups.push(tasksGroup);\n\t}\n\treturn tasksGroups;\n}\n\nfunction isTestCase(s) {\n\treturn s.type === \"test\";\n}\nfunction getTests(suite) {\n\tconst tests = [];\n\tconst arraySuites = toArray(suite);\n\tfor (const s of arraySuites) {\n\t\tif (isTestCase(s)) {\n\t\t\ttests.push(s);\n\t\t} else {\n\t\t\tfor (const task of s.tasks) {\n\t\t\t\tif (isTestCase(task)) {\n\t\t\t\t\ttests.push(task);\n\t\t\t\t} else {\n\t\t\t\t\tconst taskTests = getTests(task);\n\t\t\t\t\tfor (const test of taskTests) {\n\t\t\t\t\t\ttests.push(test);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn tests;\n}\nfunction getTasks(tasks = []) {\n\treturn toArray(tasks).flatMap((s) => isTestCase(s) ? [s] : [s, ...getTasks(s.tasks)]);\n}\nfunction getSuites(suite) {\n\treturn toArray(suite).flatMap((s) => s.type === \"suite\" ? [s, ...getSuites(s.tasks)] : []);\n}\nfunction hasTests(suite) {\n\treturn toArray(suite).some((s) => s.tasks.some((c) => isTestCase(c) || hasTests(c)));\n}\nfunction hasFailed(suite) {\n\treturn toArray(suite).some((s) => {\n\t\tvar _s$result;\n\t\treturn ((_s$result = s.result) === null || _s$result === void 0 ? void 0 : _s$result.state) === \"fail\" || s.type === \"suite\" && hasFailed(s.tasks);\n\t});\n}\nfunction getNames(task) {\n\tconst names = [task.name];\n\tlet current = task;\n\twhile (current === null || current === void 0 ? void 0 : current.suite) {\n\t\tcurrent = current.suite;\n\t\tif (current === null || current === void 0 ? void 0 : current.name) {\n\t\t\tnames.unshift(current.name);\n\t\t}\n\t}\n\tif (current !== task.file) {\n\t\tnames.unshift(task.file.name);\n\t}\n\treturn names;\n}\nfunction getFullName(task, separator = \" > \") {\n\treturn getNames(task).join(separator);\n}\nfunction getTestName(task, separator = \" > \") {\n\treturn getNames(task).slice(1).join(separator);\n}\nfunction createTaskName(names, separator = \" > \") {\n\treturn names.filter((name) => name !== undefined).join(separator);\n}\n\nexport { calculateSuiteHash as a, createFileTask as b, createChainable as c, generateHash as d, createTaskName as e, findTestFileStackTrace as f, generateFileHash as g, getFullName as h, interpretTaskModes as i, getNames as j, getSuites as k, limitConcurrency as l, getTasks as m, getTestName as n, getTests as o, partitionSuiteChildren as p, hasFailed as q, hasTests as r, someTasksAreOnly as s, isTestCase as t };\n","import { getTests } from '@vitest/runner/utils';\nimport c from 'tinyrainbow';\nimport type { RunnerTask } from 'vitest';\nimport type { Vitest } from 'vitest/node';\nimport type { Reporter } from 'vitest/reporters';\n\nexport default class TinyReporter implements Reporter {\n // biome-ignore lint/style/noNonNullAssertion: Non-null assertion is allowed here because the onInit method is called before any other method\n ctx: Vitest = undefined!;\n protected verbose = false;\n\n onInit(ctx: Vitest) {\n this.ctx = ctx;\n }\n\n onFinished(\n files = this.ctx.state.getFiles(),\n errors = this.ctx.state.getUnhandledErrors(),\n ) {\n const { logger } = this.ctx;\n const tests = getTests(files);\n const failedTests = tests.filter((i) => i.result?.state === 'fail').length;\n\n const passed = !(failedTests + errors.length);\n const status = passed ? '\\u2714 PASS' : '\\u2716 FAIL';\n const statusColor = passed ? c.green : c.red;\n\n logger.log(\n `${statusColor(c.bold(c.inverse(` ${status} `)))} ${statusColor(\n passed\n ? 'All tests passed'\n : `${failedTests} test${failedTests > 1 ? 's' : ''} failed`,\n )}`,\n );\n logger.log(this.padTitle('Test Files'), this.getStateString(files));\n logger.log(this.padTitle('Tests'), this.getStateString(tests));\n\n if (errors.length) {\n logger.log(\n this.padTitle('Errors'),\n c.bold(c.red(`${errors.length} error${errors.length > 1 ? 's' : ''}`)),\n );\n }\n\n if (!passed) {\n process.exitCode = 1;\n }\n }\n\n padTitle = (str: string) => c.dim(`${str.padStart(11)} `);\n\n getStateString(tasks: RunnerTask[], name = 'tests') {\n if (!tasks.length) {\n return c.dim(`no ${name}`);\n }\n\n const passed = tasks.filter((i) => i.result?.state === 'pass').length;\n const failed = tasks.filter((i) => i.result?.state === 'fail').length;\n const skipped = tasks.filter((i) => i.mode === 'skip').length;\n const todo = tasks.filter((i) => i.mode === 'todo').length;\n\n return (\n [\n failed && c.bold(c.red(`${failed} failed`)),\n passed && c.bold(c.green(`${passed} passed`)),\n skipped && c.yellow(`${skipped} skipped`),\n todo && c.gray(`${todo} todo`),\n ]\n .filter(Boolean)\n .join(c.dim(' | ')) + c.gray(` (${tasks.length})`)\n );\n }\n}\n"],"names":["toArray","array","isTestCase","getTests","suite","tests","arraySuites","s","task","taskTests","test","TinyReporter","ctx","files","errors","logger","failedTests","i","passed","status","statusColor","c","str","tasks","name","failed","skipped","todo"],"mappings":";AA8FA,SAASA,EAAQC,GAAO;AAIvB,SAHIA,KAAU,SACbA,IAAQ,CAAA,IAEL,MAAM,QAAQA,CAAK,IACfA,IAED,CAACA,CAAK;AACd;AC2KA,SAASC,EAAW,GAAG;AACtB,SAAO,EAAE,SAAS;AACnB;AACA,SAASC,EAASC,GAAO;AACxB,QAAMC,IAAQ,CAAA,GACRC,IAAcN,EAAQI,CAAK;AACjC,aAAWG,KAAKD;AACf,QAAIJ,EAAWK,CAAC;AACf,MAAAF,EAAM,KAAKE,CAAC;AAAA;AAEZ,iBAAWC,KAAQD,EAAE;AACpB,YAAIL,EAAWM,CAAI;AAClB,UAAAH,EAAM,KAAKG,CAAI;AAAA,aACT;AACN,gBAAMC,IAAYN,EAASK,CAAI;AAC/B,qBAAWE,KAAQD;AAClB,YAAAJ,EAAM,KAAKK,CAAI;AAAA,QAEjB;AAIH,SAAOL;AACR;AClSA,MAAqBM,EAAiC;AAAA;AAAA,EAEpD,MAAc;AAAA,EACJ,UAAU;AAAA,EAEpB,OAAOC,GAAa;AAClB,SAAK,MAAMA;AAAA,EACb;AAAA,EAEA,WACEC,IAAQ,KAAK,IAAI,MAAM,YACvBC,IAAS,KAAK,IAAI,MAAM,mBAAA,GACxB;AACA,UAAM,EAAE,QAAAC,MAAW,KAAK,KAClBV,IAAQF,EAASU,CAAK,GACtBG,IAAcX,EAAM,OAAO,CAACY,MAAMA,EAAE,QAAQ,UAAU,MAAM,EAAE,QAE9DC,IAAS,EAAEF,IAAcF,EAAO,SAChCK,IAASD,IAAS,WAAgB,UAClCE,IAAcF,IAASG,EAAE,QAAQA,EAAE;AAEzC,IAAAN,EAAO;AAAA,MACL,GAAGK,EAAYC,EAAE,KAAKA,EAAE,QAAQ,IAAIF,CAAM,GAAG,CAAC,CAAC,CAAC,IAAIC;AAAA,QAClDF,IACI,qBACA,GAAGF,CAAW,QAAQA,IAAc,IAAI,MAAM,EAAE;AAAA,MAAA,CACrD;AAAA,IAAA,GAEHD,EAAO,IAAI,KAAK,SAAS,YAAY,GAAG,KAAK,eAAeF,CAAK,CAAC,GAClEE,EAAO,IAAI,KAAK,SAAS,OAAO,GAAG,KAAK,eAAeV,CAAK,CAAC,GAEzDS,EAAO,UACTC,EAAO;AAAA,MACL,KAAK,SAAS,QAAQ;AAAA,MACtBM,EAAE,KAAKA,EAAE,IAAI,GAAGP,EAAO,MAAM,SAASA,EAAO,SAAS,IAAI,MAAM,EAAE,EAAE,CAAC;AAAA,IAAA,GAIpEI,MACH,QAAQ,WAAW;AAAA,EAEvB;AAAA,EAEA,WAAW,CAACI,MAAgBD,EAAE,IAAI,GAAGC,EAAI,SAAS,EAAE,CAAC,GAAG;AAAA,EAExD,eAAeC,GAAqBC,IAAO,SAAS;AAClD,QAAI,CAACD,EAAM;AACT,aAAOF,EAAE,IAAI,MAAMG,CAAI,EAAE;AAG3B,UAAMN,IAASK,EAAM,OAAO,CAACN,MAAMA,EAAE,QAAQ,UAAU,MAAM,EAAE,QACzDQ,IAASF,EAAM,OAAO,CAACN,MAAMA,EAAE,QAAQ,UAAU,MAAM,EAAE,QACzDS,IAAUH,EAAM,OAAO,CAACN,MAAMA,EAAE,SAAS,MAAM,EAAE,QACjDU,IAAOJ,EAAM,OAAO,CAACN,MAAMA,EAAE,SAAS,MAAM,EAAE;AAEpD,WACE;AAAA,MACEQ,KAAUJ,EAAE,KAAKA,EAAE,IAAI,GAAGI,CAAM,SAAS,CAAC;AAAA,MAC1CP,KAAUG,EAAE,KAAKA,EAAE,MAAM,GAAGH,CAAM,SAAS,CAAC;AAAA,MAC5CQ,KAAWL,EAAE,OAAO,GAAGK,CAAO,UAAU;AAAA,MACxCC,KAAQN,EAAE,KAAK,GAAGM,CAAI,OAAO;AAAA,IAAA,EAE5B,OAAO,OAAO,EACd,KAAKN,EAAE,IAAI,KAAK,CAAC,IAAIA,EAAE,KAAK,KAAKE,EAAM,MAAM,GAAG;AAAA,EAEvD;AACF;","x_google_ignoreList":[0,1]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(t,f){typeof exports=="object"&&typeof module<"u"?module.exports=f(require("tinyrainbow")):typeof define=="function"&&define.amd?define(["tinyrainbow"],f):(t=typeof globalThis<"u"?globalThis:t||self,t["vitest-tiny-reporter"]=f(t.tinyrainbow))})(this,function(t){"use strict";function f(s){return s==null&&(s=[]),Array.isArray(s)?s:[s]}function u(s){return s.type==="test"}function g(s){const e=[],r=f(s);for(const n of r)if(u(n))e.push(n);else for(const i of n.tasks)if(u(i))e.push(i);else{const d=g(i);for(const o of d)e.push(o)}return e}class h{ctx=void 0;verbose=!1;onInit(e){this.ctx=e}onFinished(e=this.ctx.state.getFiles(),r=this.ctx.state.getUnhandledErrors()){const{logger:n}=this.ctx,i=g(e),d=i.filter(p=>p.result?.state==="fail").length,o=!(d+r.length),l=o?"✔ PASS":"✖ FAIL",a=o?t.green:t.red;n.log(`${a(t.bold(t.inverse(` ${l} `)))} ${a(o?"All tests passed":`${d} test${d>1?"s":""} failed`)}`),n.log(this.padTitle("Test Files"),this.getStateString(e)),n.log(this.padTitle("Tests"),this.getStateString(i)),r.length&&n.log(this.padTitle("Errors"),t.bold(t.red(`${r.length} error${r.length>1?"s":""}`))),o||(process.exitCode=1)}padTitle=e=>t.dim(`${e.padStart(11)} `);getStateString(e,r="tests"){if(!e.length)return t.dim(`no ${r}`);const n=e.filter(l=>l.result?.state==="pass").length,i=e.filter(l=>l.result?.state==="fail").length,d=e.filter(l=>l.mode==="skip").length,o=e.filter(l=>l.mode==="todo").length;return[i&&t.bold(t.red(`${i} failed`)),n&&t.bold(t.green(`${n} passed`)),d&&t.yellow(`${d} skipped`),o&&t.gray(`${o} todo`)].filter(Boolean).join(t.dim(" | "))+t.gray(` (${e.length})`)}}return h});
|
|
1
|
+
(function(t,f){typeof exports=="object"&&typeof module<"u"?module.exports=f(require("tinyrainbow")):typeof define=="function"&&define.amd?define(["tinyrainbow"],f):(t=typeof globalThis<"u"?globalThis:t||self,t["vitest-tiny-reporter"]=f(t.tinyrainbow))})(this,(function(t){"use strict";function f(s){return s==null&&(s=[]),Array.isArray(s)?s:[s]}function u(s){return s.type==="test"}function g(s){const e=[],r=f(s);for(const n of r)if(u(n))e.push(n);else for(const i of n.tasks)if(u(i))e.push(i);else{const d=g(i);for(const o of d)e.push(o)}return e}class h{ctx=void 0;verbose=!1;onInit(e){this.ctx=e}onFinished(e=this.ctx.state.getFiles(),r=this.ctx.state.getUnhandledErrors()){const{logger:n}=this.ctx,i=g(e),d=i.filter(p=>p.result?.state==="fail").length,o=!(d+r.length),l=o?"✔ PASS":"✖ FAIL",a=o?t.green:t.red;n.log(`${a(t.bold(t.inverse(` ${l} `)))} ${a(o?"All tests passed":`${d} test${d>1?"s":""} failed`)}`),n.log(this.padTitle("Test Files"),this.getStateString(e)),n.log(this.padTitle("Tests"),this.getStateString(i)),r.length&&n.log(this.padTitle("Errors"),t.bold(t.red(`${r.length} error${r.length>1?"s":""}`))),o||(process.exitCode=1)}padTitle=e=>t.dim(`${e.padStart(11)} `);getStateString(e,r="tests"){if(!e.length)return t.dim(`no ${r}`);const n=e.filter(l=>l.result?.state==="pass").length,i=e.filter(l=>l.result?.state==="fail").length,d=e.filter(l=>l.mode==="skip").length,o=e.filter(l=>l.mode==="todo").length;return[i&&t.bold(t.red(`${i} failed`)),n&&t.bold(t.green(`${n} passed`)),d&&t.yellow(`${d} skipped`),o&&t.gray(`${o} todo`)].filter(Boolean).join(t.dim(" | "))+t.gray(` (${e.length})`)}}return h}));
|
|
2
2
|
//# sourceMappingURL=vitest-tiny-reporter.umd.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest-tiny-reporter.umd.cjs","sources":["../node_modules/@vitest/utils/dist/helpers.js","../node_modules/@vitest/runner/dist/chunk-tasks.js","../src/index.ts"],"sourcesContent":["import { VALID_ID_PREFIX, NULL_BYTE_PLACEHOLDER } from './constants.js';\n\n// port from nanoid\n// https://github.com/ai/nanoid\nconst urlAlphabet = \"useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict\";\nfunction nanoid(size = 21) {\n\tlet id = \"\";\n\tlet i = size;\n\twhile (i--) {\n\t\tid += urlAlphabet[Math.random() * 64 | 0];\n\t}\n\treturn id;\n}\n\nconst RealDate = Date;\nfunction random(seed) {\n\tconst x = Math.sin(seed++) * 1e4;\n\treturn x - Math.floor(x);\n}\nfunction shuffle(array, seed = RealDate.now()) {\n\tlet length = array.length;\n\twhile (length) {\n\t\tconst index = Math.floor(random(seed) * length--);\n\t\tconst previous = array[length];\n\t\tarray[length] = array[index];\n\t\tarray[index] = previous;\n\t\t++seed;\n\t}\n\treturn array;\n}\n\n/**\n* Get original stacktrace without source map support the most performant way.\n* - Create only 1 stack frame.\n* - Rewrite prepareStackTrace to bypass \"support-stack-trace\" (usually takes ~250ms).\n*/\nfunction createSimpleStackTrace(options) {\n\tconst { message = \"$$stack trace error\", stackTraceLimit = 1 } = options || {};\n\tconst limit = Error.stackTraceLimit;\n\tconst prepareStackTrace = Error.prepareStackTrace;\n\tError.stackTraceLimit = stackTraceLimit;\n\tError.prepareStackTrace = (e) => e.stack;\n\tconst err = new Error(message);\n\tconst stackTrace = err.stack || \"\";\n\tError.prepareStackTrace = prepareStackTrace;\n\tError.stackTraceLimit = limit;\n\treturn stackTrace;\n}\nfunction notNullish(v) {\n\treturn v != null;\n}\nfunction assertTypes(value, name, types) {\n\tconst receivedType = typeof value;\n\tconst pass = types.includes(receivedType);\n\tif (!pass) {\n\t\tthrow new TypeError(`${name} value must be ${types.join(\" or \")}, received \"${receivedType}\"`);\n\t}\n}\nfunction isPrimitive(value) {\n\treturn value === null || typeof value !== \"function\" && typeof value !== \"object\";\n}\nfunction slash(path) {\n\treturn path.replace(/\\\\/g, \"/\");\n}\nconst postfixRE = /[?#].*$/;\nfunction cleanUrl(url) {\n\treturn url.replace(postfixRE, \"\");\n}\nconst externalRE = /^(?:[a-z]+:)?\\/\\//;\nconst isExternalUrl = (url) => externalRE.test(url);\n/**\n* Prepend `/@id/` and replace null byte so the id is URL-safe.\n* This is prepended to resolved ids that are not valid browser\n* import specifiers by the importAnalysis plugin.\n*/\nfunction wrapId(id) {\n\treturn id.startsWith(VALID_ID_PREFIX) ? id : VALID_ID_PREFIX + id.replace(\"\\0\", NULL_BYTE_PLACEHOLDER);\n}\n/**\n* Undo {@link wrapId}'s `/@id/` and null byte replacements.\n*/\nfunction unwrapId(id) {\n\treturn id.startsWith(VALID_ID_PREFIX) ? id.slice(VALID_ID_PREFIX.length).replace(NULL_BYTE_PLACEHOLDER, \"\\0\") : id;\n}\nfunction withTrailingSlash(path) {\n\tif (path.at(-1) !== \"/\") {\n\t\treturn `${path}/`;\n\t}\n\treturn path;\n}\nconst bareImportRE = /^(?![a-z]:)[\\w@](?!.*:\\/\\/)/i;\nfunction isBareImport(id) {\n\treturn bareImportRE.test(id);\n}\nfunction toArray(array) {\n\tif (array === null || array === undefined) {\n\t\tarray = [];\n\t}\n\tif (Array.isArray(array)) {\n\t\treturn array;\n\t}\n\treturn [array];\n}\nfunction isObject(item) {\n\treturn item != null && typeof item === \"object\" && !Array.isArray(item);\n}\nfunction isFinalObj(obj) {\n\treturn obj === Object.prototype || obj === Function.prototype || obj === RegExp.prototype;\n}\nfunction getType(value) {\n\treturn Object.prototype.toString.apply(value).slice(8, -1);\n}\nfunction collectOwnProperties(obj, collector) {\n\tconst collect = typeof collector === \"function\" ? collector : (key) => collector.add(key);\n\tObject.getOwnPropertyNames(obj).forEach(collect);\n\tObject.getOwnPropertySymbols(obj).forEach(collect);\n}\nfunction getOwnProperties(obj) {\n\tconst ownProps = new Set();\n\tif (isFinalObj(obj)) {\n\t\treturn [];\n\t}\n\tcollectOwnProperties(obj, ownProps);\n\treturn Array.from(ownProps);\n}\nconst defaultCloneOptions = { forceWritable: false };\nfunction deepClone(val, options = defaultCloneOptions) {\n\tconst seen = new WeakMap();\n\treturn clone(val, seen, options);\n}\nfunction clone(val, seen, options = defaultCloneOptions) {\n\tlet k, out;\n\tif (seen.has(val)) {\n\t\treturn seen.get(val);\n\t}\n\tif (Array.isArray(val)) {\n\t\tout = Array.from({ length: k = val.length });\n\t\tseen.set(val, out);\n\t\twhile (k--) {\n\t\t\tout[k] = clone(val[k], seen, options);\n\t\t}\n\t\treturn out;\n\t}\n\tif (Object.prototype.toString.call(val) === \"[object Object]\") {\n\t\tout = Object.create(Object.getPrototypeOf(val));\n\t\tseen.set(val, out);\n\t\t// we don't need properties from prototype\n\t\tconst props = getOwnProperties(val);\n\t\tfor (const k of props) {\n\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(val, k);\n\t\t\tif (!descriptor) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst cloned = clone(val[k], seen, options);\n\t\t\tif (options.forceWritable) {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\tenumerable: descriptor.enumerable,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: cloned\n\t\t\t\t});\n\t\t\t} else if (\"get\" in descriptor) {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\t...descriptor,\n\t\t\t\t\tget() {\n\t\t\t\t\t\treturn cloned;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\t...descriptor,\n\t\t\t\t\tvalue: cloned\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn out;\n\t}\n\treturn val;\n}\nfunction noop() {}\nfunction objectAttr(source, path, defaultValue = undefined) {\n\t// a[3].b -> a.3.b\n\tconst paths = path.replace(/\\[(\\d+)\\]/g, \".$1\").split(\".\");\n\tlet result = source;\n\tfor (const p of paths) {\n\t\tresult = new Object(result)[p];\n\t\tif (result === undefined) {\n\t\t\treturn defaultValue;\n\t\t}\n\t}\n\treturn result;\n}\nfunction createDefer() {\n\tlet resolve = null;\n\tlet reject = null;\n\tconst p = new Promise((_resolve, _reject) => {\n\t\tresolve = _resolve;\n\t\treject = _reject;\n\t});\n\tp.resolve = resolve;\n\tp.reject = reject;\n\treturn p;\n}\n/**\n* If code starts with a function call, will return its last index, respecting arguments.\n* This will return 25 - last ending character of toMatch \")\"\n* Also works with callbacks\n* ```\n* toMatch({ test: '123' });\n* toBeAliased('123')\n* ```\n*/\nfunction getCallLastIndex(code) {\n\tlet charIndex = -1;\n\tlet inString = null;\n\tlet startedBracers = 0;\n\tlet endedBracers = 0;\n\tlet beforeChar = null;\n\twhile (charIndex <= code.length) {\n\t\tbeforeChar = code[charIndex];\n\t\tcharIndex++;\n\t\tconst char = code[charIndex];\n\t\tconst isCharString = char === \"\\\"\" || char === \"'\" || char === \"`\";\n\t\tif (isCharString && beforeChar !== \"\\\\\") {\n\t\t\tif (inString === char) {\n\t\t\t\tinString = null;\n\t\t\t} else if (!inString) {\n\t\t\t\tinString = char;\n\t\t\t}\n\t\t}\n\t\tif (!inString) {\n\t\t\tif (char === \"(\") {\n\t\t\t\tstartedBracers++;\n\t\t\t}\n\t\t\tif (char === \")\") {\n\t\t\t\tendedBracers++;\n\t\t\t}\n\t\t}\n\t\tif (startedBracers && endedBracers && startedBracers === endedBracers) {\n\t\t\treturn charIndex;\n\t\t}\n\t}\n\treturn null;\n}\nfunction isNegativeNaN(val) {\n\tif (!Number.isNaN(val)) {\n\t\treturn false;\n\t}\n\tconst f64 = new Float64Array(1);\n\tf64[0] = val;\n\tconst u32 = new Uint32Array(f64.buffer);\n\tconst isNegative = u32[1] >>> 31 === 1;\n\treturn isNegative;\n}\nfunction toString(v) {\n\treturn Object.prototype.toString.call(v);\n}\nfunction isPlainObject(val) {\n\treturn toString(val) === \"[object Object]\" && (!val.constructor || val.constructor.name === \"Object\");\n}\nfunction isMergeableObject(item) {\n\treturn isPlainObject(item) && !Array.isArray(item);\n}\n/**\n* Deep merge :P\n*\n* Will merge objects only if they are plain\n*\n* Do not merge types - it is very expensive and usually it's better to case a type here\n*/\nfunction deepMerge(target, ...sources) {\n\tif (!sources.length) {\n\t\treturn target;\n\t}\n\tconst source = sources.shift();\n\tif (source === undefined) {\n\t\treturn target;\n\t}\n\tif (isMergeableObject(target) && isMergeableObject(source)) {\n\t\tObject.keys(source).forEach((key) => {\n\t\t\tconst _source = source;\n\t\t\tif (isMergeableObject(_source[key])) {\n\t\t\t\tif (!target[key]) {\n\t\t\t\t\ttarget[key] = {};\n\t\t\t\t}\n\t\t\t\tdeepMerge(target[key], _source[key]);\n\t\t\t} else {\n\t\t\t\ttarget[key] = _source[key];\n\t\t\t}\n\t\t});\n\t}\n\treturn deepMerge(target, ...sources);\n}\n\nexport { assertTypes, cleanUrl, clone, createDefer, createSimpleStackTrace, deepClone, deepMerge, getCallLastIndex, getOwnProperties, getType, isBareImport, isExternalUrl, isNegativeNaN, isObject, isPrimitive, nanoid, noop, notNullish, objectAttr, shuffle, slash, toArray, unwrapId, withTrailingSlash, wrapId };\n","import { processError } from '@vitest/utils/error';\nimport { parseSingleStack } from '@vitest/utils/source-map';\nimport { relative } from 'pathe';\nimport { toArray } from '@vitest/utils/helpers';\n\nfunction createChainable(keys, fn) {\n\tfunction create(context) {\n\t\tconst chain = function(...args) {\n\t\t\treturn fn.apply(context, args);\n\t\t};\n\t\tObject.assign(chain, fn);\n\t\tchain.withContext = () => chain.bind(context);\n\t\tchain.setContext = (key, value) => {\n\t\t\tcontext[key] = value;\n\t\t};\n\t\tchain.mergeContext = (ctx) => {\n\t\t\tObject.assign(context, ctx);\n\t\t};\n\t\tfor (const key of keys) {\n\t\t\tObject.defineProperty(chain, key, { get() {\n\t\t\t\treturn create({\n\t\t\t\t\t...context,\n\t\t\t\t\t[key]: true\n\t\t\t\t});\n\t\t\t} });\n\t\t}\n\t\treturn chain;\n\t}\n\tconst chain = create({});\n\tchain.fn = fn;\n\treturn chain;\n}\n\n/**\n* If any tasks been marked as `only`, mark all other tasks as `skip`.\n*/\nfunction interpretTaskModes(file, namePattern, testLocations, onlyMode, parentIsOnly, allowOnly) {\n\tconst matchedLocations = [];\n\tconst traverseSuite = (suite, parentIsOnly, parentMatchedWithLocation) => {\n\t\tconst suiteIsOnly = parentIsOnly || suite.mode === \"only\";\n\t\tsuite.tasks.forEach((t) => {\n\t\t\t// Check if either the parent suite or the task itself are marked as included\n\t\t\tconst includeTask = suiteIsOnly || t.mode === \"only\";\n\t\t\tif (onlyMode) {\n\t\t\t\tif (t.type === \"suite\" && (includeTask || someTasksAreOnly(t))) {\n\t\t\t\t\t// Don't skip this suite\n\t\t\t\t\tif (t.mode === \"only\") {\n\t\t\t\t\t\tcheckAllowOnly(t, allowOnly);\n\t\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t\t}\n\t\t\t\t} else if (t.mode === \"run\" && !includeTask) {\n\t\t\t\t\tt.mode = \"skip\";\n\t\t\t\t} else if (t.mode === \"only\") {\n\t\t\t\t\tcheckAllowOnly(t, allowOnly);\n\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet hasLocationMatch = parentMatchedWithLocation;\n\t\t\t// Match test location against provided locations, only run if present\n\t\t\t// in `testLocations`. Note: if `includeTaskLocations` is not enabled,\n\t\t\t// all test will be skipped.\n\t\t\tif (testLocations !== undefined && testLocations.length !== 0) {\n\t\t\t\tif (t.location && (testLocations === null || testLocations === void 0 ? void 0 : testLocations.includes(t.location.line))) {\n\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t\tmatchedLocations.push(t.location.line);\n\t\t\t\t\thasLocationMatch = true;\n\t\t\t\t} else if (parentMatchedWithLocation) {\n\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t} else if (t.type === \"test\") {\n\t\t\t\t\tt.mode = \"skip\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (t.type === \"test\") {\n\t\t\t\tif (namePattern && !getTaskFullName(t).match(namePattern)) {\n\t\t\t\t\tt.mode = \"skip\";\n\t\t\t\t}\n\t\t\t} else if (t.type === \"suite\") {\n\t\t\t\tif (t.mode === \"skip\") {\n\t\t\t\t\tskipAllTasks(t);\n\t\t\t\t} else if (t.mode === \"todo\") {\n\t\t\t\t\ttodoAllTasks(t);\n\t\t\t\t} else {\n\t\t\t\t\ttraverseSuite(t, includeTask, hasLocationMatch);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t// if all subtasks are skipped, mark as skip\n\t\tif (suite.mode === \"run\" || suite.mode === \"queued\") {\n\t\t\tif (suite.tasks.length && suite.tasks.every((i) => i.mode !== \"run\" && i.mode !== \"queued\")) {\n\t\t\t\tsuite.mode = \"skip\";\n\t\t\t}\n\t\t}\n\t};\n\ttraverseSuite(file, parentIsOnly, false);\n\tconst nonMatching = testLocations === null || testLocations === void 0 ? void 0 : testLocations.filter((loc) => !matchedLocations.includes(loc));\n\tif (nonMatching && nonMatching.length !== 0) {\n\t\tconst message = nonMatching.length === 1 ? `line ${nonMatching[0]}` : `lines ${nonMatching.join(\", \")}`;\n\t\tif (file.result === undefined) {\n\t\t\tfile.result = {\n\t\t\t\tstate: \"fail\",\n\t\t\t\terrors: []\n\t\t\t};\n\t\t}\n\t\tif (file.result.errors === undefined) {\n\t\t\tfile.result.errors = [];\n\t\t}\n\t\tfile.result.errors.push(processError(new Error(`No test found in ${file.name} in ${message}`)));\n\t}\n}\nfunction getTaskFullName(task) {\n\treturn `${task.suite ? `${getTaskFullName(task.suite)} ` : \"\"}${task.name}`;\n}\nfunction someTasksAreOnly(suite) {\n\treturn suite.tasks.some((t) => t.mode === \"only\" || t.type === \"suite\" && someTasksAreOnly(t));\n}\nfunction skipAllTasks(suite) {\n\tsuite.tasks.forEach((t) => {\n\t\tif (t.mode === \"run\" || t.mode === \"queued\") {\n\t\t\tt.mode = \"skip\";\n\t\t\tif (t.type === \"suite\") {\n\t\t\t\tskipAllTasks(t);\n\t\t\t}\n\t\t}\n\t});\n}\nfunction todoAllTasks(suite) {\n\tsuite.tasks.forEach((t) => {\n\t\tif (t.mode === \"run\" || t.mode === \"queued\") {\n\t\t\tt.mode = \"todo\";\n\t\t\tif (t.type === \"suite\") {\n\t\t\t\ttodoAllTasks(t);\n\t\t\t}\n\t\t}\n\t});\n}\nfunction checkAllowOnly(task, allowOnly) {\n\tif (allowOnly) {\n\t\treturn;\n\t}\n\tconst error = processError(new Error(\"[Vitest] Unexpected .only modifier. Remove it or pass --allowOnly argument to bypass this error\"));\n\ttask.result = {\n\t\tstate: \"fail\",\n\t\terrors: [error]\n\t};\n}\n/* @__NO_SIDE_EFFECTS__ */\nfunction generateHash(str) {\n\tlet hash = 0;\n\tif (str.length === 0) {\n\t\treturn `${hash}`;\n\t}\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst char = str.charCodeAt(i);\n\t\thash = (hash << 5) - hash + char;\n\t\thash = hash & hash;\n\t}\n\treturn `${hash}`;\n}\nfunction calculateSuiteHash(parent) {\n\tparent.tasks.forEach((t, idx) => {\n\t\tt.id = `${parent.id}_${idx}`;\n\t\tif (t.type === \"suite\") {\n\t\t\tcalculateSuiteHash(t);\n\t\t}\n\t});\n}\nfunction createFileTask(filepath, root, projectName, pool) {\n\tconst path = relative(root, filepath);\n\tconst file = {\n\t\tid: generateFileHash(path, projectName),\n\t\tname: path,\n\t\ttype: \"suite\",\n\t\tmode: \"queued\",\n\t\tfilepath,\n\t\ttasks: [],\n\t\tmeta: Object.create(null),\n\t\tprojectName,\n\t\tfile: undefined,\n\t\tpool\n\t};\n\tfile.file = file;\n\treturn file;\n}\n/**\n* Generate a unique ID for a file based on its path and project name\n* @param file File relative to the root of the project to keep ID the same between different machines\n* @param projectName The name of the test project\n*/\n/* @__NO_SIDE_EFFECTS__ */\nfunction generateFileHash(file, projectName) {\n\treturn /* @__PURE__ */ generateHash(`${file}${projectName || \"\"}`);\n}\nfunction findTestFileStackTrace(testFilePath, error) {\n\t// first line is the error message\n\tconst lines = error.split(\"\\n\").slice(1);\n\tfor (const line of lines) {\n\t\tconst stack = parseSingleStack(line);\n\t\tif (stack && stack.file === testFilePath) {\n\t\t\treturn stack;\n\t\t}\n\t}\n}\n\n/**\n* Return a function for running multiple async operations with limited concurrency.\n*/\nfunction limitConcurrency(concurrency = Infinity) {\n\t// The number of currently active + pending tasks.\n\tlet count = 0;\n\t// The head and tail of the pending task queue, built using a singly linked list.\n\t// Both head and tail are initially undefined, signifying an empty queue.\n\t// They both become undefined again whenever there are no pending tasks.\n\tlet head;\n\tlet tail;\n\t// A bookkeeping function executed whenever a task has been run to completion.\n\tconst finish = () => {\n\t\tcount--;\n\t\t// Check if there are further pending tasks in the queue.\n\t\tif (head) {\n\t\t\t// Allow the next pending task to run and pop it from the queue.\n\t\t\thead[0]();\n\t\t\thead = head[1];\n\t\t\t// The head may now be undefined if there are no further pending tasks.\n\t\t\t// In that case, set tail to undefined as well.\n\t\t\ttail = head && tail;\n\t\t}\n\t};\n\treturn (func, ...args) => {\n\t\t// Create a promise chain that:\n\t\t// 1. Waits for its turn in the task queue (if necessary).\n\t\t// 2. Runs the task.\n\t\t// 3. Allows the next pending task (if any) to run.\n\t\treturn new Promise((resolve) => {\n\t\t\tif (count++ < concurrency) {\n\t\t\t\t// No need to queue if fewer than maxConcurrency tasks are running.\n\t\t\t\tresolve();\n\t\t\t} else if (tail) {\n\t\t\t\t// There are pending tasks, so append to the queue.\n\t\t\t\ttail = tail[1] = [resolve];\n\t\t\t} else {\n\t\t\t\t// No other pending tasks, initialize the queue with a new tail and head.\n\t\t\t\thead = tail = [resolve];\n\t\t\t}\n\t\t}).then(() => {\n\t\t\t// Running func here ensures that even a non-thenable result or an\n\t\t\t// immediately thrown error gets wrapped into a Promise.\n\t\t\treturn func(...args);\n\t\t}).finally(finish);\n\t};\n}\n\n/**\n* Partition in tasks groups by consecutive concurrent\n*/\nfunction partitionSuiteChildren(suite) {\n\tlet tasksGroup = [];\n\tconst tasksGroups = [];\n\tfor (const c of suite.tasks) {\n\t\tif (tasksGroup.length === 0 || c.concurrent === tasksGroup[0].concurrent) {\n\t\t\ttasksGroup.push(c);\n\t\t} else {\n\t\t\ttasksGroups.push(tasksGroup);\n\t\t\ttasksGroup = [c];\n\t\t}\n\t}\n\tif (tasksGroup.length > 0) {\n\t\ttasksGroups.push(tasksGroup);\n\t}\n\treturn tasksGroups;\n}\n\nfunction isTestCase(s) {\n\treturn s.type === \"test\";\n}\nfunction getTests(suite) {\n\tconst tests = [];\n\tconst arraySuites = toArray(suite);\n\tfor (const s of arraySuites) {\n\t\tif (isTestCase(s)) {\n\t\t\ttests.push(s);\n\t\t} else {\n\t\t\tfor (const task of s.tasks) {\n\t\t\t\tif (isTestCase(task)) {\n\t\t\t\t\ttests.push(task);\n\t\t\t\t} else {\n\t\t\t\t\tconst taskTests = getTests(task);\n\t\t\t\t\tfor (const test of taskTests) {\n\t\t\t\t\t\ttests.push(test);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn tests;\n}\nfunction getTasks(tasks = []) {\n\treturn toArray(tasks).flatMap((s) => isTestCase(s) ? [s] : [s, ...getTasks(s.tasks)]);\n}\nfunction getSuites(suite) {\n\treturn toArray(suite).flatMap((s) => s.type === \"suite\" ? [s, ...getSuites(s.tasks)] : []);\n}\nfunction hasTests(suite) {\n\treturn toArray(suite).some((s) => s.tasks.some((c) => isTestCase(c) || hasTests(c)));\n}\nfunction hasFailed(suite) {\n\treturn toArray(suite).some((s) => {\n\t\tvar _s$result;\n\t\treturn ((_s$result = s.result) === null || _s$result === void 0 ? void 0 : _s$result.state) === \"fail\" || s.type === \"suite\" && hasFailed(s.tasks);\n\t});\n}\nfunction getNames(task) {\n\tconst names = [task.name];\n\tlet current = task;\n\twhile (current === null || current === void 0 ? void 0 : current.suite) {\n\t\tcurrent = current.suite;\n\t\tif (current === null || current === void 0 ? void 0 : current.name) {\n\t\t\tnames.unshift(current.name);\n\t\t}\n\t}\n\tif (current !== task.file) {\n\t\tnames.unshift(task.file.name);\n\t}\n\treturn names;\n}\nfunction getFullName(task, separator = \" > \") {\n\treturn getNames(task).join(separator);\n}\nfunction getTestName(task, separator = \" > \") {\n\treturn getNames(task).slice(1).join(separator);\n}\n\nexport { calculateSuiteHash as a, createFileTask as b, createChainable as c, generateHash as d, getFullName as e, findTestFileStackTrace as f, generateFileHash as g, getNames as h, interpretTaskModes as i, getSuites as j, getTasks as k, limitConcurrency as l, getTestName as m, getTests as n, hasFailed as o, partitionSuiteChildren as p, hasTests as q, isTestCase as r, someTasksAreOnly as s };\n","import { getTests } from '@vitest/runner/utils';\nimport c from 'tinyrainbow';\nimport type { RunnerTask } from 'vitest';\nimport type { Vitest } from 'vitest/node';\nimport type { Reporter } from 'vitest/reporters';\n\nexport default class TinyReporter implements Reporter {\n // biome-ignore lint/style/noNonNullAssertion: Non-null assertion is allowed here because the onInit method is called before any other method\n ctx: Vitest = undefined!;\n protected verbose = false;\n\n onInit(ctx: Vitest) {\n this.ctx = ctx;\n }\n\n onFinished(\n files = this.ctx.state.getFiles(),\n errors = this.ctx.state.getUnhandledErrors(),\n ) {\n const { logger } = this.ctx;\n const tests = getTests(files);\n const failedTests = tests.filter((i) => i.result?.state === 'fail').length;\n\n const passed = !(failedTests + errors.length);\n const status = passed ? '\\u2714 PASS' : '\\u2716 FAIL';\n const statusColor = passed ? c.green : c.red;\n\n logger.log(\n `${statusColor(c.bold(c.inverse(` ${status} `)))} ${statusColor(\n passed\n ? 'All tests passed'\n : `${failedTests} test${failedTests > 1 ? 's' : ''} failed`,\n )}`,\n );\n logger.log(this.padTitle('Test Files'), this.getStateString(files));\n logger.log(this.padTitle('Tests'), this.getStateString(tests));\n\n if (errors.length) {\n logger.log(\n this.padTitle('Errors'),\n c.bold(c.red(`${errors.length} error${errors.length > 1 ? 's' : ''}`)),\n );\n }\n\n if (!passed) {\n process.exitCode = 1;\n }\n }\n\n padTitle = (str: string) => c.dim(`${str.padStart(11)} `);\n\n getStateString(tasks: RunnerTask[], name = 'tests') {\n if (!tasks.length) {\n return c.dim(`no ${name}`);\n }\n\n const passed = tasks.filter((i) => i.result?.state === 'pass').length;\n const failed = tasks.filter((i) => i.result?.state === 'fail').length;\n const skipped = tasks.filter((i) => i.mode === 'skip').length;\n const todo = tasks.filter((i) => i.mode === 'todo').length;\n\n return (\n [\n failed && c.bold(c.red(`${failed} failed`)),\n passed && c.bold(c.green(`${passed} passed`)),\n skipped && c.yellow(`${skipped} skipped`),\n todo && c.gray(`${todo} todo`),\n ]\n .filter(Boolean)\n .join(c.dim(' | ')) + c.gray(` (${tasks.length})`)\n );\n }\n}\n"],"names":["toArray","array","isTestCase","getTests","suite","tests","arraySuites","s","task","taskTests","test","TinyReporter","ctx","files","errors","logger","failedTests","i","passed","status","statusColor","c","str","tasks","name","failed","skipped","todo"],"mappings":"4RA8FA,SAASA,EAAQC,EAAO,CAIvB,OAHIA,GAAU,OACbA,EAAQ,CAAA,GAEL,MAAM,QAAQA,CAAK,EACfA,EAED,CAACA,CAAK,CACd,CCyKA,SAASC,EAAW,EAAG,CACtB,OAAO,EAAE,OAAS,MACnB,CACA,SAASC,EAASC,EAAO,CACxB,MAAMC,EAAQ,CAAA,EACRC,EAAcN,EAAQI,CAAK,EACjC,UAAWG,KAAKD,EACf,GAAIJ,EAAWK,CAAC,EACfF,EAAM,KAAKE,CAAC,MAEZ,WAAWC,KAAQD,EAAE,MACpB,GAAIL,EAAWM,CAAI,EAClBH,EAAM,KAAKG,CAAI,MACT,CACN,MAAMC,EAAYN,EAASK,CAAI,EAC/B,UAAWE,KAAQD,EAClBJ,EAAM,KAAKK,CAAI,CAEjB,CAIH,OAAOL,CACR,CChSA,MAAqBM,CAAiC,CAEpD,IAAc,OACJ,QAAU,GAEpB,OAAOC,EAAa,CAClB,KAAK,IAAMA,CACb,CAEA,WACEC,EAAQ,KAAK,IAAI,MAAM,WACvBC,EAAS,KAAK,IAAI,MAAM,mBAAA,EACxB,CACA,KAAM,CAAE,OAAAC,GAAW,KAAK,IAClBV,EAAQF,EAASU,CAAK,EACtBG,EAAcX,EAAM,OAAQY,GAAMA,EAAE,QAAQ,QAAU,MAAM,EAAE,OAE9DC,EAAS,EAAEF,EAAcF,EAAO,QAChCK,EAASD,EAAS,SAAgB,SAClCE,EAAcF,EAASG,EAAE,MAAQA,EAAE,IAEzCN,EAAO,IACL,GAAGK,EAAYC,EAAE,KAAKA,EAAE,QAAQ,IAAIF,CAAM,GAAG,CAAC,CAAC,CAAC,IAAIC,EAClDF,EACI,mBACA,GAAGF,CAAW,QAAQA,EAAc,EAAI,IAAM,EAAE,SAAA,CACrD,EAAA,EAEHD,EAAO,IAAI,KAAK,SAAS,YAAY,EAAG,KAAK,eAAeF,CAAK,CAAC,EAClEE,EAAO,IAAI,KAAK,SAAS,OAAO,EAAG,KAAK,eAAeV,CAAK,CAAC,EAEzDS,EAAO,QACTC,EAAO,IACL,KAAK,SAAS,QAAQ,EACtBM,EAAE,KAAKA,EAAE,IAAI,GAAGP,EAAO,MAAM,SAASA,EAAO,OAAS,EAAI,IAAM,EAAE,EAAE,CAAC,CAAA,EAIpEI,IACH,QAAQ,SAAW,EAEvB,CAEA,SAAYI,GAAgBD,EAAE,IAAI,GAAGC,EAAI,SAAS,EAAE,CAAC,GAAG,EAExD,eAAeC,EAAqBC,EAAO,QAAS,CAClD,GAAI,CAACD,EAAM,OACT,OAAOF,EAAE,IAAI,MAAMG,CAAI,EAAE,EAG3B,MAAMN,EAASK,EAAM,OAAQN,GAAMA,EAAE,QAAQ,QAAU,MAAM,EAAE,OACzDQ,EAASF,EAAM,OAAQN,GAAMA,EAAE,QAAQ,QAAU,MAAM,EAAE,OACzDS,EAAUH,EAAM,OAAQN,GAAMA,EAAE,OAAS,MAAM,EAAE,OACjDU,EAAOJ,EAAM,OAAQN,GAAMA,EAAE,OAAS,MAAM,EAAE,OAEpD,MACE,CACEQ,GAAUJ,EAAE,KAAKA,EAAE,IAAI,GAAGI,CAAM,SAAS,CAAC,EAC1CP,GAAUG,EAAE,KAAKA,EAAE,MAAM,GAAGH,CAAM,SAAS,CAAC,EAC5CQ,GAAWL,EAAE,OAAO,GAAGK,CAAO,UAAU,EACxCC,GAAQN,EAAE,KAAK,GAAGM,CAAI,OAAO,CAAA,EAE5B,OAAO,OAAO,EACd,KAAKN,EAAE,IAAI,KAAK,CAAC,EAAIA,EAAE,KAAK,KAAKE,EAAM,MAAM,GAAG,CAEvD,CACF","x_google_ignoreList":[0,1]}
|
|
1
|
+
{"version":3,"file":"vitest-tiny-reporter.umd.cjs","sources":["../node_modules/@vitest/utils/dist/helpers.js","../node_modules/@vitest/runner/dist/chunk-tasks.js","../src/index.ts"],"sourcesContent":["import { VALID_ID_PREFIX, NULL_BYTE_PLACEHOLDER } from './constants.js';\n\n// port from nanoid\n// https://github.com/ai/nanoid\nconst urlAlphabet = \"useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict\";\nfunction nanoid(size = 21) {\n\tlet id = \"\";\n\tlet i = size;\n\twhile (i--) {\n\t\tid += urlAlphabet[Math.random() * 64 | 0];\n\t}\n\treturn id;\n}\n\nconst RealDate = Date;\nfunction random(seed) {\n\tconst x = Math.sin(seed++) * 1e4;\n\treturn x - Math.floor(x);\n}\nfunction shuffle(array, seed = RealDate.now()) {\n\tlet length = array.length;\n\twhile (length) {\n\t\tconst index = Math.floor(random(seed) * length--);\n\t\tconst previous = array[length];\n\t\tarray[length] = array[index];\n\t\tarray[index] = previous;\n\t\t++seed;\n\t}\n\treturn array;\n}\n\n/**\n* Get original stacktrace without source map support the most performant way.\n* - Create only 1 stack frame.\n* - Rewrite prepareStackTrace to bypass \"support-stack-trace\" (usually takes ~250ms).\n*/\nfunction createSimpleStackTrace(options) {\n\tconst { message = \"$$stack trace error\", stackTraceLimit = 1 } = options || {};\n\tconst limit = Error.stackTraceLimit;\n\tconst prepareStackTrace = Error.prepareStackTrace;\n\tError.stackTraceLimit = stackTraceLimit;\n\tError.prepareStackTrace = (e) => e.stack;\n\tconst err = new Error(message);\n\tconst stackTrace = err.stack || \"\";\n\tError.prepareStackTrace = prepareStackTrace;\n\tError.stackTraceLimit = limit;\n\treturn stackTrace;\n}\nfunction notNullish(v) {\n\treturn v != null;\n}\nfunction assertTypes(value, name, types) {\n\tconst receivedType = typeof value;\n\tconst pass = types.includes(receivedType);\n\tif (!pass) {\n\t\tthrow new TypeError(`${name} value must be ${types.join(\" or \")}, received \"${receivedType}\"`);\n\t}\n}\nfunction isPrimitive(value) {\n\treturn value === null || typeof value !== \"function\" && typeof value !== \"object\";\n}\nfunction slash(path) {\n\treturn path.replace(/\\\\/g, \"/\");\n}\nconst postfixRE = /[?#].*$/;\nfunction cleanUrl(url) {\n\treturn url.replace(postfixRE, \"\");\n}\nconst externalRE = /^(?:[a-z]+:)?\\/\\//;\nconst isExternalUrl = (url) => externalRE.test(url);\n/**\n* Prepend `/@id/` and replace null byte so the id is URL-safe.\n* This is prepended to resolved ids that are not valid browser\n* import specifiers by the importAnalysis plugin.\n*/\nfunction wrapId(id) {\n\treturn id.startsWith(VALID_ID_PREFIX) ? id : VALID_ID_PREFIX + id.replace(\"\\0\", NULL_BYTE_PLACEHOLDER);\n}\n/**\n* Undo {@link wrapId}'s `/@id/` and null byte replacements.\n*/\nfunction unwrapId(id) {\n\treturn id.startsWith(VALID_ID_PREFIX) ? id.slice(VALID_ID_PREFIX.length).replace(NULL_BYTE_PLACEHOLDER, \"\\0\") : id;\n}\nfunction withTrailingSlash(path) {\n\tif (path.at(-1) !== \"/\") {\n\t\treturn `${path}/`;\n\t}\n\treturn path;\n}\nconst bareImportRE = /^(?![a-z]:)[\\w@](?!.*:\\/\\/)/i;\nfunction isBareImport(id) {\n\treturn bareImportRE.test(id);\n}\nfunction toArray(array) {\n\tif (array === null || array === undefined) {\n\t\tarray = [];\n\t}\n\tif (Array.isArray(array)) {\n\t\treturn array;\n\t}\n\treturn [array];\n}\nfunction isObject(item) {\n\treturn item != null && typeof item === \"object\" && !Array.isArray(item);\n}\nfunction isFinalObj(obj) {\n\treturn obj === Object.prototype || obj === Function.prototype || obj === RegExp.prototype;\n}\nfunction getType(value) {\n\treturn Object.prototype.toString.apply(value).slice(8, -1);\n}\nfunction collectOwnProperties(obj, collector) {\n\tconst collect = typeof collector === \"function\" ? collector : (key) => collector.add(key);\n\tObject.getOwnPropertyNames(obj).forEach(collect);\n\tObject.getOwnPropertySymbols(obj).forEach(collect);\n}\nfunction getOwnProperties(obj) {\n\tconst ownProps = new Set();\n\tif (isFinalObj(obj)) {\n\t\treturn [];\n\t}\n\tcollectOwnProperties(obj, ownProps);\n\treturn Array.from(ownProps);\n}\nconst defaultCloneOptions = { forceWritable: false };\nfunction deepClone(val, options = defaultCloneOptions) {\n\tconst seen = new WeakMap();\n\treturn clone(val, seen, options);\n}\nfunction clone(val, seen, options = defaultCloneOptions) {\n\tlet k, out;\n\tif (seen.has(val)) {\n\t\treturn seen.get(val);\n\t}\n\tif (Array.isArray(val)) {\n\t\tout = Array.from({ length: k = val.length });\n\t\tseen.set(val, out);\n\t\twhile (k--) {\n\t\t\tout[k] = clone(val[k], seen, options);\n\t\t}\n\t\treturn out;\n\t}\n\tif (Object.prototype.toString.call(val) === \"[object Object]\") {\n\t\tout = Object.create(Object.getPrototypeOf(val));\n\t\tseen.set(val, out);\n\t\t// we don't need properties from prototype\n\t\tconst props = getOwnProperties(val);\n\t\tfor (const k of props) {\n\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(val, k);\n\t\t\tif (!descriptor) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst cloned = clone(val[k], seen, options);\n\t\t\tif (options.forceWritable) {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\tenumerable: descriptor.enumerable,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: cloned\n\t\t\t\t});\n\t\t\t} else if (\"get\" in descriptor) {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\t...descriptor,\n\t\t\t\t\tget() {\n\t\t\t\t\t\treturn cloned;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\t...descriptor,\n\t\t\t\t\tvalue: cloned\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn out;\n\t}\n\treturn val;\n}\nfunction noop() {}\nfunction objectAttr(source, path, defaultValue = undefined) {\n\t// a[3].b -> a.3.b\n\tconst paths = path.replace(/\\[(\\d+)\\]/g, \".$1\").split(\".\");\n\tlet result = source;\n\tfor (const p of paths) {\n\t\tresult = new Object(result)[p];\n\t\tif (result === undefined) {\n\t\t\treturn defaultValue;\n\t\t}\n\t}\n\treturn result;\n}\nfunction createDefer() {\n\tlet resolve = null;\n\tlet reject = null;\n\tconst p = new Promise((_resolve, _reject) => {\n\t\tresolve = _resolve;\n\t\treject = _reject;\n\t});\n\tp.resolve = resolve;\n\tp.reject = reject;\n\treturn p;\n}\n/**\n* If code starts with a function call, will return its last index, respecting arguments.\n* This will return 25 - last ending character of toMatch \")\"\n* Also works with callbacks\n* ```\n* toMatch({ test: '123' });\n* toBeAliased('123')\n* ```\n*/\nfunction getCallLastIndex(code) {\n\tlet charIndex = -1;\n\tlet inString = null;\n\tlet startedBracers = 0;\n\tlet endedBracers = 0;\n\tlet beforeChar = null;\n\twhile (charIndex <= code.length) {\n\t\tbeforeChar = code[charIndex];\n\t\tcharIndex++;\n\t\tconst char = code[charIndex];\n\t\tconst isCharString = char === \"\\\"\" || char === \"'\" || char === \"`\";\n\t\tif (isCharString && beforeChar !== \"\\\\\") {\n\t\t\tif (inString === char) {\n\t\t\t\tinString = null;\n\t\t\t} else if (!inString) {\n\t\t\t\tinString = char;\n\t\t\t}\n\t\t}\n\t\tif (!inString) {\n\t\t\tif (char === \"(\") {\n\t\t\t\tstartedBracers++;\n\t\t\t}\n\t\t\tif (char === \")\") {\n\t\t\t\tendedBracers++;\n\t\t\t}\n\t\t}\n\t\tif (startedBracers && endedBracers && startedBracers === endedBracers) {\n\t\t\treturn charIndex;\n\t\t}\n\t}\n\treturn null;\n}\nfunction isNegativeNaN(val) {\n\tif (!Number.isNaN(val)) {\n\t\treturn false;\n\t}\n\tconst f64 = new Float64Array(1);\n\tf64[0] = val;\n\tconst u32 = new Uint32Array(f64.buffer);\n\tconst isNegative = u32[1] >>> 31 === 1;\n\treturn isNegative;\n}\nfunction toString(v) {\n\treturn Object.prototype.toString.call(v);\n}\nfunction isPlainObject(val) {\n\treturn toString(val) === \"[object Object]\" && (!val.constructor || val.constructor.name === \"Object\");\n}\nfunction isMergeableObject(item) {\n\treturn isPlainObject(item) && !Array.isArray(item);\n}\n/**\n* Deep merge :P\n*\n* Will merge objects only if they are plain\n*\n* Do not merge types - it is very expensive and usually it's better to case a type here\n*/\nfunction deepMerge(target, ...sources) {\n\tif (!sources.length) {\n\t\treturn target;\n\t}\n\tconst source = sources.shift();\n\tif (source === undefined) {\n\t\treturn target;\n\t}\n\tif (isMergeableObject(target) && isMergeableObject(source)) {\n\t\tObject.keys(source).forEach((key) => {\n\t\t\tconst _source = source;\n\t\t\tif (isMergeableObject(_source[key])) {\n\t\t\t\tif (!target[key]) {\n\t\t\t\t\ttarget[key] = {};\n\t\t\t\t}\n\t\t\t\tdeepMerge(target[key], _source[key]);\n\t\t\t} else {\n\t\t\t\ttarget[key] = _source[key];\n\t\t\t}\n\t\t});\n\t}\n\treturn deepMerge(target, ...sources);\n}\n\nexport { assertTypes, cleanUrl, clone, createDefer, createSimpleStackTrace, deepClone, deepMerge, getCallLastIndex, getOwnProperties, getType, isBareImport, isExternalUrl, isNegativeNaN, isObject, isPrimitive, nanoid, noop, notNullish, objectAttr, shuffle, slash, toArray, unwrapId, withTrailingSlash, wrapId };\n","import { processError } from '@vitest/utils/error';\nimport { parseSingleStack } from '@vitest/utils/source-map';\nimport { relative } from 'pathe';\nimport { toArray } from '@vitest/utils/helpers';\n\nfunction createChainable(keys, fn) {\n\tfunction create(context) {\n\t\tconst chain = function(...args) {\n\t\t\treturn fn.apply(context, args);\n\t\t};\n\t\tObject.assign(chain, fn);\n\t\tchain.withContext = () => chain.bind(context);\n\t\tchain.setContext = (key, value) => {\n\t\t\tcontext[key] = value;\n\t\t};\n\t\tchain.mergeContext = (ctx) => {\n\t\t\tObject.assign(context, ctx);\n\t\t};\n\t\tfor (const key of keys) {\n\t\t\tObject.defineProperty(chain, key, { get() {\n\t\t\t\treturn create({\n\t\t\t\t\t...context,\n\t\t\t\t\t[key]: true\n\t\t\t\t});\n\t\t\t} });\n\t\t}\n\t\treturn chain;\n\t}\n\tconst chain = create({});\n\tchain.fn = fn;\n\treturn chain;\n}\n\n/**\n* If any tasks been marked as `only`, mark all other tasks as `skip`.\n*/\nfunction interpretTaskModes(file, namePattern, testLocations, onlyMode, parentIsOnly, allowOnly) {\n\tconst matchedLocations = [];\n\tconst traverseSuite = (suite, parentIsOnly, parentMatchedWithLocation) => {\n\t\tconst suiteIsOnly = parentIsOnly || suite.mode === \"only\";\n\t\tsuite.tasks.forEach((t) => {\n\t\t\t// Check if either the parent suite or the task itself are marked as included\n\t\t\tconst includeTask = suiteIsOnly || t.mode === \"only\";\n\t\t\tif (onlyMode) {\n\t\t\t\tif (t.type === \"suite\" && (includeTask || someTasksAreOnly(t))) {\n\t\t\t\t\t// Don't skip this suite\n\t\t\t\t\tif (t.mode === \"only\") {\n\t\t\t\t\t\tcheckAllowOnly(t, allowOnly);\n\t\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t\t}\n\t\t\t\t} else if (t.mode === \"run\" && !includeTask) {\n\t\t\t\t\tt.mode = \"skip\";\n\t\t\t\t} else if (t.mode === \"only\") {\n\t\t\t\t\tcheckAllowOnly(t, allowOnly);\n\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet hasLocationMatch = parentMatchedWithLocation;\n\t\t\t// Match test location against provided locations, only run if present\n\t\t\t// in `testLocations`. Note: if `includeTaskLocations` is not enabled,\n\t\t\t// all test will be skipped.\n\t\t\tif (testLocations !== undefined && testLocations.length !== 0) {\n\t\t\t\tif (t.location && (testLocations === null || testLocations === void 0 ? void 0 : testLocations.includes(t.location.line))) {\n\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t\tmatchedLocations.push(t.location.line);\n\t\t\t\t\thasLocationMatch = true;\n\t\t\t\t} else if (parentMatchedWithLocation) {\n\t\t\t\t\tt.mode = \"run\";\n\t\t\t\t} else if (t.type === \"test\") {\n\t\t\t\t\tt.mode = \"skip\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (t.type === \"test\") {\n\t\t\t\tif (namePattern && !getTaskFullName(t).match(namePattern)) {\n\t\t\t\t\tt.mode = \"skip\";\n\t\t\t\t}\n\t\t\t} else if (t.type === \"suite\") {\n\t\t\t\tif (t.mode === \"skip\") {\n\t\t\t\t\tskipAllTasks(t);\n\t\t\t\t} else if (t.mode === \"todo\") {\n\t\t\t\t\ttodoAllTasks(t);\n\t\t\t\t} else {\n\t\t\t\t\ttraverseSuite(t, includeTask, hasLocationMatch);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t// if all subtasks are skipped, mark as skip\n\t\tif (suite.mode === \"run\" || suite.mode === \"queued\") {\n\t\t\tif (suite.tasks.length && suite.tasks.every((i) => i.mode !== \"run\" && i.mode !== \"queued\")) {\n\t\t\t\tsuite.mode = \"skip\";\n\t\t\t}\n\t\t}\n\t};\n\ttraverseSuite(file, parentIsOnly, false);\n\tconst nonMatching = testLocations === null || testLocations === void 0 ? void 0 : testLocations.filter((loc) => !matchedLocations.includes(loc));\n\tif (nonMatching && nonMatching.length !== 0) {\n\t\tconst message = nonMatching.length === 1 ? `line ${nonMatching[0]}` : `lines ${nonMatching.join(\", \")}`;\n\t\tif (file.result === undefined) {\n\t\t\tfile.result = {\n\t\t\t\tstate: \"fail\",\n\t\t\t\terrors: []\n\t\t\t};\n\t\t}\n\t\tif (file.result.errors === undefined) {\n\t\t\tfile.result.errors = [];\n\t\t}\n\t\tfile.result.errors.push(processError(new Error(`No test found in ${file.name} in ${message}`)));\n\t}\n}\nfunction getTaskFullName(task) {\n\treturn `${task.suite ? `${getTaskFullName(task.suite)} ` : \"\"}${task.name}`;\n}\nfunction someTasksAreOnly(suite) {\n\treturn suite.tasks.some((t) => t.mode === \"only\" || t.type === \"suite\" && someTasksAreOnly(t));\n}\nfunction skipAllTasks(suite) {\n\tsuite.tasks.forEach((t) => {\n\t\tif (t.mode === \"run\" || t.mode === \"queued\") {\n\t\t\tt.mode = \"skip\";\n\t\t\tif (t.type === \"suite\") {\n\t\t\t\tskipAllTasks(t);\n\t\t\t}\n\t\t}\n\t});\n}\nfunction todoAllTasks(suite) {\n\tsuite.tasks.forEach((t) => {\n\t\tif (t.mode === \"run\" || t.mode === \"queued\") {\n\t\t\tt.mode = \"todo\";\n\t\t\tif (t.type === \"suite\") {\n\t\t\t\ttodoAllTasks(t);\n\t\t\t}\n\t\t}\n\t});\n}\nfunction checkAllowOnly(task, allowOnly) {\n\tif (allowOnly) {\n\t\treturn;\n\t}\n\tconst error = processError(new Error(\"[Vitest] Unexpected .only modifier. Remove it or pass --allowOnly argument to bypass this error\"));\n\ttask.result = {\n\t\tstate: \"fail\",\n\t\terrors: [error]\n\t};\n}\n/* @__NO_SIDE_EFFECTS__ */\nfunction generateHash(str) {\n\tlet hash = 0;\n\tif (str.length === 0) {\n\t\treturn `${hash}`;\n\t}\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst char = str.charCodeAt(i);\n\t\thash = (hash << 5) - hash + char;\n\t\thash = hash & hash;\n\t}\n\treturn `${hash}`;\n}\nfunction calculateSuiteHash(parent) {\n\tparent.tasks.forEach((t, idx) => {\n\t\tt.id = `${parent.id}_${idx}`;\n\t\tif (t.type === \"suite\") {\n\t\t\tcalculateSuiteHash(t);\n\t\t}\n\t});\n}\nfunction createFileTask(filepath, root, projectName, pool, viteEnvironment) {\n\tconst path = relative(root, filepath);\n\tconst file = {\n\t\tid: generateFileHash(path, projectName),\n\t\tname: path,\n\t\tfullName: path,\n\t\ttype: \"suite\",\n\t\tmode: \"queued\",\n\t\tfilepath,\n\t\ttasks: [],\n\t\tmeta: Object.create(null),\n\t\tprojectName,\n\t\tfile: undefined,\n\t\tpool,\n\t\tviteEnvironment\n\t};\n\tfile.file = file;\n\treturn file;\n}\n/**\n* Generate a unique ID for a file based on its path and project name\n* @param file File relative to the root of the project to keep ID the same between different machines\n* @param projectName The name of the test project\n*/\n/* @__NO_SIDE_EFFECTS__ */\nfunction generateFileHash(file, projectName) {\n\treturn /* @__PURE__ */ generateHash(`${file}${projectName || \"\"}`);\n}\nfunction findTestFileStackTrace(testFilePath, error) {\n\t// first line is the error message\n\tconst lines = error.split(\"\\n\").slice(1);\n\tfor (const line of lines) {\n\t\tconst stack = parseSingleStack(line);\n\t\tif (stack && stack.file === testFilePath) {\n\t\t\treturn stack;\n\t\t}\n\t}\n}\n\n/**\n* Return a function for running multiple async operations with limited concurrency.\n*/\nfunction limitConcurrency(concurrency = Infinity) {\n\t// The number of currently active + pending tasks.\n\tlet count = 0;\n\t// The head and tail of the pending task queue, built using a singly linked list.\n\t// Both head and tail are initially undefined, signifying an empty queue.\n\t// They both become undefined again whenever there are no pending tasks.\n\tlet head;\n\tlet tail;\n\t// A bookkeeping function executed whenever a task has been run to completion.\n\tconst finish = () => {\n\t\tcount--;\n\t\t// Check if there are further pending tasks in the queue.\n\t\tif (head) {\n\t\t\t// Allow the next pending task to run and pop it from the queue.\n\t\t\thead[0]();\n\t\t\thead = head[1];\n\t\t\t// The head may now be undefined if there are no further pending tasks.\n\t\t\t// In that case, set tail to undefined as well.\n\t\t\ttail = head && tail;\n\t\t}\n\t};\n\treturn (func, ...args) => {\n\t\t// Create a promise chain that:\n\t\t// 1. Waits for its turn in the task queue (if necessary).\n\t\t// 2. Runs the task.\n\t\t// 3. Allows the next pending task (if any) to run.\n\t\treturn new Promise((resolve) => {\n\t\t\tif (count++ < concurrency) {\n\t\t\t\t// No need to queue if fewer than maxConcurrency tasks are running.\n\t\t\t\tresolve();\n\t\t\t} else if (tail) {\n\t\t\t\t// There are pending tasks, so append to the queue.\n\t\t\t\ttail = tail[1] = [resolve];\n\t\t\t} else {\n\t\t\t\t// No other pending tasks, initialize the queue with a new tail and head.\n\t\t\t\thead = tail = [resolve];\n\t\t\t}\n\t\t}).then(() => {\n\t\t\t// Running func here ensures that even a non-thenable result or an\n\t\t\t// immediately thrown error gets wrapped into a Promise.\n\t\t\treturn func(...args);\n\t\t}).finally(finish);\n\t};\n}\n\n/**\n* Partition in tasks groups by consecutive concurrent\n*/\nfunction partitionSuiteChildren(suite) {\n\tlet tasksGroup = [];\n\tconst tasksGroups = [];\n\tfor (const c of suite.tasks) {\n\t\tif (tasksGroup.length === 0 || c.concurrent === tasksGroup[0].concurrent) {\n\t\t\ttasksGroup.push(c);\n\t\t} else {\n\t\t\ttasksGroups.push(tasksGroup);\n\t\t\ttasksGroup = [c];\n\t\t}\n\t}\n\tif (tasksGroup.length > 0) {\n\t\ttasksGroups.push(tasksGroup);\n\t}\n\treturn tasksGroups;\n}\n\nfunction isTestCase(s) {\n\treturn s.type === \"test\";\n}\nfunction getTests(suite) {\n\tconst tests = [];\n\tconst arraySuites = toArray(suite);\n\tfor (const s of arraySuites) {\n\t\tif (isTestCase(s)) {\n\t\t\ttests.push(s);\n\t\t} else {\n\t\t\tfor (const task of s.tasks) {\n\t\t\t\tif (isTestCase(task)) {\n\t\t\t\t\ttests.push(task);\n\t\t\t\t} else {\n\t\t\t\t\tconst taskTests = getTests(task);\n\t\t\t\t\tfor (const test of taskTests) {\n\t\t\t\t\t\ttests.push(test);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn tests;\n}\nfunction getTasks(tasks = []) {\n\treturn toArray(tasks).flatMap((s) => isTestCase(s) ? [s] : [s, ...getTasks(s.tasks)]);\n}\nfunction getSuites(suite) {\n\treturn toArray(suite).flatMap((s) => s.type === \"suite\" ? [s, ...getSuites(s.tasks)] : []);\n}\nfunction hasTests(suite) {\n\treturn toArray(suite).some((s) => s.tasks.some((c) => isTestCase(c) || hasTests(c)));\n}\nfunction hasFailed(suite) {\n\treturn toArray(suite).some((s) => {\n\t\tvar _s$result;\n\t\treturn ((_s$result = s.result) === null || _s$result === void 0 ? void 0 : _s$result.state) === \"fail\" || s.type === \"suite\" && hasFailed(s.tasks);\n\t});\n}\nfunction getNames(task) {\n\tconst names = [task.name];\n\tlet current = task;\n\twhile (current === null || current === void 0 ? void 0 : current.suite) {\n\t\tcurrent = current.suite;\n\t\tif (current === null || current === void 0 ? void 0 : current.name) {\n\t\t\tnames.unshift(current.name);\n\t\t}\n\t}\n\tif (current !== task.file) {\n\t\tnames.unshift(task.file.name);\n\t}\n\treturn names;\n}\nfunction getFullName(task, separator = \" > \") {\n\treturn getNames(task).join(separator);\n}\nfunction getTestName(task, separator = \" > \") {\n\treturn getNames(task).slice(1).join(separator);\n}\nfunction createTaskName(names, separator = \" > \") {\n\treturn names.filter((name) => name !== undefined).join(separator);\n}\n\nexport { calculateSuiteHash as a, createFileTask as b, createChainable as c, generateHash as d, createTaskName as e, findTestFileStackTrace as f, generateFileHash as g, getFullName as h, interpretTaskModes as i, getNames as j, getSuites as k, limitConcurrency as l, getTasks as m, getTestName as n, getTests as o, partitionSuiteChildren as p, hasFailed as q, hasTests as r, someTasksAreOnly as s, isTestCase as t };\n","import { getTests } from '@vitest/runner/utils';\nimport c from 'tinyrainbow';\nimport type { RunnerTask } from 'vitest';\nimport type { Vitest } from 'vitest/node';\nimport type { Reporter } from 'vitest/reporters';\n\nexport default class TinyReporter implements Reporter {\n // biome-ignore lint/style/noNonNullAssertion: Non-null assertion is allowed here because the onInit method is called before any other method\n ctx: Vitest = undefined!;\n protected verbose = false;\n\n onInit(ctx: Vitest) {\n this.ctx = ctx;\n }\n\n onFinished(\n files = this.ctx.state.getFiles(),\n errors = this.ctx.state.getUnhandledErrors(),\n ) {\n const { logger } = this.ctx;\n const tests = getTests(files);\n const failedTests = tests.filter((i) => i.result?.state === 'fail').length;\n\n const passed = !(failedTests + errors.length);\n const status = passed ? '\\u2714 PASS' : '\\u2716 FAIL';\n const statusColor = passed ? c.green : c.red;\n\n logger.log(\n `${statusColor(c.bold(c.inverse(` ${status} `)))} ${statusColor(\n passed\n ? 'All tests passed'\n : `${failedTests} test${failedTests > 1 ? 's' : ''} failed`,\n )}`,\n );\n logger.log(this.padTitle('Test Files'), this.getStateString(files));\n logger.log(this.padTitle('Tests'), this.getStateString(tests));\n\n if (errors.length) {\n logger.log(\n this.padTitle('Errors'),\n c.bold(c.red(`${errors.length} error${errors.length > 1 ? 's' : ''}`)),\n );\n }\n\n if (!passed) {\n process.exitCode = 1;\n }\n }\n\n padTitle = (str: string) => c.dim(`${str.padStart(11)} `);\n\n getStateString(tasks: RunnerTask[], name = 'tests') {\n if (!tasks.length) {\n return c.dim(`no ${name}`);\n }\n\n const passed = tasks.filter((i) => i.result?.state === 'pass').length;\n const failed = tasks.filter((i) => i.result?.state === 'fail').length;\n const skipped = tasks.filter((i) => i.mode === 'skip').length;\n const todo = tasks.filter((i) => i.mode === 'todo').length;\n\n return (\n [\n failed && c.bold(c.red(`${failed} failed`)),\n passed && c.bold(c.green(`${passed} passed`)),\n skipped && c.yellow(`${skipped} skipped`),\n todo && c.gray(`${todo} todo`),\n ]\n .filter(Boolean)\n .join(c.dim(' | ')) + c.gray(` (${tasks.length})`)\n );\n }\n}\n"],"names":["toArray","array","isTestCase","getTests","suite","tests","arraySuites","s","task","taskTests","test","TinyReporter","ctx","files","errors","logger","failedTests","i","passed","status","statusColor","c","str","tasks","name","failed","skipped","todo"],"mappings":"6RA8FA,SAASA,EAAQC,EAAO,CAIvB,OAHIA,GAAU,OACbA,EAAQ,CAAA,GAEL,MAAM,QAAQA,CAAK,EACfA,EAED,CAACA,CAAK,CACd,CC2KA,SAASC,EAAW,EAAG,CACtB,OAAO,EAAE,OAAS,MACnB,CACA,SAASC,EAASC,EAAO,CACxB,MAAMC,EAAQ,CAAA,EACRC,EAAcN,EAAQI,CAAK,EACjC,UAAWG,KAAKD,EACf,GAAIJ,EAAWK,CAAC,EACfF,EAAM,KAAKE,CAAC,MAEZ,WAAWC,KAAQD,EAAE,MACpB,GAAIL,EAAWM,CAAI,EAClBH,EAAM,KAAKG,CAAI,MACT,CACN,MAAMC,EAAYN,EAASK,CAAI,EAC/B,UAAWE,KAAQD,EAClBJ,EAAM,KAAKK,CAAI,CAEjB,CAIH,OAAOL,CACR,CClSA,MAAqBM,CAAiC,CAEpD,IAAc,OACJ,QAAU,GAEpB,OAAOC,EAAa,CAClB,KAAK,IAAMA,CACb,CAEA,WACEC,EAAQ,KAAK,IAAI,MAAM,WACvBC,EAAS,KAAK,IAAI,MAAM,mBAAA,EACxB,CACA,KAAM,CAAE,OAAAC,GAAW,KAAK,IAClBV,EAAQF,EAASU,CAAK,EACtBG,EAAcX,EAAM,OAAQY,GAAMA,EAAE,QAAQ,QAAU,MAAM,EAAE,OAE9DC,EAAS,EAAEF,EAAcF,EAAO,QAChCK,EAASD,EAAS,SAAgB,SAClCE,EAAcF,EAASG,EAAE,MAAQA,EAAE,IAEzCN,EAAO,IACL,GAAGK,EAAYC,EAAE,KAAKA,EAAE,QAAQ,IAAIF,CAAM,GAAG,CAAC,CAAC,CAAC,IAAIC,EAClDF,EACI,mBACA,GAAGF,CAAW,QAAQA,EAAc,EAAI,IAAM,EAAE,SAAA,CACrD,EAAA,EAEHD,EAAO,IAAI,KAAK,SAAS,YAAY,EAAG,KAAK,eAAeF,CAAK,CAAC,EAClEE,EAAO,IAAI,KAAK,SAAS,OAAO,EAAG,KAAK,eAAeV,CAAK,CAAC,EAEzDS,EAAO,QACTC,EAAO,IACL,KAAK,SAAS,QAAQ,EACtBM,EAAE,KAAKA,EAAE,IAAI,GAAGP,EAAO,MAAM,SAASA,EAAO,OAAS,EAAI,IAAM,EAAE,EAAE,CAAC,CAAA,EAIpEI,IACH,QAAQ,SAAW,EAEvB,CAEA,SAAYI,GAAgBD,EAAE,IAAI,GAAGC,EAAI,SAAS,EAAE,CAAC,GAAG,EAExD,eAAeC,EAAqBC,EAAO,QAAS,CAClD,GAAI,CAACD,EAAM,OACT,OAAOF,EAAE,IAAI,MAAMG,CAAI,EAAE,EAG3B,MAAMN,EAASK,EAAM,OAAQN,GAAMA,EAAE,QAAQ,QAAU,MAAM,EAAE,OACzDQ,EAASF,EAAM,OAAQN,GAAMA,EAAE,QAAQ,QAAU,MAAM,EAAE,OACzDS,EAAUH,EAAM,OAAQN,GAAMA,EAAE,OAAS,MAAM,EAAE,OACjDU,EAAOJ,EAAM,OAAQN,GAAMA,EAAE,OAAS,MAAM,EAAE,OAEpD,MACE,CACEQ,GAAUJ,EAAE,KAAKA,EAAE,IAAI,GAAGI,CAAM,SAAS,CAAC,EAC1CP,GAAUG,EAAE,KAAKA,EAAE,MAAM,GAAGH,CAAM,SAAS,CAAC,EAC5CQ,GAAWL,EAAE,OAAO,GAAGK,CAAO,UAAU,EACxCC,GAAQN,EAAE,KAAK,GAAGM,CAAI,OAAO,CAAA,EAE5B,OAAO,OAAO,EACd,KAAKN,EAAE,IAAI,KAAK,CAAC,EAAIA,EAAE,KAAK,KAAKE,EAAM,MAAM,GAAG,CAEvD,CACF","x_google_ignoreList":[0,1]}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vitest-tiny-reporter",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "Tiny reporter for vitest",
|
|
5
|
-
"types": "dist/
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist"
|
|
8
8
|
],
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"scripts": {
|
|
15
15
|
"build": "npx concurrently npm:build:*",
|
|
16
16
|
"build:vite": "vite build",
|
|
17
|
-
"build:tsc": "tsc -b tsconfig.types.json",
|
|
17
|
+
"build:tsc": "tsc -b tsconfig.types.json && cp ./dist/index.d.ts ./dist/index.d.cts",
|
|
18
18
|
"test": "vitest run",
|
|
19
19
|
"coverage": "vitest run --coverage",
|
|
20
20
|
"test:watch": "vitest --watch --coverage --ui",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"repository": {
|
|
27
27
|
"type": "git",
|
|
28
|
-
"url": "https://github.com/manbearwiz/vitest-tiny-reporter.git"
|
|
28
|
+
"url": "git+https://github.com/manbearwiz/vitest-tiny-reporter.git"
|
|
29
29
|
},
|
|
30
30
|
"author": "Kevin Brey",
|
|
31
31
|
"license": "MIT",
|
|
@@ -38,22 +38,21 @@
|
|
|
38
38
|
"vitest": "^2.0.0 || ^3.0.2 || ^4.0.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@biomejs/biome": "
|
|
42
|
-
"@commitlint/cli": "^
|
|
43
|
-
"@commitlint/config-angular": "^
|
|
44
|
-
"@tsconfig/
|
|
45
|
-
"@tsconfig/
|
|
46
|
-
"@tsconfig/vite-react": "^6.3.6",
|
|
41
|
+
"@biomejs/biome": "^2.3.0",
|
|
42
|
+
"@commitlint/cli": "^20.1.0",
|
|
43
|
+
"@commitlint/config-angular": "^20.0.0",
|
|
44
|
+
"@tsconfig/strictest": "^2.0.8",
|
|
45
|
+
"@tsconfig/vite-react": "^7.0.1",
|
|
47
46
|
"@types/node": "^22.10.0",
|
|
48
47
|
"@vitest/coverage-v8": "^2.0.0 || ^3.0.2 || ^4.0.0",
|
|
49
48
|
"@vitest/ui": "^2.0.0 || ^3.0.2 || ^4.0.0",
|
|
50
|
-
"happy-dom": "^
|
|
51
|
-
"semantic-release": "^
|
|
49
|
+
"happy-dom": "^20.0.8",
|
|
50
|
+
"semantic-release": "^25.0.2",
|
|
52
51
|
"typescript": "^5.2.2",
|
|
53
52
|
"vite": "^7.1.12"
|
|
54
53
|
},
|
|
55
54
|
"dependencies": {
|
|
56
|
-
"tinyrainbow": "^1.2.0 || ^2.0.0"
|
|
55
|
+
"tinyrainbow": "^1.2.0 || ^2.0.0 || ^3.0.0"
|
|
57
56
|
},
|
|
58
57
|
"release": {
|
|
59
58
|
"branches": [
|
|
@@ -65,10 +64,18 @@
|
|
|
65
64
|
"module": "./dist/vitest-tiny-reporter.js",
|
|
66
65
|
"exports": {
|
|
67
66
|
".": {
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
"import": {
|
|
68
|
+
"types": "./dist/index.d.ts",
|
|
69
|
+
"default": "./dist/vitest-tiny-reporter.js"
|
|
70
|
+
},
|
|
71
|
+
"require": {
|
|
72
|
+
"types": "./dist/index.d.cts",
|
|
73
|
+
"default": "./dist/vitest-tiny-reporter.umd.cjs"
|
|
74
|
+
}
|
|
71
75
|
}
|
|
72
76
|
},
|
|
73
|
-
"sideEffects": false
|
|
77
|
+
"sideEffects": false,
|
|
78
|
+
"overrides": {
|
|
79
|
+
"npm": "11.6.1"
|
|
80
|
+
}
|
|
74
81
|
}
|
|
File without changes
|