@justinmiehle/reporter-vitest 0.0.6
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 +90 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +160 -0
- package/package.json +39 -0
- package/src/index.ts +181 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Panoptes Vitest Reporter
|
|
2
|
+
|
|
3
|
+
Custom reporter for Vitest that sends test results directly to Convex.
|
|
4
|
+
|
|
5
|
+
Published as **@justinmiehle/reporter-vitest** on [GitHub Packages](https://github.com/JustinMiehle?tab=packages).
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
### Within the Panoptes Monorepo
|
|
10
|
+
|
|
11
|
+
If you're using this reporter in another package within the Panoptes monorepo, use the workspace protocol:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
bun add -d @justinmiehle/reporter-vitest@workspace:*
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This will reference the local package directly without needing to publish or use a local registry.
|
|
18
|
+
|
|
19
|
+
### Outside the Monorepo (GitHub Packages)
|
|
20
|
+
|
|
21
|
+
Install from GitHub Packages. You need to point the `@justinmiehle` scope at GitHub's registry and authenticate.
|
|
22
|
+
|
|
23
|
+
**In a GitHub Action** (other repo), add a step before installing dependencies:
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
- uses: actions/setup-node@v4
|
|
27
|
+
with:
|
|
28
|
+
node-version: '20'
|
|
29
|
+
registry-url: 'https://npm.pkg.github.com'
|
|
30
|
+
scope: '@justinmiehle'
|
|
31
|
+
- run: bun install # or npm ci
|
|
32
|
+
env:
|
|
33
|
+
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Create an `.npmrc` in that repo (or inject it in CI):
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
@justinmiehle:registry=https://npm.pkg.github.com
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Then install:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
bun add -d @justinmiehle/reporter-vitest
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Local / other CI:** Use a [Personal Access Token](https://github.com/settings/tokens) with `read:packages` and set `NODE_AUTH_TOKEN` or use `npm login` against `https://npm.pkg.github.com`.
|
|
49
|
+
|
|
50
|
+
## Configuration
|
|
51
|
+
|
|
52
|
+
Add the reporter to your `vitest.config.ts`:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { defineConfig } from 'vitest/config'
|
|
56
|
+
import PanoptesReporter from '@justinmiehle/reporter-vitest'
|
|
57
|
+
|
|
58
|
+
export default defineConfig({
|
|
59
|
+
test: {
|
|
60
|
+
reporters: [
|
|
61
|
+
'default',
|
|
62
|
+
new PanoptesReporter({
|
|
63
|
+
convexUrl: process.env.CONVEX_URL,
|
|
64
|
+
projectName: process.env.PANOPTES_PROJECT_NAME || 'my-project',
|
|
65
|
+
environment: process.env.NODE_ENV || 'development',
|
|
66
|
+
ci: process.env.CI === 'true',
|
|
67
|
+
}),
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Important:** Do not add `@justinmiehle/reporter-vitest` or `@justinmiehle/shared` to `ssr.noExternal` in your Vite/Vitest config. The packages are designed to be treated as external dependencies and will be loaded from their compiled JavaScript files in the `dist/` directory.
|
|
74
|
+
|
|
75
|
+
## Environment Variables
|
|
76
|
+
|
|
77
|
+
- `CONVEX_URL` - Convex deployment URL (required, e.g., `https://xxx.convex.cloud`)
|
|
78
|
+
- `PANOPTES_PROJECT_NAME` - Project name (default: `default-project`)
|
|
79
|
+
- `NODE_ENV` - Environment name
|
|
80
|
+
- `CI` - Set to `true` if running in CI
|
|
81
|
+
|
|
82
|
+
## Usage
|
|
83
|
+
|
|
84
|
+
Run your tests as usual:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
vitest run
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The reporter will automatically send test results to Convex. Make sure `CONVEX_URL` is set in your environment.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Reporter } from "vitest/reporters";
|
|
2
|
+
interface PanoptesReporterOptions {
|
|
3
|
+
convexUrl?: string;
|
|
4
|
+
projectName?: string;
|
|
5
|
+
environment?: string;
|
|
6
|
+
ci?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export default class PanoptesReporter implements Reporter {
|
|
9
|
+
private options;
|
|
10
|
+
private startTime;
|
|
11
|
+
private tests;
|
|
12
|
+
private suites;
|
|
13
|
+
constructor(options?: PanoptesReporterOptions);
|
|
14
|
+
onInit(): void;
|
|
15
|
+
onTestRunStart(): void;
|
|
16
|
+
onTestCaseResult(test: any): void;
|
|
17
|
+
onTestRunEnd(): Promise<void>;
|
|
18
|
+
private mapStatus;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/index.ts
|
|
9
|
+
function getCommitSha() {
|
|
10
|
+
if (process.env.GITHUB_SHA) {
|
|
11
|
+
return process.env.GITHUB_SHA;
|
|
12
|
+
}
|
|
13
|
+
if (process.env.CIRCLE_SHA1) {
|
|
14
|
+
return process.env.CIRCLE_SHA1;
|
|
15
|
+
}
|
|
16
|
+
if (process.env.GITLAB_CI_COMMIT_SHA) {
|
|
17
|
+
return process.env.GITLAB_CI_COMMIT_SHA;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
const { execSync } = __require("node:child_process");
|
|
21
|
+
return execSync("git rev-parse HEAD", { encoding: "utf-8" }).trim();
|
|
22
|
+
} catch {
|
|
23
|
+
return void 0;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
var PanoptesReporter = class {
|
|
27
|
+
options;
|
|
28
|
+
startTime = 0;
|
|
29
|
+
tests = [];
|
|
30
|
+
suites = /* @__PURE__ */ new Map();
|
|
31
|
+
constructor(options = {}) {
|
|
32
|
+
this.options = {
|
|
33
|
+
convexUrl: options.convexUrl || process.env.CONVEX_URL || "",
|
|
34
|
+
projectName: options.projectName || process.env.PANOPTES_PROJECT_NAME || "default-project",
|
|
35
|
+
environment: options.environment || process.env.NODE_ENV || "development",
|
|
36
|
+
ci: options.ci ?? process.env.CI === "true"
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
onInit() {
|
|
40
|
+
this.startTime = Date.now();
|
|
41
|
+
}
|
|
42
|
+
onTestRunStart() {
|
|
43
|
+
this.tests = [];
|
|
44
|
+
this.suites.clear();
|
|
45
|
+
}
|
|
46
|
+
// biome-ignore lint/suspicious/noExplicitAny: Vitest reporter interface doesn't provide strict types
|
|
47
|
+
onTestCaseResult(test) {
|
|
48
|
+
const testResult = {
|
|
49
|
+
name: test.name || test.title || "Unknown test",
|
|
50
|
+
file: test.file?.name || test.filepath || "unknown",
|
|
51
|
+
line: test.file?.line,
|
|
52
|
+
column: test.file?.column,
|
|
53
|
+
status: this.mapStatus(test.status),
|
|
54
|
+
duration: test.duration || 0,
|
|
55
|
+
error: test.error?.message,
|
|
56
|
+
errorDetails: test.error?.stack,
|
|
57
|
+
retries: test.retryCount,
|
|
58
|
+
suite: test.suite?.name,
|
|
59
|
+
tags: test.meta?.tags,
|
|
60
|
+
metadata: {
|
|
61
|
+
type: test.type,
|
|
62
|
+
mode: test.mode
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
this.tests.push(testResult);
|
|
66
|
+
if (test.suite) {
|
|
67
|
+
const suiteKey = test.suite.name || test.file?.name || "unknown";
|
|
68
|
+
if (!this.suites.has(suiteKey)) {
|
|
69
|
+
this.suites.set(suiteKey, {
|
|
70
|
+
name: test.suite.name || suiteKey,
|
|
71
|
+
file: test.file?.name || test.filepath || "unknown",
|
|
72
|
+
tests: []
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
this.suites.get(suiteKey)?.tests.push(testResult);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async onTestRunEnd() {
|
|
79
|
+
const endTime = Date.now();
|
|
80
|
+
const duration = endTime - this.startTime;
|
|
81
|
+
const passedTests = this.tests.filter((t) => t.status === "passed").length;
|
|
82
|
+
const failedTests = this.tests.filter((t) => t.status === "failed").length;
|
|
83
|
+
const skippedTests = this.tests.filter((t) => t.status === "skipped").length;
|
|
84
|
+
const suiteData = Array.from(this.suites.values()).map((suite) => {
|
|
85
|
+
const suiteTests = suite.tests;
|
|
86
|
+
const passed = suiteTests.filter((t) => t.status === "passed").length;
|
|
87
|
+
const failed = suiteTests.filter((t) => t.status === "failed").length;
|
|
88
|
+
const skipped = suiteTests.filter((t) => t.status === "skipped").length;
|
|
89
|
+
const status = failed > 0 ? "failed" : skipped === suiteTests.length ? "skipped" : "passed";
|
|
90
|
+
return {
|
|
91
|
+
name: suite.name,
|
|
92
|
+
file: suite.file,
|
|
93
|
+
status,
|
|
94
|
+
duration: suiteTests.reduce((sum, t) => sum + t.duration, 0),
|
|
95
|
+
totalTests: suiteTests.length,
|
|
96
|
+
passedTests: passed,
|
|
97
|
+
failedTests: failed,
|
|
98
|
+
skippedTests: skipped
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
const testRun = {
|
|
102
|
+
projectName: this.options.projectName,
|
|
103
|
+
framework: "vitest",
|
|
104
|
+
testType: "unit",
|
|
105
|
+
// Vitest is typically unit tests, but could be configured
|
|
106
|
+
startedAt: this.startTime,
|
|
107
|
+
completedAt: endTime,
|
|
108
|
+
duration,
|
|
109
|
+
totalTests: this.tests.length,
|
|
110
|
+
passedTests,
|
|
111
|
+
failedTests,
|
|
112
|
+
skippedTests,
|
|
113
|
+
environment: this.options.environment,
|
|
114
|
+
ci: this.options.ci,
|
|
115
|
+
commitSha: getCommitSha(),
|
|
116
|
+
tests: this.tests,
|
|
117
|
+
suites: suiteData
|
|
118
|
+
};
|
|
119
|
+
if (!this.options.convexUrl) {
|
|
120
|
+
console.warn("[Panoptes] CONVEX_URL not set. Test results will not be sent.");
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
try {
|
|
124
|
+
const response = await fetch(`${this.options.convexUrl}/http/ingestTestRunHttp`, {
|
|
125
|
+
method: "POST",
|
|
126
|
+
headers: {
|
|
127
|
+
"Content-Type": "application/json"
|
|
128
|
+
},
|
|
129
|
+
body: JSON.stringify(testRun)
|
|
130
|
+
});
|
|
131
|
+
if (!response.ok) {
|
|
132
|
+
const error = await response.text();
|
|
133
|
+
console.error(`[Panoptes] Failed to send test results: ${error}`);
|
|
134
|
+
} else {
|
|
135
|
+
const result = await response.json();
|
|
136
|
+
console.log(`[Panoptes] Test results sent successfully. Test Run ID: ${result.testRunId}`);
|
|
137
|
+
}
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error("[Panoptes] Error sending test results:", error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
mapStatus(status) {
|
|
143
|
+
switch (status) {
|
|
144
|
+
case "passed":
|
|
145
|
+
case "pass":
|
|
146
|
+
return "passed";
|
|
147
|
+
case "failed":
|
|
148
|
+
case "fail":
|
|
149
|
+
return "failed";
|
|
150
|
+
case "skipped":
|
|
151
|
+
case "skip":
|
|
152
|
+
return "skipped";
|
|
153
|
+
default:
|
|
154
|
+
return "running";
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
export {
|
|
159
|
+
PanoptesReporter as default
|
|
160
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@justinmiehle/reporter-vitest",
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"description": "Panoptes reporter for Vitest test results",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": ["dist", "src"],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "bunx esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/index.js --external:@justinmiehle/shared --external:vitest && bunx tsc --emitDeclarationOnly --declaration --outDir dist --skipLibCheck src/index.ts"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/JustinMiehle/panoptes.git",
|
|
22
|
+
"directory": "packages/reporters/vitest"
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"registry": "https://npm.pkg.github.com",
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@justinmiehle/shared": "0.0.2"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^20.10.0",
|
|
33
|
+
"typescript": "^5.3.3",
|
|
34
|
+
"vitest": "^1.0.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"vitest": "^1.0.0"
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import type { TestResult, TestRunIngest } from "@justinmiehle/shared";
|
|
2
|
+
import type { Reporter } from "vitest/reporters";
|
|
3
|
+
|
|
4
|
+
interface PanoptesReporterOptions {
|
|
5
|
+
convexUrl?: string;
|
|
6
|
+
projectName?: string;
|
|
7
|
+
environment?: string;
|
|
8
|
+
ci?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function getCommitSha(): string | undefined {
|
|
12
|
+
// Check CI environment first (GitHub Actions, etc.)
|
|
13
|
+
if (process.env.GITHUB_SHA) {
|
|
14
|
+
return process.env.GITHUB_SHA;
|
|
15
|
+
}
|
|
16
|
+
if (process.env.CIRCLE_SHA1) {
|
|
17
|
+
return process.env.CIRCLE_SHA1;
|
|
18
|
+
}
|
|
19
|
+
if (process.env.GITLAB_CI_COMMIT_SHA) {
|
|
20
|
+
return process.env.GITLAB_CI_COMMIT_SHA;
|
|
21
|
+
}
|
|
22
|
+
// Try to get from git in local environment
|
|
23
|
+
// Note: This requires git to be available and may fail silently
|
|
24
|
+
try {
|
|
25
|
+
const { execSync } = require("node:child_process");
|
|
26
|
+
return execSync("git rev-parse HEAD", { encoding: "utf-8" }).trim();
|
|
27
|
+
} catch {
|
|
28
|
+
// Git not available or not in a git repo
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default class PanoptesReporter implements Reporter {
|
|
34
|
+
private options: Required<PanoptesReporterOptions>;
|
|
35
|
+
private startTime = 0;
|
|
36
|
+
private tests: TestResult[] = [];
|
|
37
|
+
private suites: Map<string, { name: string; file: string; tests: TestResult[] }> = new Map();
|
|
38
|
+
|
|
39
|
+
constructor(options: PanoptesReporterOptions = {}) {
|
|
40
|
+
this.options = {
|
|
41
|
+
convexUrl: options.convexUrl || process.env.CONVEX_URL || "",
|
|
42
|
+
projectName: options.projectName || process.env.PANOPTES_PROJECT_NAME || "default-project",
|
|
43
|
+
environment: options.environment || process.env.NODE_ENV || "development",
|
|
44
|
+
ci: options.ci ?? process.env.CI === "true",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
onInit() {
|
|
49
|
+
this.startTime = Date.now();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
onTestRunStart() {
|
|
53
|
+
this.tests = [];
|
|
54
|
+
this.suites.clear();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// biome-ignore lint/suspicious/noExplicitAny: Vitest reporter interface doesn't provide strict types
|
|
58
|
+
onTestCaseResult(test: any) {
|
|
59
|
+
const testResult: TestResult = {
|
|
60
|
+
name: test.name || test.title || "Unknown test",
|
|
61
|
+
file: test.file?.name || test.filepath || "unknown",
|
|
62
|
+
line: test.file?.line,
|
|
63
|
+
column: test.file?.column,
|
|
64
|
+
status: this.mapStatus(test.status),
|
|
65
|
+
duration: test.duration || 0,
|
|
66
|
+
error: test.error?.message,
|
|
67
|
+
errorDetails: test.error?.stack,
|
|
68
|
+
retries: test.retryCount,
|
|
69
|
+
suite: test.suite?.name,
|
|
70
|
+
tags: test.meta?.tags,
|
|
71
|
+
metadata: {
|
|
72
|
+
type: test.type,
|
|
73
|
+
mode: test.mode,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
this.tests.push(testResult);
|
|
78
|
+
|
|
79
|
+
// Track suites
|
|
80
|
+
if (test.suite) {
|
|
81
|
+
const suiteKey = test.suite.name || test.file?.name || "unknown";
|
|
82
|
+
if (!this.suites.has(suiteKey)) {
|
|
83
|
+
this.suites.set(suiteKey, {
|
|
84
|
+
name: test.suite.name || suiteKey,
|
|
85
|
+
file: test.file?.name || test.filepath || "unknown",
|
|
86
|
+
tests: [],
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
this.suites.get(suiteKey)?.tests.push(testResult);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async onTestRunEnd() {
|
|
94
|
+
const endTime = Date.now();
|
|
95
|
+
const duration = endTime - this.startTime;
|
|
96
|
+
|
|
97
|
+
const passedTests = this.tests.filter((t) => t.status === "passed").length;
|
|
98
|
+
const failedTests = this.tests.filter((t) => t.status === "failed").length;
|
|
99
|
+
const skippedTests = this.tests.filter((t) => t.status === "skipped").length;
|
|
100
|
+
|
|
101
|
+
// Build suite data
|
|
102
|
+
const suiteData = Array.from(this.suites.values()).map((suite) => {
|
|
103
|
+
const suiteTests = suite.tests;
|
|
104
|
+
const passed = suiteTests.filter((t) => t.status === "passed").length;
|
|
105
|
+
const failed = suiteTests.filter((t) => t.status === "failed").length;
|
|
106
|
+
const skipped = suiteTests.filter((t) => t.status === "skipped").length;
|
|
107
|
+
|
|
108
|
+
const status: "passed" | "failed" | "skipped" =
|
|
109
|
+
failed > 0 ? "failed" : skipped === suiteTests.length ? "skipped" : "passed";
|
|
110
|
+
return {
|
|
111
|
+
name: suite.name,
|
|
112
|
+
file: suite.file,
|
|
113
|
+
status,
|
|
114
|
+
duration: suiteTests.reduce((sum, t) => sum + t.duration, 0),
|
|
115
|
+
totalTests: suiteTests.length,
|
|
116
|
+
passedTests: passed,
|
|
117
|
+
failedTests: failed,
|
|
118
|
+
skippedTests: skipped,
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const testRun: TestRunIngest = {
|
|
123
|
+
projectName: this.options.projectName,
|
|
124
|
+
framework: "vitest",
|
|
125
|
+
testType: "unit", // Vitest is typically unit tests, but could be configured
|
|
126
|
+
startedAt: this.startTime,
|
|
127
|
+
completedAt: endTime,
|
|
128
|
+
duration,
|
|
129
|
+
totalTests: this.tests.length,
|
|
130
|
+
passedTests,
|
|
131
|
+
failedTests,
|
|
132
|
+
skippedTests,
|
|
133
|
+
environment: this.options.environment,
|
|
134
|
+
ci: this.options.ci,
|
|
135
|
+
commitSha: getCommitSha(),
|
|
136
|
+
tests: this.tests,
|
|
137
|
+
suites: suiteData,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
if (!this.options.convexUrl) {
|
|
141
|
+
console.warn("[Panoptes] CONVEX_URL not set. Test results will not be sent.");
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
const response = await fetch(`${this.options.convexUrl}/http/ingestTestRunHttp`, {
|
|
147
|
+
method: "POST",
|
|
148
|
+
headers: {
|
|
149
|
+
"Content-Type": "application/json",
|
|
150
|
+
},
|
|
151
|
+
body: JSON.stringify(testRun),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (!response.ok) {
|
|
155
|
+
const error = await response.text();
|
|
156
|
+
console.error(`[Panoptes] Failed to send test results: ${error}`);
|
|
157
|
+
} else {
|
|
158
|
+
const result = (await response.json()) as { testRunId?: string };
|
|
159
|
+
console.log(`[Panoptes] Test results sent successfully. Test Run ID: ${result.testRunId}`);
|
|
160
|
+
}
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error("[Panoptes] Error sending test results:", error);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private mapStatus(status: string): "passed" | "failed" | "skipped" | "running" {
|
|
167
|
+
switch (status) {
|
|
168
|
+
case "passed":
|
|
169
|
+
case "pass":
|
|
170
|
+
return "passed";
|
|
171
|
+
case "failed":
|
|
172
|
+
case "fail":
|
|
173
|
+
return "failed";
|
|
174
|
+
case "skipped":
|
|
175
|
+
case "skip":
|
|
176
|
+
return "skipped";
|
|
177
|
+
default:
|
|
178
|
+
return "running";
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|