vitest-sentry-reporter 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +143 -0
- package/dist/ci-providers/buildkite.d.ts +2 -0
- package/dist/ci-providers/circleci.d.ts +2 -0
- package/dist/ci-providers/generic.d.ts +2 -0
- package/dist/ci-providers/github.d.ts +2 -0
- package/dist/ci-providers/gitlab.d.ts +2 -0
- package/dist/ci-providers/index.d.ts +10 -0
- package/dist/ci-providers/jenkins.d.ts +2 -0
- package/dist/ci-providers/types.d.ts +13 -0
- package/dist/dry-run-transport.d.ts +5 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +34654 -0
- package/dist/reporter.d.ts +23 -0
- package/dist/types.d.ts +106 -0
- package/dist/utils.d.ts +24 -0
- package/docs/decisions/0000-use-markdown-architectural-decision-records.md +33 -0
- package/docs/decisions/0001-adopt-bun-as-package-manager.md +32 -0
- package/docs/decisions/0002-add-dry-run-transport.md +42 -0
- package/docs/decisions/0003-commit-conventions.md +50 -0
- package/docs/decisions/0004-migrate-to-vitest-4-reported-tasks-api.md +92 -0
- package/docs/decisions/0005-support-vitest-3.md +36 -0
- package/docs/decisions/README.md +58 -0
- package/docs/decisions/adr-template.md +23 -0
- package/package.json +59 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Reporter, TestCase, TestModule, TestRunEndReason, SerializedError } from 'vitest/node';
|
|
2
|
+
import type { VitestSentryReporterOptions, VitestUserConsoleLog } from './types.js';
|
|
3
|
+
export declare class VitestSentryReporter implements Reporter {
|
|
4
|
+
name: string;
|
|
5
|
+
private options;
|
|
6
|
+
private enabled;
|
|
7
|
+
private initialized;
|
|
8
|
+
private reportedIds;
|
|
9
|
+
private queued;
|
|
10
|
+
private logsByTask;
|
|
11
|
+
private maxEventsPerRun?;
|
|
12
|
+
constructor(options?: VitestSentryReporterOptions);
|
|
13
|
+
onInit(): void;
|
|
14
|
+
onUserConsoleLog(log: VitestUserConsoleLog): void;
|
|
15
|
+
onTestCaseResult(testCase: TestCase): void;
|
|
16
|
+
onTestRunEnd(testModules: ReadonlyArray<TestModule>, _unhandledErrors: ReadonlyArray<SerializedError>, _reason: TestRunEndReason): Promise<void>;
|
|
17
|
+
private collectFailure;
|
|
18
|
+
private enqueueFailure;
|
|
19
|
+
private reportFailure;
|
|
20
|
+
private initSentry;
|
|
21
|
+
private resolveEnabled;
|
|
22
|
+
}
|
|
23
|
+
export default VitestSentryReporter;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type * as Sentry from '@sentry/node';
|
|
2
|
+
export type Primitive = string | number | boolean | null | undefined;
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for the Sentry-enabled Vitest reporter.
|
|
5
|
+
*
|
|
6
|
+
* Defaults are chosen to make the reporter work out-of-the-box in CI when `SENTRY_DSN` is set.
|
|
7
|
+
* Most fields can be provided via environment variables and are merged with these options.
|
|
8
|
+
*/
|
|
9
|
+
export type VitestSentryReporterOptions = {
|
|
10
|
+
/**
|
|
11
|
+
* Sentry DSN. If omitted, `process.env.SENTRY_DSN` is used.
|
|
12
|
+
* Reporter is disabled when no DSN is available.
|
|
13
|
+
*/
|
|
14
|
+
dsn?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Force enable/disable the reporter regardless of DSN presence.
|
|
17
|
+
* Defaults to enabled when a DSN is available.
|
|
18
|
+
*/
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Event environment. If omitted, uses `SENTRY_ENVIRONMENT` or falls back to `ci` when a CI is detected,
|
|
22
|
+
* otherwise `process.env.NODE_ENV || 'local'`.
|
|
23
|
+
*/
|
|
24
|
+
environment?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Release identifier. If omitted, uses `SENTRY_RELEASE` or commonly available CI commit SHA.
|
|
27
|
+
*/
|
|
28
|
+
release?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Optional server name/hostname. If omitted, Sentry SDK defaults apply.
|
|
31
|
+
*/
|
|
32
|
+
serverName?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Optional logical project tag you can use to group events across multiple repositories.
|
|
35
|
+
*/
|
|
36
|
+
project?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Static tags to attach to every reported failure. Values are coerced to strings.
|
|
39
|
+
*/
|
|
40
|
+
tags?: Record<string, Primitive>;
|
|
41
|
+
/**
|
|
42
|
+
* Additional Sentry Node SDK options merged into the initialization call.
|
|
43
|
+
*/
|
|
44
|
+
sentryOptions?: Sentry.NodeOptions;
|
|
45
|
+
/**
|
|
46
|
+
* Predicate to determine if a given failure should be reported.
|
|
47
|
+
* Return false to skip reporting.
|
|
48
|
+
*/
|
|
49
|
+
shouldReport?: (ctx: FailureContext) => boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Produce dynamic tags per failure. Merged after static `tags`.
|
|
52
|
+
*/
|
|
53
|
+
getTags?: (ctx: FailureContext) => Record<string, Primitive> | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Sentry fingerprint to control grouping. If omitted, defaults to
|
|
56
|
+
* `['vitest-failure', filePath || 'unknown-file', testName]`.
|
|
57
|
+
*/
|
|
58
|
+
getFingerprint?: (ctx: FailureContext) => string[] | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Associate a user with the event (useful for local runs).
|
|
61
|
+
*/
|
|
62
|
+
getUser?: (ctx: FailureContext) => {
|
|
63
|
+
id?: string;
|
|
64
|
+
email?: string;
|
|
65
|
+
username?: string;
|
|
66
|
+
} | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Final event mutation hook, applied via scope event processor before sending.
|
|
69
|
+
* Return the modified event or `null` to drop it.
|
|
70
|
+
*/
|
|
71
|
+
beforeSend?: (event: Sentry.Event, hint: Sentry.EventHint, ctx: FailureContext) => Sentry.Event | null;
|
|
72
|
+
/**
|
|
73
|
+
* Upper bound on number of events sent in a single Vitest run. Useful to cap noise in very large suites.
|
|
74
|
+
*/
|
|
75
|
+
maxEventsPerRun?: number;
|
|
76
|
+
/**
|
|
77
|
+
* When true, prints what would be sent to Sentry without actually sending events.
|
|
78
|
+
* It has no effect if `enabled` is false.
|
|
79
|
+
*/
|
|
80
|
+
dryRun?: boolean;
|
|
81
|
+
};
|
|
82
|
+
export type FailureContext = {
|
|
83
|
+
id?: string;
|
|
84
|
+
filePath?: string;
|
|
85
|
+
testName: string;
|
|
86
|
+
fullTitle?: string;
|
|
87
|
+
suitePath?: string[];
|
|
88
|
+
message?: string;
|
|
89
|
+
stack?: string;
|
|
90
|
+
error?: unknown;
|
|
91
|
+
durationMs?: number;
|
|
92
|
+
retry?: number;
|
|
93
|
+
flaky?: boolean;
|
|
94
|
+
logs?: string[];
|
|
95
|
+
meta?: Record<string, unknown>;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Minimal shape of Vitest's `UserConsoleLog`, delivered to the reporter's
|
|
99
|
+
* `onUserConsoleLog` hook. We only depend on the fields we actually use so the
|
|
100
|
+
* reporter does not couple to Vitest internals beyond the public reporter API.
|
|
101
|
+
*/
|
|
102
|
+
export interface VitestUserConsoleLog {
|
|
103
|
+
content: string;
|
|
104
|
+
type: 'stdout' | 'stderr';
|
|
105
|
+
taskId?: string;
|
|
106
|
+
}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { TestCase } from 'vitest/node';
|
|
2
|
+
import type { Primitive, FailureContext } from './types.js';
|
|
3
|
+
export declare function toErrorMessage(err: unknown): string | undefined;
|
|
4
|
+
export declare function toStack(err: unknown): string | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* Walk a test case's parent chain, collecting the enclosing suite names
|
|
7
|
+
* (outermost first). The chain ends at the test module, which is not a suite.
|
|
8
|
+
*/
|
|
9
|
+
export declare function collectSuitePath(testCase: TestCase): string[];
|
|
10
|
+
/**
|
|
11
|
+
* Convert a finished Vitest {@link TestCase} into the reporter's
|
|
12
|
+
* {@link FailureContext}. `logs` are collected separately via the
|
|
13
|
+
* `onUserConsoleLog` reporter hook and threaded in by the caller.
|
|
14
|
+
*/
|
|
15
|
+
export declare function toFailureContext(testCase: TestCase, logs?: string[]): FailureContext;
|
|
16
|
+
export declare function ciProvider(): string | undefined;
|
|
17
|
+
export declare function repository(): string | undefined;
|
|
18
|
+
export declare function branch(): string | undefined;
|
|
19
|
+
export declare function commitSha(): string | undefined;
|
|
20
|
+
export declare function inferEnvironment(): string | undefined;
|
|
21
|
+
export declare function vitestVersion(): string | undefined;
|
|
22
|
+
export declare function cleanRecord(obj?: Record<string, unknown>): Record<string, Primitive>;
|
|
23
|
+
export declare function baseTags(ctx: FailureContext): Record<string, Primitive>;
|
|
24
|
+
export declare function extras(ctx: FailureContext): Record<string, unknown>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Markdown Architectural Decision Records (MADR)
|
|
3
|
+
status: accepted
|
|
4
|
+
date: 2025-09-03
|
|
5
|
+
authors:
|
|
6
|
+
- cadesalaberry
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
We want a consistent, lightweight, and review-friendly way to document architectural decisions for `vitest-sentry-reporter`. An ADR format helps capture context, options, and outcomes over time.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
Adopt MADR (Markdown Architectural Decision Records) as our ADR format and process.
|
|
16
|
+
|
|
17
|
+
- Store ADRs under `docs/decisions`
|
|
18
|
+
- Use sequential, zero-padded numbering: `NNNN-short-title.md`
|
|
19
|
+
- Start new ADRs from `docs/decisions/adr-template.md`
|
|
20
|
+
- Capture metadata (`title`, `status`, `date`, `authors`) in YAML front matter
|
|
21
|
+
- Use statuses: `proposed`, `accepted`, `rejected`, `deprecated`, `superseded`
|
|
22
|
+
- When an ADR is superseded, link the successor in both directions
|
|
23
|
+
|
|
24
|
+
## Consequences
|
|
25
|
+
|
|
26
|
+
- Clear, searchable history of decisions and their rationale
|
|
27
|
+
- Easier onboarding and code reviews through explicit rationale
|
|
28
|
+
- Small process overhead when proposing significant changes
|
|
29
|
+
|
|
30
|
+
## References
|
|
31
|
+
|
|
32
|
+
- MADR documentation: https://adr.github.io/madr/
|
|
33
|
+
- MADR repository: https://github.com/adr/madr
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Adopt Bun as the package manager and runtime
|
|
3
|
+
status: accepted
|
|
4
|
+
date: 2025-09-03
|
|
5
|
+
authors:
|
|
6
|
+
- cadesalaberry
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
This repository is an npm package intended for publication. We want a fast developer experience (installs, scripts) and a single lockfile. Bun provides an all-in-one toolchain (runtime, test runner, bundler, package manager) with strong Node compatibility, which fits this project well.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
- Use Bun as the primary package manager for this repo.
|
|
16
|
+
- Specify the required Bun version in `package.json` `engines.bun` and set `packageManager: bun@<version>`.
|
|
17
|
+
- Generate and commit `bun.lockb` for reproducible installs.
|
|
18
|
+
- Maintain Node compatibility via a CommonJS entry (`index.js`) so the package can be consumed by Node/Vitest users.
|
|
19
|
+
- Continue to publish to the public npm registry.
|
|
20
|
+
|
|
21
|
+
## Consequences
|
|
22
|
+
|
|
23
|
+
- Faster installs and scripts with Bun.
|
|
24
|
+
- One lockfile (`bun.lockb`) maintained in the repo.
|
|
25
|
+
- Contributors need Bun installed locally; Node remains supported for consumers of the published package.
|
|
26
|
+
- CI should use Bun for install and scripts.
|
|
27
|
+
|
|
28
|
+
## References
|
|
29
|
+
|
|
30
|
+
- Bun: https://bun.sh/
|
|
31
|
+
- npm Publishing Guide: https://docs.npmjs.com/creating-and-publishing-unscoped-public-packages
|
|
32
|
+
- Vitest reporters: https://vitest.dev/guide/reporters.html
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Add dry-run transport to log Sentry envelopes instead of sending
|
|
3
|
+
status: accepted
|
|
4
|
+
date: 2025-09-04
|
|
5
|
+
authors:
|
|
6
|
+
- cadesalaberry
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
- We want a way to validate what would be reported to Sentry without actually sending events (useful locally or in CI dry runs).
|
|
12
|
+
- The reporter already had a `dryRun` flag that short-circuited reporting. This prevented exercising Sentry scope logic, event processors, and grouping.
|
|
13
|
+
|
|
14
|
+
## Decision
|
|
15
|
+
|
|
16
|
+
- Implement a custom Sentry transport factory that logs envelope items (type + payload) and returns a resolved promise.
|
|
17
|
+
- Enable this transport when `dryRun` is true via `Sentry.init({ transport: makeDryRunTransport })`.
|
|
18
|
+
- Allow an inert DSN in dry-run mode to initialize the SDK and run the normal capture flow.
|
|
19
|
+
- Move the transport to `src/dry-run-transport.ts` and keep `src/reporter.ts` focused on reporter behavior.
|
|
20
|
+
|
|
21
|
+
## Details
|
|
22
|
+
|
|
23
|
+
- `makeDryRunTransport` implements `{ send(envelope), flush(timeout) }`.
|
|
24
|
+
- `send` iterates `envelope[1]` items and logs `{ type, payload }` with a clear prefix.
|
|
25
|
+
- Minimal internal `Envelope` typings are defined locally to avoid importing Sentry private types.
|
|
26
|
+
- `reportFailure` no longer short-circuits on `dryRun`; events go through scopes, tags, and `beforeSend` processors.
|
|
27
|
+
- `initSentry` chooses a fallback DSN when `dryRun` is enabled and sets the transport accordingly.
|
|
28
|
+
|
|
29
|
+
## Consequences
|
|
30
|
+
|
|
31
|
+
- Local and CI dry runs show deterministic logs of would-be sent payloads.
|
|
32
|
+
- The same code paths are exercised in both dry-run and real modes, reducing drift and surprises.
|
|
33
|
+
- No network traffic is emitted during dry runs.
|
|
34
|
+
|
|
35
|
+
## Alternatives
|
|
36
|
+
|
|
37
|
+
- Keep early-return logging in the reporter: rejected, because it bypassed Sentry's scope/event pipeline and diverged from real behavior.
|
|
38
|
+
- Mock Sentry client entirely: rejected, higher maintenance and more divergence from SDK behavior.
|
|
39
|
+
|
|
40
|
+
## Tests
|
|
41
|
+
|
|
42
|
+
- Added `src/dry-run-transport.test.ts` to assert logging behavior and `flush` returning `true`.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Adopt Conventional Commits and Gitmoji
|
|
3
|
+
status: accepted
|
|
4
|
+
date: 2025-11-25
|
|
5
|
+
authors:
|
|
6
|
+
- cadesalaberry
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
A consistent commit history is crucial for project maintainability, automated release generation, and developer collaboration. Without a strict convention, commit messages can become inconsistent, making it difficult to understand the history of changes, generate changelogs, or trigger automated workflows based on commit types.
|
|
12
|
+
|
|
13
|
+
We need a standardized way to format commit messages that is both machine-readable (for automation) and human-readable (for quick scanning).
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
We will adopt **Conventional Commits v1.0.0-beta.4** combined with **Gitmoji**.
|
|
18
|
+
|
|
19
|
+
1. **Conventional Commits**: Provides a structured format (`type(scope): description`) that is widely supported by tools for changelog generation and semantic versioning.
|
|
20
|
+
2. **Gitmoji**: Adds a visual layer to commit messages, making it easier to scan the history and identify the nature of changes at a glance.
|
|
21
|
+
|
|
22
|
+
The required format is:
|
|
23
|
+
```
|
|
24
|
+
<type>(optional scope): <gitmoji> <description>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Example:
|
|
28
|
+
```
|
|
29
|
+
feat(auth): ✨ add login functionality
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
We have documented the specific rules and the list of allowed Gitmojis in `docs/COMMIT_CONVENTION.md`.
|
|
33
|
+
All agents and contributors are expected to follow this convention.
|
|
34
|
+
|
|
35
|
+
## Consequences
|
|
36
|
+
|
|
37
|
+
**Positive:**
|
|
38
|
+
- **Automated Releases**: We can use tools like `semantic-release` or `standard-version` to automatically determine the next version number and generate changelogs based on commit types (e.g., `feat` -> minor, `fix` -> patch, `BREAKING CHANGE` -> major).
|
|
39
|
+
- **Readability**: The history becomes easier to scan. Gitmojis provide instant visual cues about the commit's purpose.
|
|
40
|
+
- **Consistency**: All contributors (human and agents) will follow the same standard.
|
|
41
|
+
|
|
42
|
+
**Negative:**
|
|
43
|
+
- **Learning Curve**: Contributors need to learn the specific types and emojis.
|
|
44
|
+
- **Overhead**: Writing commit messages takes slightly more thought and time to look up the correct emoji.
|
|
45
|
+
|
|
46
|
+
## References
|
|
47
|
+
|
|
48
|
+
- [Conventional Commits](https://www.conventionalcommits.org/)
|
|
49
|
+
- [Gitmoji](https://gitmoji.dev/)
|
|
50
|
+
- [Project Commit Convention](../COMMIT_CONVENTION.md)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Migrate the reporter to the Vitest 4 reported-tasks API
|
|
3
|
+
status: accepted
|
|
4
|
+
date: 2026-06-07
|
|
5
|
+
authors:
|
|
6
|
+
- cadesalaberry
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
The reporter was written against the pre-Vitest-4 task-based reporter API. On
|
|
12
|
+
Vitest 4 it still ran without crashing, but it produced corrupt events:
|
|
13
|
+
|
|
14
|
+
- `onTaskUpdate(packs)` — Vitest 4 keeps dispatching this *deprecated* hook, but
|
|
15
|
+
with the legacy pack shape `[id, result, meta]`. The code read `pack[0]` as a
|
|
16
|
+
*task object* when it is actually an **id string**, so every event got
|
|
17
|
+
`test_name: 'unknown'` and a `Math.random()` id. Dedup keyed on that id never
|
|
18
|
+
matched, so a single failure was reported multiple times.
|
|
19
|
+
- `onTestRunEnd(testModules)` — the hook name was correct, but the body iterated
|
|
20
|
+
`file.tasks` (the old `File` shape). Vitest 4 passes `TestModule[]` with no
|
|
21
|
+
`.tasks`, so the end-of-run sweep collected nothing.
|
|
22
|
+
- State checks compared against `'fail'`, but Vitest 4 uses `'failed'`, and
|
|
23
|
+
`types.ts` carried a whole hand-rolled legacy type layer shadowing the real
|
|
24
|
+
Vitest types.
|
|
25
|
+
|
|
26
|
+
A first migration attempt landed in #1, was reverted in #2, and is re-landed
|
|
27
|
+
here in #3.
|
|
28
|
+
|
|
29
|
+
## Decision
|
|
30
|
+
|
|
31
|
+
Rewrite the reporter onto Vitest 4's public **reported-tasks** reporter API
|
|
32
|
+
(`vitest/node`) and remove the legacy code paths.
|
|
33
|
+
|
|
34
|
+
- **`src/reporter.ts`** — drop `onTaskUpdate`; the class now `implements Reporter`
|
|
35
|
+
from `vitest/node` and uses:
|
|
36
|
+
- `onTestCaseResult(testCase)` for incremental collection of failures as they
|
|
37
|
+
happen;
|
|
38
|
+
- `onTestRunEnd(testModules, …)` iterating `TestModule.children.allTests('failed')`
|
|
39
|
+
as a defensive final sweep, then flushing;
|
|
40
|
+
- `onUserConsoleLog(log)` to buffer per-test console output (keyed by `taskId`)
|
|
41
|
+
so it can be attached to the failure event, preserving the documented `logs`
|
|
42
|
+
extra.
|
|
43
|
+
- A shared `collectFailure` dedup helper keyed on `testCase.id`, and
|
|
44
|
+
`maxEventsPerRun` now counts events actually sent rather than ids seen.
|
|
45
|
+
- **`src/utils.ts`** — `toFailureContext` consumes a `TestCase`
|
|
46
|
+
(`.result()`, `.diagnostic()`, `.module.moduleId`, `.fullName`);
|
|
47
|
+
`collectSuitePath` walks the `TestCase.parent` chain (ending at the module).
|
|
48
|
+
Removed the now-unused `buildFullTitle` and `extractLogs` helpers.
|
|
49
|
+
- **`src/types.ts`** — delete the legacy type layer (`VitestTaskLike`,
|
|
50
|
+
`VitestTaskResult`, `VitestSuiteNode`, `TaskUpdatePack`, the stale
|
|
51
|
+
`declare class`); add a minimal `VitestUserConsoleLog` covering only the fields
|
|
52
|
+
the reporter reads.
|
|
53
|
+
- **Tests** — rewrite `utils.test.ts` against the `TestCase` API, add
|
|
54
|
+
`reporter.test.ts` (dedup, end-of-run sweep, `maxEventsPerRun`, `shouldReport`,
|
|
55
|
+
log buffering, no-DSN path), and fix a pre-existing wrong assertion in
|
|
56
|
+
`dry-run-transport.test.ts`.
|
|
57
|
+
- **`package.json` / `README.md`** — bump the `vitest` peer dependency from
|
|
58
|
+
`>=1.0.0` to `>=4.0.0` and update the README compatibility note to "Vitest 4+".
|
|
59
|
+
- Clean up two leftover debug hacks in `initSentry`: `debug: true || isDryRun`
|
|
60
|
+
becomes `debug: isDryRun`, and the DSN `console.log` is gated behind dry-run.
|
|
61
|
+
|
|
62
|
+
## Consequences
|
|
63
|
+
|
|
64
|
+
- **Breaking change.** Vitest < 4 is no longer supported (peer dependency
|
|
65
|
+
`>=4.0.0`). This warrants a major version bump for the package.
|
|
66
|
+
- Events are now correct on Vitest 4: real `test_name`, `test_full_title`
|
|
67
|
+
(`suite > test`), `test_file`, `flaky`, `retry`, and `extras`
|
|
68
|
+
(`suite_path`, `duration_ms`, `vitest_version`). End-to-end verification
|
|
69
|
+
showed exactly one event per run (`count: 2` across two runs), confirming
|
|
70
|
+
dedup works.
|
|
71
|
+
- The reporter now depends on the **public** `vitest/node` reporter contract
|
|
72
|
+
rather than reverse-engineered internal task shapes, so it is less fragile and
|
|
73
|
+
easier to keep in step with future Vitest releases.
|
|
74
|
+
- Consumers still on Vitest 2/3 must either pin an older release of this package
|
|
75
|
+
or upgrade Vitest.
|
|
76
|
+
|
|
77
|
+
## Alternatives
|
|
78
|
+
|
|
79
|
+
- **Keep dual code paths for both the legacy task API and the reported-tasks
|
|
80
|
+
API.** Rejected: the deprecated `onTaskUpdate` pack shape on Vitest 4 differs
|
|
81
|
+
from the pre-4 shape, so a compatibility shim would be complex and fragile for
|
|
82
|
+
diminishing benefit as Vitest 2/3 fade out.
|
|
83
|
+
- **Stay on the deprecated `onTaskUpdate` hook and just fix the pack parsing.**
|
|
84
|
+
Rejected: the hook is deprecated and slated for removal, and it does not give
|
|
85
|
+
clean access to the new `TestCase` result/diagnostic data the reporter needs.
|
|
86
|
+
|
|
87
|
+
## References
|
|
88
|
+
|
|
89
|
+
- PR #3: https://github.com/cadesalaberry/vitest-sentry-reporter/pull/3
|
|
90
|
+
- Superseded earlier attempts: PR #1 (reverted by PR #2)
|
|
91
|
+
- Vitest reporters: https://vitest.dev/guide/reporters.html
|
|
92
|
+
- Vitest advanced reporter / reported tasks API: https://vitest.dev/advanced/api/reporters.html
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Support Vitest 3 by relaxing the peer dependency range
|
|
3
|
+
status: accepted
|
|
4
|
+
date: 2026-06-07
|
|
5
|
+
authors:
|
|
6
|
+
- cadesalaberry
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
- The reporter declared `peerDependencies.vitest: ">=4.0.0"`, which blocked installation on Vitest 3 projects.
|
|
12
|
+
- The reporter is built on the "reported-tasks" reporter API (`onTestCaseResult`, `onTestRunEnd`, and the `TestCase` / `TestModule` / `TestSuite` objects from `vitest/node`). That API was introduced in Vitest `3.0.0`; the API that was removed in Vitest 4 is the older one (`onTaskUpdate`, `onFinished`, `onCollected`), which this reporter never used.
|
|
13
|
+
- Every method and property the reporter touches — `testCase.result()`, `testCase.diagnostic()` (`duration`/`retryCount`/`flaky`), `testCase.fullName`, `testCase.module.moduleId`, `testCase.parent`, `testCase.project.name`, and `testModule.children.allTests('failed')` — exists with identical signatures in Vitest `3.0.0`. No source changes are needed for compatibility.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
- Relax `peerDependencies.vitest` from `">=4.0.0"` to `">=3.0.0"`.
|
|
18
|
+
- Keep `devDependencies.vitest` on the latest major (`^4.0.13`) so development and type-checking happen against the newest API surface.
|
|
19
|
+
- Add a CI matrix that builds and runs the test suite against both Vitest 3 and Vitest 4 so the compatibility claim is verified on every push and cannot silently regress.
|
|
20
|
+
- Do not lower support below `3.0.0`: the `onTestCaseResult` / `onTestRunEnd` lifecycle did not exist in 2.x (only the experimental reported-tasks objects did).
|
|
21
|
+
|
|
22
|
+
## Consequences
|
|
23
|
+
|
|
24
|
+
- Vitest 3 users can install and use the reporter.
|
|
25
|
+
- The `build` step (`tsc --emitDeclarationOnly`) type-checks `src/` against the installed Vitest types, so a green matrix leg doubles as a type-compatibility check for that major.
|
|
26
|
+
- The CI matrix doubles the job count for this workflow.
|
|
27
|
+
|
|
28
|
+
## Verification
|
|
29
|
+
|
|
30
|
+
- Type-check (`bun run build`) and the unit suite (`bun run test run`) pass against `vitest@3.0.0` and `vitest@3.2.6`.
|
|
31
|
+
- An end-to-end dry-run against real `vitest@3.0.0` objects (a deliberately failing test reported through the reporter in `dryRun` mode) produced the expected Sentry envelope with correct `test_file`, `test_name`, and `test_full_title` tags.
|
|
32
|
+
|
|
33
|
+
## References
|
|
34
|
+
|
|
35
|
+
- Vitest 4 migration guide: reporter APIs `onCollected`, `onTaskUpdate`, `onFinished` removed; "The new APIs were introduced in Vitest `v3.0.0`."
|
|
36
|
+
- ADR 0002 (dry-run transport), reused for the end-to-end verification above.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Architectural Decision Records (ADR)
|
|
2
|
+
|
|
3
|
+
This directory contains Architectural Decision Records using MADR (Markdown Architectural Decision Records).
|
|
4
|
+
|
|
5
|
+
- Format: MADR. See the docs at [adr.github.io/madr](https://adr.github.io/madr/) and the repository at [github.com/adr/madr](https://github.com/adr/madr).
|
|
6
|
+
- Template: `adr-template.md`
|
|
7
|
+
- Each ADR carries its metadata (`title`, `status`, `date`, `authors`) in YAML front matter, followed by `## Context`, `## Decision`, and `## Consequences` sections.
|
|
8
|
+
|
|
9
|
+
## Index
|
|
10
|
+
|
|
11
|
+
| ADR | Title | Status | Date |
|
|
12
|
+
| --- | --- | --- | --- |
|
|
13
|
+
| [0000](0000-use-markdown-architectural-decision-records.md) | Use Markdown Architectural Decision Records (MADR) | accepted | 2025-09-03 |
|
|
14
|
+
| [0001](0001-adopt-bun-as-package-manager.md) | Adopt Bun as the package manager and runtime | accepted | 2025-09-03 |
|
|
15
|
+
| [0002](0002-add-dry-run-transport.md) | Add dry-run transport to log Sentry envelopes instead of sending | accepted | 2025-09-04 |
|
|
16
|
+
| [0003](0003-commit-conventions.md) | Adopt Conventional Commits and Gitmoji | accepted | 2025-11-25 |
|
|
17
|
+
| [0004](0004-migrate-to-vitest-4-reported-tasks-api.md) | Migrate the reporter to the Vitest 4 reported-tasks API | accepted | 2026-06-07 |
|
|
18
|
+
| [0005](0005-support-vitest-3.md) | Support Vitest 3 by relaxing the peer dependency range | accepted | 2026-06-07 |
|
|
19
|
+
|
|
20
|
+
ADRs are numbered sequentially in the chronological order in which they were decided.
|
|
21
|
+
|
|
22
|
+
## How to create a new ADR
|
|
23
|
+
|
|
24
|
+
1. Choose the next zero-padded number (e.g., `0006`).
|
|
25
|
+
2. Copy the template:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
cp adr-template.md 0006-short-title.md
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
3. Fill in the front matter (`title`, `status`, `date`, `authors`) and the `## Context` / `## Decision` / `## Consequences` sections.
|
|
32
|
+
4. Add a row to the [Index](#index) above.
|
|
33
|
+
5. Commit the ADR following the project [commit convention](../COMMIT_CONVENTION.md), e.g. `docs(adr): 📝 add ADR for X`.
|
|
34
|
+
|
|
35
|
+
## Front matter
|
|
36
|
+
|
|
37
|
+
```yaml
|
|
38
|
+
---
|
|
39
|
+
title: Short imperative title
|
|
40
|
+
status: proposed
|
|
41
|
+
date: YYYY-MM-DD
|
|
42
|
+
authors:
|
|
43
|
+
- your-github-handle
|
|
44
|
+
---
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Naming
|
|
48
|
+
|
|
49
|
+
- File name: `NNNN-short-title.md` where `NNNN` is the zero-padded sequence number.
|
|
50
|
+
- Title: Use a short imperative phrase.
|
|
51
|
+
|
|
52
|
+
## Status values
|
|
53
|
+
|
|
54
|
+
- `proposed`: Under discussion
|
|
55
|
+
- `accepted`: Agreed and to be implemented (or already implemented)
|
|
56
|
+
- `rejected`: Considered but not adopted
|
|
57
|
+
- `deprecated`: No longer recommended for new work
|
|
58
|
+
- `superseded`: Replaced by another ADR (link the successor)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Short imperative title
|
|
3
|
+
status: proposed
|
|
4
|
+
date: YYYY-MM-DD
|
|
5
|
+
authors:
|
|
6
|
+
- your-github-handle
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
What is the issue that motivates this decision or change?
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
What change are we proposing and/or implementing?
|
|
16
|
+
|
|
17
|
+
## Consequences
|
|
18
|
+
|
|
19
|
+
What becomes easier or harder because of this decision?
|
|
20
|
+
|
|
21
|
+
## References
|
|
22
|
+
|
|
23
|
+
- Links to related ADRs, issues, docs, and external resources
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vitest-sentry-reporter",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Vitest reporter that sends failures and context to Sentry.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "types/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "bun build --target=node --format=esm --outdir=dist src/index.ts && bun run build:types",
|
|
10
|
+
"build:types": "tsc --emitDeclarationOnly",
|
|
11
|
+
"prepublishOnly": "bun run build",
|
|
12
|
+
"test": "vitest",
|
|
13
|
+
"test:coverage": "vitest run --coverage",
|
|
14
|
+
"test:dogfood": "DOGFOOD=true bun run test run",
|
|
15
|
+
"prepare": "echo \"Using Bun as the package manager\""
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"vitest",
|
|
19
|
+
"reporter",
|
|
20
|
+
"sentry",
|
|
21
|
+
"testing",
|
|
22
|
+
"ci"
|
|
23
|
+
],
|
|
24
|
+
"author": "C-A de Salaberry",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/chanto/vitest-sentry-reporter.git"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/chanto/vitest-sentry-reporter#readme",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/chanto/vitest-sentry-reporter/issues"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"README.md",
|
|
37
|
+
"LICENSE",
|
|
38
|
+
"docs/decisions"
|
|
39
|
+
],
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=18",
|
|
42
|
+
"bun": ">=1.1.0"
|
|
43
|
+
},
|
|
44
|
+
"packageManager": "bun@1.2.21",
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"@sentry/node": ">=10.0.0",
|
|
50
|
+
"vitest": ">=3.0.0"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@sentry/node": "^10.27.0",
|
|
54
|
+
"@types/node": "^18",
|
|
55
|
+
"@vitest/coverage-v8": "^4.0.13",
|
|
56
|
+
"typescript": "^5.9.3",
|
|
57
|
+
"vitest": "^4.0.13"
|
|
58
|
+
}
|
|
59
|
+
}
|