From 2c13f73c23bab103b17bdb1ffe96a2b00b5b4c54 Mon Sep 17 00:00:00 2001 From: Wendelin Date: Tue, 26 Nov 2024 17:14:17 +0100 Subject: [PATCH 1/3] add vitest coverage --- .gitignore | 3 + package.json | 4 +- test/vitest.config.ts | 6 ++ yarn.lock | 127 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 131 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index f67dd1894e07..7de50364e700 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,6 @@ src/cast/dev_const.ts # Jetbrains /.idea/ + +# test coverage +test/coverage/ diff --git a/package.json b/package.json index 96148050e4ba..00a39f50e342 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "postinstall": "husky", "prepack": "pinst --disable", "postpack": "pinst --enable", - "test": "vitest run --config test/vitest.config.ts" + "test": "vitest run --config test/vitest.config.ts", + "test:coverage": "vitest run --config test/vitest.config.ts --coverage" }, "author": "Paulus Schoutsen (http://paulusschoutsen.nl)", "license": "Apache-2.0", @@ -189,6 +190,7 @@ "@types/webspeechapi": "0.0.29", "@typescript-eslint/eslint-plugin": "7.18.0", "@typescript-eslint/parser": "7.18.0", + "@vitest/coverage-v8": "2.1.5", "@web/dev-server": "0.1.38", "babel-loader": "9.2.1", "babel-plugin-template-html-minifier": "4.1.0", diff --git a/test/vitest.config.ts b/test/vitest.config.ts index 84fee346b7cf..ad284c68053c 100644 --- a/test/vitest.config.ts +++ b/test/vitest.config.ts @@ -7,5 +7,11 @@ export default defineConfig({ IS_TEST: "true", }, setupFiles: ["./test/setup.ts"], + coverage: { + include: ["src/data/**/*", "src/common/**/*"], + reporter: ["text", "html"], + provider: "v8", + reportsDirectory: "test/coverage", + }, }, }); diff --git a/yarn.lock b/yarn.lock index 6486335fe1a9..c5814bef2a4b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,7 +5,7 @@ __metadata: version: 8 cacheKey: 10 -"@ampproject/remapping@npm:^2.2.0": +"@ampproject/remapping@npm:^2.2.0, @ampproject/remapping@npm:^2.3.0": version: 2.3.0 resolution: "@ampproject/remapping@npm:2.3.0" dependencies: @@ -318,7 +318,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.23.5, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0": +"@babel/parser@npm:^7.23.5, @babel/parser@npm:^7.25.4, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0": version: 7.26.2 resolution: "@babel/parser@npm:7.26.2" dependencies: @@ -1261,7 +1261,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0, @babel/types@npm:^7.4.4": +"@babel/types@npm:^7.25.4, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0, @babel/types@npm:^7.4.4": version: 7.26.0 resolution: "@babel/types@npm:7.26.0" dependencies: @@ -1271,6 +1271,13 @@ __metadata: languageName: node linkType: hard +"@bcoe/v8-coverage@npm:^0.2.3": + version: 0.2.3 + resolution: "@bcoe/v8-coverage@npm:0.2.3" + checksum: 10/1a1f0e356a3bb30b5f1ced6f79c413e6ebacf130421f15fac5fcd8be5ddf98aedb4404d7f5624e3285b700e041f9ef938321f3ca4d359d5b716f96afa120d88d + languageName: node + linkType: hard + "@braintree/sanitize-url@npm:7.1.0": version: 7.1.0 resolution: "@braintree/sanitize-url@npm:7.1.0" @@ -1911,6 +1918,13 @@ __metadata: languageName: node linkType: hard +"@istanbuljs/schema@npm:^0.1.2": + version: 0.1.3 + resolution: "@istanbuljs/schema@npm:0.1.3" + checksum: 10/a9b1e49acdf5efc2f5b2359f2df7f90c5c725f2656f16099e8b2cd3a000619ecca9fc48cf693ba789cf0fd989f6e0df6a22bc05574be4223ecdbb7997d04384b + languageName: node + linkType: hard + "@jimp/bmp@npm:^0.16.13": version: 0.16.13 resolution: "@jimp/bmp@npm:0.16.13" @@ -2086,7 +2100,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": +"@jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": version: 0.3.25 resolution: "@jridgewell/trace-mapping@npm:0.3.25" dependencies: @@ -5473,6 +5487,32 @@ __metadata: languageName: node linkType: hard +"@vitest/coverage-v8@npm:2.1.5": + version: 2.1.5 + resolution: "@vitest/coverage-v8@npm:2.1.5" + dependencies: + "@ampproject/remapping": "npm:^2.3.0" + "@bcoe/v8-coverage": "npm:^0.2.3" + debug: "npm:^4.3.7" + istanbul-lib-coverage: "npm:^3.2.2" + istanbul-lib-report: "npm:^3.0.1" + istanbul-lib-source-maps: "npm:^5.0.6" + istanbul-reports: "npm:^3.1.7" + magic-string: "npm:^0.30.12" + magicast: "npm:^0.3.5" + std-env: "npm:^3.8.0" + test-exclude: "npm:^7.0.1" + tinyrainbow: "npm:^1.2.0" + peerDependencies: + "@vitest/browser": 2.1.5 + vitest: 2.1.5 + peerDependenciesMeta: + "@vitest/browser": + optional: true + checksum: 10/14c90c9201f480b7a028086f05063a89e55897bce005f8bef322089775473384ece3acf63e2b819f50eb650bac68b3e6b30f7bd07e13e7772f4d12e739116191 + languageName: node + linkType: hard + "@vitest/expect@npm:2.1.5": version: 2.1.5 resolution: "@vitest/expect@npm:2.1.5" @@ -9085,7 +9125,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": +"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7, glob@npm:^10.4.1": version: 10.4.5 resolution: "glob@npm:10.4.5" dependencies: @@ -9533,6 +9573,7 @@ __metadata: "@vibrant/color": "npm:3.2.1-alpha.1" "@vibrant/core": "npm:3.2.1-alpha.1" "@vibrant/quantizer-mmcq": "npm:3.2.1-alpha.1" + "@vitest/coverage-v8": "npm:2.1.5" "@vue/web-component-wrapper": "npm:1.3.0" "@web/dev-server": "npm:0.1.38" "@webcomponents/scoped-custom-element-registry": "npm:0.0.9" @@ -9677,7 +9718,7 @@ __metadata: languageName: node linkType: hard -"html-escaper@npm:^2.0.2": +"html-escaper@npm:^2.0.0, html-escaper@npm:^2.0.2": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" checksum: 10/034d74029dcca544a34fb6135e98d427acd73019796ffc17383eaa3ec2fe1c0471dcbbc8f8ed39e46e86d43ccd753a160631615e4048285e313569609b66d5b7 @@ -10514,6 +10555,45 @@ __metadata: languageName: node linkType: hard +"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.2": + version: 3.2.2 + resolution: "istanbul-lib-coverage@npm:3.2.2" + checksum: 10/40bbdd1e937dfd8c830fa286d0f665e81b7a78bdabcd4565f6d5667c99828bda3db7fb7ac6b96a3e2e8a2461ddbc5452d9f8bc7d00cb00075fa6a3e99f5b6a81 + languageName: node + linkType: hard + +"istanbul-lib-report@npm:^3.0.0, istanbul-lib-report@npm:^3.0.1": + version: 3.0.1 + resolution: "istanbul-lib-report@npm:3.0.1" + dependencies: + istanbul-lib-coverage: "npm:^3.0.0" + make-dir: "npm:^4.0.0" + supports-color: "npm:^7.1.0" + checksum: 10/86a83421ca1cf2109a9f6d193c06c31ef04a45e72a74579b11060b1e7bb9b6337a4e6f04abfb8857e2d569c271273c65e855ee429376a0d7c91ad91db42accd1 + languageName: node + linkType: hard + +"istanbul-lib-source-maps@npm:^5.0.6": + version: 5.0.6 + resolution: "istanbul-lib-source-maps@npm:5.0.6" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.23" + debug: "npm:^4.1.1" + istanbul-lib-coverage: "npm:^3.0.0" + checksum: 10/569dd0a392ee3464b1fe1accbaef5cc26de3479eacb5b91d8c67ebb7b425d39fd02247d85649c3a0e9c29b600809fa60b5af5a281a75a89c01f385b1e24823a2 + languageName: node + linkType: hard + +"istanbul-reports@npm:^3.1.7": + version: 3.1.7 + resolution: "istanbul-reports@npm:3.1.7" + dependencies: + html-escaper: "npm:^2.0.0" + istanbul-lib-report: "npm:^3.0.0" + checksum: 10/f1faaa4684efaf57d64087776018d7426312a59aa6eeb4e0e3a777347d23cd286ad18f427e98f0e3dee666103d7404c9d7abc5f240406a912fa16bd6695437fa + languageName: node + linkType: hard + "jackspeak@npm:^3.1.2": version: 3.4.3 resolution: "jackspeak@npm:3.4.3" @@ -11225,6 +11305,26 @@ __metadata: languageName: node linkType: hard +"magicast@npm:^0.3.5": + version: 0.3.5 + resolution: "magicast@npm:0.3.5" + dependencies: + "@babel/parser": "npm:^7.25.4" + "@babel/types": "npm:^7.25.4" + source-map-js: "npm:^1.2.0" + checksum: 10/3a2dba6b0bdde957797361d09c7931ebdc1b30231705360eeb40ed458d28e1c3112841c3ed4e1b87ceb28f741e333c7673cd961193aa9fdb4f4946b202e6205a + languageName: node + linkType: hard + +"make-dir@npm:^4.0.0": + version: 4.0.0 + resolution: "make-dir@npm:4.0.0" + dependencies: + semver: "npm:^7.5.3" + checksum: 10/bf0731a2dd3aab4db6f3de1585cea0b746bb73eb5a02e3d8d72757e376e64e6ada190b1eddcde5b2f24a81b688a9897efd5018737d05e02e2a671dda9cff8a8a + languageName: node + linkType: hard + "make-fetch-happen@npm:^13.0.0": version: 13.0.1 resolution: "make-fetch-happen@npm:13.0.1" @@ -13388,7 +13488,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.6.0, semver@npm:^7.6.2, semver@npm:^7.6.3": +"semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.6.0, semver@npm:^7.6.2, semver@npm:^7.6.3": version: 7.6.3 resolution: "semver@npm:7.6.3" bin: @@ -13744,7 +13844,7 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:^1.2.1": +"source-map-js@npm:^1.2.0, source-map-js@npm:^1.2.1": version: 1.2.1 resolution: "source-map-js@npm:1.2.1" checksum: 10/ff9d8c8bf096d534a5b7707e0382ef827b4dd360a577d3f34d2b9f48e12c9d230b5747974ee7c607f0df65113732711bb701fe9ece3c7edbd43cb2294d707df3 @@ -14335,6 +14435,17 @@ __metadata: languageName: node linkType: hard +"test-exclude@npm:^7.0.1": + version: 7.0.1 + resolution: "test-exclude@npm:7.0.1" + dependencies: + "@istanbuljs/schema": "npm:^0.1.2" + glob: "npm:^10.4.1" + minimatch: "npm:^9.0.4" + checksum: 10/e6f6f4e1df2e7810e082e8d7dfc53be51a931e6e87925f5e1c2ef92cc1165246ba3bf2dae6b5d86251c16925683dba906bd41e40169ebc77120a2d1b5a0dbbe0 + languageName: node + linkType: hard + "text-decoder@npm:^1.1.0": version: 1.2.0 resolution: "text-decoder@npm:1.2.0" From cf1db615ba9b8737b6c2547d89a7824311af3d52 Mon Sep 17 00:00:00 2001 From: Wendelin Date: Tue, 26 Nov 2024 17:15:47 +0100 Subject: [PATCH 2/3] Add js doc to functions --- src/common/array/combinations.ts | 5 +++++ src/common/array/ensure-array.ts | 4 ++++ src/common/array/literal-includes.ts | 6 +++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/common/array/combinations.ts b/src/common/array/combinations.ts index adb6e6476dc9..98c6d2235da4 100644 --- a/src/common/array/combinations.ts +++ b/src/common/array/combinations.ts @@ -1,3 +1,8 @@ +/** + * Get all possible combinations of an array + * @param arr - The array to get combinations of + * @returns A multidimensional array of all possible combinations + */ export function getAllCombinations(arr: T[]) { return arr.reduce( (combinations, element) => diff --git a/src/common/array/ensure-array.ts b/src/common/array/ensure-array.ts index 70869a91f160..360024f6ab27 100644 --- a/src/common/array/ensure-array.ts +++ b/src/common/array/ensure-array.ts @@ -1,5 +1,9 @@ type NonUndefined = T extends undefined ? never : T; +/** + * Ensure that the input is an array or wrap it in an array + * @param value - The value to ensure is an array + */ export function ensureArray(value: undefined): undefined; export function ensureArray(value: T | T[]): NonUndefined[]; export function ensureArray(value: T | readonly T[]): NonUndefined[]; diff --git a/src/common/array/literal-includes.ts b/src/common/array/literal-includes.ts index c73648586a90..c73b000fc641 100644 --- a/src/common/array/literal-includes.ts +++ b/src/common/array/literal-includes.ts @@ -1,4 +1,8 @@ -// Creates a type predicate function for determining if an array literal includes a given value +/** + * Creates a type predicate function for determining if an array literal includes a given value + * @param array - The array to check + * @returns A type predicate function + */ export const arrayLiteralIncludes = (array: T) => (searchElement: unknown, fromIndex?: number): searchElement is T[number] => From 52a1fbca9aea9d3d7bc4c98488a66fb7bc737ead Mon Sep 17 00:00:00 2001 From: Wendelin Date: Tue, 26 Nov 2024 17:16:09 +0100 Subject: [PATCH 3/3] Add tests for common/array --- test/common/array/combination.test.ts | 33 ++++++++++++++++++++++ test/common/array/ensure-array.test.ts | 28 ++++++++++++++++++ test/common/array/literal-includes.test.ts | 30 ++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 test/common/array/combination.test.ts create mode 100644 test/common/array/ensure-array.test.ts create mode 100644 test/common/array/literal-includes.test.ts diff --git a/test/common/array/combination.test.ts b/test/common/array/combination.test.ts new file mode 100644 index 000000000000..45c35d5da184 --- /dev/null +++ b/test/common/array/combination.test.ts @@ -0,0 +1,33 @@ +import { describe, expect, it } from "vitest"; +import { getAllCombinations } from "../../../src/common/array/combinations"; + +describe("getAllCombinations", () => { + it("should return all combinations of an array", () => { + const result = getAllCombinations([1, 2, 3]); + expect(result).toEqual([ + [], + [1], + [2], + [1, 2], + [3], + [1, 3], + [2, 3], + [1, 2, 3], + ]); + }); + + it("should return an empty array for an empty input", () => { + const result = getAllCombinations([]); + expect(result).toEqual([[]]); + }); + + it("should handle an array with one element", () => { + const result = getAllCombinations([1]); + expect(result).toEqual([[], [1]]); + }); + + it("should handle an array with duplicate elements", () => { + const result = getAllCombinations([1, 1]); + expect(result).toEqual([[], [1], [1], [1, 1]]); + }); +}); diff --git a/test/common/array/ensure-array.test.ts b/test/common/array/ensure-array.test.ts new file mode 100644 index 000000000000..e58fb8ef8a74 --- /dev/null +++ b/test/common/array/ensure-array.test.ts @@ -0,0 +1,28 @@ +import { describe, expect, it } from "vitest"; +import { ensureArray } from "../../../src/common/array/ensure-array"; + +describe("ensureArray", () => { + it("should return undefined when input is undefined", () => { + expect(ensureArray(undefined)).toBeUndefined(); + }); + + it("should return the same array when input is an array", () => { + const arr = [1, 2, 3]; + expect(ensureArray(arr)).toBe(arr); + }); + + it("should wrap non-array value in an array", () => { + const value = 5; + expect(ensureArray(value)).toEqual([value]); + }); + + it("should wrap non-array object in an array", () => { + const value = { key: "value" }; + expect(ensureArray(value)).toEqual([value]); + }); + + it("should return the same readonly array when input is a readonly array", () => { + const arr = [1, 2, 3] as const; + expect(ensureArray(arr)).toBe(arr); + }); +}); diff --git a/test/common/array/literal-includes.test.ts b/test/common/array/literal-includes.test.ts new file mode 100644 index 000000000000..ceb772b30d2c --- /dev/null +++ b/test/common/array/literal-includes.test.ts @@ -0,0 +1,30 @@ +import { describe, it, expect } from "vitest"; +import { arrayLiteralIncludes } from "../../../src/common/array/literal-includes"; + +describe("arrayLiteralIncludes", () => { + const array = ["a", "b", "c"] as const; + const includes = arrayLiteralIncludes(array); + + it("should return true if the element is in the array", () => { + expect(includes("a")).toBe(true); + expect(includes("b")).toBe(true); + expect(includes("c")).toBe(true); + }); + + it("should return false if the element is not in the array", () => { + expect(includes("d")).toBe(false); + expect(includes(1)).toBe(false); + }); + + it("should respect the fromIndex parameter", () => { + expect(includes("a", 1)).toBe(false); + expect(includes("b", 1)).toBe(true); + }); + + it("should handle empty arrays", () => { + const emptyArray = [] as const; + const includesEmpty = arrayLiteralIncludes(emptyArray); + + expect(includesEmpty("a")).toBe(false); + }); +});