From 95c5f40ef86759d8a4b1411deba79ec4530429c6 Mon Sep 17 00:00:00 2001 From: KoloMl <thekolomoets@hotmail.com> Date: Wed, 2 Apr 2025 05:00:53 +0400 Subject: [PATCH 1/9] Enclosing keyboard navigation test into describe block I want to share the same context, but make a separate test for the edge-case scenario. --- .../autocomplete/__tests__/keyboard.spec.ts | 192 +++++++++--------- 1 file changed, 99 insertions(+), 93 deletions(-) diff --git a/assets/js/autocomplete/__tests__/keyboard.spec.ts b/assets/js/autocomplete/__tests__/keyboard.spec.ts index 11a3d446..86243430 100644 --- a/assets/js/autocomplete/__tests__/keyboard.spec.ts +++ b/assets/js/autocomplete/__tests__/keyboard.spec.ts @@ -1,114 +1,120 @@ -import { init } from './context'; +import { init, TestContext } from './context'; -it('supports navigation via keyboard', async () => { - const ctx = await init(); +describe('Autocomplete keyboard navigation', () => { + let ctx: TestContext; - await ctx.setInput('f'); + beforeAll(async () => { + ctx = await init(); + }); - await ctx.keyDown('ArrowDown'); + it('supports navigation via keyboard', async () => { + await ctx.setInput('f'); - ctx.expectUi().toMatchInlineSnapshot(` - { - "input": "forest<>", - "suggestions": [ - "👉 forest 3", - "force field 1", - "fog 1", - "flower 1", - ], - } - `); + await ctx.keyDown('ArrowDown'); - await ctx.keyDown('ArrowDown'); + ctx.expectUi().toMatchInlineSnapshot(` + { + "input": "forest<>", + "suggestions": [ + "👉 forest 3", + "force field 1", + "fog 1", + "flower 1", + ], + } + `); - ctx.expectUi().toMatchInlineSnapshot(` - { - "input": "force field<>", - "suggestions": [ - "forest 3", - "👉 force field 1", - "fog 1", - "flower 1", - ], - } - `); + await ctx.keyDown('ArrowDown'); - await ctx.keyDown('ArrowDown', { ctrlKey: true }); + ctx.expectUi().toMatchInlineSnapshot(` + { + "input": "force field<>", + "suggestions": [ + "forest 3", + "👉 force field 1", + "fog 1", + "flower 1", + ], + } + `); - ctx.expectUi().toMatchInlineSnapshot(` - { - "input": "flower<>", - "suggestions": [ - "forest 3", - "force field 1", - "fog 1", - "👉 flower 1", - ], - } - `); + await ctx.keyDown('ArrowDown', { ctrlKey: true }); - await ctx.keyDown('ArrowUp', { ctrlKey: true }); + ctx.expectUi().toMatchInlineSnapshot(` + { + "input": "flower<>", + "suggestions": [ + "forest 3", + "force field 1", + "fog 1", + "👉 flower 1", + ], + } + `); - ctx.expectUi().toMatchInlineSnapshot(` - { - "input": "forest<>", - "suggestions": [ - "👉 forest 3", - "force field 1", - "fog 1", - "flower 1", - ], - } - `); + await ctx.keyDown('ArrowUp', { ctrlKey: true }); - await ctx.keyDown('Enter'); + ctx.expectUi().toMatchInlineSnapshot(` + { + "input": "forest<>", + "suggestions": [ + "👉 forest 3", + "force field 1", + "fog 1", + "flower 1", + ], + } + `); - ctx.expectUi().toMatchInlineSnapshot(` - { - "input": "forest<>", - "suggestions": [], - } - `); + await ctx.keyDown('Enter'); - await ctx.setInput('forest, t<>, safe'); + ctx.expectUi().toMatchInlineSnapshot(` + { + "input": "forest<>", + "suggestions": [], + } + `); - ctx.expectUi().toMatchInlineSnapshot(` - { - "input": "forest, t<>, safe", - "suggestions": [ - "artist:test 1", - ], - } - `); + await ctx.setInput('forest, t<>, safe'); - await ctx.keyDown('ArrowDown'); + ctx.expectUi().toMatchInlineSnapshot(` + { + "input": "forest, t<>, safe", + "suggestions": [ + "artist:test 1", + ], + } + `); - ctx.expectUi().toMatchInlineSnapshot(` - { - "input": "forest, artist:test<>, safe", - "suggestions": [ - "👉 artist:test 1", - ], - } - `); + await ctx.keyDown('ArrowDown'); - await ctx.keyDown('Escape'); + ctx.expectUi().toMatchInlineSnapshot(` + { + "input": "forest, artist:test<>, safe", + "suggestions": [ + "👉 artist:test 1", + ], + } + `); - ctx.expectUi().toMatchInlineSnapshot(` - { - "input": "forest, artist:test<>, safe", - "suggestions": [], - } - `); + await ctx.keyDown('Escape'); - await ctx.setInput('forest, t<>, safe'); - await ctx.keyDown('ArrowDown'); - await ctx.keyDown('Enter'); + ctx.expectUi().toMatchInlineSnapshot(` + { + "input": "forest, artist:test<>, safe", + "suggestions": [], + } + `); - ctx.expectUi().toMatchInlineSnapshot(` - { - "input": "forest, artist:test<>, safe", - "suggestions": [], - } - `); + await ctx.setInput('forest, t<>, safe'); + await ctx.keyDown('ArrowDown'); + await ctx.keyDown('Enter'); + + ctx.expectUi().toMatchInlineSnapshot(` + { + "input": "forest, artist:test<>, safe", + "suggestions": [], + } + `); + }); }); From c77a93b45597fec4c9b62f5c19e92ac0daa79c6a Mon Sep 17 00:00:00 2001 From: KoloMl <thekolomoets@hotmail.com> Date: Wed, 2 Apr 2025 05:06:18 +0400 Subject: [PATCH 2/9] Added the test case for the keydown event with empty code --- assets/js/autocomplete/__tests__/context.ts | 2 +- .../autocomplete/__tests__/keyboard.spec.ts | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/assets/js/autocomplete/__tests__/context.ts b/assets/js/autocomplete/__tests__/context.ts index 89e949eb..1e37cc02 100644 --- a/assets/js/autocomplete/__tests__/context.ts +++ b/assets/js/autocomplete/__tests__/context.ts @@ -146,7 +146,7 @@ export class TestContext { await vi.runAllTimersAsync(); } - async keyDown(code: string, params?: { ctrlKey?: boolean }) { + async keyDown(code: string, params?: { ctrlKey?: boolean; key?: string }) { fireEvent.keyDown(this.input, { code, ...(params ?? {}) }); await vi.runAllTimersAsync(); } diff --git a/assets/js/autocomplete/__tests__/keyboard.spec.ts b/assets/js/autocomplete/__tests__/keyboard.spec.ts index 86243430..3e135034 100644 --- a/assets/js/autocomplete/__tests__/keyboard.spec.ts +++ b/assets/js/autocomplete/__tests__/keyboard.spec.ts @@ -117,4 +117,30 @@ describe('Autocomplete keyboard navigation', () => { } `); }); + + it('should handle Enter key presses with empty code property', async () => { + await ctx.setInput('f'); + + ctx.expectUi().toMatchInlineSnapshot(` + { + "input": "f<>", + "suggestions": [ + "forest 3", + "force field 1", + "fog 1", + "flower 1", + ], + } + `); + + await ctx.keyDown('ArrowDown'); + await ctx.keyDown('', { key: 'Enter' }); + + ctx.expectUi().toMatchInlineSnapshot(` + { + "input": "forest<>", + "suggestions": [], + } + `); + }); }); From da81beec515d84c46a2d91d86aca471f3bb82bf5 Mon Sep 17 00:00:00 2001 From: KoloMl <thekolomoets@hotmail.com> Date: Wed, 2 Apr 2025 05:09:14 +0400 Subject: [PATCH 3/9] Fixed `Enter` key presses not being handled properly on Android devices --- assets/js/autocomplete/index.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/assets/js/autocomplete/index.ts b/assets/js/autocomplete/index.ts index 8bffa7d0..0acc4846 100644 --- a/assets/js/autocomplete/index.ts +++ b/assets/js/autocomplete/index.ts @@ -2,12 +2,12 @@ import { LocalAutocompleter } from '../utils/local-autocompleter'; import * as history from './history'; import { AutocompletableInput, TextInputElement } from './input'; import { - SuggestionsPopupComponent, - Suggestions, - TagSuggestionComponent, - Suggestion, HistorySuggestionComponent, ItemSelectedEvent, + Suggestion, + Suggestions, + SuggestionsPopupComponent, + TagSuggestionComponent, } from '../utils/suggestions-view'; import { prefixMatchParts } from '../utils/suggestions-model'; import { $$ } from '../utils/dom'; @@ -243,13 +243,21 @@ class Autocomplete { if (!this.isActive() || this.input.element !== event.target) { return; } - if ((event.key === ',' || event.code === 'Enter') && this.input.type === 'single-tag') { + + let keyCode = event.code; + + // Chrome & Firefox on Android devices return empty code when "Enter" is pressed. + if (!keyCode && event.key === 'Enter') { + keyCode = event.key; + } + + if ((event.key === ',' || keyCode === 'Enter') && this.input.type === 'single-tag') { // Comma/Enter mean the end of input for the current tag in single-tag mode. this.hidePopup(`The user accepted the existing input via key: '${event.key}', code: '${event.code}'`); return; } - switch (event.code) { + switch (keyCode) { case 'Enter': { const { selectedSuggestion } = this.popup; if (!selectedSuggestion) { From 8f6f9a78493511600c43f7c6787da351e488083b Mon Sep 17 00:00:00 2001 From: KoloMl <thekolomoets@hotmail.com> Date: Wed, 2 Apr 2025 17:11:10 +0400 Subject: [PATCH 4/9] Uninstalled `eslint-plugin-vitest` Looks like package was renamed in NPM registry to `@vitest/eslint-plugin`. This package is from same exact repository. --- assets/package-lock.json | 158 --------------------------------------- assets/package.json | 1 - 2 files changed, 159 deletions(-) diff --git a/assets/package-lock.json b/assets/package-lock.json index 52ea697b..87a739e1 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -22,7 +22,6 @@ "@testing-library/jest-dom": "^6.6.3", "@vitest/coverage-v8": "^2.1.9", "eslint": "^9.16.0", - "eslint-plugin-vitest": "^0.5.4", "stylelint": "^16.11.0", "stylelint-config-standard": "^36.0.1", "typescript-eslint": "8.17.0", @@ -2501,163 +2500,6 @@ } } }, - "node_modules/eslint-plugin-vitest": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-vitest/-/eslint-plugin-vitest-0.5.4.tgz", - "integrity": "sha512-um+odCkccAHU53WdKAw39MY61+1x990uXjSPguUCq3VcEHdqJrOb8OTMrbYlY6f9jAKx7x98kLVlIe3RJeJqoQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^7.7.1" - }, - "engines": { - "node": "^18.0.0 || >= 20.0.0" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "vitest": "*" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "vitest": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-plugin-vitest/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/eslint-plugin-vitest/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-vitest/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/eslint-scope": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", diff --git a/assets/package.json b/assets/package.json index a2cf1ae2..3d8a9d68 100644 --- a/assets/package.json +++ b/assets/package.json @@ -27,7 +27,6 @@ "@testing-library/jest-dom": "^6.6.3", "@vitest/coverage-v8": "^2.1.9", "eslint": "^9.16.0", - "eslint-plugin-vitest": "^0.5.4", "stylelint": "^16.11.0", "stylelint-config-standard": "^36.0.1", "typescript-eslint": "8.17.0", From 0a55ed93d24e7317cbf2a7f2768d4a96765eab12 Mon Sep 17 00:00:00 2001 From: KoloMl <thekolomoets@hotmail.com> Date: Wed, 2 Apr 2025 17:17:15 +0400 Subject: [PATCH 5/9] Bumped `typescript-eslint` from 8.17.0 to 8.29.0 Resolves issue with conflicting dependencies when trying to install `@vitest/eslint-plugin`: npm error Could not resolve dependency: npm error dev @vitest/eslint-plugin@"*" from the root project npm error npm error Conflicting peer dependency: @typescript-eslint/utils@8.29.0 npm error node_modules/@typescript-eslint/utils npm error peer @typescript-eslint/utils@"^8.24.0" from @vitest/eslint-plugin@1.1.38 npm error node_modules/@vitest/eslint-plugin npm error dev @vitest/eslint-plugin@"*" from the root project --- assets/package-lock.json | 160 +++++++++++++++++---------------------- assets/package.json | 2 +- 2 files changed, 70 insertions(+), 92 deletions(-) diff --git a/assets/package-lock.json b/assets/package-lock.json index 87a739e1..5c47b98e 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -24,7 +24,7 @@ "eslint": "^9.16.0", "stylelint": "^16.11.0", "stylelint-config-standard": "^36.0.1", - "typescript-eslint": "8.17.0", + "typescript-eslint": "8.29.0", "vitest": "^2.1.9", "vitest-fetch-mock": "^0.4.2" } @@ -1442,20 +1442,20 @@ "integrity": "sha512-jxXqkf4sBn/WV9YsOlB5fFzWo9kGafMDF62VmVC1mFF367BuRn/2txr0ZaEchPsNIvyiLckMpxO6Xz3knpC6Nw==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.17.0.tgz", - "integrity": "sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.29.0.tgz", + "integrity": "sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.17.0", - "@typescript-eslint/type-utils": "8.17.0", - "@typescript-eslint/utils": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0", + "@typescript-eslint/scope-manager": "8.29.0", + "@typescript-eslint/type-utils": "8.29.0", + "@typescript-eslint/utils": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1466,24 +1466,20 @@ }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.17.0.tgz", - "integrity": "sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.29.0.tgz", + "integrity": "sha512-8C0+jlNJOwQso2GapCVWWfW/rzaq7Lbme+vGUFKE31djwNncIpgXD7Cd4weEsDdkoZDjH0lwwr3QDQFuyrMg9g==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.17.0", - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/typescript-estree": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0", + "@typescript-eslint/scope-manager": "8.29.0", + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/typescript-estree": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0", "debug": "^4.3.4" }, "engines": { @@ -1494,22 +1490,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.17.0.tgz", - "integrity": "sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.29.0.tgz", + "integrity": "sha512-aO1PVsq7Gm+tcghabUpzEnVSFMCU4/nYIgC2GOatJcllvWfnhrgW0ZEbnTxm36QsikmCN1K/6ZgM7fok2I7xNw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0" + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1520,15 +1512,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.17.0.tgz", - "integrity": "sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.29.0.tgz", + "integrity": "sha512-ahaWQ42JAOx+NKEf5++WC/ua17q5l+j1GFrbbpVKzFL/tKVc0aYY8rVSYUpUvt2hUP1YBr7mwXzx+E/DfUWI9Q==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.17.0", - "@typescript-eslint/utils": "8.17.0", + "@typescript-eslint/typescript-estree": "8.29.0", + "@typescript-eslint/utils": "8.29.0", "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1538,18 +1530,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.17.0.tgz", - "integrity": "sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.0.tgz", + "integrity": "sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1560,19 +1548,19 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.17.0.tgz", - "integrity": "sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.29.0.tgz", + "integrity": "sha512-yOfen3jE9ISZR/hHpU/bmNvTtBW1NjRbkSFdZOksL1N+ybPEE7UVGMwqvS6CP022Rp00Sb0tdiIkhSCe6NI8ow==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/visitor-keys": "8.17.0", + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1581,10 +1569,8 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { @@ -1612,15 +1598,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.17.0.tgz", - "integrity": "sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.29.0.tgz", + "integrity": "sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.17.0", - "@typescript-eslint/types": "8.17.0", - "@typescript-eslint/typescript-estree": "8.17.0" + "@typescript-eslint/scope-manager": "8.29.0", + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/typescript-estree": "8.29.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1630,21 +1616,17 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.17.0.tgz", - "integrity": "sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.29.0.tgz", + "integrity": "sha512-Sne/pVz8ryR03NFK21VpN88dZ2FdQXOlq3VIklbrTYEt8yXtRFr9tvUhqvCeKjqYk5FSim37sHbooT6vzBTZcg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.17.0", + "@typescript-eslint/types": "8.29.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -4700,15 +4682,15 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/type-check": { @@ -4736,14 +4718,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.17.0.tgz", - "integrity": "sha512-409VXvFd/f1br1DCbuKNFqQpXICoTB+V51afcwG1pn1a3Cp92MqAUges3YjwEdQ0cMUoCIodjVDAYzyD8h3SYA==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.29.0.tgz", + "integrity": "sha512-ep9rVd9B4kQsZ7ZnWCVxUE/xDLUUUsRzE0poAeNu+4CkFErLfuvPt/qtm2EpnSyfvsR0S6QzDFSrPCFBwf64fg==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "8.17.0", - "@typescript-eslint/parser": "8.17.0", - "@typescript-eslint/utils": "8.17.0" + "@typescript-eslint/eslint-plugin": "8.29.0", + "@typescript-eslint/parser": "8.29.0", + "@typescript-eslint/utils": "8.29.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4753,12 +4735,8 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/undici-types": { diff --git a/assets/package.json b/assets/package.json index 3d8a9d68..5e4013dd 100644 --- a/assets/package.json +++ b/assets/package.json @@ -29,7 +29,7 @@ "eslint": "^9.16.0", "stylelint": "^16.11.0", "stylelint-config-standard": "^36.0.1", - "typescript-eslint": "8.17.0", + "typescript-eslint": "8.29.0", "vitest": "^2.1.9", "vitest-fetch-mock": "^0.4.2" } From 7216afa7838fc5da0ca439be3afe756517fac33a Mon Sep 17 00:00:00 2001 From: KoloMl <thekolomoets@hotmail.com> Date: Wed, 2 Apr 2025 17:19:23 +0400 Subject: [PATCH 6/9] Installed `@vitest/eslint-plugin` 1.1.38 --- assets/package-lock.json | 22 ++++++++++++++++++++++ assets/package.json | 1 + 2 files changed, 23 insertions(+) diff --git a/assets/package-lock.json b/assets/package-lock.json index 5c47b98e..4e82d090 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -21,6 +21,7 @@ "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@vitest/coverage-v8": "^2.1.9", + "@vitest/eslint-plugin": "^1.1.38", "eslint": "^9.16.0", "stylelint": "^16.11.0", "stylelint-config-standard": "^36.0.1", @@ -1670,6 +1671,27 @@ } } }, + "node_modules/@vitest/eslint-plugin": { + "version": "1.1.38", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.1.38.tgz", + "integrity": "sha512-KcOTZyVz8RiM5HyriiDVrP1CyBGuhRxle+lBsmSs6NTJEO/8dKVAq+f5vQzHj1/Kc7bYXSDO6yBe62Zx0t5iaw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@typescript-eslint/utils": "^8.24.0", + "eslint": ">= 8.57.0", + "typescript": ">= 5.0.0", + "vitest": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vitest": { + "optional": true + } + } + }, "node_modules/@vitest/expect": { "version": "2.1.9", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", diff --git a/assets/package.json b/assets/package.json index 5e4013dd..1477cd88 100644 --- a/assets/package.json +++ b/assets/package.json @@ -26,6 +26,7 @@ "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@vitest/coverage-v8": "^2.1.9", + "@vitest/eslint-plugin": "^1.1.38", "eslint": "^9.16.0", "stylelint": "^16.11.0", "stylelint-config-standard": "^36.0.1", From 5d76b5d9f11e3cea89a53bfb54473bc953565496 Mon Sep 17 00:00:00 2001 From: KoloMl <thekolomoets@hotmail.com> Date: Wed, 2 Apr 2025 17:21:52 +0400 Subject: [PATCH 7/9] Replaced import from `eslint-plugin-vitest` to `@vitest/eslint-plugin` --- assets/eslint.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/eslint.config.js b/assets/eslint.config.js index 51cc1e26..c39019e8 100644 --- a/assets/eslint.config.js +++ b/assets/eslint.config.js @@ -1,5 +1,5 @@ import tsEslint from 'typescript-eslint'; -import vitestPlugin from 'eslint-plugin-vitest'; +import vitestPlugin from '@vitest/eslint-plugin'; import globals from 'globals'; export default tsEslint.config( From e68d7c3e1c9943edc76db00c3c07b4b201501c05 Mon Sep 17 00:00:00 2001 From: KoloMl <thekolomoets@hotmail.com> Date: Wed, 2 Apr 2025 17:33:55 +0400 Subject: [PATCH 8/9] Moved `init()` directly to the `describe` block As suggested by @MareStare --- assets/js/autocomplete/__tests__/keyboard.spec.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/assets/js/autocomplete/__tests__/keyboard.spec.ts b/assets/js/autocomplete/__tests__/keyboard.spec.ts index 3e135034..0eab9d02 100644 --- a/assets/js/autocomplete/__tests__/keyboard.spec.ts +++ b/assets/js/autocomplete/__tests__/keyboard.spec.ts @@ -1,11 +1,7 @@ import { init, TestContext } from './context'; -describe('Autocomplete keyboard navigation', () => { - let ctx: TestContext; - - beforeAll(async () => { - ctx = await init(); - }); +describe('Autocomplete keyboard navigation', async () => { + const ctx: TestContext = await init(); it('supports navigation via keyboard', async () => { await ctx.setInput('f'); From b69f7a3f17f1e8825cb6b3235307ecac6d1234ad Mon Sep 17 00:00:00 2001 From: KoloMl <thekolomoets@hotmail.com> Date: Wed, 2 Apr 2025 18:20:48 +0400 Subject: [PATCH 9/9] Revert "Moved `init()` directly to the `describe` block" This reverts commit e68d7c3e1c9943edc76db00c3c07b4b201501c05. --- assets/js/autocomplete/__tests__/keyboard.spec.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/assets/js/autocomplete/__tests__/keyboard.spec.ts b/assets/js/autocomplete/__tests__/keyboard.spec.ts index 0eab9d02..3e135034 100644 --- a/assets/js/autocomplete/__tests__/keyboard.spec.ts +++ b/assets/js/autocomplete/__tests__/keyboard.spec.ts @@ -1,7 +1,11 @@ import { init, TestContext } from './context'; -describe('Autocomplete keyboard navigation', async () => { - const ctx: TestContext = await init(); +describe('Autocomplete keyboard navigation', () => { + let ctx: TestContext; + + beforeAll(async () => { + ctx = await init(); + }); it('supports navigation via keyboard', async () => { await ctx.setInput('f');