@opice/harness 0.0.2 → 0.0.3
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/package.json +1 -1
- package/src/reporter.ts +42 -9
package/package.json
CHANGED
package/src/reporter.ts
CHANGED
|
@@ -81,6 +81,7 @@ export interface RunHandoff {
|
|
|
81
81
|
class HttpReporter implements Reporter {
|
|
82
82
|
private runIdPromise: Promise<string> | null = null
|
|
83
83
|
private readonly pending: Set<Promise<unknown>> = new Set()
|
|
84
|
+
private warnedUnreachable = false
|
|
84
85
|
|
|
85
86
|
constructor(private readonly config: ReporterConfig) {}
|
|
86
87
|
|
|
@@ -173,19 +174,51 @@ class HttpReporter implements Reporter {
|
|
|
173
174
|
}
|
|
174
175
|
|
|
175
176
|
private async fetch(method: string, path: string, body?: unknown): Promise<Record<string, unknown>> {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
177
|
+
let response: Response
|
|
178
|
+
try {
|
|
179
|
+
response = await fetch(this.config.endpoint + path, {
|
|
180
|
+
method,
|
|
181
|
+
headers: {
|
|
182
|
+
'authorization': `Bearer ${this.config.apiKey}`,
|
|
183
|
+
'content-type': 'application/json',
|
|
184
|
+
},
|
|
185
|
+
body: body == null ? undefined : JSON.stringify(body),
|
|
186
|
+
})
|
|
187
|
+
} catch (err) {
|
|
188
|
+
// Network error / blocked request (e.g. a test runner that installs a
|
|
189
|
+
// DOM and routes fetch through a same-origin policy). Callers swallow
|
|
190
|
+
// reporter errors so the test still runs, so this is the one place the
|
|
191
|
+
// failure is visible — make it loud and actionable.
|
|
192
|
+
this.warnUnreachable(`${method} ${path}`, err instanceof Error ? err.message : String(err))
|
|
193
|
+
throw err
|
|
194
|
+
}
|
|
184
195
|
if (!response.ok) {
|
|
185
|
-
|
|
196
|
+
const detail = `${response.status} ${await response.text()}`.trim()
|
|
197
|
+
this.warnUnreachable(`${method} ${path}`, detail)
|
|
198
|
+
throw new Error(`opice reporter ${method} ${path} failed: ${detail}`)
|
|
186
199
|
}
|
|
187
200
|
return (await response.json()) as Record<string, unknown>
|
|
188
201
|
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* A configured reporter that can't reach the platform means the run is
|
|
205
|
+
* silently NOT recorded — the most confusing failure mode in onboarding
|
|
206
|
+
* (the test passes, but nothing shows on the dashboard). Surface it once,
|
|
207
|
+
* with the usual culprits, instead of letting the swallowed throw vanish.
|
|
208
|
+
*/
|
|
209
|
+
private warnUnreachable(call: string, detail: string): void {
|
|
210
|
+
if (this.warnedUnreachable) return
|
|
211
|
+
this.warnedUnreachable = true
|
|
212
|
+
console.error(
|
|
213
|
+
`[opice] reporter could not reach the platform (${call}: ${detail}). `
|
|
214
|
+
+ `This run will NOT be recorded on the dashboard.\n`
|
|
215
|
+
+ `[opice] Common causes:\n`
|
|
216
|
+
+ `[opice] - the test runner's global setup installs a DOM (happy-dom/jsdom) or mocks\n`
|
|
217
|
+
+ `[opice] fetch, so the cross-origin POST is blocked (look for "Cross-Origin Request\n`
|
|
218
|
+
+ `[opice] Blocked" / an OPTIONS … 401). Scope that setup so it skips the e2e dir.\n`
|
|
219
|
+
+ `[opice] - a missing / expired OPICE_DSN api key (401), or an unreachable endpoint.`,
|
|
220
|
+
)
|
|
221
|
+
}
|
|
189
222
|
}
|
|
190
223
|
|
|
191
224
|
let active: Reporter = new NoopReporter()
|