fix mocha test runner

This commit is contained in:
Sarthak Agarwal 2026-03-04 03:42:10 +05:30
parent 4766daac7e
commit bc5e3e878a
10 changed files with 1514 additions and 10 deletions

View file

@ -0,0 +1,5 @@
# Codeflash Configuration for Mocha CJS JavaScript Project
module_root: "."
tests_root: "tests"
test_framework: "mocha"
formatter_cmds: []

View file

@ -0,0 +1,60 @@
/**
* Fibonacci implementations - CommonJS module
* Intentionally inefficient for optimization testing.
*/
/**
* Calculate the nth Fibonacci number using naive recursion.
* This is intentionally slow to demonstrate optimization potential.
* @param {number} n - The index of the Fibonacci number to calculate
* @returns {number} The nth Fibonacci number
*/
function fibonacci(n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
/**
* Check if a number is a Fibonacci number.
* @param {number} num - The number to check
* @returns {boolean} True if num is a Fibonacci number
*/
function isFibonacci(num) {
// A number is Fibonacci if one of (5*n*n + 4) or (5*n*n - 4) is a perfect square
const check1 = 5 * num * num + 4;
const check2 = 5 * num * num - 4;
return isPerfectSquare(check1) || isPerfectSquare(check2);
}
/**
* Check if a number is a perfect square.
* @param {number} n - The number to check
* @returns {boolean} True if n is a perfect square
*/
function isPerfectSquare(n) {
const sqrt = Math.sqrt(n);
return sqrt === Math.floor(sqrt);
}
/**
* Generate an array of Fibonacci numbers up to n.
* @param {number} n - The number of Fibonacci numbers to generate
* @returns {number[]} Array of Fibonacci numbers
*/
function fibonacciSequence(n) {
const result = [];
for (let i = 0; i < n; i++) {
result.push(fibonacci(i));
}
return result;
}
// CommonJS exports
module.exports = {
fibonacci,
isFibonacci,
isPerfectSquare,
fibonacciSequence,
};

View file

@ -0,0 +1,966 @@
{
"name": "code-to-optimize-mocha",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "code-to-optimize-mocha",
"version": "1.0.0",
"devDependencies": {
"codeflash": "file:../../../packages/codeflash",
"mocha": "^10.7.0"
}
},
"../../../packages/codeflash": {
"version": "0.10.1",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@msgpack/msgpack": "^3.0.0",
"better-sqlite3": "^12.0.0"
},
"bin": {
"codeflash": "bin/codeflash.js",
"codeflash-setup": "bin/codeflash-setup.js"
},
"engines": {
"node": ">=18.0.0"
},
"peerDependencies": {
"jest": ">=27.0.0",
"jest-runner": ">=27.0.0",
"vitest": ">=1.0.0"
},
"peerDependenciesMeta": {
"jest": {
"optional": true
},
"jest-runner": {
"optional": true
},
"vitest": {
"optional": true
}
}
},
"node_modules/ansi-colors": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
"integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"license": "ISC",
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
"license": "Python-2.0"
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true,
"license": "MIT"
},
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/browser-stdout": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
"dev": true,
"license": "ISC"
},
"node_modules/camelcase": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/chalk/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"license": "MIT",
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"license": "ISC",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^7.0.0"
}
},
"node_modules/codeflash": {
"resolved": "../../../packages/codeflash",
"link": true
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true,
"license": "MIT"
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/decamelize": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
"integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/diff": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz",
"integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true,
"license": "MIT"
},
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
"license": "MIT",
"dependencies": {
"locate-path": "^6.0.0",
"path-exists": "^4.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/flat": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
"integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
"dev": true,
"license": "BSD-3-Clause",
"bin": {
"flat": "cli.js"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true,
"license": "ISC"
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true,
"license": "ISC",
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
},
"node_modules/glob": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
"deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"dev": true,
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^5.0.1",
"once": "^1.3.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true,
"license": "MIT",
"bin": {
"he": "bin/he"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
"dev": true,
"license": "ISC",
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true,
"license": "ISC"
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"license": "MIT",
"dependencies": {
"binary-extensions": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/is-plain-obj": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/js-yaml": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
"license": "MIT",
"dependencies": {
"p-locate": "^5.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/log-symbols": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
"integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
"dev": true,
"license": "MIT",
"dependencies": {
"chalk": "^4.1.0",
"is-unicode-supported": "^0.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/minimatch": {
"version": "5.1.9",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
"integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=10"
}
},
"node_modules/mocha": {
"version": "10.8.2",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz",
"integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-colors": "^4.1.3",
"browser-stdout": "^1.3.1",
"chokidar": "^3.5.3",
"debug": "^4.3.5",
"diff": "^5.2.0",
"escape-string-regexp": "^4.0.0",
"find-up": "^5.0.0",
"glob": "^8.1.0",
"he": "^1.2.0",
"js-yaml": "^4.1.0",
"log-symbols": "^4.1.0",
"minimatch": "^5.1.6",
"ms": "^2.1.3",
"serialize-javascript": "^6.0.2",
"strip-json-comments": "^3.1.1",
"supports-color": "^8.1.1",
"workerpool": "^6.5.1",
"yargs": "^16.2.0",
"yargs-parser": "^20.2.9",
"yargs-unparser": "^2.0.0"
},
"bin": {
"_mocha": "bin/_mocha",
"mocha": "bin/mocha.js"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true,
"license": "MIT"
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"yocto-queue": "^0.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-locate": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
"license": "MIT",
"dependencies": {
"p-limit": "^3.0.2"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"safe-buffer": "^5.1.0"
}
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/serialize-javascript": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"randombytes": "^2.1.0"
}
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/supports-color": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/workerpool": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz",
"integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true,
"license": "ISC"
},
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true,
"license": "ISC",
"engines": {
"node": ">=10"
}
},
"node_modules/yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"license": "MIT",
"dependencies": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/yargs-parser": {
"version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"dev": true,
"license": "ISC",
"engines": {
"node": ">=10"
}
},
"node_modules/yargs-unparser": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
"integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
"dev": true,
"license": "MIT",
"dependencies": {
"camelcase": "^6.0.0",
"decamelize": "^4.0.0",
"flat": "^5.0.2",
"is-plain-obj": "^2.1.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
}
}
}

