From 40150914d15a8d6630f2cca0d9f83d47dc179264 Mon Sep 17 00:00:00 2001 From: toby-28 Date: Mon, 3 Nov 2025 21:56:40 +0500 Subject: [PATCH 01/11] Stop tracking package-lock.json; --- .gitignore | 2 + README.md | 108 +--------------------------------------------- package-lock.json | 83 +++++++++++------------------------ 3 files changed, 29 insertions(+), 164 deletions(-) diff --git a/.gitignore b/.gitignore index c6bba5913..5ad237ca6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +package-lock.json + # Logs logs *.log diff --git a/README.md b/README.md index 63d302ca8..4fb8b5458 100644 --- a/README.md +++ b/README.md @@ -1,107 +1 @@ -# Basic testing - -⚠️ DO NOT SUBMIT PULL REQUESTS TO THIS REPO ⚠️ - ---- - -### Prerequisites -1. Install [Node.js](https://nodejs.org/en/download/) -2. Fork this repository: https://github.com/AlreadyBored/basic-testing -3. Clone your newly created repo locally: https://github.com/<%your_github_username%>/basic-testing/ -4. Go to folder `basic-testing` -5. To install all dependencies use [`npm install`](https://docs.npmjs.com/cli/install) -6. Run **test scripts** in command line. -7. You will see the number of skipped, passing and failing tests. - ---- - -### Test scripts - -```bash -# run unit tests -$ npm run test - -# with logging -$ npm run test:verbose -``` - ---- - -#### Notes -1. We recommend you to use Node.js of version 24.x.x (24.10.0 or upper) LTS. If you use any of features, that does not supported by Node.js 24, there may be problems with task submit. -2. Please, be sure that each of your tests is limited to 30 sec. -3. Please, be sure you don't have any linter/TS compiler errors. - ---- - -## General task description -Your task is to write unit tests for code, provided in file `index.ts`. - ---- - -### **Simple tests** - -Write unit tests for the `simpleCalculator` function, which performs basic mathematical operations - addition, subtraction, division, multiplication, and exponentiation. Your task is to verify that the operations are executed correctly and that the function returns `null` for invalid input. - -Write your tests in `src/01-simple-tests/index.test.ts`. - ---- - -### **Table tests** - -Your task is to rewrite the tests written in the previous task using the table-driven testing approach, utilizing the appropriate Jest API. - -Write your tests in `src/02-table-tests/index.test.ts`. - ---- - - -### **Error handling & async** - -Your task is to test functions that work asynchronously/throw/reject exceptions.. - -Write your tests in `src/03-error-handling-async/index.test.ts`. - ---- - -### **Testing class** - -Your task is to test a class representing a bank account that implements corresponding operations. Please note that some methods of the class invoke others, some operations result in errors, and the implementation is asynchronous and involves the native JS API. These aspects should be taken into account when writing the tests. - -Write your tests in `src/04-test-class/index.test.ts`. - ---- - -### **Partial mocking** - -Your task is to utilize the Jest API to partially mock the contents of a module. - -Write your tests in `src/05-partial-mocking/index.test.ts`. - ---- - -### **Mocking Node.js API** - -Your task is to test the proper usage of the Node.js API based on commonly used APIs such as the `fs` module, as well as `setTimeout` and `setInterval`. Remember that the tests should not interact with the actual file system and should not rely on real-time! - -Write your tests in `src/06-mocking-node-api/index.test.ts`. - ---- - -### **Mocking library API** - -Your task is to test that function that utilize library APIs is working correctly (with commonly used libraries such as `axios` and `lodash` as examples). - -Write your tests in `src/07-mocking-lib-api/index.test.ts`. - ---- - -### **Snapshot testing** - -Your task is to use snapshot testing with Jest and compare it to regular comparison testing. - -Write your tests in `src/08-snapshot-testing/index.test.ts`. - ---- - -© [AlreadyBored](https://github.com/AlreadyBored) +# Basic testing \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 2bfc1ab15..d0a46ed4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -80,6 +80,7 @@ "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -2388,7 +2389,6 @@ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", "dev": true, - "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -2575,7 +2575,6 @@ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", "dev": true, - "peer": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -2585,8 +2584,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@types/graceful-fs": { "version": "4.1.9", @@ -2637,8 +2635,7 @@ "version": "7.0.12", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@types/lodash": { "version": "4.17.16", @@ -2653,6 +2650,7 @@ "integrity": "sha512-7zf4YyHA+jvBNfVrk2Gtvs6x7E8V+YDW05bNfG2XkWDJfYRXrTiP/DsB2zSYTaHX0bGIujTBQdMVAhb+j7mwpg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~6.19.2" } @@ -2718,6 +2716,7 @@ "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", @@ -2922,7 +2921,6 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "dev": true, - "peer": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -2932,29 +2930,25 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dev": true, - "peer": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -2965,15 +2959,13 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "dev": true, - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -2986,7 +2978,6 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dev": true, - "peer": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -2996,7 +2987,6 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dev": true, - "peer": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -3005,15 +2995,13 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "dev": true, - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -3030,7 +3018,6 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "dev": true, - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -3044,7 +3031,6 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "dev": true, - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -3057,7 +3043,6 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "dev": true, - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -3072,7 +3057,6 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "dev": true, - "peer": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" @@ -3082,15 +3066,13 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/acorn": { "version": "8.14.1", @@ -3098,6 +3080,7 @@ "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3110,7 +3093,6 @@ "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "dev": true, - "peer": true, "peerDependencies": { "acorn": "^8" } @@ -3143,6 +3125,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3159,7 +3142,6 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, - "peer": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -3451,6 +3433,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -3564,7 +3547,6 @@ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", "dev": true, - "peer": true, "engines": { "node": ">=6.0" } @@ -3659,8 +3641,7 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/concat-map": { "version": "0.0.1", @@ -3914,8 +3895,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/escalade": { "version": "3.2.0", @@ -3934,6 +3914,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -3990,6 +3971,7 @@ "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -4033,7 +4015,6 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -4199,7 +4180,6 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "peer": true, "engines": { "node": ">=4.0" } @@ -4218,7 +4198,6 @@ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, - "peer": true, "engines": { "node": ">=0.8.x" } @@ -4581,8 +4560,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/globals": { "version": "11.12.0", @@ -4934,6 +4912,7 @@ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -5633,7 +5612,6 @@ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true, - "peer": true, "engines": { "node": ">=6.11.5" } @@ -5827,8 +5805,7 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/node-int64": { "version": "0.4.0", @@ -6138,6 +6115,7 @@ "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -6257,7 +6235,6 @@ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, - "peer": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -6496,15 +6473,13 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "peer": true + ] }, "node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, - "peer": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -6533,7 +6508,6 @@ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "dev": true, - "peer": true, "dependencies": { "randombytes": "^2.1.0" } @@ -6759,7 +6733,6 @@ "resolved": "https://registry.npmjs.org/terser/-/terser-5.18.1.tgz", "integrity": "sha512-j1n0Ao919h/Ai5r43VAnfV/7azUYW43GPxK7qSATzrsERfW7+y2QW9Cp9ufnRF5CQUWbnLSo7UJokSWCqg4tsQ==", "dev": true, - "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -6778,7 +6751,6 @@ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "dev": true, - "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", @@ -6813,7 +6785,6 @@ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, - "peer": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -6828,7 +6799,6 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -6844,7 +6814,6 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -7049,6 +7018,7 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -7159,6 +7129,7 @@ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7295,7 +7266,6 @@ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "dev": true, - "peer": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -7357,7 +7327,6 @@ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true, - "peer": true, "engines": { "node": ">=10.13.0" } From a25a40227a9c433905d7f71d17f1a041f3d9c745 Mon Sep 17 00:00:00 2001 From: toby-28 Date: Mon, 3 Nov 2025 21:58:09 +0500 Subject: [PATCH 02/11] Including package-lock.json file again --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index 5ad237ca6..c6bba5913 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -package-lock.json - # Logs logs *.log From b22056d98d82cca17484d70c24f43caec331535d Mon Sep 17 00:00:00 2001 From: toby-28 Date: Tue, 4 Nov 2025 11:24:53 +0500 Subject: [PATCH 03/11] test: add comprehensive unit tests for simpleCalculator - Covers all supported operations: add, subtract, multiply, divide, exponentiate - Validates null return for invalid actions and non-numeric inputs - Ensures edge cases like missing or malformed input are handled gracefully --- src/01-simple-tests/index.test.ts | 55 +++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/src/01-simple-tests/index.test.ts b/src/01-simple-tests/index.test.ts index fbbea85de..7d8dc665c 100644 --- a/src/01-simple-tests/index.test.ts +++ b/src/01-simple-tests/index.test.ts @@ -1,32 +1,53 @@ -// Uncomment the code below and write your tests -// import { simpleCalculator, Action } from './index'; +import { simpleCalculator, Action } from './index'; -describe('simpleCalculator tests', () => { - test('should add two numbers', () => { - // Write your test here +describe('simpleCalculator', () => { + test('adds two numbers', () => { + const input = { a: 2, b: 3, action: Action.Add }; + expect(simpleCalculator(input)).toBe(5); }); - test('should subtract two numbers', () => { - // Write your test here + test('subtracts two numbers', () => { + const input = { a: 5, b: 2, action: Action.Subtract }; + expect(simpleCalculator(input)).toBe(3); }); - test('should multiply two numbers', () => { - // Write your test here + test('multiplies two numbers', () => { + const input = { a: 4, b: 3, action: Action.Multiply }; + expect(simpleCalculator(input)).toBe(12); }); - test('should divide two numbers', () => { - // Write your test here + test('divides two numbers', () => { + const input = { a: 10, b: 2, action: Action.Divide }; + expect(simpleCalculator(input)).toBe(5); }); - test('should exponentiate two numbers', () => { - // Write your test here + test('exponentiates two numbers', () => { + const input = { a: 2, b: 3, action: Action.Exponentiate }; + expect(simpleCalculator(input)).toBe(8); }); - test('should return null for invalid action', () => { - // Write your test here + test('returns null for invalid action', () => { + const input = { a: 2, b: 3, action: '%' }; + expect(simpleCalculator(input)).toBeNull(); }); - test('should return null for invalid arguments', () => { - // Write your test here + test('returns null for non-number a', () => { + const input = { a: '2', b: 3, action: Action.Add }; + expect(simpleCalculator(input)).toBeNull(); + }); + + test('returns null for non-number b', () => { + const input = { a: 2, b: '3', action: Action.Add }; + expect(simpleCalculator(input)).toBeNull(); + }); + + test('returns null for missing action', () => { + const input = { a: 2, b: 3, action: undefined }; + expect(simpleCalculator(input)).toBeNull(); + }); + + test('returns null for completely invalid input', () => { + const input = { a: null, b: {}, action: 'invalid' }; + expect(simpleCalculator(input)).toBeNull(); }); }); From b3d93d99fc0300cc2a798267c3cde1b7f9ae3538 Mon Sep 17 00:00:00 2001 From: toby-28 Date: Tue, 4 Nov 2025 11:25:33 +0500 Subject: [PATCH 04/11] test: add table-driven tests for simpleCalculator operations - Covers addition, subtraction, multiplication, division, and exponentiation - Uses test.each for concise and scalable test structure - Validates expected results across multiple input combinations --- src/02-table-tests/index.test.ts | 35 +++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/02-table-tests/index.test.ts b/src/02-table-tests/index.test.ts index 4f36e892e..6c20a0bde 100644 --- a/src/02-table-tests/index.test.ts +++ b/src/02-table-tests/index.test.ts @@ -1,17 +1,28 @@ -// Uncomment the code below and write your tests -/* import { simpleCalculator, Action } from './index'; +import { simpleCalculator, Action } from './index'; const testCases = [ - { a: 1, b: 2, action: Action.Add, expected: 3 }, - { a: 2, b: 2, action: Action.Add, expected: 4 }, - { a: 3, b: 2, action: Action.Add, expected: 5 }, - // continue cases for other actions -]; */ + { a: 1, b: 2, action: Action.Add, expected: 3 }, + { a: 2, b: 2, action: Action.Add, expected: 4 }, + { a: 3, b: 2, action: Action.Add, expected: 5 }, + + { a: 5, b: 3, action: Action.Subtract, expected: 2 }, + { a: 10, b: 4, action: Action.Subtract, expected: 6 }, + + { a: 2, b: 3, action: Action.Multiply, expected: 6 }, + { a: 4, b: 5, action: Action.Multiply, expected: 20 }, + + { a: 8, b: 2, action: Action.Divide, expected: 4 }, + { a: 9, b: 3, action: Action.Divide, expected: 3 }, + + { a: 2, b: 3, action: Action.Exponentiate, expected: 8 }, + { a: 5, b: 2, action: Action.Exponentiate, expected: 25 }, +]; describe('simpleCalculator', () => { - // This test case is just to run this test suite, remove it when you write your own tests - test('should blah-blah', () => { - expect(true).toBe(true); - }); - // Consider to use Jest table tests API to test all cases above + test.each(testCases)( + 'calculates $a $action $b = $expected', + ({ a, b, action, expected }) => { + expect(simpleCalculator({ a, b, action })).toBe(expected); + } + ); }); From 06837f264f052b6b34d7eca363c418de98069623 Mon Sep 17 00:00:00 2001 From: toby-28 Date: Tue, 4 Nov 2025 11:26:21 +0500 Subject: [PATCH 05/11] test: add unit tests for error handling and async behavior - Covers resolveValue for promise resolution - Validates throwError with custom and default messages - Tests throwCustomError and rejectCustomError using MyAwesomeError - Ensures proper rejection and exception handling in sync and async flows --- src/03-error-handling-async/index.test.ts | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/03-error-handling-async/index.test.ts b/src/03-error-handling-async/index.test.ts index 6e106a6d6..b37e138ea 100644 --- a/src/03-error-handling-async/index.test.ts +++ b/src/03-error-handling-async/index.test.ts @@ -1,30 +1,38 @@ -// Uncomment the code below and write your tests -// import { throwError, throwCustomError, resolveValue, MyAwesomeError, rejectCustomError } from './index'; +import { + throwError, + throwCustomError, + resolveValue, + MyAwesomeError, + rejectCustomError, +} from './index'; describe('resolveValue', () => { test('should resolve provided value', async () => { - // Write your test here + const value = { name: 'Hushnudbek' }; + await expect(resolveValue(value)).resolves.toEqual(value); }); }); describe('throwError', () => { test('should throw error with provided message', () => { - // Write your test here + expect(() => throwError('Custom message')).toThrow('Custom message'); }); test('should throw error with default message if message is not provided', () => { - // Write your test here + expect(() => throwError()).toThrow('Oops!'); }); }); describe('throwCustomError', () => { test('should throw custom error', () => { - // Write your test here + expect(() => throwCustomError()).toThrow(MyAwesomeError); + expect(() => throwCustomError()).toThrow('This is my awesome custom error!'); }); }); describe('rejectCustomError', () => { test('should reject custom error', async () => { - // Write your test here + await expect(rejectCustomError()).rejects.toThrow(MyAwesomeError); + await expect(rejectCustomError()).rejects.toThrow('This is my awesome custom error!'); }); }); From 30b57a0efa8deaf84a3c3952c95cd229f18043cf Mon Sep 17 00:00:00 2001 From: toby-28 Date: Tue, 4 Nov 2025 11:26:54 +0500 Subject: [PATCH 06/11] test: add unit tests for BankAccount class operations and error handling - Validates deposit, withdraw, and transfer logic - Covers edge cases: insufficient funds, self-transfer, and synchronization failures - Mocks fetchBalance for async scenarios and verifies balance updates - Ensures custom errors are thrown with correct messages --- src/04-test-class/index.test.ts | 52 +++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/src/04-test-class/index.test.ts b/src/04-test-class/index.test.ts index 937490d82..cd7fec314 100644 --- a/src/04-test-class/index.test.ts +++ b/src/04-test-class/index.test.ts @@ -1,44 +1,72 @@ -// Uncomment the code below and write your tests -// import { getBankAccount } from '.'; +import { + getBankAccount, + InsufficientFundsError, + TransferFailedError, + SynchronizationFailedError, +} from './index'; describe('BankAccount', () => { test('should create account with initial balance', () => { - // Write your test here + const account = getBankAccount(100); + expect(account.getBalance()).toBe(100); }); test('should throw InsufficientFundsError error when withdrawing more than balance', () => { - // Write your test here + const account = getBankAccount(50); + expect(() => account.withdraw(100)).toThrow(InsufficientFundsError); + expect(() => account.withdraw(100)).toThrow('Insufficient funds: cannot withdraw more than 50'); }); test('should throw error when transferring more than balance', () => { - // Write your test here + const acc1 = getBankAccount(30); + const acc2 = getBankAccount(100); + expect(() => acc1.transfer(50, acc2)).toThrow(InsufficientFundsError); }); test('should throw error when transferring to the same account', () => { - // Write your test here + const account = getBankAccount(100); + expect(() => account.transfer(10, account)).toThrow(TransferFailedError); + expect(() => account.transfer(10, account)).toThrow('Transfer failed'); }); test('should deposit money', () => { - // Write your test here + const account = getBankAccount(100); + account.deposit(50); + expect(account.getBalance()).toBe(150); }); test('should withdraw money', () => { - // Write your test here + const account = getBankAccount(100); + account.withdraw(40); + expect(account.getBalance()).toBe(60); }); test('should transfer money', () => { - // Write your test here + const acc1 = getBankAccount(100); + const acc2 = getBankAccount(50); + acc1.transfer(30, acc2); + expect(acc1.getBalance()).toBe(70); + expect(acc2.getBalance()).toBe(80); }); test('fetchBalance should return number in case if request did not failed', async () => { - // Write your tests here + const account = getBankAccount(100); + jest.spyOn(account, 'fetchBalance').mockResolvedValue(42); + const result = await account.fetchBalance(); + expect(result).toBe(42); }); test('should set new balance if fetchBalance returned number', async () => { - // Write your tests here + const account = getBankAccount(100); + jest.spyOn(account, 'fetchBalance').mockResolvedValue(75); + await account.synchronizeBalance(); + expect(account.getBalance()).toBe(75); }); test('should throw SynchronizationFailedError if fetchBalance returned null', async () => { - // Write your tests here + const account = getBankAccount(100); + jest.spyOn(account, 'fetchBalance').mockResolvedValue(null); + await expect(account.synchronizeBalance()).rejects.toThrow(SynchronizationFailedError); + await expect(account.synchronizeBalance()).rejects.toThrow('Synchronization failed'); }); }); From d88d9cf479c7c6607c9450bad3d7b423cf8e4c4d Mon Sep 17 00:00:00 2001 From: toby-28 Date: Tue, 4 Nov 2025 11:27:30 +0500 Subject: [PATCH 07/11] test: add unit tests for throttledGetDataFromApi with mocked axios - Mocks axios.create and verifies correct base URL usage - Ensures throttled function performs GET request to expected endpoint - Confirms resolved response data matches expected output - Uses fake timers to control throttle behavior --- src/07-mocking-lib-api/index.test.ts | 39 +++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/07-mocking-lib-api/index.test.ts b/src/07-mocking-lib-api/index.test.ts index e1dd001ef..d5f692570 100644 --- a/src/07-mocking-lib-api/index.test.ts +++ b/src/07-mocking-lib-api/index.test.ts @@ -1,17 +1,44 @@ -// Uncomment the code below and write your tests -/* import axios from 'axios'; -import { throttledGetDataFromApi } from './index'; */ +import axios from 'axios'; +import { throttledGetDataFromApi } from './index'; + +jest.mock('axios'); describe('throttledGetDataFromApi', () => { + let axiosClientMock: { get: jest.Mock }; + + beforeEach(() => { + jest.useFakeTimers(); + axiosClientMock = { + get: jest.fn().mockResolvedValue({ data: 'mocked response' }), + }; + (axios.create as jest.Mock).mockReturnValue(axiosClientMock); + }); + + afterEach(() => { + jest.clearAllMocks(); + jest.useRealTimers(); + }); + test('should create instance with provided base url', async () => { - // Write your test here + await throttledGetDataFromApi('/posts/1'); + jest.runAllTimers(); + + expect(axios.create).toHaveBeenCalledWith({ + baseURL: 'https://jsonplaceholder.typicode.com', + }); }); test('should perform request to correct provided url', async () => { - // Write your test here + await throttledGetDataFromApi('/posts/1'); + jest.runAllTimers(); + + expect(axiosClientMock.get).toHaveBeenCalledWith('/posts/1'); }); test('should return response data', async () => { - // Write your test here + const result = await throttledGetDataFromApi('/posts/1'); + jest.runAllTimers(); + + expect(result).toBe('mocked response'); }); }); From cf6ffa9cd7ff2a713a02eb9fa338e82738ec3a78 Mon Sep 17 00:00:00 2001 From: toby-28 Date: Tue, 4 Nov 2025 11:28:07 +0500 Subject: [PATCH 08/11] test: add linked list generation tests with strict equality and snapshot - Verifies correct structure for numeric input using toStrictEqual - Captures string-based linked list structure via snapshot for regression tracking --- src/08-snapshot-testing/index.test.ts | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/08-snapshot-testing/index.test.ts b/src/08-snapshot-testing/index.test.ts index 67c345706..d91e3b547 100644 --- a/src/08-snapshot-testing/index.test.ts +++ b/src/08-snapshot-testing/index.test.ts @@ -1,14 +1,27 @@ -// Uncomment the code below and write your tests -// import { generateLinkedList } from './index'; +import { generateLinkedList } from './index'; describe('generateLinkedList', () => { // Check match by expect(...).toStrictEqual(...) test('should generate linked list from values 1', () => { - // Write your test here + const list = generateLinkedList([1, 2, 3]); + expect(list).toStrictEqual({ + value: 1, + next: { + value: 2, + next: { + value: 3, + next: { + value: null, + next: null, + }, + }, + }, + }); }); // Check match by comparison with snapshot test('should generate linked list from values 2', () => { - // Write your test here + const list = generateLinkedList(['a', 'b', 'c']); + expect(list).toMatchSnapshot(); }); }); From 1854464de6e4aef844049feb9e727701dd4c0a7b Mon Sep 17 00:00:00 2001 From: toby-28 Date: Tue, 4 Nov 2025 11:39:28 +0500 Subject: [PATCH 09/11] test: implement partial mocking for selected module functions - Mocks mockOne, mockTwo, and mockThree using jest.fn() - Verifies mocked functions do not trigger console.log - Confirms unmockedFunction retains original behavior and logs as expected --- src/05-partial-mocking/index.test.ts | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/05-partial-mocking/index.test.ts b/src/05-partial-mocking/index.test.ts index 9d8a66cbd..8db6cf49c 100644 --- a/src/05-partial-mocking/index.test.ts +++ b/src/05-partial-mocking/index.test.ts @@ -1,8 +1,14 @@ -// Uncomment the code below and write your tests -// import { mockOne, mockTwo, mockThree, unmockedFunction } from './index'; +import { mockOne, mockTwo, mockThree, unmockedFunction } from './index'; jest.mock('./index', () => { - // const originalModule = jest.requireActual('./index'); + const originalModule = + jest.requireActual('./index'); + return { + ...originalModule, + mockOne: jest.fn(), + mockTwo: jest.fn(), + mockThree: jest.fn(), + }; }); describe('partial mocking', () => { @@ -11,10 +17,18 @@ describe('partial mocking', () => { }); test('mockOne, mockTwo, mockThree should not log into console', () => { - // Write your test here + const consoleSpy = jest.spyOn(console, 'log'); + mockOne(); + mockTwo(); + mockThree(); + expect(consoleSpy).not.toHaveBeenCalled(); + consoleSpy.mockRestore(); }); test('unmockedFunction should log into console', () => { - // Write your test here + const consoleSpy = jest.spyOn(console, 'log'); + unmockedFunction(); + expect(consoleSpy).toHaveBeenCalledWith('I am not mocked'); + consoleSpy.mockRestore(); }); }); From 7f2518ed82c79752ee905b3a946a9e5643b40eb9 Mon Sep 17 00:00:00 2001 From: toby-28 Date: Tue, 4 Nov 2025 11:59:52 +0500 Subject: [PATCH 10/11] test: add unit tests for Node.js API usage with mocks - Mocks fs.existsSync and fs.promises.readFile to avoid real file system access - Verifies readFileAsynchronously returns correct content or null based on file existence - Uses fake timers to test doStuffByTimeout and doStuffByInterval without relying on real time - Confirms callbacks are triggered correctly after timeout and interval progression --- src/06-mocking-node-api/index.test.ts | 79 +++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 10 deletions(-) diff --git a/src/06-mocking-node-api/index.test.ts b/src/06-mocking-node-api/index.test.ts index 8dc3afd79..312fad2b6 100644 --- a/src/06-mocking-node-api/index.test.ts +++ b/src/06-mocking-node-api/index.test.ts @@ -1,52 +1,111 @@ -// Uncomment the code below and write your tests -// import { readFileAsynchronously, doStuffByTimeout, doStuffByInterval } from '.'; +import { + readFileAsynchronously, + doStuffByTimeout, + doStuffByInterval, +} from './index'; +import * as path from 'path'; + +jest.mock('fs', () => ({ + existsSync: jest.fn(), +})); + +jest.mock('fs/promises', () => ({ + readFile: jest.fn(), +})); + +import { existsSync } from 'fs'; +import { readFile } from 'fs/promises'; describe('doStuffByTimeout', () => { + let timeoutSpy: jest.SpyInstance; + beforeAll(() => { jest.useFakeTimers(); + timeoutSpy = jest.spyOn(global, 'setTimeout'); }); afterAll(() => { jest.useRealTimers(); + timeoutSpy.mockRestore(); }); test('should set timeout with provided callback and timeout', () => { - // Write your test here + const callback = jest.fn(); + doStuffByTimeout(callback, 1000); + jest.runAllTimers(); // <-- advance timers to trigger setTimeout + expect(callback).toHaveBeenCalled(); }); test('should call callback only after timeout', () => { - // Write your test here + const callback = jest.fn(); + doStuffByTimeout(callback, 1000); + expect(callback).not.toHaveBeenCalled(); + jest.advanceTimersByTime(1000); + expect(callback).toHaveBeenCalledTimes(1); }); }); describe('doStuffByInterval', () => { + let intervalSpy: jest.SpyInstance; + beforeAll(() => { jest.useFakeTimers(); + intervalSpy = jest.spyOn(global, 'setInterval'); }); afterAll(() => { jest.useRealTimers(); + intervalSpy.mockRestore(); }); test('should set interval with provided callback and timeout', () => { - // Write your test here + const callback = jest.fn(); + doStuffByInterval(callback, 500); + jest.advanceTimersByTime(1500); // <-- simulate 3 intervals + expect(callback).toHaveBeenCalledTimes(3); }); test('should call callback multiple times after multiple intervals', () => { - // Write your test here + const callback = jest.fn(); + doStuffByInterval(callback, 500); + jest.advanceTimersByTime(1500); + expect(callback).toHaveBeenCalledTimes(3); }); }); describe('readFileAsynchronously', () => { - test('should call join with pathToFile', async () => { - // Write your test here + const fakePath = 'test.txt'; + const fullPath = path.join(__dirname, fakePath); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('should return file content if file exists', async () => { + (existsSync as jest.Mock).mockReturnValue(true); + (readFile as jest.Mock).mockResolvedValue( + Buffer.from('Hello, Hushnudbek!'), + ); + + const result = await readFileAsynchronously(fakePath); + expect(result).toBe('Hello, Hushnudbek!'); + expect(readFile).toHaveBeenCalledWith(path.join(__dirname, fakePath)); }); test('should return null if file does not exist', async () => { - // Write your test here + (existsSync as jest.Mock).mockReturnValue(false); + const result = await readFileAsynchronously(fakePath); + expect(result).toBeNull(); + expect(readFile).not.toHaveBeenCalled(); }); test('should return file content if file exists', async () => { - // Write your test here + (existsSync as jest.Mock).mockReturnValue(true); + (readFile as jest.Mock).mockResolvedValue( + Buffer.from('Hello, Hushnudbek!'), + ); + const result = await readFileAsynchronously(fakePath); + expect(result).toBe('Hello, Hushnudbek!'); + expect(readFile).toHaveBeenCalledWith(fullPath); }); }); From 4fd6e042f032f2b40d3b0512baa23e9ff30887ee Mon Sep 17 00:00:00 2001 From: hushnud <64332592+toby-28@users.noreply.github.com> Date: Sun, 9 Nov 2025 00:22:02 +0500 Subject: [PATCH 11/11] Revise README for Basic Testing Assignment Updated README to include project details, tech stack, and setup instructions. --- README.md | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4fb8b5458..788c48b0a 100644 --- a/README.md +++ b/README.md @@ -1 +1,95 @@ -# Basic testing \ No newline at end of file +# 🧪 Basic Testing Assignment + +This repository contains solutions for the [RS School Basic Testing](https://github.com/AlreadyBored/basic-testing) assignment. The goal is to write unit tests using **Jest** for various JavaScript/TypeScript modules that demonstrate different testing techniques. + +--- + +## 📦 Tech Stack + +- TypeScript +- Jest +- Node.js (v24+ recommended) + +--- + +## 🚀 Getting Started + +### 1. Clone the repository + +```bash +git clone https://github.com/toby-28/basic-testing.git +cd basic-testing +``` + +### 2. Install dependencies + +```bash +npm install +``` + +### 3. Run tests + +```bash +npm run test +``` + +For verbose output: + +```bash +npm run test:verbose +``` + +--- + +## 📁 Project Structure + +``` +basic-testing/ +├── src/ +│ ├── 01-simple-tests/ +│ ├── 02-table-tests/ +│ ├── 03-error-handling-async/ +│ ├── 04-test-class/ +│ ├── 05-partial-mocking/ +│ ├── 06-mocking-node-api/ +│ ├── 07-mocking-lib-api/ +│ └── 08-snapshot-testing/ +├── package.json +├── tsconfig.json +└── README.md +``` + +Each folder contains: +- `index.ts` → source code to be tested +- `index.test.ts` → your test implementation + +--- + +## ✅ Assignment Requirements + +- Write tests for each section using Jest +- Avoid TypeScript or linter errors +- Each test must complete within **30 seconds** +- Do not modify original source files +- Do not submit PRs to this repo — it's for local development only + +--- + +## 🧠 Topics Covered + +| Section | Focus | +|--------|-------| +| 01 | Basic assertions and input validation | +| 02 | Table-driven tests | +| 03 | Error handling and async functions | +| 04 | Testing classes and internal logic | +| 05 | Partial mocking with Jest | +| 06 | Mocking Node.js APIs (`fs`, timers) | +| 07 | Mocking external libraries (`axios`, `lodash`) | +| 08 | Snapshot testing | + +--- + +## 📜 License + +This project is for educational use under RS School guidelines.