@side-quest/bun-runner 1.0.2 → 1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @side-quest/bun-runner
2
2
 
3
+ ## 1.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#12](https://github.com/nathanvale/side-quest-runners/pull/12) [`aa20a3f`](https://github.com/nathanvale/side-quest-runners/commit/aa20a3f190a86e978f9bd7039e525a1321b6e4dd) Thanks [@nathanvale](https://github.com/nathanvale)! - Fix console.error false positive in bun_runTests parser. Tests emitting console.error output as part of expected behavior no longer create spurious failures when the summary line shows 0 fail.
8
+
3
9
  ## 1.0.2
4
10
 
5
11
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -16,7 +16,17 @@ interface TestSummary {
16
16
  failures: TestFailure[];
17
17
  }
18
18
  /**
19
- * Parse bun test output to extract test results
19
+ * Parse bun test output to extract test results.
20
+ *
21
+ * The summary line (e.g., "3 pass\n0 fail") is the source of truth.
22
+ * Console.error output from tests can create false positives if we
23
+ * start failure blocks from orphan "error:" lines without a (fail) marker.
24
+ *
25
+ * Strategy:
26
+ * 1. Extract pass/fail counts from summary FIRST
27
+ * 2. If summary shows 0 failures, trust it and skip failure parsing
28
+ * 3. Only parse failure details when summary indicates failures > 0
29
+ * 4. In v1.3+ format, only create failures that have a (fail) marker
20
30
  */
21
31
  declare function parseBunTestOutput(output: string): TestSummary;
22
32
  export { parseBunTestOutput, TestSummary, TestFailure };
package/dist/index.js CHANGED
@@ -20,66 +20,15 @@ import {
20
20
 
21
21
  // mcp/parse-utils.ts
22
22
  function parseBunTestOutput(output) {
23
- const failures = [];
24
- const lines = output.split(`
25
- `);
26
- let currentFailure = null;
27
- let currentTestName;
28
- for (const line of lines) {
29
- if (!line)
30
- continue;
31
- const failMatch = line.match(/\(fail\)\s+(.+?)\s+\[/);
32
- if (failMatch) {
33
- if (currentFailure) {
34
- currentTestName = failMatch[1];
35
- currentFailure.message = `${currentTestName}: ${currentFailure.message}`;
36
- failures.push(currentFailure);
37
- currentFailure = null;
38
- }
39
- continue;
40
- }
41
- if (line.includes("\u2717") || line.startsWith("FAIL ")) {
42
- if (currentFailure)
43
- failures.push(currentFailure);
44
- currentFailure = {
45
- file: "unknown",
46
- message: line.trim()
47
- };
48
- continue;
49
- }
50
- if (line.trim().startsWith("error:")) {
51
- if (currentFailure) {
52
- currentFailure.message += `
53
- ${line.trim()}`;
54
- } else {
55
- currentFailure = {
56
- file: "unknown",
57
- message: line.trim()
58
- };
59
- }
60
- continue;
61
- }
62
- if (currentFailure) {
63
- if (line.trim().startsWith("at ")) {
64
- const match = line.match(/\((.+):(\d+):(\d+)\)/) || line.match(/at (.+):(\d+):(\d+)/);
65
- if (match?.[1] && match[2]) {
66
- currentFailure.file = match[1];
67
- currentFailure.line = Number.parseInt(match[2], 10);
68
- }
69
- currentFailure.stack = `${currentFailure.stack || ""}${line}
70
- `;
71
- } else if (line.trim() && !line.match(/^\d+ \| /)) {
72
- currentFailure.message += `
73
- ${line.trim()}`;
74
- }
75
- }
76
- }
77
- if (currentFailure)
78
- failures.push(currentFailure);
79
23
  const passMatch = output.match(/(\d+) pass/);
80
- const failMatchNum = output.match(/(\d+) fail/);
24
+ const failMatch = output.match(/(\d+) fail/);
81
25
  const passed = passMatch?.[1] ? Number.parseInt(passMatch[1], 10) : 0;
82
- const failed = failMatchNum?.[1] ? Number.parseInt(failMatchNum[1], 10) : failures.length;
26
+ const failedFromSummary = failMatch?.[1] ? Number.parseInt(failMatch[1], 10) : null;
27
+ if (failedFromSummary === 0) {
28
+ return { passed, failed: 0, total: passed, failures: [] };
29
+ }
30
+ const failures = parseFailureDetails(output);
31
+ const failed = failedFromSummary ?? failures.length;
83
32
  return {
84
33
  passed,
85
34
  failed,
@@ -87,15 +36,7 @@ ${line.trim()}`;
87
36
  failures
88
37
  };
89
38
  }
90
-
91
- // mcp/index.ts
92
- var { initLogger, getSubsystemLogger } = createPluginLogger({
93
- name: "bun-runner",
94
- subsystems: ["mcp"]
95
- });
96
- initLogger().catch(console.error);
97
- var mcpLogger = getSubsystemLogger("mcp");
98
- function parseBunTestOutputImpl(output) {
39
+ function parseFailureDetails(output) {
99
40
  const failures = [];
100
41
  const lines = output.split(`
101
42
  `);
@@ -150,19 +91,19 @@ ${line.trim()}`;
150
91
  }
151
92
  }
152
93
  }
153
- if (currentFailure)
94
+ if (currentFailure && (currentFailure.message.includes("\u2717") || currentFailure.message.startsWith("FAIL "))) {
154
95
  failures.push(currentFailure);
155
- const passMatch = output.match(/(\d+) pass/);
156
- const failMatchNum = output.match(/(\d+) fail/);
157
- const passed = passMatch?.[1] ? Number.parseInt(passMatch[1], 10) : 0;
158
- const failed = failMatchNum?.[1] ? Number.parseInt(failMatchNum[1], 10) : failures.length;
159
- return {
160
- passed,
161
- failed,
162
- total: passed + failed,
163
- failures
164
- };
96
+ }
97
+ return failures;
165
98
  }
99
+
100
+ // mcp/index.ts
101
+ var { initLogger, getSubsystemLogger } = createPluginLogger({
102
+ name: "bun-runner",
103
+ subsystems: ["mcp"]
104
+ });
105
+ initLogger().catch(console.error);
106
+ var mcpLogger = getSubsystemLogger("mcp");
166
107
  async function runBunTests(pattern) {
167
108
  const cmd = pattern ? ["bun", "test", pattern] : ["bun", "test"];
168
109
  const TIMEOUT_MS = 30000;
@@ -192,7 +133,7 @@ ${stderr}`;
192
133
  failures: []
193
134
  };
194
135
  }
195
- return parseBunTestOutputImpl(output);
136
+ return parseBunTestOutput(output);
196
137
  }
197
138
  async function runBunTestCoverage() {
198
139
  const TIMEOUT_MS = 60000;
@@ -216,7 +157,7 @@ ${stderr}`;
216
157
  coverage: { percent: 0, uncovered: [] }
217
158
  };
218
159
  }
219
- const summary = exitCode === 0 ? parseBunTestOutputImpl(stdout) : parseBunTestOutputImpl(output);
160
+ const summary = exitCode === 0 ? parseBunTestOutput(stdout) : parseBunTestOutput(output);
220
161
  const coverageMatch = output.match(/(\d+(?:\.\d+)?)\s*%/);
221
162
  const percent = coverageMatch?.[1] ? Number.parseFloat(coverageMatch[1]) : 0;
222
163
  const uncovered = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@side-quest/bun-runner",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Bun test runner MCP server — structured, token-efficient test output for Claude Code",
5
5
  "author": {
6
6
  "name": "Nathan Vale",