View file

@ -0,0 +1,13 @@
{
"name": "code-to-optimize-mocha",
"version": "1.0.0",
"description": "Mocha CJS JavaScript test project for Codeflash E2E testing",
"main": "index.js",
"scripts": {
"test": "mocha"
},
"devDependencies": {
"codeflash": "file:../../../packages/codeflash",
"mocha": "^10.7.0"
}
}

View file

@ -0,0 +1,77 @@
/**
* Tests for Fibonacci functions - Mocha + node:assert/strict
*/
const assert = require('node:assert/strict');
const { fibonacci, isFibonacci, isPerfectSquare, fibonacciSequence } = require('../fibonacci');
describe('fibonacci', () => {
it('returns 0 for n=0', () => {
assert.strictEqual(fibonacci(0), 0);
});
it('returns 1 for n=1', () => {
assert.strictEqual(fibonacci(1), 1);
});
it('returns 1 for n=2', () => {
assert.strictEqual(fibonacci(2), 1);
});
it('returns 5 for n=5', () => {
assert.strictEqual(fibonacci(5), 5);
});
it('returns 55 for n=10', () => {
assert.strictEqual(fibonacci(10), 55);
});
it('returns 233 for n=13', () => {
assert.strictEqual(fibonacci(13), 233);
});
});
describe('isFibonacci', () => {
it('returns true for Fibonacci numbers', () => {
assert.strictEqual(isFibonacci(0), true);
assert.strictEqual(isFibonacci(1), true);
assert.strictEqual(isFibonacci(5), true);
assert.strictEqual(isFibonacci(8), true);
assert.strictEqual(isFibonacci(13), true);
});
it('returns false for non-Fibonacci numbers', () => {
assert.strictEqual(isFibonacci(4), false);
assert.strictEqual(isFibonacci(6), false);
assert.strictEqual(isFibonacci(7), false);
});
});
describe('isPerfectSquare', () => {
it('returns true for perfect squares', () => {
assert.strictEqual(isPerfectSquare(0), true);
assert.strictEqual(isPerfectSquare(1), true);
assert.strictEqual(isPerfectSquare(4), true);
assert.strictEqual(isPerfectSquare(9), true);
assert.strictEqual(isPerfectSquare(16), true);
});
it('returns false for non-perfect squares', () => {
assert.strictEqual(isPerfectSquare(2), false);
assert.strictEqual(isPerfectSquare(3), false);
assert.strictEqual(isPerfectSquare(5), false);
});
});
describe('fibonacciSequence', () => {
it('returns empty array for n=0', () => {
assert.deepStrictEqual(fibonacciSequence(0), []);
});
it('returns first 5 Fibonacci numbers', () => {
assert.deepStrictEqual(fibonacciSequence(5), [0, 1, 1, 2, 3]);
});
it('returns first 10 Fibonacci numbers', () => {
assert.deepStrictEqual(fibonacciSequence(10), [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]);
});
});

