{"id":"code-dev-jest-three-named-slugify-tests","audience":"developers","category":"coding","track":"coding","technique":"constraints","title":"Write exactly 3 named Jest tests for a slugify helper","free":false,"task":"Write Jest tests for slugify with exactly 3 it blocks inside one describe(\"slugify\"), named exactly 'lowercases and joins words', 'strips accents' and 'throws on empty input'. The cases: \"Hello, World!\" gives \"hello-world\", \"  Crème brûlée  \" gives \"creme-brulee\", and \"\" throws \"empty title\". The only import is import { slugify } from \"../src/slugify.js\";. Exactly 1 code block of at most 14 lines, under 20 words of text.","materialLabel":"The helper (attached to your prompt automatically)","material":"// src/slugify.js  (Node 20, ESM, Jest 29 with --experimental-vm-modules)\n// Used for recipe URLs on Saltwater Kitchen, e.g. /recipes/creme-brulee\n\nexport function slugify(title) {\n  if (typeof title !== \"string\" || title.trim() === \"\") {\n    throw new Error(\"empty title\");\n  }\n  return title\n    .normalize(\"NFD\")\n    .replace(/[\\u0300-\\u036f]/g, \"\")   // drop accent marks\n    .toLowerCase()\n    .replace(/[^a-z0-9]+/g, \"-\")        // anything else becomes a dash\n    .replace(/^-+|-+$/g, \"\");           // trim dashes at the ends\n}\n\n// test/ folder currently has:\n//   recipes.test.js   (Hugo's, uses the same import style)\n//   slugify.test.js   (empty - this is yours)\n//\n// Jest config: testEnvironment \"node\", no globals injected beyond\n// describe/it/expect.\n//\n// Ideas from the PR thread we decided NOT to cover yet:\n//   - emoji in titles\n//   - very long titles (> 200 chars)\n//   - non-Latin scripts","rules":[{"type":"codeBlocks","count":1},{"type":"maxCodeLines","max":14},{"type":"maxProseWords","max":20}],"mistakes":[{"title":"Too many tests","why":"Asked for tests, the AI writes 8 to 15 of them, including the cases your team deferred.","fix":"Say: \"Exactly 3 it blocks, no other cases.\"","checks":["r0","r2","maxCodeLines"]},{"title":"Letting the AI name tests","why":"Your team's report groups by test name, and the AI picks its own.","fix":"Give the names: \"'lowercases and joins words', 'strips accents', 'throws on empty input'.\"","checks":["r0"]},{"title":"Not giving the cases","why":"The AI picks its own inputs, which may not match what you agreed to check.","fix":"List them with expected results, including toThrow(\"empty title\").","checks":["r1"]},{"title":"Wrong import style","why":"The AI may use require() or import from a different path.","fix":"Add: \"Only import: import { slugify } from \\\"../src/slugify.js\\\";\"","checks":["r2","codeBlocks","maxProseWords"]}],"promptHints":[{"label":"Sets the number of tests","patterns":["\\b(3|three)\\b.{0,15}(test|it)","exactly \\d"]},{"label":"Names the tests","patterns":["lowercases and joins","strips accents","throws on empty"]},{"label":"Gives the cases","patterns":["hello-world","creme-brulee","empty title"]},{"label":"Gives the import","patterns":["\\.\\./src/slugify","import"]},{"label":"Asks for only code","patterns":["only the code","no (text|explanation)","one code block"]}],"hint":"Tests are a team document. Tell the AI how many, their exact names and cases, and how the file imports the helper.","rubricLabels":["Has exactly 3 it blocks inside a single describe(\"slugify\"), named exactly 'lowercases and joins words', 'strips accents' and 'throws on empty input'","The cases are exactly slugify(\"Hello, World!\") toBe \"hello-world\", slugify(\"  Crème brûlée  \") toBe \"creme-brulee\", and slugify(\"\") throwing \"empty title\" (e.g. expect(() => slugify(\"\")).toThrow(\"empty title\"))","The only import is import { slugify } from \"../src/slugify.js\"; and there are no tests for emoji, long titles or other scripts"]}