@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/cli/index.js CHANGED
@@ -276,6 +276,7 @@ var GitHubClient = class {
276
276
  async fileExists(ref, path) {
277
277
  const originalError = console.error;
278
278
  const originalWarn = console.warn;
279
+ const originalLog = console.log;
279
280
  const suppress404 = (...args) => {
280
281
  const message = String(args[0] || "");
281
282
  if (message.includes("404") || message.includes("Not Found")) {
@@ -290,9 +291,17 @@ var GitHubClient = class {
290
291
  }
291
292
  originalWarn(...args);
292
293
  };
294
+ const suppress404Log = (...args) => {
295
+ const message = String(args[0] || "");
296
+ if (message.includes("404") || message.includes("Not Found")) {
297
+ return;
298
+ }
299
+ originalLog(...args);
300
+ };
293
301
  try {
294
302
  console.error = suppress404;
295
303
  console.warn = suppress404Warn;
304
+ console.log = suppress404Log;
296
305
  await this.octokit.rest.repos.getContent({
297
306
  owner: this.owner,
298
307
  repo: this.repo,
@@ -315,6 +324,7 @@ var GitHubClient = class {
315
324
  } finally {
316
325
  console.error = originalError;
317
326
  console.warn = originalWarn;
327
+ console.log = originalLog;
318
328
  }
319
329
  }
320
330
  /**
@@ -356,6 +366,7 @@ var KakarotConfigSchema = z.object({
356
366
  enableAutoCommit: z.boolean().default(true),
357
367
  commitStrategy: z.enum(["direct", "branch-pr"]).default("direct"),
358
368
  enablePRComments: z.boolean().default(true),
369
+ enableCoverage: z.boolean().default(false),
359
370
  debug: z.boolean().default(false)
360
371
  });
361
372
 
@@ -373,24 +384,11 @@ async function findProjectRoot(startPath) {
373
384
  async function loadConfig() {
374
385
  const explorer = cosmiconfig("kakarot", {
375
386
  searchPlaces: [
376
- "kakarot.config.ts",
377
387
  "kakarot.config.js",
378
- ".kakarot-ci.config.ts",
379
388
  ".kakarot-ci.config.js",
380
389
  ".kakarot-ci.config.json",
381
390
  "package.json"
382
- ],
383
- loaders: {
384
- ".ts": async (filepath) => {
385
- try {
386
- const configModule = await import(filepath);
387
- return configModule.default || configModule.config || null;
388
- } catch (err) {
389
- error(`Failed to load TypeScript config: ${err instanceof Error ? err.message : String(err)}`);
390
- return null;
391
- }
392
- }
393
- }
391
+ ]
394
392
  });
395
393
  try {
396
394
  const result = await explorer.search();
@@ -427,7 +425,7 @@ async function loadConfig() {
427
425
  } catch (err) {
428
426
  if (err instanceof Error && err.message.includes("apiKey")) {
429
427
  error(
430
- "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"
428
+ "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"
431
429
  );
432
430
  }
433
431
  throw err;
@@ -1067,15 +1065,49 @@ function buildSystemPrompt(framework) {
1067
1065
  const importStatement = framework === "jest" ? "import { describe, it, expect } from 'jest';" : "import { describe, it, expect } from 'vitest';";
1068
1066
  return `You are an expert ${frameworkName} test writer. Your task is to generate comprehensive unit tests for TypeScript/JavaScript functions.
1069
1067
 
1068
+ CRITICAL: Test the ACTUAL behavior of the code, not assumed behavior.
1069
+
1070
1070
  Requirements:
1071
1071
  1. Generate complete, runnable ${frameworkName} test code
1072
1072
  2. Use ${frameworkName} syntax and best practices
1073
- 3. Test edge cases, error conditions, and normal operation
1074
- 4. Use descriptive test names that explain what is being tested
1075
- 5. Include proper setup/teardown if needed
1076
- 6. Mock external dependencies appropriately
1077
- 7. Test both success and failure scenarios
1078
- 8. Follow the existing test file structure if one exists
1073
+ 3. Analyze the function code to determine its ACTUAL runtime behavior before writing tests
1074
+ 4. Test edge cases and normal operation based on what the code actually does
1075
+ 5. Only test for errors/exceptions if the code actually throws them (check for try/catch, throw statements, or validation logic)
1076
+ 6. Match JavaScript/TypeScript runtime semantics:
1077
+ - Arithmetic operations (+, -, *, /, %, **) do NOT throw errors for invalid inputs; they return NaN or Infinity
1078
+ - Division by zero returns Infinity (not an error)
1079
+ - Modulo by zero returns NaN (not an error)
1080
+ - Bitwise operations convert values to 32-bit integers
1081
+ - Operations with null/undefined may coerce to numbers or return NaN
1082
+ - TypeScript types are compile-time only; runtime behavior follows JavaScript rules
1083
+ 7. For async functions:
1084
+ - Use async/await or .then()/.catch() appropriately
1085
+ - Test both resolved and rejected promises
1086
+ - Use resolves and rejects matchers when appropriate
1087
+ - Await async function calls in tests
1088
+ 8. For functions with side effects or external dependencies:
1089
+ - Mock external dependencies (APIs, file system, databases, etc.)
1090
+ - Mock imported modules using ${framework === "jest" ? "jest.mock()" : "vi.mock()"}
1091
+ - Reset mocks between tests to ensure test isolation
1092
+ - Verify mock calls if the function's behavior depends on them
1093
+ 9. For functions that modify state:
1094
+ - Test state before and after function calls
1095
+ - Reset state between tests if needed
1096
+ - Test state mutations, not just return values
1097
+ 10. For error testing:
1098
+ - Only test for errors if the function actually throws them
1099
+ - Match actual error types and messages (use toThrow() with specific error types/messages)
1100
+ - For async errors, use rejects matcher
1101
+ 11. Import handling:
1102
+ - Use the same import paths as the source file
1103
+ - Import types correctly (type imports for TypeScript types)
1104
+ - Mock dependencies at the module level, not the function level
1105
+ 12. Test isolation:
1106
+ - Each test should be independent and not rely on other tests
1107
+ - Use beforeEach/afterEach for setup/teardown when needed
1108
+ - Don't share mutable state between tests
1109
+ 13. Use descriptive test names that explain what is being tested
1110
+ 14. Follow the existing test file structure if one exists
1079
1111
 
1080
1112
  Output format:
1081
1113
  - Return ONLY the test code, no explanations or markdown code blocks
@@ -1145,18 +1177,38 @@ ${existingTestFile}
1145
1177
 
1146
1178
  `;
1147
1179
  }
1148
- prompt += `Generate comprehensive unit tests for ${target.functionName}. Include:
1180
+ prompt += `Generate comprehensive unit tests for ${target.functionName}. IMPORTANT: Analyze the function code above to determine its ACTUAL behavior before writing tests.
1181
+
1182
+ `;
1183
+ prompt += `Include:
1149
1184
  `;
1150
1185
  prompt += `- Tests for normal operation with various inputs
1151
1186
  `;
1152
- prompt += `- Tests for edge cases (null, undefined, empty arrays, etc.)
1187
+ prompt += `- Tests for edge cases based on what the code actually does (null, undefined, empty arrays, etc.)
1153
1188
  `;
1154
- prompt += `- Tests for error conditions if applicable
1189
+ prompt += `- Tests for error conditions ONLY if the code actually throws errors (check for throw statements, validation, or error handling)
1155
1190
  `;
1156
1191
  prompt += `- Tests for boundary conditions
1157
1192
  `;
1158
1193
  prompt += `- Proper mocking of dependencies if needed
1159
1194
 
1195
+ `;
1196
+ prompt += `Key considerations:
1197
+ `;
1198
+ prompt += `- If the function is async, use async/await in tests and test both success and error cases
1199
+ `;
1200
+ prompt += `- If the function uses external dependencies (imports), mock them appropriately
1201
+ `;
1202
+ prompt += `- If the function modifies state, test the state changes
1203
+ `;
1204
+ prompt += `- Match actual return types and values, not assumed types
1205
+ `;
1206
+ prompt += `- TypeScript types are compile-time only; test runtime behavior
1207
+ `;
1208
+ 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.
1209
+ `;
1210
+ prompt += `- Use the same import paths as the source file for consistency
1211
+
1160
1212
  `;
1161
1213
  prompt += `Return ONLY the test code, no explanations or markdown formatting.`;
1162
1214
  return prompt;
@@ -1181,13 +1233,34 @@ Context:
1181
1233
  - The test code failed to run or produced incorrect results
1182
1234
  - You need to analyze the error and fix the test code
1183
1235
 
1236
+ CRITICAL: Tests must match the ACTUAL behavior of the code being tested, not assumed behavior.
1237
+
1184
1238
  Requirements:
1185
- 1. Fix the test code to make it pass
1186
- 2. Maintain the original test intent
1187
- 3. Use proper ${frameworkName} syntax
1188
- 4. Ensure all imports and dependencies are correct
1189
- 5. Fix any syntax errors, type errors, or logical errors
1190
- 6. If the original code being tested has issues, note that but focus on fixing the test
1239
+ 1. Analyze the original function code to understand its ACTUAL runtime behavior
1240
+ 2. Fix the test code to match what the function actually does, not what it "should" do
1241
+ 3. Only expect errors/exceptions if the function code actually throws them
1242
+ 4. Match JavaScript/TypeScript runtime semantics:
1243
+ - Arithmetic operations do NOT throw errors; they return NaN or Infinity
1244
+ - Division by zero returns Infinity (not an error)
1245
+ - Modulo by zero returns NaN (not an error)
1246
+ - Bitwise operations convert values to 32-bit integers
1247
+ - TypeScript types are compile-time only; runtime behavior follows JavaScript rules
1248
+ 5. For async functions:
1249
+ - Ensure tests properly await async calls
1250
+ - Use resolves/rejects matchers appropriately
1251
+ - Test both success and error cases for async functions
1252
+ 6. For functions with dependencies:
1253
+ - Ensure mocks are properly set up
1254
+ - Verify import paths match the source file
1255
+ - Reset mocks if needed for test isolation
1256
+ 7. For error testing:
1257
+ - Only expect errors if the function actually throws them
1258
+ - Match actual error types and messages
1259
+ - Use appropriate matchers (toThrow, rejects, etc.)
1260
+ 8. Maintain the original test intent where possible, but prioritize correctness
1261
+ 9. Use proper ${frameworkName} syntax
1262
+ 10. Ensure all imports and dependencies are correct
1263
+ 11. Fix any syntax errors, type errors, or logical errors
1191
1264
 
1192
1265
  Output format:
1193
1266
  - Return ONLY the fixed test code, no explanations or markdown code blocks
@@ -1944,7 +2017,7 @@ async function runPullRequest(context) {
1944
2017
  })),
1945
2018
  errors
1946
2019
  };
1947
- if (testFiles.size > 0) {
2020
+ if (config.enableCoverage && testFiles.size > 0) {
1948
2021
  const testRunner = createTestRunner(framework);
1949
2022
  const writtenPaths = Array.from(testFiles.keys());
1950
2023
  try {
@@ -1962,12 +2035,12 @@ async function runPullRequest(context) {
1962
2035
  summary.coverageReport = coverageReport;
1963
2036
  summary.testResults = finalTestResults;
1964
2037
  } else {
1965
- debug("Could not read coverage report (coverage package may be missing)");
2038
+ warn("Could not read coverage report (coverage package may be missing)");
1966
2039
  }
1967
2040
  } catch (err) {
1968
2041
  const errorMessage = err instanceof Error ? err.message : String(err);
1969
2042
  if (errorMessage.includes("coverage") || errorMessage.includes("MISSING DEPENDENCY")) {
1970
- debug(`Coverage collection skipped (missing coverage package): ${errorMessage.split("\n")[0]}`);
2043
+ warn(`Coverage collection failed (coverage package may be missing): ${errorMessage.split("\n")[0]}`);
1971
2044
  } else {
1972
2045
  throw err;
1973
2046
  }
@@ -2064,7 +2137,8 @@ async function commitTests(githubClient, pr, testFiles, config, summary) {
2064
2137
  info(`Committing ${testFiles.length} test file(s)`);
2065
2138
  try {
2066
2139
  if (config.commitStrategy === "branch-pr") {
2067
- const branchName = `kakarot-ci/tests-pr-${pr.number}`;
2140
+ const timestamp = Date.now();
2141
+ const branchName = `kakarot-ci/tests-pr-${pr.number}-${timestamp}`;
2068
2142
  const baseSha = await githubClient.createBranch(branchName, pr.head.ref);
2069
2143
  await githubClient.commitFiles({
2070
2144
  files: testFiles.map((file) => ({