View file

@ -226,9 +226,13 @@ def inject_test_globals(
)
for test in generated_tests.generated_tests:
test.generated_original_test_source = global_import + test.generated_original_test_source
test.instrumented_behavior_test_source = global_import + test.instrumented_behavior_test_source
test.instrumented_perf_test_source = global_import + test.instrumented_perf_test_source
# Skip injection if the source already has the import (LLM may have included it)
if global_import.strip() not in test.generated_original_test_source:
test.generated_original_test_source = global_import + test.generated_original_test_source
if global_import.strip() not in test.instrumented_behavior_test_source:
test.instrumented_behavior_test_source = global_import + test.instrumented_behavior_test_source
if global_import.strip() not in test.instrumented_perf_test_source:
test.instrumented_perf_test_source = global_import + test.instrumented_perf_test_source
return generated_tests
@ -245,20 +249,30 @@ _MOCHA_REQUIRE_RE = re.compile(
)
_VITEST_COMMENT_RE = re.compile(r"^.*//.*vitest imports.*\n?", re.MULTILINE | re.IGNORECASE)
# Chai import patterns — LLMs sometimes associate Mocha with Chai
_CHAI_IMPORT_RE = re.compile(r"^.*import\s+.*\s+from\s+['\"]chai['\"].*\n?", re.MULTILINE)
_CHAI_REQUIRE_RE = re.compile(r"^.*(?:const|let|var)\s+.*\s*=\s*require\s*\(\s*['\"]chai['\"]\s*\).*\n?", re.MULTILINE)
# Pattern to convert test() → it() — Mocha uses it(), not test()
_TEST_CALL_RE = re.compile(r"(\s*)test\s*\(")
def sanitize_mocha_imports(source: str) -> str:
"""Remove vitest/jest/mocha-require imports from Mocha test source.
"""Remove vitest/jest/mocha-require/chai imports from Mocha test source.
The AI service sometimes generates vitest or jest-style imports when the
framework is mocha. Mocha provides describe/it/before*/after* as globals,
so these imports must be removed. Also removes ``require('mocha')``
destructures since Mocha doesn't export those.
Additionally converts ``test()`` calls to ``it()`` since Mocha only
supports ``it()`` as its test function.
Args:
source: Generated test source code.
Returns:
Source with incorrect framework imports stripped.
Source with incorrect framework imports stripped and test() converted to it().
"""
source = _VITEST_IMPORT_RE.sub("", source)
@ -266,7 +280,227 @@ def sanitize_mocha_imports(source: str) -> str:
source = _JEST_GLOBALS_IMPORT_RE.sub("", source)
source = _JEST_GLOBALS_REQUIRE_RE.sub("", source)
source = _MOCHA_REQUIRE_RE.sub("", source)
return _VITEST_COMMENT_RE.sub("", source)
source = _VITEST_COMMENT_RE.sub("", source)
source = _CHAI_IMPORT_RE.sub("", source)
source = _CHAI_REQUIRE_RE.sub("", source)
source = _TEST_CALL_RE.sub(r"\1it(", source)
return convert_expect_to_assert(source)
def _find_matching_paren(source: str, open_pos: int) -> int:
"""Find the position of the closing parenthesis matching the one at open_pos."""
depth = 0
in_string = False
string_char = None
i = open_pos
while i < len(source):
char = source[i]
if char in ('"', "'", "`") and (i == 0 or source[i - 1] != "\\"):
if not in_string:
in_string = True
string_char = char
elif char == string_char:
in_string = False
string_char = None
elif not in_string:
if char == "(":
depth += 1
elif char == ")":
depth -= 1
if depth == 0:
return i
i += 1
return -1
def convert_expect_to_assert(source: str) -> str:
"""Convert expect()-style assertions to node:assert/strict equivalents.
LLMs frequently generate Chai-style (``expect(x).to.equal(y)``) or
Jest-style (``expect(x).toBe(y)``) assertions for Mocha tests despite
being instructed to use ``assert``. This function converts the common
patterns to their ``node:assert/strict`` equivalents so that
instrumentation and Mocha execution work correctly.
Any ``expect()`` calls that cannot be converted are commented out with
``// SKIPPED`` to prevent ``ReferenceError: expect is not defined``.
Args:
source: Test source code that may contain expect() calls.
Returns:
Source with expect() calls converted to assert equivalents.
"""
if "expect(" not in source:
return source
lines = source.split("\n")
converted: list[str] = []
for line in lines:
converted_line = _convert_expect_line(line)
converted.append(converted_line)
return "\n".join(converted)
# Patterns mapping (chain_suffix → conversion_type)
# "simple" = assert.func(actual, value), "ok_cmp" = assert.ok(actual OP value)
# "ok_method" = assert.ok(actual.method(value)), "type" = assert.ok(typeof actual === ...)
# "truthy" = assert.ok(actual) / assert.strictEqual(actual, bool)
# "throws" = assert.throws, "noop" = assert.ok(actual !== undefined)
_EXPECT_CHAIN_MAP: list[tuple[str, str, str | None]] = [
# Jest patterns (most common)
(".toBe(", "simple_strictEqual", None),
(".toEqual(", "simple_deepStrictEqual", None),
(".toStrictEqual(", "simple_deepStrictEqual", None),
(".toBeGreaterThan(", "ok_gt", None),
(".toBeGreaterThanOrEqual(", "ok_gte", None),
(".toBeLessThan(", "ok_lt", None),
(".toBeLessThanOrEqual(", "ok_lte", None),
(".toContain(", "ok_includes", None),
(".toHaveLength(", "ok_length", None),
(".toBeNull(", "null_check", None),
(".toBeUndefined(", "undef_check", None),
(".toBeTruthy(", "truthy", None),
(".toBeFalsy(", "falsy", None),
(".toThrow(", "throws", None),
(".toMatch(", "ok_match", None),
# Chai .to. patterns
(".to.equal(", "simple_strictEqual", None),
(".to.eql(", "simple_deepStrictEqual", None),
(".to.deep.equal(", "simple_deepStrictEqual", None),
(".to.be.greaterThan(", "ok_gt", None),
(".to.be.lessThan(", "ok_lt", None),
(".to.be.above(", "ok_gt", None),
(".to.be.below(", "ok_lt", None),
(".to.be.at.least(", "ok_gte", None),
(".to.be.at.most(", "ok_lte", None),
(".to.include(", "ok_includes", None),
(".to.contain(", "ok_includes", None),
(".to.not.include(", "ok_not_includes", None),
(".to.not.contain(", "ok_not_includes", None),
(".to.have.length(", "ok_length", None),
(".to.have.lengthOf(", "ok_length", None),
(".to.throw(", "throws", None),
(".to.match(", "ok_match", None),
(".to.be.a(", "noop", None),
(".to.be.an(", "noop", None),
(".to.be.instanceOf(", "noop", None),
(".to.be.instanceof(", "noop", None),
(".to.exist", "truthy_no_arg", None),
(".to.not.exist", "falsy_no_arg", None),
(".to.be.true", "true_no_arg", None),
(".to.be.false", "false_no_arg", None),
(".to.be.null", "null_no_arg", None),
(".to.be.undefined", "undef_no_arg", None),
(".to.be.ok", "truthy_no_arg", None),
(".to.not.be.ok", "falsy_no_arg", None),
]
def _convert_expect_line(line: str) -> str:
"""Convert a single line containing expect() to an assert equivalent."""
stripped = line.lstrip()
if "expect(" not in stripped:
return line
indent = line[: len(line) - len(stripped)]
expect_idx = line.find("expect(")
if expect_idx == -1:
return line
open_paren = expect_idx + len("expect")
close_paren = _find_matching_paren(line, open_paren)
if close_paren == -1:
# Multi-line expect or malformed — comment out to prevent ReferenceError
return f"{indent}// SKIPPED (unconvertible expect): {stripped}"
actual_expr = line[open_paren + 1 : close_paren]
rest = line[close_paren + 1 :].strip()
trailing_semi = ";" if rest.endswith(";") else ""
# Try each chain pattern
for chain_prefix, conversion_type, _ in _EXPECT_CHAIN_MAP:
if not rest.startswith(chain_prefix):
continue
# No-argument chains (e.g. .to.be.true, .to.exist)
if conversion_type.endswith("_no_arg"):
return _convert_no_arg(indent, actual_expr, conversion_type, trailing_semi)
# Extract the argument inside the chain's parentheses
chain_open = rest.find("(")
if chain_open == -1:
break
chain_close = _find_matching_paren(rest, chain_open)
if chain_close == -1:
break
value_expr = rest[chain_open + 1 : chain_close]
return _convert_with_arg(indent, actual_expr, value_expr, conversion_type, trailing_semi)
# Fallback: comment out unconvertible expect() to prevent ReferenceError
return f"{indent}// SKIPPED (unconvertible expect): {stripped}"
def _convert_no_arg(indent: str, actual: str, conversion_type: str, semi: str) -> str:
"""Convert expect patterns that take no argument (e.g., .to.be.true)."""
if conversion_type == "true_no_arg":
return f"{indent}assert.strictEqual({actual}, true){semi}"
if conversion_type == "false_no_arg":
return f"{indent}assert.strictEqual({actual}, false){semi}"
if conversion_type == "null_no_arg":
return f"{indent}assert.strictEqual({actual}, null){semi}"
if conversion_type == "undef_no_arg":
return f"{indent}assert.strictEqual({actual}, undefined){semi}"
if conversion_type == "truthy_no_arg":
return f"{indent}assert.ok({actual}){semi}"
if conversion_type == "falsy_no_arg":
return f"{indent}assert.ok(!({actual})){semi}"
return f"{indent}assert.ok({actual} !== undefined){semi}"
def _convert_with_arg(indent: str, actual: str, value: str, conversion_type: str, semi: str) -> str:
"""Convert expect patterns that take an argument."""
if conversion_type == "simple_strictEqual":
return f"{indent}assert.strictEqual({actual}, {value}){semi}"
if conversion_type == "simple_deepStrictEqual":
return f"{indent}assert.deepStrictEqual({actual}, {value}){semi}"
if conversion_type == "ok_gt":
return f"{indent}assert.ok(({actual}) > ({value})){semi}"
if conversion_type == "ok_gte":
return f"{indent}assert.ok(({actual}) >= ({value})){semi}"
if conversion_type == "ok_lt":
return f"{indent}assert.ok(({actual}) < ({value})){semi}"
if conversion_type == "ok_lte":
return f"{indent}assert.ok(({actual}) <= ({value})){semi}"
if conversion_type == "ok_includes":
return f"{indent}assert.ok(String({actual}).includes({value})){semi}"
if conversion_type == "ok_not_includes":
return f"{indent}assert.ok(!String({actual}).includes({value})){semi}"
if conversion_type == "ok_length":
return f"{indent}assert.strictEqual(({actual}).length, {value}){semi}"
if conversion_type == "ok_match":
return f"{indent}assert.match(String({actual}), {value}){semi}"
if conversion_type == "null_check":
return f"{indent}assert.strictEqual({actual}, null){semi}"
if conversion_type == "undef_check":
return f"{indent}assert.strictEqual({actual}, undefined){semi}"
if conversion_type == "truthy":
return f"{indent}assert.ok({actual}){semi}"
if conversion_type == "falsy":
return f"{indent}assert.ok(!({actual})){semi}"
if conversion_type == "throws":
if value:
return f"{indent}assert.throws(() => {{ {actual}; }}, {value}){semi}"
return f"{indent}assert.throws(() => {{ {actual}; }}){semi}"
# noop: type checks like .to.be.a('string') — just verify defined
if conversion_type == "noop":
return f"{indent}assert.ok({actual} !== undefined){semi}"
return f"{indent}assert.ok({actual} !== undefined){semi}"
# Author: ali <mohammed18200118@gmail.com>

View file

@ -8,6 +8,7 @@ and converts the output to JUnit XML in Python, avoiding extra npm dependencies.
from __future__ import annotations
import json
import re
import subprocess
import time
from pathlib import Path
@ -86,7 +87,7 @@ def _ensure_runtime_files(project_root: Path) -> None:
logger.error(f"Could not install codeflash. Please install it manually: {' '.join(install_cmd)}")
def mocha_json_to_junit_xml(json_str: str, output_file: Path) -> None:
def mocha_json_to_junit_xml(json_str: str, output_file: Path, test_files: list[Path] | None = None) -> None:
"""Convert Mocha's JSON reporter output to JUnit XML.
Mocha JSON format:
@ -94,9 +95,16 @@ def mocha_json_to_junit_xml(json_str: str, output_file: Path) -> None:
Each test object has: fullTitle, title, duration, err, ...
Mocha's JSON reporter does NOT include a ``file`` field on test objects,
so we accept the known ``test_files`` list from the caller and set the
``file`` attribute on testcase/testsuite elements. This allows
``parse_jest_test_xml()`` to resolve the test file via its ``file``
attribute lookup path.
Args:
json_str: JSON string from Mocha's --reporter json output.
output_file: Path to write the JUnit XML file.
test_files: Optional list of test file paths that were passed to Mocha.
"""
try:
@ -125,11 +133,35 @@ def mocha_json_to_junit_xml(json_str: str, output_file: Path) -> None:
suite_name = suite_name or "root"
suites.setdefault(suite_name, []).append(test)
# Build a mapping from describe block names to file paths by reading test files.
# Each generated test file wraps tests in describe('functionName', ...) so we
# can map suite names back to their source file.
suite_to_file: dict[str, str] = {}
if test_files:
for tf in test_files:
suite_to_file[tf.name] = str(tf)
# Try to extract the top-level describe name from the file content
try:
content = tf.read_text(encoding="utf-8")
m = re.search(r"describe\s*\(\s*['\"]([^'\"]+)['\"]", content)
if m:
suite_to_file[m.group(1)] = str(tf)
except Exception:
pass
# Fallback: if we have test files, use the first one as default for any unmatched suites
default_file = str(test_files[0]) if test_files else ""
for suite_name, suite_tests in suites.items():
testsuite = SubElement(testsuites, "testsuite")
testsuite.set("name", suite_name)
testsuite.set("tests", str(len(suite_tests)))
# Resolve file path: try suite name match, then use default
resolved_file = suite_to_file.get(suite_name, default_file)
if resolved_file:
testsuite.set("file", resolved_file)
suite_failures = 0
suite_time = 0.0
@ -140,6 +172,9 @@ def mocha_json_to_junit_xml(json_str: str, output_file: Path) -> None:
duration_ms = test.get("duration", 0) or 0
duration_s = duration_ms / 1000.0
testcase.set("time", str(duration_s))
if resolved_file:
testcase.set("file", resolved_file)
suite_time += duration_s
err = test.get("err", {})
@ -292,6 +327,7 @@ def _run_mocha_and_convert(
result_file_path: Path,
subprocess_timeout: int,
label: str,
test_files: list[Path] | None = None,
) -> subprocess.CompletedProcess:
"""Run Mocha subprocess, extract JSON output, and convert to JUnit XML.
@ -302,6 +338,7 @@ def _run_mocha_and_convert(
result_file_path: Path to write JUnit XML.
subprocess_timeout: Timeout in seconds.
label: Label for log messages (e.g. "behavioral", "benchmarking").
test_files: Test file paths passed to Mocha (for file attribute in XML).
Returns:
CompletedProcess with combined stdout/stderr.
@ -343,7 +380,7 @@ def _run_mocha_and_convert(
if result.stdout:
mocha_json = _extract_mocha_json(result.stdout)
if mocha_json:
mocha_json_to_junit_xml(mocha_json, result_file_path)
mocha_json_to_junit_xml(mocha_json, result_file_path, test_files=test_files)
logger.debug(f"Converted Mocha JSON to JUnit XML: {result_file_path}")
else:
logger.warning(f"Could not extract Mocha JSON from stdout (len={len(result.stdout)})")
@ -414,6 +451,7 @@ def run_mocha_behavioral_tests(
result_file_path=result_file_path,
subprocess_timeout=subprocess_timeout,
label="behavioral",
test_files=test_files,
)
finally:
wall_clock_ns = time.perf_counter_ns() - start_time_ns
@ -515,6 +553,7 @@ def run_mocha_benchmarking_tests(
result_file_path=result_file_path,
subprocess_timeout=total_timeout,
label="benchmarking",
test_files=test_files,
)
finally:
wall_clock_seconds = time.time() - total_start_time
@ -589,6 +628,7 @@ def run_mocha_line_profile_tests(
result_file_path=result_file_path,
subprocess_timeout=subprocess_timeout,
label="line_profile",
test_files=test_files,
)
finally:
wall_clock_ns = time.perf_counter_ns() - start_time_ns

View file

@ -1970,6 +1970,13 @@ class JavaScriptSupport:
# Ensure vitest imports are present when using vitest framework
generated_test_source = ensure_vitest_imports(generated_test_source, test_cfg.test_framework)
# For Mocha: convert expect()/test() to assert/it() BEFORE instrumentation
# to prevent instrumentation from breaking Chai-style assertion chains
if test_cfg.test_framework == "mocha":
from codeflash.languages.javascript.edit_tests import sanitize_mocha_imports
generated_test_source = sanitize_mocha_imports(generated_test_source)
# Instrument for behavior verification (writes to SQLite)
instrumented_behavior_test_source = instrument_generated_js_test(
test_code=generated_test_source, function_to_optimize=function_to_optimize, mode=TestingMode.BEHAVIOR

View file

@ -1,12 +1,12 @@
{
"name": "codeflash",
"version": "0.9.0",
"version": "0.10.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "codeflash",
"version": "0.9.0",
"version": "0.10.1",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {

View file

@ -147,6 +147,108 @@ class TestMochaJsonToJunitXml:
assert "suite A" in suite_names
assert "suite B" in suite_names
def test_file_attribute_set_from_test_files(self):
"""When test_files are passed, the file attribute should be set on testcase elements."""
from codeflash.languages.javascript.mocha_runner import mocha_json_to_junit_xml
mocha_json = json.dumps(
{
"stats": {"tests": 2, "passes": 2, "failures": 0, "duration": 50},
"tests": [
{"title": "test1", "fullTitle": "escapeHtml test1", "duration": 10, "err": {}},
{"title": "test2", "fullTitle": "escapeHtml test2", "duration": 20, "err": {}},
],
"passes": [],
"failures": [],
"pending": [],
}
)
with tempfile.TemporaryDirectory() as tmpdir:
tmpdir_path = Path(tmpdir)
# Create a test file whose describe block matches the suite name
test_file = tmpdir_path / "test_escapeHtml__unit_test_0.test.js"
test_file.write_text(
"const assert = require('node:assert/strict');\n"
"const escapeHtml = require('../index.js');\n"
"describe('escapeHtml', () => {\n"
" it('test1', () => { assert.ok(true); });\n"
" it('test2', () => { assert.ok(true); });\n"
"});\n",
encoding="utf-8",
)
output_file = tmpdir_path / "results.xml"
mocha_json_to_junit_xml(mocha_json, output_file, test_files=[test_file])
# Parse the XML and verify file attributes
import xml.etree.ElementTree as ET
tree = ET.parse(output_file)
root = tree.getroot()
testcases = root.findall(".//testcase")
assert len(testcases) == 2
for tc in testcases:
assert tc.get("file") == str(test_file)
def test_file_attribute_uses_default_when_no_describe_match(self):
"""When describe name doesn't match, the default (first) test file should be used."""
from codeflash.languages.javascript.mocha_runner import mocha_json_to_junit_xml
mocha_json = json.dumps(
{
"stats": {"tests": 1, "passes": 1, "failures": 0, "duration": 10},
"tests": [
{"title": "test1", "fullTitle": "someOtherSuite test1", "duration": 10, "err": {}},
],
"passes": [],
"failures": [],
"pending": [],
}
)
with tempfile.TemporaryDirectory() as tmpdir:
tmpdir_path = Path(tmpdir)
test_file = tmpdir_path / "test.test.js"
test_file.write_text("// no describe block", encoding="utf-8")
output_file = tmpdir_path / "results.xml"
mocha_json_to_junit_xml(mocha_json, output_file, test_files=[test_file])
import xml.etree.ElementTree as ET
tree = ET.parse(output_file)
testcases = tree.getroot().findall(".//testcase")
assert len(testcases) == 1
assert testcases[0].get("file") == str(test_file)
def test_no_file_attribute_when_no_test_files(self):
"""When test_files is not passed, no file attribute should be set."""
from codeflash.languages.javascript.mocha_runner import mocha_json_to_junit_xml
mocha_json = json.dumps(
{
"stats": {"tests": 1, "passes": 1, "failures": 0, "duration": 10},
"tests": [
{"title": "test1", "fullTitle": "suite test1", "duration": 10, "err": {}},
],
"passes": [],
"failures": [],
"pending": [],
}
)
with tempfile.TemporaryDirectory() as tmpdir:
output_file = Path(tmpdir) / "results.xml"
mocha_json_to_junit_xml(mocha_json, output_file)
import xml.etree.ElementTree as ET
tree = ET.parse(output_file)
testcases = tree.getroot().findall(".//testcase")
assert len(testcases) == 1
assert testcases[0].get("file") is None
class TestExtractMochaJson:
"""Tests for extracting Mocha JSON from mixed stdout."""