@mushi-mushi/web 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +170 -5
- package/dist/index.cjs +1119 -93
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -7
- package/dist/index.d.ts +61 -7
- package/dist/index.js +1120 -95
- package/dist/index.js.map +1 -1
- package/dist/test-utils.cjs +17 -0
- package/dist/test-utils.cjs.map +1 -1
- package/dist/test-utils.d.cts +21 -2
- package/dist/test-utils.d.ts +21 -2
- package/dist/test-utils.js +15 -1
- package/dist/test-utils.js.map +1 -1
- package/package.json +4 -4
package/dist/test-utils.cjs
CHANGED
|
@@ -11,10 +11,27 @@ async function triggerBug(opts = {}) {
|
|
|
11
11
|
function openReport(category) {
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
|
+
function openMushiWidget(category) {
|
|
15
|
+
}
|
|
16
|
+
async function expectMushiReady(options = {}) {
|
|
17
|
+
const timeoutMs = options.timeoutMs ?? 5e3;
|
|
18
|
+
const started = Date.now();
|
|
19
|
+
let lastDiagnostics = null;
|
|
20
|
+
while (Date.now() - started < timeoutMs) {
|
|
21
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
22
|
+
}
|
|
23
|
+
throw new Error(`[mushi:test-utils] SDK not ready: ${JSON.stringify(lastDiagnostics)}`);
|
|
24
|
+
}
|
|
25
|
+
async function expectNoMushiSelfCascade(options = {}) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
14
28
|
async function waitForQueueDrain(options = {}) {
|
|
15
29
|
return 0;
|
|
16
30
|
}
|
|
17
31
|
|
|
32
|
+
exports.expectMushiReady = expectMushiReady;
|
|
33
|
+
exports.expectNoMushiSelfCascade = expectNoMushiSelfCascade;
|
|
34
|
+
exports.openMushiWidget = openMushiWidget;
|
|
18
35
|
exports.openReport = openReport;
|
|
19
36
|
exports.triggerBug = triggerBug;
|
|
20
37
|
exports.waitForQueueDrain = waitForQueueDrain;
|
package/dist/test-utils.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/test-utils.ts"],"names":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"sources":["../src/test-utils.ts"],"names":[],"mappings":";;;;;;;AAuDA,eAAsB,UAAA,CAAW,IAAA,GAA0B,EAAC,EAA2B;AAErF,EAAU,OAAO,IAAA;AAqBnB;AAOO,SAAS,WAAW,QAAA,EAAsC;AAE/D,EAAU;AAEZ;AAGO,SAAS,gBAAgB,QAAA,EAAsC;AAEtE;AAOA,eAAsB,gBAAA,CAAiB,OAAA,GAAkC,EAAC,EAAoC;AAC5G,EAAA,MAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,GAAA;AACvC,EAAA,MAAM,OAAA,GAAU,KAAK,GAAA,EAAI;AACzB,EAAA,IAAI,eAAA,GAAiD,IAAA;AAErD,EAAA,OAAO,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA,GAAU,SAAA,EAAW;AAQvC,IAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,MAAM,UAAA,CAAW,CAAA,EAAG,GAAG,CAAC,CAAA;AAAA,EAC7C;AAEA,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kCAAA,EAAqC,KAAK,SAAA,CAAU,eAAe,CAAC,CAAA,CAAE,CAAA;AACxF;AAOA,eAAsB,wBAAA,CAAyB,OAAA,GAG3C,EAAC,EAAkB;AAErB,EAAU;AAgBZ;AAOA,eAAsB,iBAAA,CAAkB,OAAA,GAAkC,EAAC,EAAoB;AAE7F,EAAU,OAAO,CAAA;AAenB","file":"test-utils.cjs","sourcesContent":["/**\n * @mushi-mushi/web/test-utils\n *\n * Playwright / jsdom helpers for deterministic SDK tests. This module is\n * published as a separate entry-point so production bundles never pay the\n * cost — import it via `import { triggerBug, openReport } from\n * '@mushi-mushi/web/test-utils'`.\n *\n * Design goals:\n * 1. Zero production footprint. Nothing here is imported from `./mushi`,\n * `./widget`, or any runtime module. We reach for the live SDK via\n * `Mushi.getInstance()` so the test process sees exactly what the app\n * bootstrapped — no duplicate SDK singletons, no double-init races.\n * 2. Safe in a test harness even when Mushi is disabled. Every helper\n * no-ops when `Mushi.getInstance()` returns `null`, so Playwright\n * specs that conditionally wire Mushi (e.g. cloud vs local targets)\n * don't have to branch.\n * 3. Flat surface. Tests want 3 verbs: \"open the widget\", \"submit a\n * report programmatically\", \"wait until the SDK confirms the POST\n * landed\". Anything beyond that belongs in the app under test.\n */\n\nimport { Mushi } from './mushi';\nimport type {\n MushiDiagnosticsResult,\n MushiReportCategory,\n MushiSDKInstance,\n} from '@mushi-mushi/core';\n\n/** Options accepted by `triggerBug`. Mirrors the core report contract but\n * keeps every field optional so a Playwright test can say\n * `triggerBug({ description: 'button dead' })` without a category. */\nexport interface TriggerBugOptions {\n /** Short free-text description of the issue. Defaults to a marker\n * string so tests that forget to pass a description still produce a\n * distinguishable report in the admin console. */\n description?: string;\n /** Severity-free category tag. */\n category?: MushiReportCategory;\n /** Arbitrary metadata the test wants to round-trip. Merged on top of\n * whatever `setMetadata` has already stored. */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Submit a report bypassing the widget UI. Returns the server-assigned\n * `reportId` when the POST lands, or `null` if Mushi isn't initialised in\n * this test context (or the submit failed — the SDK swallows network\n * errors silently by design).\n *\n * Use this from Playwright `page.evaluate(...)` calls to round-trip a\n * report into the backend without needing to drive the widget's DOM. It's\n * the fastest way to assert \"a bug report made it from the browser into\n * reports/ in Supabase\".\n */\nexport async function triggerBug(opts: TriggerBugOptions = {}): Promise<string | null> {\n const sdk = Mushi.getInstance();\n if (!sdk) return null;\n\n const description = opts.description\n ?? `[test-utils] triggerBug marker ${new Date().toISOString()}`;\n\n if (opts.metadata) {\n for (const [k, v] of Object.entries(opts.metadata)) {\n try { sdk.setMetadata(k, v); } catch { /* ignore */ }\n }\n }\n\n // `captureEvent` is the documented programmatic-submit API since 0.3.0\n // — it bypasses the widget, resolves with the server-assigned report\n // id, and participates in the same offline queue / pre-filter pipeline\n // as a widget submission.\n return await sdk.captureEvent({\n description,\n source: 'test-utils',\n ...(opts.category ? { category: opts.category } : {}),\n ...(opts.metadata ? { metadata: opts.metadata } : {}),\n });\n}\n\n/**\n * Programmatically open the Mushi widget without submitting anything. Use\n * for interaction tests that want to assert \"the widget is mounted and\n * reachable\" or to drive a user-like flow via Playwright selectors.\n */\nexport function openReport(category?: MushiReportCategory): void {\n const sdk = Mushi.getInstance();\n if (!sdk) return;\n sdk.report(category ? { category } : undefined);\n}\n\n/** Alias with language that reads better in Playwright smoke tests. */\nexport function openMushiWidget(category?: MushiReportCategory): void {\n openReport(category);\n}\n\n/**\n * Wait until the live SDK instance exists and reports a mounted widget.\n * Throws with the diagnostics payload so CI failures point at CSP / Shadow DOM\n * / capture setup instead of a generic timeout.\n */\nexport async function expectMushiReady(options: { timeoutMs?: number } = {}): Promise<MushiDiagnosticsResult> {\n const timeoutMs = options.timeoutMs ?? 5_000;\n const started = Date.now();\n let lastDiagnostics: MushiDiagnosticsResult | null = null;\n\n while (Date.now() - started < timeoutMs) {\n const sdk = Mushi.getInstance();\n if (sdk) {\n lastDiagnostics = await sdk.diagnose();\n if (lastDiagnostics.widgetMounted && lastDiagnostics.shadowDomAvailable) {\n return lastDiagnostics;\n }\n }\n await new Promise((r) => setTimeout(r, 100));\n }\n\n throw new Error(`[mushi:test-utils] SDK not ready: ${JSON.stringify(lastDiagnostics)}`);\n}\n\n/**\n * Run an optional action and fail if the SDK fires an api_cascade proactive\n * prompt during the observation window. This catches the exact glot.it class\n * of bug where Mushi reports on its own runtime-config/report endpoints.\n */\nexport async function expectNoMushiSelfCascade(options: {\n timeoutMs?: number;\n action?: () => void | Promise<void>;\n} = {}): Promise<void> {\n const sdk = Mushi.getInstance();\n if (!sdk) return;\n const timeoutMs = options.timeoutMs ?? 1_000;\n let cascade: unknown = null;\n const unsubscribe = sdk.on('proactive:triggered', (event) => {\n const payload = event.data as { type?: string } | undefined;\n if (payload?.type === 'api_cascade') cascade = event.data ?? true;\n });\n try {\n await options.action?.();\n await new Promise((r) => setTimeout(r, timeoutMs));\n } finally {\n unsubscribe();\n }\n if (cascade) {\n throw new Error(`[mushi:test-utils] unexpected api_cascade from SDK self-noise: ${JSON.stringify(cascade)}`);\n }\n}\n\n/**\n * Wait until the offline queue drains — useful after `triggerBug` in tests\n * that submit while offline then assert the report eventually syncs.\n * Resolves with the number of queued items remaining (0 = fully drained).\n */\nexport async function waitForQueueDrain(options: { timeoutMs?: number } = {}): Promise<number> {\n const sdk = Mushi.getInstance();\n if (!sdk) return 0;\n const timeoutMs = options.timeoutMs ?? 5_000;\n const started = Date.now();\n // The SDK instance doesn't publicly expose the queue, but `getQueueSize`\n // has been in the contract since 0.2.x. We tolerate its absence so\n // upgrading doesn't break tests that only need triggerBug/openReport.\n const getQueueSize = (sdk as MushiSDKInstance & { getQueueSize?: () => number }).getQueueSize;\n if (typeof getQueueSize !== 'function') return 0;\n\n while (Date.now() - started < timeoutMs) {\n const remaining = getQueueSize.call(sdk);\n if (remaining === 0) return 0;\n await new Promise((r) => setTimeout(r, 100));\n }\n return getQueueSize.call(sdk);\n}\n"]}
|
package/dist/test-utils.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MushiReportCategory } from '@mushi-mushi/core';
|
|
1
|
+
import { MushiReportCategory, MushiDiagnosticsResult } from '@mushi-mushi/core';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @mushi-mushi/web/test-utils
|
|
@@ -54,6 +54,25 @@ declare function triggerBug(opts?: TriggerBugOptions): Promise<string | null>;
|
|
|
54
54
|
* reachable" or to drive a user-like flow via Playwright selectors.
|
|
55
55
|
*/
|
|
56
56
|
declare function openReport(category?: MushiReportCategory): void;
|
|
57
|
+
/** Alias with language that reads better in Playwright smoke tests. */
|
|
58
|
+
declare function openMushiWidget(category?: MushiReportCategory): void;
|
|
59
|
+
/**
|
|
60
|
+
* Wait until the live SDK instance exists and reports a mounted widget.
|
|
61
|
+
* Throws with the diagnostics payload so CI failures point at CSP / Shadow DOM
|
|
62
|
+
* / capture setup instead of a generic timeout.
|
|
63
|
+
*/
|
|
64
|
+
declare function expectMushiReady(options?: {
|
|
65
|
+
timeoutMs?: number;
|
|
66
|
+
}): Promise<MushiDiagnosticsResult>;
|
|
67
|
+
/**
|
|
68
|
+
* Run an optional action and fail if the SDK fires an api_cascade proactive
|
|
69
|
+
* prompt during the observation window. This catches the exact glot.it class
|
|
70
|
+
* of bug where Mushi reports on its own runtime-config/report endpoints.
|
|
71
|
+
*/
|
|
72
|
+
declare function expectNoMushiSelfCascade(options?: {
|
|
73
|
+
timeoutMs?: number;
|
|
74
|
+
action?: () => void | Promise<void>;
|
|
75
|
+
}): Promise<void>;
|
|
57
76
|
/**
|
|
58
77
|
* Wait until the offline queue drains — useful after `triggerBug` in tests
|
|
59
78
|
* that submit while offline then assert the report eventually syncs.
|
|
@@ -63,4 +82,4 @@ declare function waitForQueueDrain(options?: {
|
|
|
63
82
|
timeoutMs?: number;
|
|
64
83
|
}): Promise<number>;
|
|
65
84
|
|
|
66
|
-
export { type TriggerBugOptions, openReport, triggerBug, waitForQueueDrain };
|
|
85
|
+
export { type TriggerBugOptions, expectMushiReady, expectNoMushiSelfCascade, openMushiWidget, openReport, triggerBug, waitForQueueDrain };
|
package/dist/test-utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MushiReportCategory } from '@mushi-mushi/core';
|
|
1
|
+
import { MushiReportCategory, MushiDiagnosticsResult } from '@mushi-mushi/core';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @mushi-mushi/web/test-utils
|
|
@@ -54,6 +54,25 @@ declare function triggerBug(opts?: TriggerBugOptions): Promise<string | null>;
|
|
|
54
54
|
* reachable" or to drive a user-like flow via Playwright selectors.
|
|
55
55
|
*/
|
|
56
56
|
declare function openReport(category?: MushiReportCategory): void;
|
|
57
|
+
/** Alias with language that reads better in Playwright smoke tests. */
|
|
58
|
+
declare function openMushiWidget(category?: MushiReportCategory): void;
|
|
59
|
+
/**
|
|
60
|
+
* Wait until the live SDK instance exists and reports a mounted widget.
|
|
61
|
+
* Throws with the diagnostics payload so CI failures point at CSP / Shadow DOM
|
|
62
|
+
* / capture setup instead of a generic timeout.
|
|
63
|
+
*/
|
|
64
|
+
declare function expectMushiReady(options?: {
|
|
65
|
+
timeoutMs?: number;
|
|
66
|
+
}): Promise<MushiDiagnosticsResult>;
|
|
67
|
+
/**
|
|
68
|
+
* Run an optional action and fail if the SDK fires an api_cascade proactive
|
|
69
|
+
* prompt during the observation window. This catches the exact glot.it class
|
|
70
|
+
* of bug where Mushi reports on its own runtime-config/report endpoints.
|
|
71
|
+
*/
|
|
72
|
+
declare function expectNoMushiSelfCascade(options?: {
|
|
73
|
+
timeoutMs?: number;
|
|
74
|
+
action?: () => void | Promise<void>;
|
|
75
|
+
}): Promise<void>;
|
|
57
76
|
/**
|
|
58
77
|
* Wait until the offline queue drains — useful after `triggerBug` in tests
|
|
59
78
|
* that submit while offline then assert the report eventually syncs.
|
|
@@ -63,4 +82,4 @@ declare function waitForQueueDrain(options?: {
|
|
|
63
82
|
timeoutMs?: number;
|
|
64
83
|
}): Promise<number>;
|
|
65
84
|
|
|
66
|
-
export { type TriggerBugOptions, openReport, triggerBug, waitForQueueDrain };
|
|
85
|
+
export { type TriggerBugOptions, expectMushiReady, expectNoMushiSelfCascade, openMushiWidget, openReport, triggerBug, waitForQueueDrain };
|
package/dist/test-utils.js
CHANGED
|
@@ -9,10 +9,24 @@ async function triggerBug(opts = {}) {
|
|
|
9
9
|
function openReport(category) {
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
|
+
function openMushiWidget(category) {
|
|
13
|
+
}
|
|
14
|
+
async function expectMushiReady(options = {}) {
|
|
15
|
+
const timeoutMs = options.timeoutMs ?? 5e3;
|
|
16
|
+
const started = Date.now();
|
|
17
|
+
let lastDiagnostics = null;
|
|
18
|
+
while (Date.now() - started < timeoutMs) {
|
|
19
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
20
|
+
}
|
|
21
|
+
throw new Error(`[mushi:test-utils] SDK not ready: ${JSON.stringify(lastDiagnostics)}`);
|
|
22
|
+
}
|
|
23
|
+
async function expectNoMushiSelfCascade(options = {}) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
12
26
|
async function waitForQueueDrain(options = {}) {
|
|
13
27
|
return 0;
|
|
14
28
|
}
|
|
15
29
|
|
|
16
|
-
export { openReport, triggerBug, waitForQueueDrain };
|
|
30
|
+
export { expectMushiReady, expectNoMushiSelfCascade, openMushiWidget, openReport, triggerBug, waitForQueueDrain };
|
|
17
31
|
//# sourceMappingURL=test-utils.js.map
|
|
18
32
|
//# sourceMappingURL=test-utils.js.map
|
package/dist/test-utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/test-utils.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"sources":["../src/test-utils.ts"],"names":[],"mappings":";;;;;AAuDA,eAAsB,UAAA,CAAW,IAAA,GAA0B,EAAC,EAA2B;AAErF,EAAU,OAAO,IAAA;AAqBnB;AAOO,SAAS,WAAW,QAAA,EAAsC;AAE/D,EAAU;AAEZ;AAGO,SAAS,gBAAgB,QAAA,EAAsC;AAEtE;AAOA,eAAsB,gBAAA,CAAiB,OAAA,GAAkC,EAAC,EAAoC;AAC5G,EAAA,MAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,GAAA;AACvC,EAAA,MAAM,OAAA,GAAU,KAAK,GAAA,EAAI;AACzB,EAAA,IAAI,eAAA,GAAiD,IAAA;AAErD,EAAA,OAAO,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA,GAAU,SAAA,EAAW;AAQvC,IAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,MAAM,UAAA,CAAW,CAAA,EAAG,GAAG,CAAC,CAAA;AAAA,EAC7C;AAEA,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kCAAA,EAAqC,KAAK,SAAA,CAAU,eAAe,CAAC,CAAA,CAAE,CAAA;AACxF;AAOA,eAAsB,wBAAA,CAAyB,OAAA,GAG3C,EAAC,EAAkB;AAErB,EAAU;AAgBZ;AAOA,eAAsB,iBAAA,CAAkB,OAAA,GAAkC,EAAC,EAAoB;AAE7F,EAAU,OAAO,CAAA;AAenB","file":"test-utils.js","sourcesContent":["/**\n * @mushi-mushi/web/test-utils\n *\n * Playwright / jsdom helpers for deterministic SDK tests. This module is\n * published as a separate entry-point so production bundles never pay the\n * cost — import it via `import { triggerBug, openReport } from\n * '@mushi-mushi/web/test-utils'`.\n *\n * Design goals:\n * 1. Zero production footprint. Nothing here is imported from `./mushi`,\n * `./widget`, or any runtime module. We reach for the live SDK via\n * `Mushi.getInstance()` so the test process sees exactly what the app\n * bootstrapped — no duplicate SDK singletons, no double-init races.\n * 2. Safe in a test harness even when Mushi is disabled. Every helper\n * no-ops when `Mushi.getInstance()` returns `null`, so Playwright\n * specs that conditionally wire Mushi (e.g. cloud vs local targets)\n * don't have to branch.\n * 3. Flat surface. Tests want 3 verbs: \"open the widget\", \"submit a\n * report programmatically\", \"wait until the SDK confirms the POST\n * landed\". Anything beyond that belongs in the app under test.\n */\n\nimport { Mushi } from './mushi';\nimport type {\n MushiDiagnosticsResult,\n MushiReportCategory,\n MushiSDKInstance,\n} from '@mushi-mushi/core';\n\n/** Options accepted by `triggerBug`. Mirrors the core report contract but\n * keeps every field optional so a Playwright test can say\n * `triggerBug({ description: 'button dead' })` without a category. */\nexport interface TriggerBugOptions {\n /** Short free-text description of the issue. Defaults to a marker\n * string so tests that forget to pass a description still produce a\n * distinguishable report in the admin console. */\n description?: string;\n /** Severity-free category tag. */\n category?: MushiReportCategory;\n /** Arbitrary metadata the test wants to round-trip. Merged on top of\n * whatever `setMetadata` has already stored. */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Submit a report bypassing the widget UI. Returns the server-assigned\n * `reportId` when the POST lands, or `null` if Mushi isn't initialised in\n * this test context (or the submit failed — the SDK swallows network\n * errors silently by design).\n *\n * Use this from Playwright `page.evaluate(...)` calls to round-trip a\n * report into the backend without needing to drive the widget's DOM. It's\n * the fastest way to assert \"a bug report made it from the browser into\n * reports/ in Supabase\".\n */\nexport async function triggerBug(opts: TriggerBugOptions = {}): Promise<string | null> {\n const sdk = Mushi.getInstance();\n if (!sdk) return null;\n\n const description = opts.description\n ?? `[test-utils] triggerBug marker ${new Date().toISOString()}`;\n\n if (opts.metadata) {\n for (const [k, v] of Object.entries(opts.metadata)) {\n try { sdk.setMetadata(k, v); } catch { /* ignore */ }\n }\n }\n\n // `captureEvent` is the documented programmatic-submit API since 0.3.0\n // — it bypasses the widget, resolves with the server-assigned report\n // id, and participates in the same offline queue / pre-filter pipeline\n // as a widget submission.\n return await sdk.captureEvent({\n description,\n source: 'test-utils',\n ...(opts.category ? { category: opts.category } : {}),\n ...(opts.metadata ? { metadata: opts.metadata } : {}),\n });\n}\n\n/**\n * Programmatically open the Mushi widget without submitting anything. Use\n * for interaction tests that want to assert \"the widget is mounted and\n * reachable\" or to drive a user-like flow via Playwright selectors.\n */\nexport function openReport(category?: MushiReportCategory): void {\n const sdk = Mushi.getInstance();\n if (!sdk) return;\n sdk.report(category ? { category } : undefined);\n}\n\n/** Alias with language that reads better in Playwright smoke tests. */\nexport function openMushiWidget(category?: MushiReportCategory): void {\n openReport(category);\n}\n\n/**\n * Wait until the live SDK instance exists and reports a mounted widget.\n * Throws with the diagnostics payload so CI failures point at CSP / Shadow DOM\n * / capture setup instead of a generic timeout.\n */\nexport async function expectMushiReady(options: { timeoutMs?: number } = {}): Promise<MushiDiagnosticsResult> {\n const timeoutMs = options.timeoutMs ?? 5_000;\n const started = Date.now();\n let lastDiagnostics: MushiDiagnosticsResult | null = null;\n\n while (Date.now() - started < timeoutMs) {\n const sdk = Mushi.getInstance();\n if (sdk) {\n lastDiagnostics = await sdk.diagnose();\n if (lastDiagnostics.widgetMounted && lastDiagnostics.shadowDomAvailable) {\n return lastDiagnostics;\n }\n }\n await new Promise((r) => setTimeout(r, 100));\n }\n\n throw new Error(`[mushi:test-utils] SDK not ready: ${JSON.stringify(lastDiagnostics)}`);\n}\n\n/**\n * Run an optional action and fail if the SDK fires an api_cascade proactive\n * prompt during the observation window. This catches the exact glot.it class\n * of bug where Mushi reports on its own runtime-config/report endpoints.\n */\nexport async function expectNoMushiSelfCascade(options: {\n timeoutMs?: number;\n action?: () => void | Promise<void>;\n} = {}): Promise<void> {\n const sdk = Mushi.getInstance();\n if (!sdk) return;\n const timeoutMs = options.timeoutMs ?? 1_000;\n let cascade: unknown = null;\n const unsubscribe = sdk.on('proactive:triggered', (event) => {\n const payload = event.data as { type?: string } | undefined;\n if (payload?.type === 'api_cascade') cascade = event.data ?? true;\n });\n try {\n await options.action?.();\n await new Promise((r) => setTimeout(r, timeoutMs));\n } finally {\n unsubscribe();\n }\n if (cascade) {\n throw new Error(`[mushi:test-utils] unexpected api_cascade from SDK self-noise: ${JSON.stringify(cascade)}`);\n }\n}\n\n/**\n * Wait until the offline queue drains — useful after `triggerBug` in tests\n * that submit while offline then assert the report eventually syncs.\n * Resolves with the number of queued items remaining (0 = fully drained).\n */\nexport async function waitForQueueDrain(options: { timeoutMs?: number } = {}): Promise<number> {\n const sdk = Mushi.getInstance();\n if (!sdk) return 0;\n const timeoutMs = options.timeoutMs ?? 5_000;\n const started = Date.now();\n // The SDK instance doesn't publicly expose the queue, but `getQueueSize`\n // has been in the contract since 0.2.x. We tolerate its absence so\n // upgrading doesn't break tests that only need triggerBug/openReport.\n const getQueueSize = (sdk as MushiSDKInstance & { getQueueSize?: () => number }).getQueueSize;\n if (typeof getQueueSize !== 'function') return 0;\n\n while (Date.now() - started < timeoutMs) {\n const remaining = getQueueSize.call(sdk);\n if (remaining === 0) return 0;\n await new Promise((r) => setTimeout(r, 100));\n }\n return getQueueSize.call(sdk);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mushi-mushi/web",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Mushi Mushi browser SDK — embeddable bug reporting widget with Shadow DOM isolation",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -81,17 +81,17 @@
|
|
|
81
81
|
{
|
|
82
82
|
"name": "Core SDK bundle (minified + gzipped)",
|
|
83
83
|
"path": "dist/index.js",
|
|
84
|
-
"limit": "
|
|
84
|
+
"limit": "30 KB",
|
|
85
85
|
"gzip": true
|
|
86
86
|
},
|
|
87
87
|
{
|
|
88
88
|
"name": "Core SDK bundle (uncompressed)",
|
|
89
89
|
"path": "dist/index.js",
|
|
90
|
-
"limit": "
|
|
90
|
+
"limit": "70 KB"
|
|
91
91
|
}
|
|
92
92
|
],
|
|
93
93
|
"dependencies": {
|
|
94
|
-
"@mushi-mushi/core": "^0.
|
|
94
|
+
"@mushi-mushi/core": "^0.9.0"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|
|
97
97
|
"@size-limit/file": "^12.1.0",
|