@kakarot-ci/core 0.6.6 → 0.7.1

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/dist/index.js CHANGED
@@ -21,6 +21,7 @@ var KakarotConfigSchema = z.object({
21
21
  enableAutoCommit: z.boolean().default(true),
22
22
  commitStrategy: z.enum(["direct", "branch-pr"]).default("direct"),
23
23
  enablePRComments: z.boolean().default(true),
24
+ enableCoverage: z.boolean().default(false),
24
25
  debug: z.boolean().default(false)
25
26
  });
26
27
 
@@ -94,24 +95,11 @@ async function findProjectRoot(startPath) {
94
95
  async function loadConfig() {
95
96
  const explorer = cosmiconfig("kakarot", {
96
97
  searchPlaces: [
97
- "kakarot.config.ts",
98
98
  "kakarot.config.js",
99
- ".kakarot-ci.config.ts",
100
99
  ".kakarot-ci.config.js",
101
100
  ".kakarot-ci.config.json",
102
101
  "package.json"
103
- ],
104
- loaders: {
105
- ".ts": async (filepath) => {
106
- try {
107
- const configModule = await import(filepath);
108
- return configModule.default || configModule.config || null;
109
- } catch (err) {
110
- error(`Failed to load TypeScript config: ${err instanceof Error ? err.message : String(err)}`);
111
- return null;
112
- }
113
- }
114
- }
102
+ ]
115
103
  });
116
104
  try {
117
105
  const result = await explorer.search();
@@ -148,7 +136,7 @@ async function loadConfig() {
148
136
  } catch (err) {
149
137
  if (err instanceof Error && err.message.includes("apiKey")) {
150
138
  error(
151
- "Missing required apiKey. Provide it via:\n - Config file (kakarot.config.ts, .kakarot-ci.config.js/json, or package.json)\n - Environment variable: KAKAROT_API_KEY"
139
+ "Missing required apiKey. Provide it via:\n - Config file (kakarot.config.js, .kakarot-ci.config.js/json, or package.json)\n - Environment variable: KAKAROT_API_KEY"
152
140
  );
153
141
  }
154
142
  throw err;
@@ -371,6 +359,7 @@ var GitHubClient = class {
371
359
  async fileExists(ref, path) {
372
360
  const originalError = console.error;
373
361
  const originalWarn = console.warn;
362
+ const originalLog = console.log;
374
363
  const suppress404 = (...args) => {
375
364
  const message = String(args[0] || "");
376
365
  if (message.includes("404") || message.includes("Not Found")) {
@@ -385,9 +374,17 @@ var GitHubClient = class {
385
374
  }
386
375
  originalWarn(...args);
387
376
  };
377
+ const suppress404Log = (...args) => {
378
+ const message = String(args[0] || "");
379
+ if (message.includes("404") || message.includes("Not Found")) {
380
+ return;
381
+ }
382
+ originalLog(...args);
383
+ };
388
384
  try {
389
385
  console.error = suppress404;
390
386
  console.warn = suppress404Warn;
387
+ console.log = suppress404Log;
391
388
  await this.octokit.rest.repos.getContent({
392
389
  owner: this.owner,
393
390
  repo: this.repo,
@@ -410,6 +407,7 @@ var GitHubClient = class {
410
407
  } finally {
411
408
  console.error = originalError;
412
409
  console.warn = originalWarn;
410
+ console.log = originalLog;
413
411
  }
414
412
  }
415
413
  /**
@@ -1081,15 +1079,49 @@ function buildSystemPrompt(framework) {
1081
1079
  const importStatement = framework === "jest" ? "import { describe, it, expect } from 'jest';" : "import { describe, it, expect } from 'vitest';";
1082
1080
  return `You are an expert ${frameworkName} test writer. Your task is to generate comprehensive unit tests for TypeScript/JavaScript functions.
1083
1081
 
1082
+ CRITICAL: Test the ACTUAL behavior of the code, not assumed behavior.
1083
+
1084
1084
  Requirements:
1085
1085
  1. Generate complete, runnable ${frameworkName} test code
1086
1086
  2. Use ${frameworkName} syntax and best practices
1087
- 3. Test edge cases, error conditions, and normal operation
1088
- 4. Use descriptive test names that explain what is being tested
1089
- 5. Include proper setup/teardown if needed
1090
- 6. Mock external dependencies appropriately
1091
- 7. Test both success and failure scenarios
1092
- 8. Follow the existing test file structure if one exists
1087
+ 3. Analyze the function code to determine its ACTUAL runtime behavior before writing tests
1088
+ 4. Test edge cases and normal operation based on what the code actually does
1089
+ 5. Only test for errors/exceptions if the code actually throws them (check for try/catch, throw statements, or validation logic)
1090
+ 6. Match JavaScript/TypeScript runtime semantics:
1091
+ - Arithmetic operations (+, -, *, /, %, **) do NOT throw errors for invalid inputs; they return NaN or Infinity
1092
+ - Division by zero returns Infinity (not an error)
1093
+ - Modulo by zero returns NaN (not an error)
1094
+ - Bitwise operations convert values to 32-bit integers
1095
+ - Operations with null/undefined may coerce to numbers or return NaN
1096
+ - TypeScript types are compile-time only; runtime behavior follows JavaScript rules
1097
+ 7. For async functions:
1098
+ - Use async/await or .then()/.catch() appropriately
1099
+ - Test both resolved and rejected promises
1100
+ - Use resolves and rejects matchers when appropriate
1101
+ - Await async function calls in tests
1102
+ 8. For functions with side effects or external dependencies:
1103
+ - Mock external dependencies (APIs, file system, databases, etc.)
1104
+ - Mock imported modules using ${framework === "jest" ? "jest.mock()" : "vi.mock()"}
1105
+ - Reset mocks between tests to ensure test isolation
1106
+ - Verify mock calls if the function's behavior depends on them
1107
+ 9. For functions that modify state:
1108
+ - Test state before and after function calls
1109
+ - Reset state between tests if needed
1110
+ - Test state mutations, not just return values
1111
+ 10. For error testing:
1112
+ - Only test for errors if the function actually throws them
1113
+ - Match actual error types and messages (use toThrow() with specific error types/messages)
1114
+ - For async errors, use rejects matcher
1115
+ 11. Import handling:
1116
+ - Use the same import paths as the source file
1117
+ - Import types correctly (type imports for TypeScript types)
1118
+ - Mock dependencies at the module level, not the function level
1119
+ 12. Test isolation:
1120
+ - Each test should be independent and not rely on other tests
1121
+ - Use beforeEach/afterEach for setup/teardown when needed
1122
+ - Don't share mutable state between tests
1123
+ 13. Use descriptive test names that explain what is being tested
1124
+ 14. Follow the existing test file structure if one exists
1093
1125
 
1094
1126
  Output format:
1095
1127
  - Return ONLY the test code, no explanations or markdown code blocks
@@ -1159,18 +1191,38 @@ ${existingTestFile}
1159
1191
 
1160
1192
  `;
1161
1193
  }
1162
- prompt += `Generate comprehensive unit tests for ${target.functionName}. Include:
1194
+ prompt += `Generate comprehensive unit tests for ${target.functionName}. IMPORTANT: Analyze the function code above to determine its ACTUAL behavior before writing tests.
1195
+
1196
+ `;
1197
+ prompt += `Include:
1163
1198
  `;
1164
1199
  prompt += `- Tests for normal operation with various inputs
1165
1200
  `;
1166
- prompt += `- Tests for edge cases (null, undefined, empty arrays, etc.)
1201
+ prompt += `- Tests for edge cases based on what the code actually does (null, undefined, empty arrays, etc.)
1167
1202
  `;
1168
- prompt += `- Tests for error conditions if applicable
1203
+ prompt += `- Tests for error conditions ONLY if the code actually throws errors (check for throw statements, validation, or error handling)
1169
1204
  `;
1170
1205
  prompt += `- Tests for boundary conditions
1171
1206
  `;
1172
1207
  prompt += `- Proper mocking of dependencies if needed
1173
1208
 
1209
+ `;
1210
+ prompt += `Key considerations:
1211
+ `;
1212
+ prompt += `- If the function is async, use async/await in tests and test both success and error cases
1213
+ `;
1214
+ prompt += `- If the function uses external dependencies (imports), mock them appropriately
1215
+ `;
1216
+ prompt += `- If the function modifies state, test the state changes
1217
+ `;
1218
+ prompt += `- Match actual return types and values, not assumed types
1219
+ `;
1220
+ prompt += `- TypeScript types are compile-time only; test runtime behavior
1221
+ `;
1222
+ prompt += `- JavaScript/TypeScript arithmetic and bitwise operations do NOT throw errors for invalid inputs. They return NaN, Infinity, or perform type coercion. Only test for errors if the function code explicitly throws them.
1223
+ `;
1224
+ prompt += `- Use the same import paths as the source file for consistency
1225
+
1174
1226
  `;
1175
1227
  prompt += `Return ONLY the test code, no explanations or markdown formatting.`;
1176
1228
  return prompt;
@@ -1195,13 +1247,34 @@ Context:
1195
1247
  - The test code failed to run or produced incorrect results
1196
1248
  - You need to analyze the error and fix the test code
1197
1249
 
1250
+ CRITICAL: Tests must match the ACTUAL behavior of the code being tested, not assumed behavior.
1251
+
1198
1252
  Requirements:
1199
- 1. Fix the test code to make it pass
1200
- 2. Maintain the original test intent
1201
- 3. Use proper ${frameworkName} syntax
1202
- 4. Ensure all imports and dependencies are correct
1203
- 5. Fix any syntax errors, type errors, or logical errors
1204
- 6. If the original code being tested has issues, note that but focus on fixing the test
1253
+ 1. Analyze the original function code to understand its ACTUAL runtime behavior
1254
+ 2. Fix the test code to match what the function actually does, not what it "should" do
1255
+ 3. Only expect errors/exceptions if the function code actually throws them
1256
+ 4. Match JavaScript/TypeScript runtime semantics:
1257
+ - Arithmetic operations do NOT throw errors; they return NaN or Infinity
1258
+ - Division by zero returns Infinity (not an error)
1259
+ - Modulo by zero returns NaN (not an error)
1260
+ - Bitwise operations convert values to 32-bit integers
1261
+ - TypeScript types are compile-time only; runtime behavior follows JavaScript rules
1262
+ 5. For async functions:
1263
+ - Ensure tests properly await async calls
1264
+ - Use resolves/rejects matchers appropriately
1265
+ - Test both success and error cases for async functions
1266
+ 6. For functions with dependencies:
1267
+ - Ensure mocks are properly set up
1268
+ - Verify import paths match the source file
1269
+ - Reset mocks if needed for test isolation
1270
+ 7. For error testing:
1271
+ - Only expect errors if the function actually throws them
1272
+ - Match actual error types and messages
1273
+ - Use appropriate matchers (toThrow, rejects, etc.)
1274
+ 8. Maintain the original test intent where possible, but prioritize correctness
1275
+ 9. Use proper ${frameworkName} syntax
1276
+ 10. Ensure all imports and dependencies are correct
1277
+ 11. Fix any syntax errors, type errors, or logical errors
1205
1278
 
1206
1279
  Output format:
1207
1280
  - Return ONLY the fixed test code, no explanations or markdown code blocks
@@ -1934,7 +2007,7 @@ async function runPullRequest(context) {
1934
2007
  })),
1935
2008
  errors
1936
2009
  };
1937
- if (testFiles.size > 0) {
2010
+ if (config.enableCoverage && testFiles.size > 0) {
1938
2011
  const testRunner = createTestRunner(framework);
1939
2012
  const writtenPaths = Array.from(testFiles.keys());
1940
2013
  try {
@@ -1952,12 +2025,12 @@ async function runPullRequest(context) {
1952
2025
  summary.coverageReport = coverageReport;
1953
2026
  summary.testResults = finalTestResults;
1954
2027
  } else {
1955
- debug("Could not read coverage report (coverage package may be missing)");
2028
+ warn("Could not read coverage report (coverage package may be missing)");
1956
2029
  }
1957
2030
  } catch (err) {
1958
2031
  const errorMessage = err instanceof Error ? err.message : String(err);
1959
2032
  if (errorMessage.includes("coverage") || errorMessage.includes("MISSING DEPENDENCY")) {
1960
- debug(`Coverage collection skipped (missing coverage package): ${errorMessage.split("\n")[0]}`);
2033
+ warn(`Coverage collection failed (coverage package may be missing): ${errorMessage.split("\n")[0]}`);
1961
2034
  } else {
1962
2035
  throw err;
1963
2036
  }
@@ -2054,7 +2127,8 @@ async function commitTests(githubClient, pr, testFiles, config, summary) {
2054
2127
  info(`Committing ${testFiles.length} test file(s)`);
2055
2128
  try {
2056
2129
  if (config.commitStrategy === "branch-pr") {
2057
- const branchName = `kakarot-ci/tests-pr-${pr.number}`;
2130
+ const timestamp = Date.now();
2131
+ const branchName = `kakarot-ci/tests-pr-${pr.number}-${timestamp}`;
2058
2132
  const baseSha = await githubClient.createBranch(branchName, pr.head.ref);
2059
2133
  await githubClient.commitFiles({
2060
2134
  files: testFiles.map((file) => ({