From c49c63c2aad442b43bd8730c8119bc9f295f6e20 Mon Sep 17 00:00:00 2001 From: mervereis Date: Mon, 16 Mar 2026 22:44:24 +0000 Subject: [PATCH 01/21] median function updated according to requests --- Sprint-1/fix/median.js | 30 +++++- Sprint-1/package-lock.json | 215 +++++++++---------------------------- 2 files changed, 76 insertions(+), 169 deletions(-) diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index b22590bc6..4b038b057 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -5,10 +5,34 @@ // Hint: Please consider scenarios when 'list' doesn't have numbers (the function is expected to return null) // or 'list' has mixed values (the function is expected to sort only numbers). +// function calculateMedian(list) { +// const middleIndex = Math.floor(list.length / 2); +// const median = list.splice(middleIndex, 1)[0]; +// return median; +// } + +// module.exports = calculateMedian; + function calculateMedian(list) { - const middleIndex = Math.floor(list.length / 2); - const median = list.splice(middleIndex, 1)[0]; - return median; + if (!Array.isArray(list)) { + return null; + } + + const numbers = list.filter((item) => typeof item === "number"); + + if (numbers.length === 0) { + return null; + } + + numbers.sort((a, b) => a - b); + + const middle = Math.floor(numbers.length / 2); + + if (numbers.length % 2 === 0) { + return (numbers[middle - 1] + numbers[middle]) / 2; + } + + return numbers[middle]; } module.exports = calculateMedian; diff --git a/Sprint-1/package-lock.json b/Sprint-1/package-lock.json index 83e427d0b..e3f3f866b 100644 --- a/Sprint-1/package-lock.json +++ b/Sprint-1/package-lock.json @@ -27,14 +27,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", - "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/highlight": "^7.25.7", - "picocolors": "^1.0.0" + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -172,21 +172,19 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", - "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", - "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -202,121 +200,25 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", - "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.25.7", - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", - "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", - "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.25.8" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -565,15 +467,14 @@ } }, "node_modules/@babel/template": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", - "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -599,15 +500,13 @@ } }, "node_modules/@babel/types": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", - "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -1325,11 +1224,10 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1579,11 +1477,10 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, - "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2781,15 +2678,13 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -2952,11 +2847,10 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3153,11 +3047,10 @@ "license": "MIT" }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", - "dev": true, - "license": "ISC" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true }, "node_modules/picomatch": { "version": "2.3.1", @@ -3543,16 +3436,6 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", From 8bac04f62f76904b3fa928ccd85956d6914928cb Mon Sep 17 00:00:00 2001 From: mervereis Date: Mon, 16 Mar 2026 22:45:04 +0000 Subject: [PATCH 02/21] dedupe function created & test cases created --- Sprint-1/implement/dedupe.js | 7 +++- Sprint-1/implement/dedupe.test.js | 63 +++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/Sprint-1/implement/dedupe.js b/Sprint-1/implement/dedupe.js index 781e8718a..4932fbd40 100644 --- a/Sprint-1/implement/dedupe.js +++ b/Sprint-1/implement/dedupe.js @@ -1 +1,6 @@ -function dedupe() {} +function dedupe(arr) { + if (arr.length === 0) return []; + return [...new Set(arr)]; +} + +module.exports = dedupe; diff --git a/Sprint-1/implement/dedupe.test.js b/Sprint-1/implement/dedupe.test.js index 23e0f8638..376a302e4 100644 --- a/Sprint-1/implement/dedupe.test.js +++ b/Sprint-1/implement/dedupe.test.js @@ -1,27 +1,50 @@ -const dedupe = require("./dedupe.js"); -/* -Dedupe Array +const dedupe = require("./dedupe"); -📖 Dedupe means **deduplicate** +describe("dedupe", () => { + // Given an empty array + // When passed to the dedupe function + // Then it should return an empty array + test.todo("given an empty array, it returns an empty array"); + test("given an empty array, it returns an empty array", () => { + const result = dedupe([]); + expect(result).toEqual([]); + }); -In this kata, you will need to deduplicate the elements of an array + // Given an array with no duplicates + // When passed to the dedupe function + // Then it should return a copy of the original array + test("given an array with no duplicates, it returns a copy of the original array", () => { + const input = [1, 2, 3, 4]; + const result = dedupe(input); -E.g. dedupe(['a','a','a','b','b','c']) target output: ['a','b','c'] -E.g. dedupe([5, 1, 1, 2, 3, 2, 5, 8]) target output: [5, 1, 2, 3, 8] -E.g. dedupe([1, 2, 1]) target output: [1, 2] -*/ + expect(result).toEqual([1, 2, 3, 4]); + expect(result).not.toBe(input); // should be a new copy + }); -// Acceptance Criteria: + // Given an array with strings + // When passed to the dedupe function + // Then it should remove duplicates preserving first occurrence + test("removes duplicate strings preserving first occurrence", () => { + const input = ["a", "a", "a", "b", "b", "c"]; + const result = dedupe(input); -// Given an empty array -// When passed to the dedupe function -// Then it should return an empty array -test.todo("given an empty array, it returns an empty array"); + expect(result).toEqual(["a", "b", "c"]); + }); -// Given an array with no duplicates -// When passed to the dedupe function -// Then it should return a copy of the original array + // Given an array with numbers + // When passed to the dedupe function + // Then it should remove the duplicate values, preserving the first occurence of each element + test("removes duplicate numbers preserving first occurrence", () => { + const input = [5, 1, 1, 2, 3, 2, 5, 8]; + const result = dedupe(input); -// Given an array with strings or numbers -// When passed to the dedupe function -// Then it should remove the duplicate values, preserving the first occurence of each element + expect(result).toEqual([5, 1, 2, 3, 8]); + }); + + test("removes duplicates in mixed order", () => { + const input = [1, 2, 1]; + const result = dedupe(input); + + expect(result).toEqual([1, 2]); + }); +}); From 64e7ec04159264334f1571f93404bef62c2f0332 Mon Sep 17 00:00:00 2001 From: mervereis Date: Mon, 16 Mar 2026 22:45:17 +0000 Subject: [PATCH 03/21] findMax function created & test cases created --- Sprint-1/implement/max.js | 15 ++++++ Sprint-1/implement/max.test.js | 91 +++++++++++++++++++--------------- 2 files changed, 65 insertions(+), 41 deletions(-) diff --git a/Sprint-1/implement/max.js b/Sprint-1/implement/max.js index 6dd76378e..7aeef8376 100644 --- a/Sprint-1/implement/max.js +++ b/Sprint-1/implement/max.js @@ -1,4 +1,19 @@ function findMax(elements) { + const numbers = elements.filter((el) => typeof el === "number"); + + if (numbers.length === 0) { + return -Infinity; + } + + let max = numbers[0]; + + for (let i = 1; i < numbers.length; i++) { + if (numbers[i] > max) { + max = numbers[i]; + } + } + + return max; } module.exports = findMax; diff --git a/Sprint-1/implement/max.test.js b/Sprint-1/implement/max.test.js index 82f18fd88..526bc7abd 100644 --- a/Sprint-1/implement/max.test.js +++ b/Sprint-1/implement/max.test.js @@ -1,43 +1,52 @@ -/* Find the maximum element of an array of numbers - -In this kata, you will need to implement a function that find the largest numerical element of an array. - -E.g. max([30, 50, 10, 40]), target output: 50 -E.g. max(['hey', 10, 'hi', 60, 10]), target output: 60 (sum ignores any non-numerical elements) - -You should implement this function in max.js, and add tests for it in this file. - -We have set things up already so that this file can see your function from the other file. -*/ - const findMax = require("./max.js"); -// Given an empty array -// When passed to the max function -// Then it should return -Infinity -// Delete this test.todo and replace it with a test. -test.todo("given an empty array, returns -Infinity"); - -// Given an array with one number -// When passed to the max function -// Then it should return that number - -// Given an array with both positive and negative numbers -// When passed to the max function -// Then it should return the largest number overall - -// Given an array with just negative numbers -// When passed to the max function -// Then it should return the closest one to zero - -// Given an array with decimal numbers -// When passed to the max function -// Then it should return the largest decimal number - -// Given an array with non-number values -// When passed to the max function -// Then it should return the max and ignore non-numeric values - -// Given an array with only non-number values -// When passed to the max function -// Then it should return the least surprising value given how it behaves for all other inputs +describe("findMax", () => { + // Given an empty array + // When passed to the max function + // Then it should return -Infinity + test("given an empty array, returns -Infinity", () => { + expect(findMax([])).toBe(-Infinity); + }); + + // Given an array with one number + // When passed to the max function + // Then it should return that number + test("given an array with one number, returns that number", () => { + expect(findMax([5])).toBe(5); + }); + + // Given an array with both positive and negative numbers + // When passed to the max function + // Then it should return the largest number overall + test("returns the largest number from positive and negative numbers", () => { + expect(findMax([-10, 20, -5, 15])).toBe(20); + }); + + // Given an array with just negative numbers + // When passed to the max function + // Then it should return the closest one to zero + test("returns the largest number among negative numbers", () => { + expect(findMax([-10, -3, -50, -1])).toBe(-1); + }); + + // Given an array with decimal numbers + // When passed to the max function + // Then it should return the largest decimal number + test("returns the largest decimal number", () => { + expect(findMax([1.2, 3.7, 2.5, 3.6])).toBe(3.7); + }); + + // Given an array with non-number values + // When passed to the max function + // Then it should return the max and ignore non-numeric values + test("ignores non-number values", () => { + expect(findMax(["hey", 10, "hi", 60, 10])).toBe(60); + }); + + // Given an array with only non-number values + // When passed to the max function + // Then it should return the least surprising value given how it behaves for all other inputs + test("returns -Infinity when array has only non-number values", () => { + expect(findMax(["a", "b", "c"])).toBe(-Infinity); + }); +}); From 4fb239658eae0acb241d572e3eb1e7c12e5b10db Mon Sep 17 00:00:00 2001 From: mervereis Date: Mon, 16 Mar 2026 22:45:24 +0000 Subject: [PATCH 04/21] sum function created & test cases created --- Sprint-1/implement/sum.js | 8 ++++ Sprint-1/implement/sum.test.js | 77 +++++++++++++++++++--------------- 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/Sprint-1/implement/sum.js b/Sprint-1/implement/sum.js index 9062aafe3..cafd1825a 100644 --- a/Sprint-1/implement/sum.js +++ b/Sprint-1/implement/sum.js @@ -1,4 +1,12 @@ function sum(elements) { + const numbers = elements.filter((el) => typeof el === "number"); + + if (numbers.length === 0) return 0; + + if (numbers.length === 1) return numbers[0]; + + const sumNumbers = numbers.reduce((a, b) => a + b, 0); + return sumNumbers; } module.exports = sum; diff --git a/Sprint-1/implement/sum.test.js b/Sprint-1/implement/sum.test.js index dd0a090ca..cd2e22d61 100644 --- a/Sprint-1/implement/sum.test.js +++ b/Sprint-1/implement/sum.test.js @@ -1,36 +1,45 @@ -/* Sum the numbers in an array - -In this kata, you will need to implement a function that sums the numerical elements of an array - -E.g. sum([10, 20, 30]), target output: 60 -E.g. sum(['hey', 10, 'hi', 60, 10]), target output: 80 (ignore any non-numerical elements) -*/ - const sum = require("./sum.js"); -// Acceptance Criteria: - -// Given an empty array -// When passed to the sum function -// Then it should return 0 -test.todo("given an empty array, returns 0") - -// Given an array with just one number -// When passed to the sum function -// Then it should return that number - -// Given an array containing negative numbers -// When passed to the sum function -// Then it should still return the correct total sum - -// Given an array with decimal/float numbers -// When passed to the sum function -// Then it should return the correct total sum - -// Given an array containing non-number values -// When passed to the sum function -// Then it should ignore the non-numerical values and return the sum of the numerical elements - -// Given an array with only non-number values -// When passed to the sum function -// Then it should return the least surprising value given how it behaves for all other inputs +describe("sum", () => { + // Given an empty array + // When passed to the sum function + // Then it should return 0 + test("given an empty array, returns 0", () => { + expect(sum([])).toBe(0); + }); + + // Given an array with just one number + // When passed to the sum function + // Then it should return that number + test("given an array with one number, returns that number", () => { + expect(sum([5])).toBe(5); + }); + + // Given an array containing negative numbers + // When passed to the sum function + // Then it should still return the correct total sum + test("sums negative numbers correctly", () => { + expect(sum([-5, -10, 15])).toBe(0); + }); + + // Given an array with decimal/float numbers + // When passed to the sum function + // Then it should return the correct total sum + test("sums decimal numbers correctly", () => { + expect(sum([1.5, 2.5, 3.5])).toBe(7.5); + }); + + // Given an array containing non-number values + // When passed to the sum function + // Then it should ignore the non-numerical values + test("ignores non-number values", () => { + expect(sum(["hey", 10, "hi", 60, 10])).toBe(80); + }); + + // Given an array with only non-number values + // When passed to the sum function + // Then it should return the least surprising value + test("returns 0 when array contains only non-number values", () => { + expect(sum(["a", "b", "c"])).toBe(0); + }); +}); From 5d9fa86c7ccf65a10045c6370e79f900fb19b90e Mon Sep 17 00:00:00 2001 From: mervereis Date: Tue, 17 Mar 2026 22:08:49 +0000 Subject: [PATCH 05/21] functions updated --- Sprint-2/debug/address.js | 4 +- Sprint-2/debug/author.js | 3 +- Sprint-2/debug/recipe.js | 6 +- Sprint-2/package-lock.json | 215 +++++++++---------------------------- 4 files changed, 58 insertions(+), 170 deletions(-) diff --git a/Sprint-2/debug/address.js b/Sprint-2/debug/address.js index 940a6af83..34aa6c9ea 100644 --- a/Sprint-2/debug/address.js +++ b/Sprint-2/debug/address.js @@ -1,5 +1,7 @@ // Predict and explain first... +// Adress is not an array its an object, objects use key values so [0] is an array not a key value for a houseNumber. + // This code should log out the houseNumber from the address object // but it isn't working... // Fix anything that isn't working @@ -12,4 +14,4 @@ const address = { postcode: "XYZ 123", }; -console.log(`My house number is ${address[0]}`); +console.log(`My house number is ${address.houseNumber}`); diff --git a/Sprint-2/debug/author.js b/Sprint-2/debug/author.js index 8c2125977..b40a7da95 100644 --- a/Sprint-2/debug/author.js +++ b/Sprint-2/debug/author.js @@ -1,4 +1,5 @@ // Predict and explain first... +//The code fails because:for...of only works with iterable objects,Plain JavaScript objects,which is author here,are not iterable. // This program attempts to log out all the property values in the object. // But it isn't working. Explain why first and then fix the problem @@ -11,6 +12,6 @@ const author = { alive: true, }; -for (const value of author) { +for (const value of Object.values(author)) { console.log(value); } diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 6cbdd22cd..533ac4ec5 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -11,5 +11,7 @@ const recipe = { }; console.log(`${recipe.title} serves ${recipe.serves} - ingredients: -${recipe}`); + ingredients:`); +for (const ingredient of recipe.ingredients) { + console.log(ingredient); +} diff --git a/Sprint-2/package-lock.json b/Sprint-2/package-lock.json index 9b4c725d6..d636b043b 100644 --- a/Sprint-2/package-lock.json +++ b/Sprint-2/package-lock.json @@ -27,14 +27,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", - "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/highlight": "^7.25.7", - "picocolors": "^1.0.0" + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -172,21 +172,19 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", - "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", - "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -202,121 +200,25 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", - "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.25.7", - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", - "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", - "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.25.8" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -565,15 +467,14 @@ } }, "node_modules/@babel/template": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", - "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -599,15 +500,13 @@ } }, "node_modules/@babel/types": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", - "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -1325,11 +1224,10 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1579,11 +1477,10 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, - "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2781,15 +2678,13 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -2952,11 +2847,10 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3153,11 +3047,10 @@ "license": "MIT" }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", - "dev": true, - "license": "ISC" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true }, "node_modules/picomatch": { "version": "2.3.1", @@ -3543,16 +3436,6 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", From 9208c476440f8c984d94a1794485fb76e4b6692c Mon Sep 17 00:00:00 2001 From: mervereis Date: Tue, 17 Mar 2026 22:09:15 +0000 Subject: [PATCH 06/21] contains function created & test cases added --- Sprint-2/implement/contains.js | 20 +++++++++- Sprint-2/implement/contains.test.js | 59 +++++++++++++---------------- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index cd779308a..03a53a805 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,3 +1,21 @@ -function contains() {} +function contains(obj, prop) { + if (obj === null) { + return false; + } + + if (typeof obj !== "object") { + return false; + } + + if (Array.isArray(obj)) { + return false; + } + + if (prop in obj) { + return true; + } else { + return false; + } +} module.exports = contains; diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 326bdb1f2..0f8470140 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -1,35 +1,28 @@ const contains = require("./contains.js"); -/* -Implement a function called contains that checks an object contains a -particular property - -E.g. contains({a: 1, b: 2}, 'a') // returns true -as the object contains a key of 'a' - -E.g. contains({a: 1, b: 2}, 'c') // returns false -as the object doesn't contains a key of 'c' -*/ - -// Acceptance criteria: - -// Given a contains function -// When passed an object and a property name -// Then it should return true if the object contains the property, false otherwise - -// Given an empty object -// When passed to contains -// Then it should return false -test.todo("contains on empty object returns false"); - -// Given an object with properties -// When passed to contains with an existing property name -// Then it should return true - -// Given an object with properties -// When passed to contains with a non-existent property name -// Then it should return false - -// Given invalid parameters like an array -// When passed to contains -// Then it should return false or throw an error +describe("contains", () => { + test("returns false for an empty object", () => { + expect(contains({}, "a")).toBe(false); + }); + + test("returns true when object contains the property", () => { + expect(contains({ a: 1, b: 2 }, "a")).toBe(true); + }); + + test("returns false when object does not contain the property", () => { + expect(contains({ a: 1, b: 2 }, "c")).toBe(false); + }); + + test("returns false when given an array instead of an object", () => { + expect(contains([], "a")).toBe(false); + }); + + test("returns false when given null", () => { + expect(contains(null, "a")).toBe(false); + }); + + test("returns false when given a non-object type", () => { + expect(contains(42, "a")).toBe(false); + expect(contains("string", "a")).toBe(false); + }); +}); \ No newline at end of file From 5615f714edd0afb7b9e8cee4a1b19ee0ff89992d Mon Sep 17 00:00:00 2001 From: mervereis Date: Tue, 17 Mar 2026 22:09:29 +0000 Subject: [PATCH 07/21] lookup function created & test cases added --- Sprint-2/implement/lookup.js | 17 +++++++-- Sprint-2/implement/lookup.test.js | 57 ++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/Sprint-2/implement/lookup.js b/Sprint-2/implement/lookup.js index a6746e07f..0611a334f 100644 --- a/Sprint-2/implement/lookup.js +++ b/Sprint-2/implement/lookup.js @@ -1,5 +1,18 @@ -function createLookup() { - // implementation here +function createLookup(pairs) { + if (!Array.isArray(pairs)) { + return {}; + } + + const lookup = {}; + + for (const pair of pairs) { + if (Array.isArray(pair) && pair.length === 2) { + const [country, currency] = pair; + lookup[country] = currency; + } + } + + return lookup; } module.exports = createLookup; diff --git a/Sprint-2/implement/lookup.test.js b/Sprint-2/implement/lookup.test.js index 547e06c5a..b9c506d72 100644 --- a/Sprint-2/implement/lookup.test.js +++ b/Sprint-2/implement/lookup.test.js @@ -1,6 +1,60 @@ const createLookup = require("./lookup.js"); -test.todo("creates a country currency code lookup for multiple codes"); +describe("createLookup", () => { + test("creates a country currency code lookup for multiple codes", () => { + const input = [ + ["US", "USD"], + ["CA", "CAD"], + ]; + const result = createLookup(input); + + expect(result).toEqual({ + US: "USD", + CA: "CAD", + }); + }); + + test("returns empty object for empty array", () => { + expect(createLookup([])).toEqual({}); + }); + + test("handles a single pair", () => { + const input = [["GB", "GBP"]]; + expect(createLookup(input)).toEqual({ + GB: "GBP", + }); + }); + + test("ignores invalid pairs (not arrays)", () => { + const input = [["US", "USD"], "invalid", null]; + expect(createLookup(input)).toEqual({ + US: "USD", + }); + }); + + test("ignores pairs that do not have exactly two elements", () => { + const input = [["US", "USD"], ["CA"], ["MX", "MXN", "extra"]]; + expect(createLookup(input)).toEqual({ + US: "USD", + }); + }); + + test("overwrites duplicate country codes with the latest value", () => { + const input = [ + ["US", "USD"], + ["US", "USN"], + ]; + expect(createLookup(input)).toEqual({ + US: "USN", + }); + }); + + test("returns empty object for invalid input (not an array)", () => { + expect(createLookup(null)).toEqual({}); + expect(createLookup({})).toEqual({}); + expect(createLookup("string")).toEqual({}); + }); +}); /* @@ -21,6 +75,7 @@ Then - The values are the corresponding currency codes Example + Given: [['US', 'USD'], ['CA', 'CAD']] When From 167b175dda64f3c80613fd09cae31c8052c5cfda Mon Sep 17 00:00:00 2001 From: mervereis Date: Tue, 17 Mar 2026 22:09:44 +0000 Subject: [PATCH 08/21] queryString function created & test cases added --- Sprint-2/implement/querystring.js | 26 +++++++++++-- Sprint-2/implement/querystring.test.js | 53 +++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/Sprint-2/implement/querystring.js b/Sprint-2/implement/querystring.js index 45ec4e5f3..2c34b052c 100644 --- a/Sprint-2/implement/querystring.js +++ b/Sprint-2/implement/querystring.js @@ -1,16 +1,34 @@ + function parseQueryString(queryString) { const queryParams = {}; - if (queryString.length === 0) { + + if (!queryString || typeof queryString !== "string") { return queryParams; } + const keyValuePairs = queryString.split("&"); for (const pair of keyValuePairs) { - const [key, value] = pair.split("="); - queryParams[key] = value; + if (!pair) continue; + + const index = pair.indexOf("="); + + let key, value; + + if (index === -1) { + key = pair; + value = ""; + } else { + key = pair.slice(0, index); + value = pair.slice(index + 1); + } + + if (key) { + queryParams[key] = value; + } } return queryParams; } -module.exports = parseQueryString; +module.exports = parseQueryString; \ No newline at end of file diff --git a/Sprint-2/implement/querystring.test.js b/Sprint-2/implement/querystring.test.js index 3e218b789..f640ce7ec 100644 --- a/Sprint-2/implement/querystring.test.js +++ b/Sprint-2/implement/querystring.test.js @@ -3,10 +3,59 @@ // Below is one test case for an edge case the implementation doesn't handle well. // Fix the implementation for this test, and try to think of as many other edge cases as possible - write tests and fix those too. -const parseQueryString = require("./querystring.js") +const parseQueryString = require("./querystring.js"); test("parses querystring values containing =", () => { expect(parseQueryString("equation=x=y+1")).toEqual({ - "equation": "x=y+1", + equation: "x=y+1", + }); +}); + +describe("parseQueryString edge cases", () => { + test("returns empty object for empty string", () => { + expect(parseQueryString("")).toEqual({}); + }); + + test("handles multiple key value pairs", () => { + expect(parseQueryString("a=1&b=2")).toEqual({ + a: "1", + b: "2", + }); + }); + + test("handles missing value", () => { + expect(parseQueryString("a=")).toEqual({ + a: "", + }); + }); + + test("handles missing equals sign", () => { + expect(parseQueryString("a")).toEqual({ + a: "", + }); + }); + + test("handles multiple equals signs in value", () => { + expect(parseQueryString("a=1=2=3")).toEqual({ + a: "1=2=3", + }); + }); + + test("ignores empty pairs", () => { + expect(parseQueryString("a=1&&b=2")).toEqual({ + a: "1", + b: "2", + }); + }); + + test("overwrites duplicate keys with last value", () => { + expect(parseQueryString("a=1&a=2")).toEqual({ + a: "2", + }); + }); + + test("returns empty object for invalid input", () => { + expect(parseQueryString(null)).toEqual({}); + expect(parseQueryString(undefined)).toEqual({}); }); }); From de3dc87ddc4f40ec03385100b8eec388ff645c4b Mon Sep 17 00:00:00 2001 From: mervereis Date: Tue, 17 Mar 2026 22:10:16 +0000 Subject: [PATCH 09/21] tally function created & test cases added --- Sprint-2/implement/tally.js | 14 ++++++++- Sprint-2/implement/tally.test.js | 51 +++++++++++++++----------------- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index f47321812..459a301c7 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -1,3 +1,15 @@ -function tally() {} +function tally(items) { + if (!Array.isArray(items)) { + throw new Error("Input must be an array"); + } + + const counts = {}; + + for (const item of items) { + counts[item] = (counts[item] || 0) + 1; + } + + return counts; +} module.exports = tally; diff --git a/Sprint-2/implement/tally.test.js b/Sprint-2/implement/tally.test.js index 2ceffa8dd..4c0afac3f 100644 --- a/Sprint-2/implement/tally.test.js +++ b/Sprint-2/implement/tally.test.js @@ -1,34 +1,31 @@ const tally = require("./tally.js"); -/** - * tally array - * - * In this task, you'll need to implement a function called tally - * that will take a list of items and count the frequency of each item - * in an array - * - * For example: - * - * tally(['a']), target output: { a: 1 } - * tally(['a', 'a', 'a']), target output: { a: 3 } - * tally(['a', 'a', 'b', 'c']), target output: { a : 2, b: 1, c: 1 } - */ +describe("tally", () => { + test("tally on an empty array returns an empty object", () => { + expect(tally([])).toEqual({}); + }); -// Acceptance criteria: + test("counts duplicate items correctly", () => { + expect(tally(["a", "a", "b", "c"])).toEqual({ + a: 2, + b: 1, + c: 1, + }); + }); -// Given a function called tally -// When passed an array of items -// Then it should return an object containing the count for each unique item + test("counts single item array", () => { + expect(tally(["a"])).toEqual({ a: 1 }); + }); -// Given an empty array -// When passed to tally -// Then it should return an empty object -test.todo("tally on an empty array returns an empty object"); + test("counts all same items", () => { + expect(tally(["a", "a", "a"])).toEqual({ a: 3 }); + }); -// Given an array with duplicate items -// When passed to tally -// Then it should return counts for each unique item + test("throws error for invalid input (string)", () => { + expect(() => tally("abc")).toThrow("Input must be an array"); + }); -// Given an invalid input like a string -// When passed to tally -// Then it should throw an error + test("throws error for invalid input (null)", () => { + expect(() => tally(null)).toThrow("Input must be an array"); + }); +}); From 823860736f21fe5981cef363508d097e7955ab53 Mon Sep 17 00:00:00 2001 From: mervereis Date: Tue, 17 Mar 2026 22:10:47 +0000 Subject: [PATCH 10/21] functions updated & questions answered --- Sprint-2/interpret/invert.js | 25 +++++++++++++++++++++---- Sprint-2/stretch/count-words.js | 18 ++++++++++++++++++ Sprint-2/stretch/mode.js | 29 +++++++++++++++++------------ 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/Sprint-2/interpret/invert.js b/Sprint-2/interpret/invert.js index bb353fb1f..14271d306 100644 --- a/Sprint-2/interpret/invert.js +++ b/Sprint-2/interpret/invert.js @@ -17,13 +17,30 @@ function invert(obj) { } // a) What is the current return value when invert is called with { a : 1 } +// { key: 1 } Because `invertedObj.key = value` uses the literal string "key" instead of the variable `key`. // b) What is the current return value when invert is called with { a: 1, b: 2 } +// { key: 2 } Each iteration overwrites the same "key" property, so only the last value remains. -// c) What is the target return value when invert is called with {a : 1, b: 2} +// c) What is the target return value when invert is called with { a: 1, b: 2 } +// { "1": "a", "2": "b" } -// c) What does Object.entries return? Why is it needed in this program? +// d) What does Object.entries return? Why is it needed in this program? +// Object.entries(obj) returns an array of [key, value] pairs: [["a",1], ["b",2]] This allows us to easily iterate over each key-value pair and swap them (key becomes value, value becomes key). -// d) Explain why the current return value is different from the target output +//e) Explain why the current return value is different from the target output +// Because the original code uses a fixed string property (`invertedObj.key = value`) instead of using the dynamic variable `key`. +// This overwrites the same property and doesn’t produce the correct inverted object. -// e) Fix the implementation of invert (and write tests to prove it's fixed!) +// f) Fix the implementation of invert (and write tests to prove it's fixed!) +// See below: + +// function invert(obj) { +// const invertedObj = {}; + +// for (const [key, value] of Object.entries(obj)) { +// invertedObj[value] = key; // dynamic key assignment +// } + +// return invertedObj; +// } diff --git a/Sprint-2/stretch/count-words.js b/Sprint-2/stretch/count-words.js index 8e85d19d7..e8a8927a9 100644 --- a/Sprint-2/stretch/count-words.js +++ b/Sprint-2/stretch/count-words.js @@ -26,3 +26,21 @@ 3. Order the results to find out which word is the most common in the input */ + +function countWords(str) { + if (typeof str !== "string") { + throw new Error("Input must be a string"); + } + + const counts = {}; + const words = str.split(/\s+/); + + for (const word of words) { + if (word === "") continue; + counts[word] = (counts[word] || 0) + 1; + } + + return counts; +} + +module.exports = countWords; diff --git a/Sprint-2/stretch/mode.js b/Sprint-2/stretch/mode.js index 3f7609d79..9efce35f9 100644 --- a/Sprint-2/stretch/mode.js +++ b/Sprint-2/stretch/mode.js @@ -8,29 +8,34 @@ // refactor calculateMode by splitting up the code // into smaller functions using the stages above -function calculateMode(list) { - // track frequency of each value - let freqs = new Map(); - - for (let num of list) { - if (typeof num !== "number") { - continue; - } +function trackFrequencies(list) { + const frequencies = new Map(); - freqs.set(num, (freqs.get(num) || 0) + 1); + for (const num of list) { + if (typeof num !== "number") continue; + frequencies.set(num, (frequencies.get(num) || 0) + 1); } - // Find the value with the highest frequency + return frequencies; +} + +function findMode(frequencies) { let maxFreq = 0; let mode; - for (let [num, freq] of freqs) { + + for (const [num, freq] of frequencies) { if (freq > maxFreq) { - mode = num; maxFreq = freq; + mode = num; } } return maxFreq === 0 ? NaN : mode; } +function calculateMode(list) { + const frequencies = trackFrequencies(list); + return findMode(frequencies); +} + module.exports = calculateMode; From 5d6304881cb8b72d101f322fe42699735d189f80 Mon Sep 17 00:00:00 2001 From: mervereis Date: Tue, 17 Mar 2026 22:10:56 +0000 Subject: [PATCH 11/21] till function created & test cases added --- Sprint-2/stretch/till.js | 22 ++++++++++++++++++---- Sprint-2/stretch/till.test.js | 21 +++++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 Sprint-2/stretch/till.test.js diff --git a/Sprint-2/stretch/till.js b/Sprint-2/stretch/till.js index 6a08532e7..b9624022d 100644 --- a/Sprint-2/stretch/till.js +++ b/Sprint-2/stretch/till.js @@ -8,10 +8,10 @@ function totalTill(till) { let total = 0; for (const [coin, quantity] of Object.entries(till)) { - total += coin * quantity; + const value = parseInt(coin); // "1p" → 1 + total += value * quantity; } - - return `£${total / 100}`; + return `£${(total / 100).toFixed(2)}`; } const till = { @@ -22,10 +22,24 @@ const till = { }; const totalAmount = totalTill(till); -// a) What is the target output when totalTill is called with the till object +module.exports = totalTill; + +// a) What is the target output when totalTill is called with the till object\ +// "£4.40" +// Explanation: +// 1p * 10 = 10p +// 5p * 6 = 30p +// 50p * 4 = 200p +// 20p * 10 = 200p +// Total = 440p → £4.40 // b) Why do we need to use Object.entries inside the for...of loop in this function? +// Object.entries(till) returns an array of [key, value] pairs. This allows us to iterate over both the coin type (key) and its quantity (value) easily. // c) What does coin * quantity evaluate to inside the for...of loop? +// As currently written, coin is a string like "1p", "5p". +// Multiplying a string by a number (e.g., "1p" * 10) results in NaN. +// Therefore, we need to convert the string to a number first using parseInt(coin). // d) Write a test for this function to check it works and then fix the implementation of totalTill +// See the test file till.test.js diff --git a/Sprint-2/stretch/till.test.js b/Sprint-2/stretch/till.test.js new file mode 100644 index 000000000..e8e4cf077 --- /dev/null +++ b/Sprint-2/stretch/till.test.js @@ -0,0 +1,21 @@ +const totalTill = require("./till.js"); + +describe("totalTill", () => { + test("calculates total correctly", () => { + const till = { + "1p": 10, + "5p": 6, + "50p": 4, + "20p": 10, + }; + expect(totalTill(till)).toBe("£4.40"); + }); + + test("handles empty till", () => { + expect(totalTill({})).toBe("£0.00"); // now passes + }); + + test("handles single coin type", () => { + expect(totalTill({ "100p": 3 })).toBe("£3.00"); + }); +}); From 0f617f26ca2c0b03b9e3c4348336c47c45e8095f Mon Sep 17 00:00:00 2001 From: mervereis Date: Tue, 17 Mar 2026 22:24:49 +0000 Subject: [PATCH 12/21] reverted wrong sprint changes --- Sprint-1/fix/median.js | 30 +--------- Sprint-1/fix/median.test.js | 22 ++++++-- Sprint-1/implement/dedupe.js | 7 +-- Sprint-1/implement/dedupe.test.js | 63 +++++++-------------- Sprint-1/implement/max.js | 18 +----- Sprint-1/implement/max.test.js | 91 ++++++++++++++----------------- Sprint-1/implement/sum.js | 11 +--- Sprint-1/implement/sum.test.js | 77 ++++++++++++-------------- 8 files changed, 118 insertions(+), 201 deletions(-) diff --git a/Sprint-1/fix/median.js b/Sprint-1/fix/median.js index 4b038b057..b22590bc6 100644 --- a/Sprint-1/fix/median.js +++ b/Sprint-1/fix/median.js @@ -5,34 +5,10 @@ // Hint: Please consider scenarios when 'list' doesn't have numbers (the function is expected to return null) // or 'list' has mixed values (the function is expected to sort only numbers). -// function calculateMedian(list) { -// const middleIndex = Math.floor(list.length / 2); -// const median = list.splice(middleIndex, 1)[0]; -// return median; -// } - -// module.exports = calculateMedian; - function calculateMedian(list) { - if (!Array.isArray(list)) { - return null; - } - - const numbers = list.filter((item) => typeof item === "number"); - - if (numbers.length === 0) { - return null; - } - - numbers.sort((a, b) => a - b); - - const middle = Math.floor(numbers.length / 2); - - if (numbers.length % 2 === 0) { - return (numbers[middle - 1] + numbers[middle]) / 2; - } - - return numbers[middle]; + const middleIndex = Math.floor(list.length / 2); + const median = list.splice(middleIndex, 1)[0]; + return median; } module.exports = calculateMedian; diff --git a/Sprint-1/fix/median.test.js b/Sprint-1/fix/median.test.js index 21da654d7..c262c3776 100644 --- a/Sprint-1/fix/median.test.js +++ b/Sprint-1/fix/median.test.js @@ -13,7 +13,8 @@ describe("calculateMedian", () => { { input: [1, 2, 3, 4], expected: 2.5 }, { input: [1, 2, 3, 4, 5, 6], expected: 3.5 }, ].forEach(({ input, expected }) => - it(`returns the median for [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) + it(`returns the median for [${input}]`, () => + expect(calculateMedian(input)).toEqual(expected)) ); [ @@ -24,7 +25,8 @@ describe("calculateMedian", () => { { input: [110, 20, 0], expected: 20 }, { input: [6, -2, 2, 12, 14], expected: 6 }, ].forEach(({ input, expected }) => - it(`returns the correct median for unsorted array [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) + it(`returns the correct median for unsorted array [${input}]`, () => + expect(calculateMedian(input)).toEqual(expected)) ); it("doesn't modify the input array [3, 1, 2]", () => { @@ -33,8 +35,17 @@ describe("calculateMedian", () => { expect(list).toEqual([3, 1, 2]); }); - [ 'not an array', 123, null, undefined, {}, [], ["apple", null, undefined] ].forEach(val => - it(`returns null for non-numeric array (${val})`, () => expect(calculateMedian(val)).toBe(null)) + [ + "not an array", + 123, + null, + undefined, + {}, + [], + ["apple", null, undefined], + ].forEach((val) => + it(`returns null for non-numeric array (${val})`, () => + expect(calculateMedian(val)).toBe(null)) ); [ @@ -45,6 +56,7 @@ describe("calculateMedian", () => { { input: [3, "apple", 1, null, 2, undefined, 4], expected: 2.5 }, { input: ["banana", 5, 3, "apple", 1, 4, 2], expected: 3 }, ].forEach(({ input, expected }) => - it(`filters out non-numeric values and calculates the median for [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) + it(`filters out non-numeric values and calculates the median for [${input}]`, () => + expect(calculateMedian(input)).toEqual(expected)) ); }); diff --git a/Sprint-1/implement/dedupe.js b/Sprint-1/implement/dedupe.js index 4932fbd40..781e8718a 100644 --- a/Sprint-1/implement/dedupe.js +++ b/Sprint-1/implement/dedupe.js @@ -1,6 +1 @@ -function dedupe(arr) { - if (arr.length === 0) return []; - return [...new Set(arr)]; -} - -module.exports = dedupe; +function dedupe() {} diff --git a/Sprint-1/implement/dedupe.test.js b/Sprint-1/implement/dedupe.test.js index 376a302e4..23e0f8638 100644 --- a/Sprint-1/implement/dedupe.test.js +++ b/Sprint-1/implement/dedupe.test.js @@ -1,50 +1,27 @@ -const dedupe = require("./dedupe"); +const dedupe = require("./dedupe.js"); +/* +Dedupe Array -describe("dedupe", () => { - // Given an empty array - // When passed to the dedupe function - // Then it should return an empty array - test.todo("given an empty array, it returns an empty array"); - test("given an empty array, it returns an empty array", () => { - const result = dedupe([]); - expect(result).toEqual([]); - }); +📖 Dedupe means **deduplicate** - // Given an array with no duplicates - // When passed to the dedupe function - // Then it should return a copy of the original array - test("given an array with no duplicates, it returns a copy of the original array", () => { - const input = [1, 2, 3, 4]; - const result = dedupe(input); +In this kata, you will need to deduplicate the elements of an array - expect(result).toEqual([1, 2, 3, 4]); - expect(result).not.toBe(input); // should be a new copy - }); +E.g. dedupe(['a','a','a','b','b','c']) target output: ['a','b','c'] +E.g. dedupe([5, 1, 1, 2, 3, 2, 5, 8]) target output: [5, 1, 2, 3, 8] +E.g. dedupe([1, 2, 1]) target output: [1, 2] +*/ - // Given an array with strings - // When passed to the dedupe function - // Then it should remove duplicates preserving first occurrence - test("removes duplicate strings preserving first occurrence", () => { - const input = ["a", "a", "a", "b", "b", "c"]; - const result = dedupe(input); +// Acceptance Criteria: - expect(result).toEqual(["a", "b", "c"]); - }); +// Given an empty array +// When passed to the dedupe function +// Then it should return an empty array +test.todo("given an empty array, it returns an empty array"); - // Given an array with numbers - // When passed to the dedupe function - // Then it should remove the duplicate values, preserving the first occurence of each element - test("removes duplicate numbers preserving first occurrence", () => { - const input = [5, 1, 1, 2, 3, 2, 5, 8]; - const result = dedupe(input); +// Given an array with no duplicates +// When passed to the dedupe function +// Then it should return a copy of the original array - expect(result).toEqual([5, 1, 2, 3, 8]); - }); - - test("removes duplicates in mixed order", () => { - const input = [1, 2, 1]; - const result = dedupe(input); - - expect(result).toEqual([1, 2]); - }); -}); +// Given an array with strings or numbers +// When passed to the dedupe function +// Then it should remove the duplicate values, preserving the first occurence of each element diff --git a/Sprint-1/implement/max.js b/Sprint-1/implement/max.js index 7aeef8376..69ca11e9c 100644 --- a/Sprint-1/implement/max.js +++ b/Sprint-1/implement/max.js @@ -1,19 +1,3 @@ -function findMax(elements) { - const numbers = elements.filter((el) => typeof el === "number"); - - if (numbers.length === 0) { - return -Infinity; - } - - let max = numbers[0]; - - for (let i = 1; i < numbers.length; i++) { - if (numbers[i] > max) { - max = numbers[i]; - } - } - - return max; -} +function findMax(elements) {} module.exports = findMax; diff --git a/Sprint-1/implement/max.test.js b/Sprint-1/implement/max.test.js index 526bc7abd..82f18fd88 100644 --- a/Sprint-1/implement/max.test.js +++ b/Sprint-1/implement/max.test.js @@ -1,52 +1,43 @@ +/* Find the maximum element of an array of numbers + +In this kata, you will need to implement a function that find the largest numerical element of an array. + +E.g. max([30, 50, 10, 40]), target output: 50 +E.g. max(['hey', 10, 'hi', 60, 10]), target output: 60 (sum ignores any non-numerical elements) + +You should implement this function in max.js, and add tests for it in this file. + +We have set things up already so that this file can see your function from the other file. +*/ + const findMax = require("./max.js"); -describe("findMax", () => { - // Given an empty array - // When passed to the max function - // Then it should return -Infinity - test("given an empty array, returns -Infinity", () => { - expect(findMax([])).toBe(-Infinity); - }); - - // Given an array with one number - // When passed to the max function - // Then it should return that number - test("given an array with one number, returns that number", () => { - expect(findMax([5])).toBe(5); - }); - - // Given an array with both positive and negative numbers - // When passed to the max function - // Then it should return the largest number overall - test("returns the largest number from positive and negative numbers", () => { - expect(findMax([-10, 20, -5, 15])).toBe(20); - }); - - // Given an array with just negative numbers - // When passed to the max function - // Then it should return the closest one to zero - test("returns the largest number among negative numbers", () => { - expect(findMax([-10, -3, -50, -1])).toBe(-1); - }); - - // Given an array with decimal numbers - // When passed to the max function - // Then it should return the largest decimal number - test("returns the largest decimal number", () => { - expect(findMax([1.2, 3.7, 2.5, 3.6])).toBe(3.7); - }); - - // Given an array with non-number values - // When passed to the max function - // Then it should return the max and ignore non-numeric values - test("ignores non-number values", () => { - expect(findMax(["hey", 10, "hi", 60, 10])).toBe(60); - }); - - // Given an array with only non-number values - // When passed to the max function - // Then it should return the least surprising value given how it behaves for all other inputs - test("returns -Infinity when array has only non-number values", () => { - expect(findMax(["a", "b", "c"])).toBe(-Infinity); - }); -}); +// Given an empty array +// When passed to the max function +// Then it should return -Infinity +// Delete this test.todo and replace it with a test. +test.todo("given an empty array, returns -Infinity"); + +// Given an array with one number +// When passed to the max function +// Then it should return that number + +// Given an array with both positive and negative numbers +// When passed to the max function +// Then it should return the largest number overall + +// Given an array with just negative numbers +// When passed to the max function +// Then it should return the closest one to zero + +// Given an array with decimal numbers +// When passed to the max function +// Then it should return the largest decimal number + +// Given an array with non-number values +// When passed to the max function +// Then it should return the max and ignore non-numeric values + +// Given an array with only non-number values +// When passed to the max function +// Then it should return the least surprising value given how it behaves for all other inputs diff --git a/Sprint-1/implement/sum.js b/Sprint-1/implement/sum.js index cafd1825a..873b75249 100644 --- a/Sprint-1/implement/sum.js +++ b/Sprint-1/implement/sum.js @@ -1,12 +1,3 @@ -function sum(elements) { - const numbers = elements.filter((el) => typeof el === "number"); - - if (numbers.length === 0) return 0; - - if (numbers.length === 1) return numbers[0]; - - const sumNumbers = numbers.reduce((a, b) => a + b, 0); - return sumNumbers; -} +function sum(elements) {} module.exports = sum; diff --git a/Sprint-1/implement/sum.test.js b/Sprint-1/implement/sum.test.js index cd2e22d61..38f6f252e 100644 --- a/Sprint-1/implement/sum.test.js +++ b/Sprint-1/implement/sum.test.js @@ -1,45 +1,36 @@ +/* Sum the numbers in an array + +In this kata, you will need to implement a function that sums the numerical elements of an array + +E.g. sum([10, 20, 30]), target output: 60 +E.g. sum(['hey', 10, 'hi', 60, 10]), target output: 80 (ignore any non-numerical elements) +*/ + const sum = require("./sum.js"); -describe("sum", () => { - // Given an empty array - // When passed to the sum function - // Then it should return 0 - test("given an empty array, returns 0", () => { - expect(sum([])).toBe(0); - }); - - // Given an array with just one number - // When passed to the sum function - // Then it should return that number - test("given an array with one number, returns that number", () => { - expect(sum([5])).toBe(5); - }); - - // Given an array containing negative numbers - // When passed to the sum function - // Then it should still return the correct total sum - test("sums negative numbers correctly", () => { - expect(sum([-5, -10, 15])).toBe(0); - }); - - // Given an array with decimal/float numbers - // When passed to the sum function - // Then it should return the correct total sum - test("sums decimal numbers correctly", () => { - expect(sum([1.5, 2.5, 3.5])).toBe(7.5); - }); - - // Given an array containing non-number values - // When passed to the sum function - // Then it should ignore the non-numerical values - test("ignores non-number values", () => { - expect(sum(["hey", 10, "hi", 60, 10])).toBe(80); - }); - - // Given an array with only non-number values - // When passed to the sum function - // Then it should return the least surprising value - test("returns 0 when array contains only non-number values", () => { - expect(sum(["a", "b", "c"])).toBe(0); - }); -}); +// Acceptance Criteria: + +// Given an empty array +// When passed to the sum function +// Then it should return 0 +test.todo("given an empty array, returns 0"); + +// Given an array with just one number +// When passed to the sum function +// Then it should return that number + +// Given an array containing negative numbers +// When passed to the sum function +// Then it should still return the correct total sum + +// Given an array with decimal/float numbers +// When passed to the sum function +// Then it should return the correct total sum + +// Given an array containing non-number values +// When passed to the sum function +// Then it should ignore the non-numerical values and return the sum of the numerical elements + +// Given an array with only non-number values +// When passed to the sum function +// Then it should return the least surprising value given how it behaves for all other inputs From 7da2b61b37c592b81262ac77aa38606d2f9f0089 Mon Sep 17 00:00:00 2001 From: mervereis <124799990+mervereis@users.noreply.github.com> Date: Tue, 17 Mar 2026 22:30:46 +0000 Subject: [PATCH 13/21] Update median.test.js --- Sprint-1/fix/median.test.js | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/Sprint-1/fix/median.test.js b/Sprint-1/fix/median.test.js index c262c3776..21da654d7 100644 --- a/Sprint-1/fix/median.test.js +++ b/Sprint-1/fix/median.test.js @@ -13,8 +13,7 @@ describe("calculateMedian", () => { { input: [1, 2, 3, 4], expected: 2.5 }, { input: [1, 2, 3, 4, 5, 6], expected: 3.5 }, ].forEach(({ input, expected }) => - it(`returns the median for [${input}]`, () => - expect(calculateMedian(input)).toEqual(expected)) + it(`returns the median for [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) ); [ @@ -25,8 +24,7 @@ describe("calculateMedian", () => { { input: [110, 20, 0], expected: 20 }, { input: [6, -2, 2, 12, 14], expected: 6 }, ].forEach(({ input, expected }) => - it(`returns the correct median for unsorted array [${input}]`, () => - expect(calculateMedian(input)).toEqual(expected)) + it(`returns the correct median for unsorted array [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) ); it("doesn't modify the input array [3, 1, 2]", () => { @@ -35,17 +33,8 @@ describe("calculateMedian", () => { expect(list).toEqual([3, 1, 2]); }); - [ - "not an array", - 123, - null, - undefined, - {}, - [], - ["apple", null, undefined], - ].forEach((val) => - it(`returns null for non-numeric array (${val})`, () => - expect(calculateMedian(val)).toBe(null)) + [ 'not an array', 123, null, undefined, {}, [], ["apple", null, undefined] ].forEach(val => + it(`returns null for non-numeric array (${val})`, () => expect(calculateMedian(val)).toBe(null)) ); [ @@ -56,7 +45,6 @@ describe("calculateMedian", () => { { input: [3, "apple", 1, null, 2, undefined, 4], expected: 2.5 }, { input: ["banana", 5, 3, "apple", 1, 4, 2], expected: 3 }, ].forEach(({ input, expected }) => - it(`filters out non-numeric values and calculates the median for [${input}]`, () => - expect(calculateMedian(input)).toEqual(expected)) + it(`filters out non-numeric values and calculates the median for [${input}]`, () => expect(calculateMedian(input)).toEqual(expected)) ); }); From f32e1a7530b5660be156fd493f3b91f84198c1b3 Mon Sep 17 00:00:00 2001 From: mervereis <124799990+mervereis@users.noreply.github.com> Date: Tue, 17 Mar 2026 22:31:26 +0000 Subject: [PATCH 14/21] Update max.js --- Sprint-1/implement/max.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sprint-1/implement/max.js b/Sprint-1/implement/max.js index 69ca11e9c..6dd76378e 100644 --- a/Sprint-1/implement/max.js +++ b/Sprint-1/implement/max.js @@ -1,3 +1,4 @@ -function findMax(elements) {} +function findMax(elements) { +} module.exports = findMax; From d51b2d2968ae522bed18f14b2ae0ffac7f8775e4 Mon Sep 17 00:00:00 2001 From: mervereis <124799990+mervereis@users.noreply.github.com> Date: Tue, 17 Mar 2026 22:32:06 +0000 Subject: [PATCH 15/21] Update sum.js --- Sprint-1/implement/sum.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sprint-1/implement/sum.js b/Sprint-1/implement/sum.js index 873b75249..9062aafe3 100644 --- a/Sprint-1/implement/sum.js +++ b/Sprint-1/implement/sum.js @@ -1,3 +1,4 @@ -function sum(elements) {} +function sum(elements) { +} module.exports = sum; From 6f42a8d2698785f6f01d617a47ff583505708564 Mon Sep 17 00:00:00 2001 From: mervereis <124799990+mervereis@users.noreply.github.com> Date: Tue, 17 Mar 2026 22:32:36 +0000 Subject: [PATCH 16/21] Update sum.test.js --- Sprint-1/implement/sum.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sprint-1/implement/sum.test.js b/Sprint-1/implement/sum.test.js index 38f6f252e..dd0a090ca 100644 --- a/Sprint-1/implement/sum.test.js +++ b/Sprint-1/implement/sum.test.js @@ -13,7 +13,7 @@ const sum = require("./sum.js"); // Given an empty array // When passed to the sum function // Then it should return 0 -test.todo("given an empty array, returns 0"); +test.todo("given an empty array, returns 0") // Given an array with just one number // When passed to the sum function From 72d6630e65d9656fd97eb680b00e93235e2d544d Mon Sep 17 00:00:00 2001 From: mervereis <124799990+mervereis@users.noreply.github.com> Date: Tue, 17 Mar 2026 22:33:49 +0000 Subject: [PATCH 17/21] Update package-lock.json --- Sprint-1/package-lock.json | 215 ++++++++++++++++++++++++++++--------- 1 file changed, 166 insertions(+), 49 deletions(-) diff --git a/Sprint-1/package-lock.json b/Sprint-1/package-lock.json index e3f3f866b..83e427d0b 100644 --- a/Sprint-1/package-lock.json +++ b/Sprint-1/package-lock.json @@ -27,14 +27,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" + "@babel/highlight": "^7.25.7", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -172,19 +172,21 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -200,25 +202,121 @@ } }, "node_modules/@babel/helpers": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", - "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", + "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0" + "@babel/helper-validator-identifier": "^7.25.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/parser": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", - "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", + "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.29.0" + "@babel/types": "^7.25.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -467,14 +565,15 @@ } }, "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", + "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/code-frame": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -500,13 +599,15 @@ } }, "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "version": "7.25.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", + "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" @@ -1224,10 +1325,11 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1477,10 +1579,11 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2678,13 +2781,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -2847,10 +2952,11 @@ } }, "node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3047,10 +3153,11 @@ "license": "MIT" }, "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", @@ -3436,6 +3543,16 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", From 0cdfa174e291855e14ea4f32e598345d95a927be Mon Sep 17 00:00:00 2001 From: mervereis Date: Fri, 27 Mar 2026 12:51:05 +0000 Subject: [PATCH 18/21] updated string concat --- Sprint-2/debug/recipe.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Sprint-2/debug/recipe.js b/Sprint-2/debug/recipe.js index 533ac4ec5..7b93b17b8 100644 --- a/Sprint-2/debug/recipe.js +++ b/Sprint-2/debug/recipe.js @@ -11,7 +11,5 @@ const recipe = { }; console.log(`${recipe.title} serves ${recipe.serves} - ingredients:`); -for (const ingredient of recipe.ingredients) { - console.log(ingredient); -} +ingredients: +${recipe.ingredients.join("\n")}`); From 59c72d3d13e52c96ff930894928ba05b8466a815 Mon Sep 17 00:00:00 2001 From: mervereis Date: Fri, 27 Mar 2026 12:53:26 +0000 Subject: [PATCH 19/21] use Object.hasOwn instead of in --- Sprint-2/implement/contains.js | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/Sprint-2/implement/contains.js b/Sprint-2/implement/contains.js index 03a53a805..43f9ef014 100644 --- a/Sprint-2/implement/contains.js +++ b/Sprint-2/implement/contains.js @@ -1,21 +1,9 @@ function contains(obj, prop) { - if (obj === null) { + if (obj === null || typeof obj !== "object" || Array.isArray(obj)) { return false; } - if (typeof obj !== "object") { - return false; - } - - if (Array.isArray(obj)) { - return false; - } - - if (prop in obj) { - return true; - } else { - return false; - } + return Object.hasOwn(obj, prop); } module.exports = contains; From 86e8a7c85ac77c3030d013a18da1e7a703cdc1fe Mon Sep 17 00:00:00 2001 From: mervereis Date: Fri, 27 Mar 2026 12:55:43 +0000 Subject: [PATCH 20/21] test case updated --- Sprint-2/implement/contains.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sprint-2/implement/contains.test.js b/Sprint-2/implement/contains.test.js index 0f8470140..5a8f1ae58 100644 --- a/Sprint-2/implement/contains.test.js +++ b/Sprint-2/implement/contains.test.js @@ -14,7 +14,7 @@ describe("contains", () => { }); test("returns false when given an array instead of an object", () => { - expect(contains([], "a")).toBe(false); + expect(contains([1, 2, 3], "0")).toBe(false); }); test("returns false when given null", () => { @@ -25,4 +25,4 @@ describe("contains", () => { expect(contains(42, "a")).toBe(false); expect(contains("string", "a")).toBe(false); }); -}); \ No newline at end of file +}); From 285f6a28e1c0b37183867f9ef4a56a21ba38c213 Mon Sep 17 00:00:00 2001 From: mervereis Date: Fri, 27 Mar 2026 12:57:57 +0000 Subject: [PATCH 21/21] object creation updated --- Sprint-2/implement/tally.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sprint-2/implement/tally.js b/Sprint-2/implement/tally.js index 459a301c7..e9e64329b 100644 --- a/Sprint-2/implement/tally.js +++ b/Sprint-2/implement/tally.js @@ -3,7 +3,7 @@ function tally(items) { throw new Error("Input must be an array"); } - const counts = {}; + const counts = Object.create(null); for (const item of items) { counts[item] = (counts[item] || 0) + 1;