Repository: symfony/ux
Pull request #2931 (2025-07-20 10:38:43)

Explicitly import Vitest APIs instead of relying on globals
| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Docs?         | no <!-- required for new features -->
| Issues        | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead -->
| License       | MIT

<!--
Replace this notice by a description of your feature/bugfix.
This will help reviewers and should be a good start for the documentation.

Additionally (see https://symfony.com/releases):
 - Always add tests and ensure they pass.
 - For new features, provide some code snippets to help understand usage.
 - Features and deprecations must be submitted against branch main.
 - Update/add documentation as required (we can help!)
 - Changelog entry should follow https://symfony.com/doc/current/contributing/code/conventions.html#writing-a-changelog-entry
 - Never break backward compatibility (see https://symfony.com/bc).
-->

Purely internal.

With Vitest, it is "recommended" to not use globals ([disabled by default](https://vitest.dev/config/#globals)) and instead relying on explicit `import`.

Even if it means to add more code in the codebase, “Explicit is better than implicit”, and global types definitions can be a mess sometimes.


Patch:
diff --git a/tsconfig.json b/tsconfig.json
index bcfaa51f..d5cd3e1c 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -6,7 +6,7 @@
         "module": "esnext",
         "moduleResolution": "node",
         "resolveJsonModule": true,
-        "types": ["vitest/globals", "@testing-library/jest-dom"]
+        "types": ["@testing-library/jest-dom"]
     },
     "include": ["bin/**/*.ts"]
 }


Test patch:
diff --git a/src/Autocomplete/assets/test/controller.test.ts b/src/Autocomplete/assets/test/controller.test.ts
index e6a6d6d3..9c02e4b0 100644
--- a/src/Autocomplete/assets/test/controller.test.ts
+++ b/src/Autocomplete/assets/test/controller.test.ts
@@ -11,7 +11,7 @@ import { Application } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
 import userEvent from '@testing-library/user-event';
 import type TomSelect from 'tom-select';
-import { vi } from 'vitest';
+import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
 import createFetchMock from 'vitest-fetch-mock';
 import AutocompleteController, {
     type AutocompleteConnectOptions,
diff --git a/src/Chartjs/assets/test/controller.test.ts b/src/Chartjs/assets/test/controller.test.ts
index 4378bf4d..b31821b5 100644
--- a/src/Chartjs/assets/test/controller.test.ts
+++ b/src/Chartjs/assets/test/controller.test.ts
@@ -9,6 +9,7 @@
 
 import { Application } from '@hotwired/stimulus';
 import { waitFor } from '@testing-library/dom';
+import { afterEach, beforeAll, describe, expect, it } from 'vitest';
 import ChartjsController from '../src/controller';
 
 // Kept track of globally, but just used in one test.
diff --git a/src/Cropperjs/assets/test/controller.test.ts b/src/Cropperjs/assets/test/controller.test.ts
index 02e45acc..42f20bd9 100644
--- a/src/Cropperjs/assets/test/controller.test.ts
+++ b/src/Cropperjs/assets/test/controller.test.ts
@@ -9,6 +9,7 @@
 
 import { Application, Controller } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
+import { afterEach, beforeEach, describe, expect, it } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../test/stimulus-helpers';
 import CropperjsController from '../src/controller';
 
diff --git a/src/Dropzone/assets/test/controller.test.ts b/src/Dropzone/assets/test/controller.test.ts
index 571868c6..b13f3384 100644
--- a/src/Dropzone/assets/test/controller.test.ts
+++ b/src/Dropzone/assets/test/controller.test.ts
@@ -10,6 +10,7 @@
 import { Application, Controller } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
 import user from '@testing-library/user-event';
+import { afterEach, beforeEach, describe, expect, it } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../test/stimulus-helpers';
 import DropzoneController from '../src/controller';
 
diff --git a/src/LazyImage/assets/test/controller.test.ts b/src/LazyImage/assets/test/controller.test.ts
index 2dd5cc4c..fa6737e7 100644
--- a/src/LazyImage/assets/test/controller.test.ts
+++ b/src/LazyImage/assets/test/controller.test.ts
@@ -9,6 +9,7 @@
 
 import { Application, Controller } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
+import { afterEach, beforeEach, describe, expect, it } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../test/stimulus-helpers';
 import LazyImageController from '../src/controller';
 
diff --git a/src/LiveComponent/assets/test/Backend/RequestBuilder.test.ts b/src/LiveComponent/assets/test/Backend/RequestBuilder.test.ts
index 44521271..1b55fd27 100644
--- a/src/LiveComponent/assets/test/Backend/RequestBuilder.test.ts
+++ b/src/LiveComponent/assets/test/Backend/RequestBuilder.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
 import RequestBuilder from '../../src/Backend/RequestBuilder';
 
 describe('buildRequest', () => {
diff --git a/src/LiveComponent/assets/test/Component/index.test.ts b/src/LiveComponent/assets/test/Component/index.test.ts
index 79ef3655..865723b3 100644
--- a/src/LiveComponent/assets/test/Component/index.test.ts
+++ b/src/LiveComponent/assets/test/Component/index.test.ts
@@ -1,5 +1,6 @@
 import { waitFor } from '@testing-library/dom';
 import { Response } from 'node-fetch';
+import { describe, expect, it } from 'vitest';
 import type { BackendAction, BackendInterface } from '../../src/Backend/Backend';
 import BackendRequest from '../../src/Backend/BackendRequest';
 import type BackendResponse from '../../src/Backend/BackendResponse';
@@ -13,7 +14,7 @@ interface MockBackend extends BackendInterface {
 const makeTestComponent = (): { component: Component; backend: MockBackend } => {
     const backend: MockBackend = {
         actions: [],
-        makeRequest(data: any, actions: BackendAction[]): BackendRequest {
+        makeRequest(_data: any, actions: BackendAction[]): BackendRequest {
             this.actions = actions;
 
             return new BackendRequest(
diff --git a/src/LiveComponent/assets/test/ComponentRegistry.test.ts b/src/LiveComponent/assets/test/ComponentRegistry.test.ts
index 3d1867de..4156e3cb 100644
--- a/src/LiveComponent/assets/test/ComponentRegistry.test.ts
+++ b/src/LiveComponent/assets/test/ComponentRegistry.test.ts
@@ -1,4 +1,5 @@
 import { Response } from 'node-fetch';
+import { beforeEach, describe, expect, it } from 'vitest';
 import type { BackendInterface } from '../src/Backend/Backend';
 import BackendRequest from '../src/Backend/BackendRequest';
 import Component from '../src/Component';
diff --git a/src/LiveComponent/assets/test/Directive/directives_parser.test.ts b/src/LiveComponent/assets/test/Directive/directives_parser.test.ts
index b0488b88..474a01e5 100644
--- a/src/LiveComponent/assets/test/Directive/directives_parser.test.ts
+++ b/src/LiveComponent/assets/test/Directive/directives_parser.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
 import { type Directive, parseDirectives } from '../../src/Directive/directives_parser';
 
 const assertDirectiveEquals = (actual: Directive, expected: any) => {
diff --git a/src/LiveComponent/assets/test/Directive/get_model_binding.test.ts b/src/LiveComponent/assets/test/Directive/get_model_binding.test.ts
index d2c0ee07..a78555af 100644
--- a/src/LiveComponent/assets/test/Directive/get_model_binding.test.ts
+++ b/src/LiveComponent/assets/test/Directive/get_model_binding.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
 import { parseDirectives } from '../../src/Directive/directives_parser';
 import getModelBinding from '../../src/Directive/get_model_binding';
 
diff --git a/src/LiveComponent/assets/test/Rendering/ChangingItemsTracker.test.ts b/src/LiveComponent/assets/test/Rendering/ChangingItemsTracker.test.ts
index fbf3ed09..5318ca79 100644
--- a/src/LiveComponent/assets/test/Rendering/ChangingItemsTracker.test.ts
+++ b/src/LiveComponent/assets/test/Rendering/ChangingItemsTracker.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
 import ChangingItemsTracker from '../../src/Rendering/ChangingItemsTracker';
 
 describe('ChangingItemsTracker', () => {
diff --git a/src/LiveComponent/assets/test/Rendering/ElementChanges.test.ts b/src/LiveComponent/assets/test/Rendering/ElementChanges.test.ts
index d48bfb13..7be09803 100644
--- a/src/LiveComponent/assets/test/Rendering/ElementChanges.test.ts
+++ b/src/LiveComponent/assets/test/Rendering/ElementChanges.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
 import ElementChanges from '../../src/Rendering/ElementChanges';
 
 describe('ElementChanges', () => {
diff --git a/src/LiveComponent/assets/test/Rendering/ExternalMutationTracker.test.ts b/src/LiveComponent/assets/test/Rendering/ExternalMutationTracker.test.ts
index f3a46132..98b882e8 100644
--- a/src/LiveComponent/assets/test/Rendering/ExternalMutationTracker.test.ts
+++ b/src/LiveComponent/assets/test/Rendering/ExternalMutationTracker.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
 import { htmlToElement } from '../../src/dom_utils';
 import ExternalMutationTracker from '../../src/Rendering/ExternalMutationTracker';
 
diff --git a/src/LiveComponent/assets/test/UnsyncedInputContainer.test.ts b/src/LiveComponent/assets/test/UnsyncedInputContainer.test.ts
index c7b614de..245a2eb3 100644
--- a/src/LiveComponent/assets/test/UnsyncedInputContainer.test.ts
+++ b/src/LiveComponent/assets/test/UnsyncedInputContainer.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
 import { UnsyncedInputContainer } from '../src/Component/UnsyncedInputsTracker';
 import { htmlToElement } from '../src/dom_utils';
 
diff --git a/src/LiveComponent/assets/test/Util/getElementAsTagText.test.ts b/src/LiveComponent/assets/test/Util/getElementAsTagText.test.ts
index 4bd12b3a..da7ba3cf 100644
--- a/src/LiveComponent/assets/test/Util/getElementAsTagText.test.ts
+++ b/src/LiveComponent/assets/test/Util/getElementAsTagText.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
 import { htmlToElement } from '../../src/dom_utils';
 import getElementAsTagText from '../../src/Util/getElementAsTagText';
 
diff --git a/src/LiveComponent/assets/test/ValueStore.test.ts b/src/LiveComponent/assets/test/ValueStore.test.ts
index 762e8a52..bc79641c 100644
--- a/src/LiveComponent/assets/test/ValueStore.test.ts
+++ b/src/LiveComponent/assets/test/ValueStore.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
 import ValueStore from '../src/Component/ValueStore';
 
 describe('ValueStore', () => {
diff --git a/src/LiveComponent/assets/test/controller/action.test.ts b/src/LiveComponent/assets/test/controller/action.test.ts
index d3e10c1a..bbd84898 100644
--- a/src/LiveComponent/assets/test/controller/action.test.ts
+++ b/src/LiveComponent/assets/test/controller/action.test.ts
@@ -9,6 +9,7 @@
 
 import { getByText, waitFor } from '@testing-library/dom';
 import userEvent from '@testing-library/user-event';
+import { afterEach, describe, expect, it } from 'vitest';
 import { createTest, initComponent, shutdownTests } from '../tools';
 
 describe('LiveController Action Tests', () => {
diff --git a/src/LiveComponent/assets/test/controller/basic.test.ts b/src/LiveComponent/assets/test/controller/basic.test.ts
index 3b4d149a..2cf516cf 100644
--- a/src/LiveComponent/assets/test/controller/basic.test.ts
+++ b/src/LiveComponent/assets/test/controller/basic.test.ts
@@ -7,6 +7,7 @@
  * file that was distributed with this source code.
  */
 
+import { afterEach, describe, expect, it } from 'vitest';
 import Component from '../../src/Component';
 import { findComponents } from '../../src/ComponentRegistry';
 import { htmlToElement } from '../../src/dom_utils';
diff --git a/src/LiveComponent/assets/test/controller/child-model.test.ts b/src/LiveComponent/assets/test/controller/child-model.test.ts
index 1bfa53a2..4372fdc9 100644
--- a/src/LiveComponent/assets/test/controller/child-model.test.ts
+++ b/src/LiveComponent/assets/test/controller/child-model.test.ts
@@ -9,6 +9,7 @@
 
 import { getByTestId, waitFor } from '@testing-library/dom';
 import userEvent from '@testing-library/user-event';
+import { afterEach, describe, expect, it } from 'vitest';
 import { createTest, initComponent, shutdownTests } from '../tools';
 
 describe('Component parent -> child data-model binding tests', () => {
diff --git a/src/LiveComponent/assets/test/controller/child.test.ts b/src/LiveComponent/assets/test/controller/child.test.ts
index 58f50060..bd767b67 100644
--- a/src/LiveComponent/assets/test/controller/child.test.ts
+++ b/src/LiveComponent/assets/test/controller/child.test.ts
@@ -10,6 +10,7 @@
 import { Controller } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
 import userEvent from '@testing-library/user-event';
+import { afterEach, describe, expect, it } from 'vitest';
 import { findChildren } from '../../src/ComponentRegistry';
 import {
     createTest,
diff --git a/src/LiveComponent/assets/test/controller/dispatch-event.test.ts b/src/LiveComponent/assets/test/controller/dispatch-event.test.ts
index e20283e9..f56cf2fc 100644
--- a/src/LiveComponent/assets/test/controller/dispatch-event.test.ts
+++ b/src/LiveComponent/assets/test/controller/dispatch-event.test.ts
@@ -7,6 +7,7 @@
  * file that was distributed with this source code.
  */
 
+import { afterEach, describe, expect, it } from 'vitest';
 import { createTest, initComponent, shutdownTests } from '../tools';
 
 describe('LiveController Event Dispatching Tests', () => {
diff --git a/src/LiveComponent/assets/test/controller/emit.test.ts b/src/LiveComponent/assets/test/controller/emit.test.ts
index 1451f7c9..2794c880 100644
--- a/src/LiveComponent/assets/test/controller/emit.test.ts
+++ b/src/LiveComponent/assets/test/controller/emit.test.ts
@@ -8,6 +8,7 @@
  */
 
 import { getByText, waitFor } from '@testing-library/dom';
+import { afterEach, describe, expect, it } from 'vitest';
 import { createTest, initComponent, shutdownTests } from '../tools';
 
 describe('LiveController Emit Tests', () => {
diff --git a/src/LiveComponent/assets/test/controller/error.test.ts b/src/LiveComponent/assets/test/controller/error.test.ts
index 70acd75b..d8447e7b 100644
--- a/src/LiveComponent/assets/test/controller/error.test.ts
+++ b/src/LiveComponent/assets/test/controller/error.test.ts
@@ -8,6 +8,7 @@
  */
 
 import { getByText, waitFor } from '@testing-library/dom';
+import { afterEach, describe, expect, it } from 'vitest';
 import type BackendResponse from '../../src/Backend/BackendResponse';
 import { createTest, initComponent, shutdownTests } from '../tools';
 
@@ -108,7 +109,7 @@ describe('LiveController Error Handling', () => {
             .expectActionCalled('save');
 
         let isHookCalled = false;
-        test.component.on('response:error', (backendResponse: BackendResponse, controls) => {
+        test.component.on('response:error', (_backendResponse: BackendResponse, controls) => {
             isHookCalled = true;
             controls.displayError = false;
         });
diff --git a/src/LiveComponent/assets/test/controller/loading.test.ts b/src/LiveComponent/assets/test/controller/loading.test.ts
index 69236671..47d89077 100644
--- a/src/LiveComponent/assets/test/controller/loading.test.ts
+++ b/src/LiveComponent/assets/test/controller/loading.test.ts
@@ -9,6 +9,7 @@
 
 import { getByTestId, getByText, waitFor } from '@testing-library/dom';
 import userEvent from '@testing-library/user-event';
+import { afterEach, describe, expect, it } from 'vitest';
 import { createTest, initComponent, shutdownTests } from '../tools';
 
 describe('LiveController data-loading Tests', () => {
@@ -21,7 +22,7 @@ describe('LiveController data-loading Tests', () => {
             { food: 'pizza' },
             (data: any) => `
             <div ${initComponent(data)}>
-                <span>I like: ${data.food}</span> 
+                <span>I like: ${data.food}</span>
                 <span data-loading="show" data-testid="loading-element">Loading...</span>
             </div>
         `
@@ -53,7 +54,7 @@ describe('LiveController data-loading Tests', () => {
             { food: 'pizza' },
             (data: any) => `
             <div ${initComponent(data)} data-loading="addClass(opacity-20)">
-                <span>I like: ${data.food}</span> 
+                <span>I like: ${data.food}</span>
                 <button data-action="live#$render">Re-Render</button>
             </div>
         `
@@ -84,7 +85,7 @@ describe('LiveController data-loading Tests', () => {
         const test = await createTest(
             {},
             (data: any) => `
-            <div ${initComponent(data)}> 
+            <div ${initComponent(data)}>
                 <span data-loading="action(save)|show" data-testid="loading-element">Loading...</span>
 
                 <button data-action="live#action" data-live-action-param="save">Save</button>
@@ -131,7 +132,7 @@ describe('LiveController data-loading Tests', () => {
         const test = await createTest(
             { comments: '', user: { email: '' } },
             (data: any) => `
-            <div ${initComponent(data)}> 
+            <div ${initComponent(data)}>
                 <textarea data-model="comments"></textarea>
                 <span data-loading="model(comments)|show" data-testid="comments-loading">Comments change loading...</span>
 
@@ -185,7 +186,7 @@ describe('LiveController data-loading Tests', () => {
         const test = await createTest(
             {},
             (data: any) => `
-            <div ${initComponent(data)}> 
+            <div ${initComponent(data)}>
                 <span data-loading="action(otherAction)|show" data-testid="loading-element">Loading...</span>
 
                 <button data-action="live#action" data-live-action-param="debounce(50)|save">Save</button>
@@ -215,7 +216,7 @@ describe('LiveController data-loading Tests', () => {
         const test = await createTest(
             {},
             (data: any) => `
-           <div ${initComponent(data)}> 
+           <div ${initComponent(data)}>
                <span data-loading="action(save)|delay(50)|show" data-testid="loading-element">Loading...</span>
 
                <button data-action="live#action" data-live-action-param="save">Save</button>
diff --git a/src/LiveComponent/assets/test/controller/model.test.ts b/src/LiveComponent/assets/test/controller/model.test.ts
index 63756d9c..085f2761 100644
--- a/src/LiveComponent/assets/test/controller/model.test.ts
+++ b/src/LiveComponent/assets/test/controller/model.test.ts
@@ -9,6 +9,7 @@
 
 import { getByLabelText, getByTestId, getByText, waitFor } from '@testing-library/dom';
 import userEvent from '@testing-library/user-event';
+import { afterEach, describe, expect, it } from 'vitest';
 import { createTest, initComponent, shutdownTests } from '../tools';
 
 describe('LiveController data-model Tests', () => {
diff --git a/src/LiveComponent/assets/test/controller/poll.test.ts b/src/LiveComponent/assets/test/controller/poll.test.ts
index 1519172f..d45a5b4c 100644
--- a/src/LiveComponent/assets/test/controller/poll.test.ts
+++ b/src/LiveComponent/assets/test/controller/poll.test.ts
@@ -9,6 +9,7 @@
 
 import { waitFor } from '@testing-library/dom';
 import userEvent from '@testing-library/user-event';
+import { afterEach, describe, expect, it } from 'vitest';
 import { createTest, initComponent, shutdownTests } from '../tools';
 
 describe('LiveController polling Tests', () => {
diff --git a/src/LiveComponent/assets/test/controller/query-binding.test.ts b/src/LiveComponent/assets/test/controller/query-binding.test.ts
index f0654efe..cde1fbbf 100644
--- a/src/LiveComponent/assets/test/controller/query-binding.test.ts
+++ b/src/LiveComponent/assets/test/controller/query-binding.test.ts
@@ -8,6 +8,7 @@
  */
 
 import { getByText, waitFor } from '@testing-library/dom';
+import { afterEach, describe, expect, it } from 'vitest';
 import { createTest, expectCurrentSearch, initComponent, setCurrentSearch, shutdownTests } from '../tools';
 
 describe('LiveController query string binding', () => {
diff --git a/src/LiveComponent/assets/test/controller/render-with-external-changes.test.ts b/src/LiveComponent/assets/test/controller/render-with-external-changes.test.ts
index 7109dcc7..b5046e0e 100644
--- a/src/LiveComponent/assets/test/controller/render-with-external-changes.test.ts
+++ b/src/LiveComponent/assets/test/controller/render-with-external-changes.test.ts
@@ -8,6 +8,7 @@
  */
 
 import { getByTestId } from '@testing-library/dom';
+import { afterEach, describe, expect, it } from 'vitest';
 import { htmlToElement } from '../../src/dom_utils';
 import { createTest, initComponent, shutdownTests } from '../tools';
 
diff --git a/src/LiveComponent/assets/test/controller/render.test.ts b/src/LiveComponent/assets/test/controller/render.test.ts
index 5dc6c64d..1f69026f 100644
--- a/src/LiveComponent/assets/test/controller/render.test.ts
+++ b/src/LiveComponent/assets/test/controller/render.test.ts
@@ -9,6 +9,7 @@
 
 import { getByTestId, getByText, waitFor } from '@testing-library/dom';
 import userEvent from '@testing-library/user-event';
+import { afterEach, describe, expect, it } from 'vitest';
 import { htmlToElement } from '../../src/dom_utils';
 import { createTest, initComponent, shutdownTests } from '../tools';
 
@@ -51,7 +52,7 @@ describe('LiveController rendering Tests', () => {
                     We want the first to finish, to see if it overwrites our value
                 -->
                 <textarea data-model="norender|comment">${data.comment}</textarea>
-                
+
                 Title: "${data.title}"
                 Comment: "${data.comment}"
 
@@ -213,7 +214,7 @@ describe('LiveController rendering Tests', () => {
             (data: any) => `
             <div ${initComponent(data)}>
                 <div data-live-ignore>Inside Ignore Name: <span>${data.firstName}</span></div>
-                
+
                 Outside Ignore Name: ${data.firstName}
 
                 <button data-action="live#$render">Reload</button>
@@ -249,7 +250,7 @@ describe('LiveController rendering Tests', () => {
                 <div id="${data.containerId}">
                     <div data-live-ignore>Inside Ignore Name: <span>${data.firstName}</span></div>
                 </div>
-                
+
                 Outside Ignore Name: ${data.firstName}
 
                 <button data-action="live#$render">Reload</button>
@@ -491,8 +492,8 @@ describe('LiveController rendering Tests', () => {
             // correctly delayed, the "first render finish" and "second render
             // start" times could be the same, because no time has passed.
             const sleep = (milliseconds: number) => {
-                const startTime = new Date().getTime();
-                while (new Date().getTime() < startTime + milliseconds);
+                const startTime = Date.now();
+                while (Date.now() < startTime + milliseconds);
             };
             sleep(10);
         });
@@ -585,7 +586,7 @@ describe('LiveController rendering Tests', () => {
                         <option value="2">Two</option>
                         <option value="3">Three</option>
                     </select>
-                    
+
                     <select id="select_option_2">
                         <option value="">Choose option 2</option>
                         <option value="1_1">One - One</option>
@@ -610,7 +611,7 @@ describe('LiveController rendering Tests', () => {
                             <option value="2" selected>Two</option>
                             <option value="3">Three</option>
                         </select>
-                        
+
                         <select id="select_option_2">
                             <option value="">Choose option 2</option>
                             <option value="2_1">Two - One</option>
diff --git a/src/LiveComponent/assets/test/dom_utils.test.ts b/src/LiveComponent/assets/test/dom_utils.test.ts
index 0e656d5f..8eb62921 100644
--- a/src/LiveComponent/assets/test/dom_utils.test.ts
+++ b/src/LiveComponent/assets/test/dom_utils.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
 import Backend from '../src/Backend/Backend';
 import Component from '../src/Component';
 import ValueStore from '../src/Component/ValueStore';
diff --git a/src/LiveComponent/assets/test/normalize_attributes_for_comparison.test.ts b/src/LiveComponent/assets/test/normalize_attributes_for_comparison.test.ts
index 2ed1b2a5..0b2e8022 100644
--- a/src/LiveComponent/assets/test/normalize_attributes_for_comparison.test.ts
+++ b/src/LiveComponent/assets/test/normalize_attributes_for_comparison.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
 import { htmlToElement } from '../src/dom_utils';
 import { normalizeAttributesForComparison } from '../src/normalize_attributes_for_comparison';
 
diff --git a/src/LiveComponent/assets/test/string_utils.test.ts b/src/LiveComponent/assets/test/string_utils.test.ts
index 4d03c644..25d44e9a 100644
--- a/src/LiveComponent/assets/test/string_utils.test.ts
+++ b/src/LiveComponent/assets/test/string_utils.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
 import { combineSpacedArray, normalizeModelName } from '../src/string_utils';
 
 describe('combinedSpacedArray', () => {
diff --git a/src/LiveComponent/assets/test/tools.ts b/src/LiveComponent/assets/test/tools.ts
index 41a6b11a..975241b1 100644
--- a/src/LiveComponent/assets/test/tools.ts
+++ b/src/LiveComponent/assets/test/tools.ts
@@ -1,6 +1,7 @@
 import { Application } from '@hotwired/stimulus';
 import { waitFor } from '@testing-library/dom';
 import { Response } from 'node-fetch';
+import { expect } from 'vitest';
 import type { BackendAction, BackendInterface, ChildrenFingerprints } from '../src/Backend/Backend';
 import BackendRequest from '../src/Backend/BackendRequest';
 import Component from '../src/Component';
diff --git a/src/LiveComponent/assets/test/url_utils.test.ts b/src/LiveComponent/assets/test/url_utils.test.ts
index bce7f86b..3a6353ed 100644
--- a/src/LiveComponent/assets/test/url_utils.test.ts
+++ b/src/LiveComponent/assets/test/url_utils.test.ts
@@ -7,6 +7,7 @@
  * file that was distributed with this source code.
  */
 
+import { afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
 import { HistoryStrategy, UrlUtils } from '../src/url_utils';
 
 describe('url_utils', () => {
diff --git a/src/Map/assets/test/abstract_map_controller.test.ts b/src/Map/assets/test/abstract_map_controller.test.ts
index b8f4ff28..df69ec57 100644
--- a/src/Map/assets/test/abstract_map_controller.test.ts
+++ b/src/Map/assets/test/abstract_map_controller.test.ts
@@ -1,5 +1,6 @@
 import { Application } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
+import { afterEach, beforeEach, describe, expect, it } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../test/stimulus-helpers';
 import AbstractMapController from '../src/abstract_map_controller.ts';
 
diff --git a/src/Map/src/Bridge/Google/assets/test/map_controller.test.ts b/src/Map/src/Bridge/Google/assets/test/map_controller.test.ts
index b6f75d00..3bd69aaa 100644
--- a/src/Map/src/Bridge/Google/assets/test/map_controller.test.ts
+++ b/src/Map/src/Bridge/Google/assets/test/map_controller.test.ts
@@ -9,17 +9,18 @@
 
 import { Application, Controller } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
+import { afterEach, beforeEach, describe, expect, it } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../../../../test/stimulus-helpers';
 import GoogleController from '../src/map_controller';
 
 // Controller used to check the actual controller was properly booted
 class CheckController extends Controller {
     connect() {
-        this.element.addEventListener('ux:map:pre-connect', (event) => {
+        this.element.addEventListener('ux:map:pre-connect', (_event) => {
             this.element.classList.add('pre-connected');
         });
 
-        this.element.addEventListener('ux:map:connect', (event) => {
+        this.element.addEventListener('ux:map:connect', (_event) => {
             this.element.classList.add('connected');
         });
     }
diff --git a/src/Map/src/Bridge/Leaflet/assets/test/map_controller.test.ts b/src/Map/src/Bridge/Leaflet/assets/test/map_controller.test.ts
index 1d07b494..bec0b43c 100644
--- a/src/Map/src/Bridge/Leaflet/assets/test/map_controller.test.ts
+++ b/src/Map/src/Bridge/Leaflet/assets/test/map_controller.test.ts
@@ -9,17 +9,18 @@
 
 import { Application, Controller } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
+import { afterEach, beforeEach, describe, expect, it } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../../../../test/stimulus-helpers';
 import LeafletController from '../src/map_controller';
 
 // Controller used to check the actual controller was properly booted
 class CheckController extends Controller {
     connect() {
-        this.element.addEventListener('ux:map:pre-connect', (event) => {
+        this.element.addEventListener('ux:map:pre-connect', (_event) => {
             this.element.classList.add('pre-connected');
         });
 
-        this.element.addEventListener('ux:map:connect', (event) => {
+        this.element.addEventListener('ux:map:connect', (_event) => {
             this.element.classList.add('connected');
         });
     }
diff --git a/src/Notify/assets/test/controller.test.ts b/src/Notify/assets/test/controller.test.ts
index 937b0f10..52e613bc 100644
--- a/src/Notify/assets/test/controller.test.ts
+++ b/src/Notify/assets/test/controller.test.ts
@@ -9,7 +9,7 @@
 
 import { Application, Controller } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
-import { vi } from 'vitest';
+import { afterEach, describe, expect, it, vi } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../test/stimulus-helpers';
 import NotifyController from '../src/controller';
 
diff --git a/src/React/assets/test/register_controller.test.tsx b/src/React/assets/test/register_controller.test.tsx
index 66e04ee1..75e90e6e 100644
--- a/src/React/assets/test/register_controller.test.tsx
+++ b/src/React/assets/test/register_controller.test.tsx
@@ -7,6 +7,7 @@
  * file that was distributed with this source code.
  */
 
+import { describe, expect, it } from 'vitest';
 import { registerReactControllerComponents } from '../src/register_controller';
 // @ts-ignore
 import MyJsxComponent from './fixtures/MyJsxComponent';
diff --git a/src/React/assets/test/render_controller.test.tsx b/src/React/assets/test/render_controller.test.tsx
index 8c466ec5..cb9aaa5b 100644
--- a/src/React/assets/test/render_controller.test.tsx
+++ b/src/React/assets/test/render_controller.test.tsx
@@ -9,7 +9,7 @@
 
 import { Application, Controller } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
-import React from 'react';
+import { describe, expect, it } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../test/stimulus-helpers';
 import ReactController from '../src/render_controller';
 
diff --git a/src/StimulusBundle/assets/test/loader.test.ts b/src/StimulusBundle/assets/test/loader.test.ts
index 27fdb650..528758cd 100644
--- a/src/StimulusBundle/assets/test/loader.test.ts
+++ b/src/StimulusBundle/assets/test/loader.test.ts
@@ -1,5 +1,6 @@
 import { Application, Controller } from '@hotwired/stimulus';
 import { waitFor } from '@testing-library/dom';
+import { describe, expect, it } from 'vitest';
 // load from dist because the source TypeScript file points directly to controllers.js,
 // which does not actually exist in the source code
 import { loadControllers } from '../dist/loader';
diff --git a/src/Svelte/assets/test/register_controller.test.ts b/src/Svelte/assets/test/register_controller.test.ts
index ca56d416..8f5ca388 100644
--- a/src/Svelte/assets/test/register_controller.test.ts
+++ b/src/Svelte/assets/test/register_controller.test.ts
@@ -7,6 +7,7 @@
  * file that was distributed with this source code.
  */
 
+import { describe, expect, it } from 'vitest';
 import { registerSvelteControllerComponents } from '../src/register_controller';
 import MyComponent from './fixtures/MyComponent.svelte';
 
diff --git a/src/Svelte/assets/test/render_controller.test.ts b/src/Svelte/assets/test/render_controller.test.ts
index c22a2f7d..bede47dd 100644
--- a/src/Svelte/assets/test/render_controller.test.ts
+++ b/src/Svelte/assets/test/render_controller.test.ts
@@ -9,6 +9,7 @@
 
 import { Application, Controller } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
+import { afterEach, describe, expect, it } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../test/stimulus-helpers';
 import SvelteController from '../src/render_controller';
 import MyComponent from './fixtures/MyComponent.svelte';
diff --git a/src/Swup/assets/test/controller.test.ts b/src/Swup/assets/test/controller.test.ts
index f180b19a..8805a0a6 100644
--- a/src/Swup/assets/test/controller.test.ts
+++ b/src/Swup/assets/test/controller.test.ts
@@ -9,6 +9,7 @@
 
 import { Application, Controller } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
+import { afterEach, describe, expect, it } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../test/stimulus-helpers';
 import SwupController from '../src/controller';
 
diff --git a/src/TogglePassword/assets/test/controller.test.ts b/src/TogglePassword/assets/test/controller.test.ts
index b7afb80b..8d1e0304 100644
--- a/src/TogglePassword/assets/test/controller.test.ts
+++ b/src/TogglePassword/assets/test/controller.test.ts
@@ -10,6 +10,7 @@
 import { Application, Controller } from '@hotwired/stimulus';
 import { getByTestId, getByText, waitFor } from '@testing-library/dom';
 import user from '@testing-library/user-event';
+import { afterEach, beforeEach, describe, expect, it } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../test/stimulus-helpers';
 import TogglePasswordController from '../src/controller';
 
diff --git a/src/Translator/assets/test/formatters/formatter.test.ts b/src/Translator/assets/test/formatters/formatter.test.ts
index e8c58427..5847a60a 100644
--- a/src/Translator/assets/test/formatters/formatter.test.ts
+++ b/src/Translator/assets/test/formatters/formatter.test.ts
@@ -7,6 +7,7 @@
  * file that was distributed with this source code.
  */
 
+import { describe, expect, test } from 'vitest';
 import { format } from '../../src/formatters/formatter';
 
 describe('Formatter', () => {
diff --git a/src/Translator/assets/test/formatters/intl-formatter.test.ts b/src/Translator/assets/test/formatters/intl-formatter.test.ts
index cf995772..f54583e2 100644
--- a/src/Translator/assets/test/formatters/intl-formatter.test.ts
+++ b/src/Translator/assets/test/formatters/intl-formatter.test.ts
@@ -7,6 +7,7 @@
  * file that was distributed with this source code.
  */
 
+import { describe, expect, test } from 'vitest';
 import { formatIntl } from '../../src/formatters/intl-formatter';
 
 describe('Intl Formatter', () => {
diff --git a/src/Translator/assets/test/translator.test.ts b/src/Translator/assets/test/translator.test.ts
index 77cf2c78..af671d25 100644
--- a/src/Translator/assets/test/translator.test.ts
+++ b/src/Translator/assets/test/translator.test.ts
@@ -1,3 +1,4 @@
+import { beforeEach, describe, expect, test } from 'vitest';
 import {
     getLocale,
     type Message,
diff --git a/src/Translator/assets/test/utils.test.ts b/src/Translator/assets/test/utils.test.ts
index 3b0f0597..2fb2ffed 100644
--- a/src/Translator/assets/test/utils.test.ts
+++ b/src/Translator/assets/test/utils.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, test } from 'vitest';
 import { strtr } from '../src/utils';
 
 describe('Utils', () => {
diff --git a/src/Turbo/assets/test/turbo_controller.test.ts b/src/Turbo/assets/test/turbo_controller.test.ts
index 9aa7bf2b..d0442960 100644
--- a/src/Turbo/assets/test/turbo_controller.test.ts
+++ b/src/Turbo/assets/test/turbo_controller.test.ts
@@ -9,6 +9,7 @@
 
 import { Application } from '@hotwired/stimulus';
 import { getByTestId } from '@testing-library/dom';
+import { afterEach, beforeEach, describe, expect, it } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../test/stimulus-helpers';
 import TurboController from '../src/turbo_controller';
 
diff --git a/src/Turbo/assets/test/turbo_stream_controller.test.ts b/src/Turbo/assets/test/turbo_stream_controller.test.ts
index 1cb9c6ad..06a58586 100644
--- a/src/Turbo/assets/test/turbo_stream_controller.test.ts
+++ b/src/Turbo/assets/test/turbo_stream_controller.test.ts
@@ -9,7 +9,7 @@
 
 import { Application } from '@hotwired/stimulus';
 import { getByTestId } from '@testing-library/dom';
-import { vi } from 'vitest';
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../test/stimulus-helpers';
 import TurboStreamController from '../src/turbo_stream_controller';
 
diff --git a/src/Typed/assets/test/controller.test.ts b/src/Typed/assets/test/controller.test.ts
index 6d1a1f7c..453a35ec 100644
--- a/src/Typed/assets/test/controller.test.ts
+++ b/src/Typed/assets/test/controller.test.ts
@@ -9,6 +9,7 @@
 
 import { Application, Controller } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
+import { afterEach, beforeEach, describe, expect, it } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../test/stimulus-helpers';
 import TypedController from '../src/controller';
 
diff --git a/src/Vue/assets/test/register_controller.test.ts b/src/Vue/assets/test/register_controller.test.ts
index 50b7b4e0..9fa21676 100644
--- a/src/Vue/assets/test/register_controller.test.ts
+++ b/src/Vue/assets/test/register_controller.test.ts
@@ -7,6 +7,7 @@
  * file that was distributed with this source code.
  */
 
+import { describe, expect, it } from 'vitest';
 import { registerVueControllerComponents } from '../src/register_controller';
 import Hello from './fixtures/Hello.vue';
 import Goodbye from './fixtures-lazy/Goodbye.vue';
diff --git a/src/Vue/assets/test/render_controller.test.ts b/src/Vue/assets/test/render_controller.test.ts
index 227c2bda..b3f7eadc 100644
--- a/src/Vue/assets/test/render_controller.test.ts
+++ b/src/Vue/assets/test/render_controller.test.ts
@@ -9,6 +9,7 @@
 
 import { Application, Controller } from '@hotwired/stimulus';
 import { getByTestId, waitFor } from '@testing-library/dom';
+import { describe, expect, it } from 'vitest';
 import { clearDOM, mountDOM } from '../../../../test/stimulus-helpers';
 import VueController from '../src/render_controller';
 
diff --git a/test/setup.js b/test/setup.js
index b892bdbb..61c39b84 100644
--- a/test/setup.js
+++ b/test/setup.js
@@ -7,4 +7,4 @@
  * file that was distributed with this source code.
  */
 
-import '@testing-library/jest-dom';
+import '@testing-library/jest-dom/vitest';
diff --git a/vitest.config.mjs b/vitest.config.mjs
index 97470d1e..2543fa3e 100644
--- a/vitest.config.mjs
+++ b/vitest.config.mjs
@@ -3,7 +3,6 @@ import path from 'path';
 
 export default defineConfig({
     test: {
-        globals: true,
         environment: 'jsdom',
         setupFiles: [path.join(__dirname, 'test', 'setup.js')],
         coverage: {