From 56436608067d56acf5a421e2301dc70d0483fc6f Mon Sep 17 00:00:00 2001 From: David Joseph Guzsik Date: Wed, 1 May 2024 00:20:14 +0200 Subject: [PATCH] Eliminate chai-dom and restore @testing-library/jest-dom (#244) --- assets/js/utils/__tests__/dom.spec.ts | 84 ++-- assets/js/utils/__tests__/draggable.spec.ts | 24 +- assets/js/utils/__tests__/image.spec.ts | 68 +-- assets/package-lock.json | 507 +++++++++++--------- assets/package.json | 3 +- assets/test/vitest-setup.ts | 5 +- 6 files changed, 368 insertions(+), 323 deletions(-) diff --git a/assets/js/utils/__tests__/dom.spec.ts b/assets/js/utils/__tests__/dom.spec.ts index 51207776..a1bb03eb 100644 --- a/assets/js/utils/__tests__/dom.spec.ts +++ b/assets/js/utils/__tests__/dom.spec.ts @@ -83,7 +83,7 @@ describe('DOM Utilities', () => { it(`should remove the ${hiddenClass} class from the provided element`, () => { const mockElement = createHiddenElement('div'); showEl(mockElement); - expect(mockElement).not.to.have.class(hiddenClass); + expect(mockElement).not.toHaveClass(hiddenClass); }); it(`should remove the ${hiddenClass} class from all provided elements`, () => { @@ -93,9 +93,9 @@ describe('DOM Utilities', () => { createHiddenElement('strong'), ]; showEl(mockElements); - expect(mockElements[0]).not.to.have.class(hiddenClass); - expect(mockElements[1]).not.to.have.class(hiddenClass); - expect(mockElements[2]).not.to.have.class(hiddenClass); + expect(mockElements[0]).not.toHaveClass(hiddenClass); + expect(mockElements[1]).not.toHaveClass(hiddenClass); + expect(mockElements[2]).not.toHaveClass(hiddenClass); }); it(`should remove the ${hiddenClass} class from elements provided in multiple arrays`, () => { @@ -108,10 +108,10 @@ describe('DOM Utilities', () => { createHiddenElement('em'), ]; showEl(mockElements1, mockElements2); - expect(mockElements1[0]).not.to.have.class(hiddenClass); - expect(mockElements1[1]).not.to.have.class(hiddenClass); - expect(mockElements2[0]).not.to.have.class(hiddenClass); - expect(mockElements2[1]).not.to.have.class(hiddenClass); + expect(mockElements1[0]).not.toHaveClass(hiddenClass); + expect(mockElements1[1]).not.toHaveClass(hiddenClass); + expect(mockElements2[0]).not.toHaveClass(hiddenClass); + expect(mockElements2[1]).not.toHaveClass(hiddenClass); }); }); @@ -119,7 +119,7 @@ describe('DOM Utilities', () => { it(`should add the ${hiddenClass} class to the provided element`, () => { const mockElement = document.createElement('div'); hideEl(mockElement); - expect(mockElement).to.have.class(hiddenClass); + expect(mockElement).toHaveClass(hiddenClass); }); it(`should add the ${hiddenClass} class to all provided elements`, () => { @@ -129,9 +129,9 @@ describe('DOM Utilities', () => { document.createElement('strong'), ]; hideEl(mockElements); - expect(mockElements[0]).to.have.class(hiddenClass); - expect(mockElements[1]).to.have.class(hiddenClass); - expect(mockElements[2]).to.have.class(hiddenClass); + expect(mockElements[0]).toHaveClass(hiddenClass); + expect(mockElements[1]).toHaveClass(hiddenClass); + expect(mockElements[2]).toHaveClass(hiddenClass); }); it(`should add the ${hiddenClass} class to elements provided in multiple arrays`, () => { @@ -144,10 +144,10 @@ describe('DOM Utilities', () => { document.createElement('em'), ]; hideEl(mockElements1, mockElements2); - expect(mockElements1[0]).to.have.class(hiddenClass); - expect(mockElements1[1]).to.have.class(hiddenClass); - expect(mockElements2[0]).to.have.class(hiddenClass); - expect(mockElements2[1]).to.have.class(hiddenClass); + expect(mockElements1[0]).toHaveClass(hiddenClass); + expect(mockElements1[1]).toHaveClass(hiddenClass); + expect(mockElements2[0]).toHaveClass(hiddenClass); + expect(mockElements2[1]).toHaveClass(hiddenClass); }); }); @@ -155,7 +155,7 @@ describe('DOM Utilities', () => { it('should set the disabled attribute to true', () => { const mockElement = document.createElement('button'); disableEl(mockElement); - expect(mockElement).to.have.property('disabled', true); + expect(mockElement).toBeDisabled(); }); it('should set the disabled attribute to true on all provided elements', () => { @@ -164,8 +164,8 @@ describe('DOM Utilities', () => { document.createElement('button'), ]; disableEl(mockElements); - expect(mockElements[0]).to.have.property('disabled', true); - expect(mockElements[1]).to.have.property('disabled', true); + expect(mockElements[0]).toBeDisabled(); + expect(mockElements[1]).toBeDisabled(); }); it('should set the disabled attribute to true on elements provided in multiple arrays', () => { @@ -178,10 +178,10 @@ describe('DOM Utilities', () => { document.createElement('button'), ]; disableEl(mockElements1, mockElements2); - expect(mockElements1[0]).to.have.property('disabled', true); - expect(mockElements1[1]).to.have.property('disabled', true); - expect(mockElements2[0]).to.have.property('disabled', true); - expect(mockElements2[1]).to.have.property('disabled', true); + expect(mockElements1[0]).toBeDisabled(); + expect(mockElements1[1]).toBeDisabled(); + expect(mockElements2[0]).toBeDisabled(); + expect(mockElements2[1]).toBeDisabled(); }); }); @@ -189,7 +189,7 @@ describe('DOM Utilities', () => { it('should set the disabled attribute to false', () => { const mockElement = document.createElement('button'); enableEl(mockElement); - expect(mockElement).to.have.property('disabled', false); + expect(mockElement).toBeEnabled(); }); it('should set the disabled attribute to false on all provided elements', () => { @@ -198,8 +198,8 @@ describe('DOM Utilities', () => { document.createElement('button'), ]; enableEl(mockElements); - expect(mockElements[0]).to.have.property('disabled', false); - expect(mockElements[1]).to.have.property('disabled', false); + expect(mockElements[0]).toBeEnabled(); + expect(mockElements[1]).toBeEnabled(); }); it('should set the disabled attribute to false on elements provided in multiple arrays', () => { @@ -212,10 +212,10 @@ describe('DOM Utilities', () => { document.createElement('button'), ]; enableEl(mockElements1, mockElements2); - expect(mockElements1[0]).to.have.property('disabled', false); - expect(mockElements1[1]).to.have.property('disabled', false); - expect(mockElements2[0]).to.have.property('disabled', false); - expect(mockElements2[1]).to.have.property('disabled', false); + expect(mockElements1[0]).toBeEnabled(); + expect(mockElements1[1]).toBeEnabled(); + expect(mockElements2[0]).toBeEnabled(); + expect(mockElements2[1]).toBeEnabled(); }); }); @@ -223,11 +223,11 @@ describe('DOM Utilities', () => { it(`should toggle the ${hiddenClass} class on the provided element`, () => { const mockVisibleElement = document.createElement('div'); toggleEl(mockVisibleElement); - expect(mockVisibleElement).to.have.class(hiddenClass); + expect(mockVisibleElement).toHaveClass(hiddenClass); const mockHiddenElement = createHiddenElement('div'); toggleEl(mockHiddenElement); - expect(mockHiddenElement).not.to.have.class(hiddenClass); + expect(mockHiddenElement).not.toHaveClass(hiddenClass); }); it(`should toggle the ${hiddenClass} class on all provided elements`, () => { @@ -238,10 +238,10 @@ describe('DOM Utilities', () => { createHiddenElement('em'), ]; toggleEl(mockElements); - expect(mockElements[0]).to.have.class(hiddenClass); - expect(mockElements[1]).not.to.have.class(hiddenClass); - expect(mockElements[2]).to.have.class(hiddenClass); - expect(mockElements[3]).not.to.have.class(hiddenClass); + expect(mockElements[0]).toHaveClass(hiddenClass); + expect(mockElements[1]).not.toHaveClass(hiddenClass); + expect(mockElements[2]).toHaveClass(hiddenClass); + expect(mockElements[3]).not.toHaveClass(hiddenClass); }); it(`should toggle the ${hiddenClass} class on elements provided in multiple arrays`, () => { @@ -254,10 +254,10 @@ describe('DOM Utilities', () => { document.createElement('em'), ]; toggleEl(mockElements1, mockElements2); - expect(mockElements1[0]).not.to.have.class(hiddenClass); - expect(mockElements1[1]).to.have.class(hiddenClass); - expect(mockElements2[0]).not.to.have.class(hiddenClass); - expect(mockElements2[1]).to.have.class(hiddenClass); + expect(mockElements1[0]).not.toHaveClass(hiddenClass); + expect(mockElements1[1]).toHaveClass(hiddenClass); + expect(mockElements2[0]).not.toHaveClass(hiddenClass); + expect(mockElements2[1]).toHaveClass(hiddenClass); }); }); @@ -361,8 +361,8 @@ describe('DOM Utilities', () => { const mockClassTwo = 'class-two'; const el = makeEl('p', { className: `${mockClassOne} ${mockClassTwo}` }); expect(el.nodeName).toEqual('P'); - expect(el).to.have.class(mockClassOne); - expect(el).to.have.class(mockClassTwo); + expect(el).toHaveClass(mockClassOne); + expect(el).toHaveClass(mockClassTwo); }); }); diff --git a/assets/js/utils/__tests__/draggable.spec.ts b/assets/js/utils/__tests__/draggable.spec.ts index 835a4d24..e9e3daad 100644 --- a/assets/js/utils/__tests__/draggable.spec.ts +++ b/assets/js/utils/__tests__/draggable.spec.ts @@ -63,7 +63,7 @@ describe('Draggable Utilities', () => { fireEvent(mockDraggable, mockEvent); - expect(mockDraggable).to.have.class(draggingClass); + expect(mockDraggable).toHaveClass(draggingClass); }); it('should add dummy data to the dragstart event if it\'s empty', () => { @@ -146,7 +146,7 @@ describe('Draggable Utilities', () => { fireEvent(mockDraggable, mockEvent); - expect(mockDraggable).to.have.class(dragOverClass); + expect(mockDraggable).toHaveClass(dragOverClass); }); }); @@ -159,7 +159,7 @@ describe('Draggable Utilities', () => { fireEvent(mockDraggable, mockEvent); - expect(mockDraggable).not.to.have.class(dragOverClass); + expect(mockDraggable).not.toHaveClass(dragOverClass); }); }); @@ -170,13 +170,13 @@ describe('Draggable Utilities', () => { const mockStartEvent = createDragEvent('dragstart'); fireEvent(mockDraggable, mockStartEvent); - expect(mockDraggable).to.have.class(draggingClass); + expect(mockDraggable).toHaveClass(draggingClass); const mockDropEvent = createDragEvent('drop'); fireEvent(mockDraggable, mockDropEvent); expect(mockDropEvent.defaultPrevented).toBe(true); - expect(mockDraggable).not.to.have.class(draggingClass); + expect(mockDraggable).not.toHaveClass(draggingClass); }); it('should cancel the event and insert source before target if dropped on left side', () => { @@ -188,7 +188,7 @@ describe('Draggable Utilities', () => { const mockStartEvent = createDragEvent('dragstart'); fireEvent(mockSecondDraggable, mockStartEvent); - expect(mockSecondDraggable).to.have.class(draggingClass); + expect(mockSecondDraggable).toHaveClass(draggingClass); const mockDropEvent = createDragEvent('drop'); Object.assign(mockDropEvent, { clientX: 124 }); @@ -200,7 +200,7 @@ describe('Draggable Utilities', () => { try { expect(mockDropEvent.defaultPrevented).toBe(true); - expect(mockSecondDraggable).not.to.have.class(draggingClass); + expect(mockSecondDraggable).not.toHaveClass(draggingClass); expect(mockSecondDraggable.nextElementSibling).toBe(mockDraggable); } finally { @@ -217,7 +217,7 @@ describe('Draggable Utilities', () => { const mockStartEvent = createDragEvent('dragstart'); fireEvent(mockSecondDraggable, mockStartEvent); - expect(mockSecondDraggable).to.have.class(draggingClass); + expect(mockSecondDraggable).toHaveClass(draggingClass); const mockDropEvent = createDragEvent('drop'); Object.assign(mockDropEvent, { clientX: 125 }); @@ -229,7 +229,7 @@ describe('Draggable Utilities', () => { try { expect(mockDropEvent.defaultPrevented).toBe(true); - expect(mockSecondDraggable).not.to.have.class(draggingClass); + expect(mockSecondDraggable).not.toHaveClass(draggingClass); expect(mockDraggable.nextElementSibling).toBe(mockSecondDraggable); } finally { @@ -259,7 +259,7 @@ describe('Draggable Utilities', () => { const mockStartEvent = createDragEvent('dragstart'); fireEvent(mockDraggable, mockStartEvent); - expect(mockDraggable).to.have.class(draggingClass); + expect(mockDraggable).toHaveClass(draggingClass); const mockOverElement = createDraggableElement(); mockOverElement.classList.add(dragOverClass); @@ -270,8 +270,8 @@ describe('Draggable Utilities', () => { const mockDropEvent = createDragEvent('dragend'); fireEvent(mockDraggable, mockDropEvent); - expect(mockDraggable).not.to.have.class(draggingClass); - expect(mockOverElement).not.to.have.class(dragOverClass); + expect(mockDraggable).not.toHaveClass(draggingClass); + expect(mockOverElement).not.toHaveClass(dragOverClass); }); }); diff --git a/assets/js/utils/__tests__/image.spec.ts b/assets/js/utils/__tests__/image.spec.ts index fb43b52f..b091380d 100644 --- a/assets/js/utils/__tests__/image.spec.ts +++ b/assets/js/utils/__tests__/image.spec.ts @@ -146,7 +146,7 @@ describe('Image utils', () => { const result = showThumb(mockElement); - expect(mockImage).to.have.class(hiddenClass); + expect(mockImage).toHaveClass(hiddenClass); expect(mockVideo.children).toHaveLength(2); const webmSourceElement = mockVideo.children[0]; @@ -160,10 +160,10 @@ describe('Image utils', () => { expect(mp4SourceElement.getAttribute('type')).toEqual('video/mp4'); expect(mp4SourceElement.getAttribute('src')).toEqual(webmSource.replace('webm', 'mp4')); - expect(mockVideo).not.to.have.class(hiddenClass); + expect(mockVideo).not.toHaveClass(hiddenClass); expect(playSpy).toHaveBeenCalledTimes(1); - expect(mockSpoilerOverlay).to.have.class(hiddenClass); + expect(mockSpoilerOverlay).toHaveClass(hiddenClass); expect(result).toBe(true); }); @@ -238,7 +238,7 @@ describe('Image utils', () => { expect(mockSizeImage.src).toBe(mockSizeUrls[mockSize]); expect(mockSizeImage.srcset).toBe(''); - expect(mockSpoilerOverlay).to.have.class(hiddenClass); + expect(mockSpoilerOverlay).toHaveClass(hiddenClass); expect(result).toBe(true); }); @@ -255,7 +255,7 @@ describe('Image utils', () => { expect(mockSizeImage.src).toBe(mockSizeUrls[mockSize]); expect(mockSizeImage.srcset).toBe(''); - expect(mockSpoilerOverlay).to.have.class(hiddenClass); + expect(mockSpoilerOverlay).toHaveClass(hiddenClass); expect(result).toBe(true); }); @@ -272,8 +272,8 @@ describe('Image utils', () => { expect(mockSizeImage.src).toBe(mockSizeUrls[mockSize].replace('webm', 'gif')); expect(mockSizeImage.srcset).toBe(''); - expect(mockSpoilerOverlay).not.to.have.class(hiddenClass); - expect(mockSpoilerOverlay).to.have.text('WebM'); + expect(mockSpoilerOverlay).not.toHaveClass(hiddenClass); + expect(mockSpoilerOverlay).toHaveTextContent('WebM'); expect(result).toBe(true); }); @@ -296,7 +296,7 @@ describe('Image utils', () => { expect(mockSizeImage.srcset).toContain(`${mockSizeUrls[size]} 1x`); expect(mockSizeImage.srcset).toContain(`${mockSizeUrls[x2size]} 2x`); - expect(mockSpoilerOverlay).to.have.class(hiddenClass); + expect(mockSpoilerOverlay).toHaveClass(hiddenClass); return result; }; @@ -323,7 +323,7 @@ describe('Image utils', () => { expect(mockSizeImage.src).toBe(mockSizeUrls[mockSize]); expect(mockSizeImage.srcset).toBe(''); - expect(mockSpoilerOverlay).to.have.class(hiddenClass); + expect(mockSpoilerOverlay).toHaveClass(hiddenClass); expect(result).toBe(true); }); }); @@ -364,9 +364,9 @@ describe('Image utils', () => { showBlock(mockElement); - expect(mockFilteredImageElement).to.have.class(hiddenClass); - expect(mockShowElement).not.to.have.class(hiddenClass); - expect(mockShowElement).to.have.class(spoilerPendingClass); + expect(mockFilteredImageElement).toHaveClass(hiddenClass); + expect(mockShowElement).not.toHaveClass(hiddenClass); + expect(mockShowElement).toHaveClass(spoilerPendingClass); }); it('should not throw if image-filtered element is missing', () => { @@ -416,7 +416,7 @@ describe('Image utils', () => { expect(querySelectorSpy).toHaveBeenNthCalledWith(2, 'video'); expect(querySelectorSpy).toHaveBeenNthCalledWith(3, 'img'); expect(querySelectorSpy).toHaveBeenNthCalledWith(4, `.${spoilerOverlayClass}`); - expect(mockVideo).not.to.have.class(hiddenClass); + expect(mockVideo).not.toHaveClass(hiddenClass); } finally { querySelectorSpy.mockRestore(); @@ -439,11 +439,11 @@ describe('Image utils', () => { hideThumb(mockElement, mockSpoilerUri, mockSpoilerReason); try { - expect(mockImage).not.to.have.class(hiddenClass); - expect(mockImage).to.have.attribute('src', mockSpoilerUri); - expect(mockOverlay).to.have.text(mockSpoilerReason); - expect(mockVideo).not.to.have.descendants('*'); - expect(mockVideo).to.have.class(hiddenClass); + expect(mockImage).not.toHaveClass(hiddenClass); + expect(mockImage).toHaveAttribute('src', mockSpoilerUri); + expect(mockOverlay).toHaveTextContent(mockSpoilerReason); + expect(mockVideo).toBeEmptyDOMElement(); + expect(mockVideo).toHaveClass(hiddenClass); expect(pauseSpy).toHaveBeenCalled(); } finally { @@ -488,10 +488,10 @@ describe('Image utils', () => { hideThumb(mockElement, mockSpoilerUri, mockSpoilerReason); - expect(mockImage).to.have.attribute('srcset', ''); - expect(mockImage).to.have.attribute('src', mockSpoilerUri); - expect(mockOverlay).to.contain.html(mockSpoilerReason); - expect(mockOverlay).not.to.have.class(hiddenClass); + expect(mockImage).toHaveAttribute('srcset', ''); + expect(mockImage).toHaveAttribute('src', mockSpoilerUri); + expect(mockOverlay).toContainHTML(mockSpoilerReason); + expect(mockOverlay).not.toHaveClass(hiddenClass); }); }); @@ -503,9 +503,9 @@ describe('Image utils', () => { spoilerThumb(mockElement, mockSpoilerUri, mockSpoilerReason); // Element should be hidden by the call - expect(mockSizeImage).to.have.attribute('src', mockSpoilerUri); - expect(mockSpoilerOverlay).not.to.have.class(hiddenClass); - expect(mockSpoilerOverlay).to.contain.html(mockSpoilerReason); + expect(mockSizeImage).toHaveAttribute('src', mockSpoilerUri); + expect(mockSpoilerOverlay).not.toHaveClass(hiddenClass); + expect(mockSpoilerOverlay).toContainHTML(mockSpoilerReason); // If addEventListener calls are not expected, bail if (!handlers) { @@ -526,8 +526,8 @@ describe('Image utils', () => { if (firstHandler === 'click') { expect(clickEvent.defaultPrevented).toBe(true); } - expect(mockSizeImage).not.to.have.attribute('src', mockSpoilerUri); - expect(mockSpoilerOverlay).to.have.class(hiddenClass); + expect(mockSizeImage).not.toHaveAttribute('src', mockSpoilerUri); + expect(mockSpoilerOverlay).toHaveClass(hiddenClass); if (firstHandler === 'click') { // Second attempt to click a shown spoiler should not cause default prevention @@ -539,9 +539,9 @@ describe('Image utils', () => { // Moving the mouse away should hide the image and show the overlay again const mouseLeaveEvent = createEvent.mouseLeave(mockElement); fireEvent(mockElement, mouseLeaveEvent); - expect(mockSizeImage).to.have.attribute('src', mockSpoilerUri); - expect(mockSpoilerOverlay).not.to.have.class(hiddenClass); - expect(mockSpoilerOverlay).to.contain.html(mockSpoilerReason); + expect(mockSizeImage).toHaveAttribute('src', mockSpoilerUri); + expect(mockSpoilerOverlay).not.toHaveClass(hiddenClass); + expect(mockSpoilerOverlay).toContainHTML(mockSpoilerReason); }; let lastSpoilerType: SpoilerType; @@ -618,10 +618,10 @@ describe('Image utils', () => { spoilerBlock(mockElement, mockSpoilerUri, mockSpoilerReason); - expect(mockImage).to.have.attribute('src', mockSpoilerUri); - expect(mockExplanation).to.contain.html(mockSpoilerReason); - expect(mockImageShow).to.have.class(hiddenClass); - expect(mockImageFiltered).not.to.have.class(hiddenClass); + expect(mockImage).toHaveAttribute('src', mockSpoilerUri); + expect(mockExplanation).toContainHTML(mockSpoilerReason); + expect(mockImageShow).toHaveClass(hiddenClass); + expect(mockImageFiltered).not.toHaveClass(hiddenClass); }); it('should not throw if image-filtered element is missing', () => { diff --git a/assets/package-lock.json b/assets/package-lock.json index 2dae097a..bdd7c28a 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -20,16 +20,22 @@ }, "devDependencies": { "@testing-library/dom": "^10.1.0", + "@testing-library/jest-dom": "^6.4.2", "@types/chai-dom": "^1.11.3", "@vitest/coverage-v8": "^1.5.3", - "c8": "^9.1.0", - "chai-dom": "^1.12.0", + "chai": "^5", "eslint-plugin-vitest": "^0.5.4", "jsdom": "^24.0.0", "vitest": "^1.5.3", "vitest-fetch-mock": "^0.2.2" } }, + "node_modules/@adobe/css-tools": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", + "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", + "dev": true + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -1048,6 +1054,70 @@ "node": ">=18" } }, + "node_modules/@testing-library/jest-dom": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.2.tgz", + "integrity": "sha512-CzqH0AFymEMG48CpzXFriYYkOjk6ZGPCLMhW9e9jg3KMCn5OfJecF8GtGW7yGfR/IgCe3SX8BSwjdzI6BBbZLw==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.3.2", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + }, + "peerDependencies": { + "@jest/globals": ">= 28", + "@types/bun": "latest", + "@types/jest": ">= 28", + "jest": ">= 28", + "vitest": ">= 0.32" + }, + "peerDependenciesMeta": { + "@jest/globals": { + "optional": true + }, + "@types/bun": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "jest": { + "optional": true + }, + "vitest": { + "optional": true + } + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -1387,6 +1457,66 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/expect/node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/@vitest/expect/node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@vitest/expect/node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@vitest/expect/node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@vitest/expect/node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/@vitest/runner": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.5.3.tgz", @@ -1659,12 +1789,12 @@ } }, "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "engines": { - "node": "*" + "node": ">=12" } }, "node_modules/asynckit": { @@ -1774,31 +1904,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/c8": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-9.1.0.tgz", - "integrity": "sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^3.1.1", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.1.6", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.0.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=14.14.0" - } - }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -1836,33 +1941,28 @@ ] }, "node_modules/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.0.tgz", + "integrity": "sha512-kDZ7MZyM6Q1DhR9jy7dalKohXQ2yrlXkk59CR52aRKxJrobmlBNqnFQxX9xOX8w+4mz8SYlKJa/7D7ddltFXCw==", "dev": true, "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" + "assertion-error": "^2.0.1", + "check-error": "^2.0.0", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/chai-dom": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/chai-dom/-/chai-dom-1.12.0.tgz", - "integrity": "sha512-pLP8h6IBR8z1AdeQ+EMcJ7dXPdsax/1Q7gdGZjsnAmSBl3/gItQUYSCo32br1qOy4SlcBjvqId7ilAf3uJ2K1w==", + "node_modules/chai/node_modules/loupe": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.0.tgz", + "integrity": "sha512-qKl+FrLXUhFuHUoDJG7f8P8gEMHq9NFS0c6ghXG1J0rldmZFQZoNVv/vyirE9qwCIhWZDsvEFd1sbFu3GvRQFg==", "dev": true, - "engines": { - "node": ">= 0.12.0" - }, - "peerDependencies": { - "chai": ">= 3" + "dependencies": { + "get-func-name": "^2.0.1" } }, "node_modules/chalk": { @@ -1881,15 +1981,12 @@ } }, "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.0.0.tgz", + "integrity": "sha512-tjLAOBHKVxtPoHe/SA7kNOMvhCRdCJ3vETdeY0RuAc9popf+hyaSV6ZEg9hr4cpWF7jmo/JSWEnLDrnijS9Tog==", "dev": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, "engines": { - "node": "*" + "node": ">= 16" } }, "node_modules/chokidar": { @@ -1940,20 +2037,6 @@ "node": ">=8" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1992,12 +2075,6 @@ "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", "dev": true }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, "node_modules/cross-env": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", @@ -2037,6 +2114,12 @@ "node": ">= 8" } }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, "node_modules/cssom": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", @@ -2089,13 +2172,10 @@ "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" }, "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.1.tgz", + "integrity": "sha512-nwQCf6ne2gez3o1MxWifqkciwt0zhl0LO1/UwVu4uMBuPmflWM4oQ70XMqHqnBJA+nhzncaqL9HVL6KkHJ28lw==", "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, "engines": { "node": ">=6" } @@ -2176,12 +2256,6 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.751.tgz", "integrity": "sha512-2DEPi++qa89SMGRhufWTiLmzqyuGmNF3SK4+PQetW1JKiZdEpF4XQonJXJCzyuYSA6mauiMhbyVhqYAP45Hvfw==" }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -2597,34 +2671,6 @@ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -2668,15 +2714,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, "node_modules/get-func-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", @@ -2878,6 +2915,15 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2911,15 +2957,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -3412,6 +3449,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3515,6 +3558,15 @@ "node": ">= 0.6" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "9.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", @@ -3754,12 +3806,12 @@ "dev": true }, "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", "dev": true, "engines": { - "node": "*" + "node": ">= 14.16" } }, "node_modules/picocolors": { @@ -3909,21 +3961,25 @@ "node": ">=8.10.0" } }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", "dev": true }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -4165,20 +4221,6 @@ "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", "dev": true }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4190,6 +4232,18 @@ "node": ">=8" } }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4464,20 +4518,6 @@ "requires-port": "^1.0.0" } }, - "node_modules/v8-to-istanbul": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", - "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, "node_modules/vite": { "version": "5.2.10", "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.10.tgz", @@ -4634,6 +4674,57 @@ "vitest": ">=0.16.0" } }, + "node_modules/vitest/node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/vitest/node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/vitest/node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/vitest/node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/vitest/node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -4744,6 +4835,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/vitest/node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/vitest/node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -4860,23 +4960,6 @@ "node": ">=0.10.0" } }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -4916,42 +4999,6 @@ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/assets/package.json b/assets/package.json index a3aa0df9..eba4cbe7 100644 --- a/assets/package.json +++ b/assets/package.json @@ -25,9 +25,10 @@ }, "devDependencies": { "@testing-library/dom": "^10.1.0", + "@testing-library/jest-dom": "^6.4.2", "@types/chai-dom": "^1.11.3", "@vitest/coverage-v8": "^1.5.3", - "chai-dom": "^1.12.0", + "chai": "^5", "eslint-plugin-vitest": "^0.5.4", "jsdom": "^24.0.0", "vitest": "^1.5.3", diff --git a/assets/test/vitest-setup.ts b/assets/test/vitest-setup.ts index 03c0d647..d889b27f 100644 --- a/assets/test/vitest-setup.ts +++ b/assets/test/vitest-setup.ts @@ -1,12 +1,9 @@ import { matchNone } from '../js/query/boolean'; -import chai from 'chai'; -import chaiDom from 'chai-dom'; +import '@testing-library/jest-dom/vitest'; import { URL } from 'node:url'; import { Blob } from 'node:buffer'; import { fireEvent } from '@testing-library/dom'; -chai.use(chaiDom); - window.booru = { // eslint-disable-next-line @typescript-eslint/no-empty-function timeAgo: () => {},