@@ -494,12 +494,12 @@ describe("When user is in state", () => {
});
afterEach(() => {
- jest.useRealTimers();
+ vi.useRealTimers();
});
test("removes if user data is removed from local storage", () => {
localStorage.removeItem(authKey);
- jest.advanceTimersByTime(50000);
+ vi.advanceTimersByTime(50000);
expect(store.getActions()).toEqual(
expect.arrayContaining([setUser(null)]),
);
@@ -513,7 +513,7 @@ describe("When user is in state", () => {
other_user_data: "data",
}),
);
- jest.advanceTimersByTime(50000);
+ vi.advanceTimersByTime(50000);
expect(store.getActions()).toEqual(
expect.arrayContaining([
setUser({ access_token: "new_token", other_user_data: "data" }),
diff --git a/src/hooks/useAutoSave/useAutoSave.test.js b/src/hooks/useAutoSave/useAutoSave.test.js
index 5a370e313..6d67bce44 100644
--- a/src/hooks/useAutoSave/useAutoSave.test.js
+++ b/src/hooks/useAutoSave/useAutoSave.test.js
@@ -11,8 +11,8 @@ let mockDispatch;
let resolveSave;
let rejectSave;
-jest.mock("react-redux", () => ({
- ...jest.requireActual("react-redux"),
+vi.mock("react-redux", async () => ({
+ ...(await vi.importActual("react-redux")),
useDispatch: () => mockDispatch,
useSelector: (selector) =>
selector({
@@ -26,12 +26,12 @@ jest.mock("react-redux", () => ({
}),
}));
-jest.mock("../../redux/EditorSlice", () => ({
- ...jest.requireActual("../../redux/EditorSlice"),
- syncProject: jest.fn((_) => jest.fn()),
+vi.mock("../../redux/EditorSlice", async () => ({
+ ...(await vi.importActual("../../redux/EditorSlice")),
+ syncProject: vi.fn((_) => vi.fn()),
}));
-jest.useFakeTimers();
+vi.useFakeTimers();
const user1 = {
access_token: "myAccessToken1",
@@ -71,10 +71,10 @@ const editedProject = {
};
const saveAction = { type: "SAVE_PROJECT" };
-const saveProject = jest.fn(() => saveAction);
+const saveProject = vi.fn(() => saveAction);
const createAsyncThunkDispatchMock = () =>
- jest.fn(() => {
+ vi.fn(() => {
const thunkPromise = new Promise((resolve) => {
resolveSave = resolve;
rejectSave = (error) =>
@@ -99,7 +99,7 @@ beforeEach(() => {
mockInitialProjectInstructions = project.instructions ?? null;
mockSaving = "idle";
mockCodeRunInProgress = false;
- syncProject.mockImplementation(jest.fn((_) => saveProject));
+ syncProject.mockImplementation(vi.fn((_) => saveProject));
mockDispatch = createAsyncThunkDispatchMock();
});
@@ -182,7 +182,7 @@ describe("useAutoSave", () => {
});
act(() => {
- jest.advanceTimersByTime(10000);
+ vi.advanceTimersByTime(10000);
});
expect(mockDispatch).toHaveBeenCalledTimes(2);
@@ -319,7 +319,7 @@ describe("useAutoSave", () => {
expect(mockDispatch).toHaveBeenCalledTimes(1);
act(() => {
- jest.advanceTimersByTime(10000);
+ vi.advanceTimersByTime(10000);
});
expect(mockDispatch).toHaveBeenCalledTimes(2);
diff --git a/src/hooks/useContainerMinWidth.test.js b/src/hooks/useContainerMinWidth.test.js
index e74743819..1ed9de359 100644
--- a/src/hooks/useContainerMinWidth.test.js
+++ b/src/hooks/useContainerMinWidth.test.js
@@ -8,14 +8,14 @@ let observers;
class MockResizeObserver {
constructor(callback) {
this.callback = callback;
- this.observe = jest.fn();
- this.disconnect = jest.fn();
+ this.observe = vi.fn();
+ this.disconnect = vi.fn();
observers.push(this);
}
}
const makeElement = (width) => ({
- getBoundingClientRect: jest.fn(() => ({ width })),
+ getBoundingClientRect: vi.fn(() => ({ width })),
});
const renderObservedHook = (width) => {
diff --git a/src/hooks/useIsOnline.test.js b/src/hooks/useIsOnline.test.js
index d8406b664..0c38c4d1a 100644
--- a/src/hooks/useIsOnline.test.js
+++ b/src/hooks/useIsOnline.test.js
@@ -17,7 +17,7 @@ describe("useIsOnline", () => {
get: () => true,
});
- mockPostMessage = jest.fn();
+ mockPostMessage = vi.fn();
swEventTarget = new EventTarget();
swEventTarget.controller = { postMessage: mockPostMessage };
@@ -82,17 +82,17 @@ describe("useIsOnline", () => {
describe("CHECK_ONLINE polling", () => {
beforeEach(() => {
- jest.useFakeTimers();
+ vi.useFakeTimers();
});
afterEach(() => {
- jest.useRealTimers();
+ vi.useRealTimers();
});
test("does not poll while online", async () => {
renderHook(() => useIsOnline());
await act(async () => {
- jest.advanceTimersByTime(6000);
+ vi.advanceTimersByTime(6000);
});
expect(mockPostMessage).not.toHaveBeenCalled();
});
@@ -103,13 +103,13 @@ describe("useIsOnline", () => {
expect(result.current).toBe(false);
await act(async () => {
- jest.advanceTimersByTime(3000);
+ vi.advanceTimersByTime(3000);
});
expect(mockPostMessage).toHaveBeenCalledTimes(1);
expect(mockPostMessage).toHaveBeenCalledWith({ type: "CHECK_ONLINE" });
await act(async () => {
- jest.advanceTimersByTime(3000);
+ vi.advanceTimersByTime(3000);
});
expect(mockPostMessage).toHaveBeenCalledTimes(2);
});
@@ -121,7 +121,7 @@ describe("useIsOnline", () => {
expect(result.current).toBe(true);
await act(async () => {
- jest.advanceTimersByTime(6000);
+ vi.advanceTimersByTime(6000);
});
expect(mockPostMessage).not.toHaveBeenCalled();
});
@@ -134,7 +134,7 @@ describe("useIsOnline", () => {
unmount();
await act(async () => {
- jest.advanceTimersByTime(6000);
+ vi.advanceTimersByTime(6000);
});
expect(mockPostMessage).not.toHaveBeenCalled();
});
diff --git a/src/hooks/useProject.test.jsx b/src/hooks/useProject.test.jsx
index d2805d7af..f13ff2b3f 100644
--- a/src/hooks/useProject.test.jsx
+++ b/src/hooks/useProject.test.jsx
@@ -6,21 +6,23 @@ import { useProject } from "./useProject";
import { syncProject, setProject } from "../redux/EditorSlice";
import { defaultPythonProject } from "../utils/defaultProjects";
-jest.mock("react-redux", () => ({
- ...jest.requireActual("react-redux"),
- useDispatch: () => jest.fn(),
+vi.mock("react-redux", async () => ({
+ ...(await vi.importActual("react-redux")),
+ useDispatch: () => vi.fn(),
}));
-const loadProject = jest.fn();
+const loadProject = vi.fn();
const reactAppApiEndpoint = "localhost";
-jest.mock("../redux/EditorSlice");
+vi.mock("../redux/EditorSlice");
-jest.mock("../utils/apiCallHandler", () => () => ({
- readProject: async (identifier, projectType) =>
- Promise.resolve({
- data: { identifier: identifier, project_type: projectType },
- }),
+vi.mock("../utils/apiCallHandler", () => ({
+ default: () => ({
+ readProject: async (identifier, projectType) =>
+ Promise.resolve({
+ data: { identifier: identifier, project_type: projectType },
+ }),
+ }),
}));
const cachedProject = {
@@ -136,7 +138,7 @@ describe("When not embedded", () => {
});
test("If embedded prop is true before embedded state is set, loads from server instead of cache", () => {
- syncProject.mockImplementation(jest.fn((_) => jest.fn()));
+ syncProject.mockImplementation(vi.fn((_) => vi.fn()));
localStorage.setItem(
cachedProject.identifier,
JSON.stringify(cachedProject),
@@ -157,7 +159,7 @@ describe("When not embedded", () => {
});
test("If cached project does not match identifier, does not use cached project", async () => {
- syncProject.mockImplementationOnce(jest.fn((_) => jest.fn()));
+ syncProject.mockImplementationOnce(vi.fn((_) => vi.fn()));
localStorage.setItem("project", JSON.stringify(cachedProject));
renderHook(
() => useProject({ projectIdentifier: "my-favourite-project" }),
@@ -172,7 +174,7 @@ describe("When not embedded", () => {
});
test("If cached project does not match locale, does not use cached project", async () => {
- syncProject.mockImplementationOnce(jest.fn((_) => jest.fn()));
+ syncProject.mockImplementationOnce(vi.fn((_) => vi.fn()));
localStorage.setItem("project", JSON.stringify(cachedProject));
renderHook(
() =>
@@ -190,7 +192,7 @@ describe("When not embedded", () => {
test("If current project has changed and locale changes, keeps current project", async () => {
setCurrentProjectWithEdits();
- syncProject.mockImplementationOnce(jest.fn((_) => loadProject));
+ syncProject.mockImplementationOnce(vi.fn((_) => loadProject));
renderHook(
() =>
@@ -233,7 +235,7 @@ describe("When not embedded", () => {
});
test("If cached project does not match locale and browserPreview query is used outside embedded viewer, does not use cached project", () => {
- syncProject.mockImplementation(jest.fn((_) => jest.fn()));
+ syncProject.mockImplementation(vi.fn((_) => vi.fn()));
window.history.pushState(
{},
"",
@@ -258,7 +260,7 @@ describe("When not embedded", () => {
});
test("If cached project does not match identifier and locale, loads correct uncached project", async () => {
- syncProject.mockImplementationOnce(jest.fn((_) => loadProject));
+ syncProject.mockImplementationOnce(vi.fn((_) => loadProject));
localStorage.setItem("project", JSON.stringify(cachedProject));
renderHook(
() =>
@@ -282,7 +284,7 @@ describe("When not embedded", () => {
});
test("If loadCache is set to false, loads correct uncached project", async () => {
- syncProject.mockImplementationOnce(jest.fn((_) => loadProject));
+ syncProject.mockImplementationOnce(vi.fn((_) => loadProject));
localStorage.setItem("project", JSON.stringify(cachedProject));
renderHook(
() =>
@@ -306,7 +308,7 @@ describe("When not embedded", () => {
});
test("If no cached project, loads uncached project", async () => {
- syncProject.mockImplementationOnce(jest.fn((_) => loadProject));
+ syncProject.mockImplementationOnce(vi.fn((_) => loadProject));
renderHook(
() =>
useProject({
@@ -328,7 +330,7 @@ describe("When not embedded", () => {
});
test("If requested locale does not match the set language, does not set project", async () => {
- syncProject.mockImplementationOnce(jest.fn((_) => jest.fn()));
+ syncProject.mockImplementationOnce(vi.fn((_) => vi.fn()));
renderHook(
() => useProject({ projectIdentifier: "my-favourite-project" }),
{
@@ -374,7 +376,7 @@ describe("When not embedded", () => {
});
test("If loadRemix of a project is requested and remixLoadFailed is false", async () => {
- syncProject.mockImplementationOnce(jest.fn((_) => loadProject));
+ syncProject.mockImplementationOnce(vi.fn((_) => loadProject));
renderHook(
() =>
useProject({
@@ -396,7 +398,7 @@ describe("When not embedded", () => {
});
test("If loadRemix of a project is requested and remixLoadFailed is true", async () => {
- syncProject.mockImplementationOnce(jest.fn((_) => loadProject));
+ syncProject.mockImplementationOnce(vi.fn((_) => loadProject));
renderHook(
() =>
useProject({
@@ -420,7 +422,7 @@ describe("When not embedded", () => {
});
test("it calls loadProject when access token becomes available", async () => {
- syncProject.mockImplementation(jest.fn((_) => loadProject));
+ syncProject.mockImplementation(vi.fn((_) => loadProject));
const { rerender } = renderHook((props) => useProject(props), {
initialProps: {
projectIdentifier: project1.identifier,
@@ -444,7 +446,7 @@ describe("When not embedded", () => {
});
test("it does not call loadProject when access token changes", async () => {
- syncProject.mockImplementation(jest.fn((_) => loadProject));
+ syncProject.mockImplementation(vi.fn((_) => loadProject));
const { rerender } = renderHook((props) => useProject(props), {
initialProps: {
projectIdentifier: project1.identifier,
@@ -468,7 +470,7 @@ describe("When not embedded", () => {
});
test("If assetsIdentifer is set then set assetsOnly to true when loading project", async () => {
- syncProject.mockImplementationOnce(jest.fn((_) => loadProject));
+ syncProject.mockImplementationOnce(vi.fn((_) => loadProject));
renderHook(
() =>
useProject({
@@ -723,7 +725,7 @@ describe("When embedded", () => {
});
test("If embedded and cached project, loads from server", async () => {
- syncProject.mockImplementationOnce(jest.fn((_) => loadProject));
+ syncProject.mockImplementationOnce(vi.fn((_) => loadProject));
localStorage.setItem("hello-world-project", JSON.stringify(cachedProject));
renderHook(
() =>
diff --git a/src/hooks/useProjectPersistence.test.js b/src/hooks/useProjectPersistence.test.js
index 601121a97..d3c72ae09 100644
--- a/src/hooks/useProjectPersistence.test.js
+++ b/src/hooks/useProjectPersistence.test.js
@@ -14,8 +14,8 @@ let mockSaving = "idle";
let mockCodeRunInProgress = false;
let mockDispatch;
-jest.mock("react-redux", () => ({
- ...jest.requireActual("react-redux"),
+vi.mock("react-redux", async () => ({
+ ...(await vi.importActual("react-redux")),
useDispatch: () => mockDispatch,
useSelector: (selector) =>
selector({
@@ -29,22 +29,22 @@ jest.mock("react-redux", () => ({
}),
}));
-jest.mock("../redux/EditorSlice", () => ({
- ...jest.requireActual("../redux/EditorSlice"),
- syncProject: jest.fn((_) => jest.fn()),
- expireJustLoaded: jest.fn(),
- setHasShownSavePrompt: jest.fn(),
+vi.mock("../redux/EditorSlice", async () => ({
+ ...(await vi.importActual("../redux/EditorSlice")),
+ syncProject: vi.fn((_) => vi.fn()),
+ expireJustLoaded: vi.fn(),
+ setHasShownSavePrompt: vi.fn(),
}));
-jest.mock("../utils/Notifications");
+vi.mock("../utils/Notifications");
const remixAction = { type: "REMIX_PROJECT" };
-const remixProject = jest.fn(() => remixAction);
+const remixProject = vi.fn(() => remixAction);
const saveAction = { type: "SAVE_PROJECT" };
-const saveProject = jest.fn(() => saveAction);
-const loadProject = jest.fn();
+const saveProject = vi.fn(() => saveAction);
+const loadProject = vi.fn();
-jest.useFakeTimers();
+vi.useFakeTimers();
const user1 = {
access_token: "myAccessToken1",
@@ -89,7 +89,7 @@ const editedProject = {
};
const createAsyncThunkDispatchMock = (resolveImmediately = saveAction) =>
- jest.fn(() => {
+ vi.fn(() => {
const thunkPromise =
typeof resolveImmediately === "function"
? new Promise((resolve) => {
@@ -135,7 +135,7 @@ describe("When not logged in", () => {
justLoaded: true,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
});
test("Expires justLoaded", () => {
@@ -156,7 +156,7 @@ describe("When not logged in", () => {
justLoaded: false,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
});
test("Login prompt shown", () => {
@@ -184,7 +184,7 @@ describe("When not logged in", () => {
hasShownSavePrompt: true,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
});
test("Login prompt shown", () => {
@@ -210,7 +210,7 @@ describe("When logged in", () => {
justLoaded: true,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
});
test("Expires justLoaded", () => {
@@ -231,7 +231,7 @@ describe("When logged in", () => {
justLoaded: true,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
});
test("Expires justLoaded", () => {
@@ -254,7 +254,7 @@ describe("When logged in", () => {
justLoaded: false,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
});
test("Save prompt shown", () => {
@@ -282,7 +282,7 @@ describe("When logged in", () => {
hasShownSavePrompt: true,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
});
test("Save prompt not shown again", () => {
@@ -298,8 +298,8 @@ describe("When logged in", () => {
describe("When project has identifier and save triggered", () => {
beforeEach(() => {
- syncProject.mockImplementationOnce(jest.fn((_) => remixProject));
- syncProject.mockImplementationOnce(jest.fn((_) => loadProject));
+ syncProject.mockImplementationOnce(vi.fn((_) => remixProject));
+ syncProject.mockImplementationOnce(vi.fn((_) => loadProject));
renderHook(() =>
useProjectPersistence({
@@ -308,7 +308,7 @@ describe("When logged in", () => {
saveTriggered: true,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
});
test("Clicking save dispatches remixProject with correct parameters", async () => {
@@ -329,8 +329,8 @@ describe("When logged in", () => {
describe("When project has identifier and save triggered without loadRemix", () => {
beforeEach(() => {
- syncProject.mockImplementationOnce(jest.fn((_) => remixProject));
- syncProject.mockImplementationOnce(jest.fn((_) => loadProject));
+ syncProject.mockImplementationOnce(vi.fn((_) => remixProject));
+ syncProject.mockImplementationOnce(vi.fn((_) => loadProject));
renderHook(() =>
useProjectPersistence({
@@ -340,7 +340,7 @@ describe("When logged in", () => {
loadRemix: false,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
});
test("Clicking save dispatches remixProject with correct parameters", async () => {
@@ -358,7 +358,7 @@ describe("When logged in", () => {
describe("When project has no identifier and save triggered", () => {
beforeEach(() => {
- syncProject.mockImplementationOnce(jest.fn((_) => saveProject));
+ syncProject.mockImplementationOnce(vi.fn((_) => saveProject));
renderHook(() =>
useProjectPersistence({
user: user2,
@@ -366,7 +366,7 @@ describe("When logged in", () => {
saveTriggered: true,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
});
test("Save project is called with the correct parameters", async () => {
@@ -381,7 +381,7 @@ describe("When logged in", () => {
describe("When user can autosave to the API", () => {
beforeEach(() => {
- syncProject.mockImplementation(jest.fn((_) => saveProject));
+ syncProject.mockImplementation(vi.fn((_) => saveProject));
});
test("Does not autosave unchanged project to database", () => {
@@ -392,7 +392,7 @@ describe("When logged in", () => {
saveTriggered: false,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
expect(saveProject).not.toHaveBeenCalled();
});
@@ -404,7 +404,7 @@ describe("When logged in", () => {
saveTriggered: false,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
expect(saveProject).toHaveBeenCalledWith({
project: editedProject,
accessToken: user1.access_token,
@@ -439,7 +439,7 @@ describe("When logged in", () => {
);
act(() => {
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
});
expect(saveProject).toHaveBeenCalledTimes(1);
@@ -447,7 +447,7 @@ describe("When logged in", () => {
rerender({ project: furtherEditedProject });
act(() => {
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
});
expect(saveProject).toHaveBeenCalledTimes(1);
@@ -458,7 +458,7 @@ describe("When logged in", () => {
});
act(() => {
- jest.advanceTimersByTime(10000);
+ vi.advanceTimersByTime(10000);
});
expect(saveProject).toHaveBeenCalledTimes(2);
@@ -478,7 +478,7 @@ describe("When logged in", () => {
saveTriggered: false,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
expect(saveProject).not.toHaveBeenCalled();
expect(expireJustLoaded).toHaveBeenCalled();
});
@@ -492,7 +492,7 @@ describe("When logged in", () => {
saveTriggered: false,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
expect(saveProject).toHaveBeenCalledWith({
project: editedProject,
accessToken: user1.access_token,
@@ -519,9 +519,9 @@ describe("When logged in", () => {
saveTriggered: false,
}),
);
- jest.advanceTimersByTime(2500);
+ vi.advanceTimersByTime(2500);
expect(saveProject).not.toHaveBeenCalled();
- jest.runAllTimers();
+ vi.runAllTimers();
expect(saveProject).toHaveBeenCalledWith({
project: largeProject,
accessToken: user1.access_token,
@@ -537,7 +537,7 @@ describe("When logged in", () => {
saveTriggered: true,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
expect(saveProject).toHaveBeenCalledWith({
project,
accessToken: user1.access_token,
@@ -555,7 +555,7 @@ describe("When logged in", () => {
saveTriggered: false,
}),
);
- jest.runAllTimers();
+ vi.runAllTimers();
expect(saveProject).toHaveBeenCalledWith({
project,
accessToken: user1.access_token,
diff --git a/src/hooks/useScratchSave/scratchSaveLifecycle.test.js b/src/hooks/useScratchSave/scratchSaveLifecycle.test.js
index dc7bff4e5..1b6a3fea0 100644
--- a/src/hooks/useScratchSave/scratchSaveLifecycle.test.js
+++ b/src/hooks/useScratchSave/scratchSaveLifecycle.test.js
@@ -1,6 +1,6 @@
import { createScratchSaveLifecycle } from "./scratchSaveLifecycle";
-jest.useFakeTimers();
+vi.useFakeTimers();
const createLifecycle = ({
context = {},
@@ -16,7 +16,7 @@ const createLifecycle = ({
let dirty = context.dirty ?? true;
let projectChangedAt = context.projectChangedAt ?? Date.now();
- const postSave = jest.fn();
+ const postSave = vi.fn();
const baseContext = {
canAutoSave: () => context.canAutoSave ?? true,
@@ -68,7 +68,7 @@ describe("scratchSaveLifecycle", () => {
expect(postSave).not.toHaveBeenCalled();
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
expect(postSave).toHaveBeenCalledWith({ autosave: true });
});
@@ -78,16 +78,16 @@ describe("scratchSaveLifecycle", () => {
createLifecycle();
triggerProjectChanged();
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
expect(postSave).toHaveBeenCalledTimes(1);
triggerProjectChanged();
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
expect(postSave).toHaveBeenCalledTimes(1);
resolveInFlight();
lifecycle.markSaveSucceeded(false);
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
expect(postSave).toHaveBeenCalledTimes(2);
});
@@ -97,12 +97,12 @@ describe("scratchSaveLifecycle", () => {
createLifecycle();
triggerProjectChanged();
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
resolveInFlight();
lifecycle.markSaveSucceeded(true);
triggerProjectChanged();
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
expect(postSave).toHaveBeenCalledTimes(1);
const flushPromise = lifecycle.flushPendingAutoSave();
@@ -141,18 +141,18 @@ describe("scratchSaveLifecycle", () => {
createLifecycle();
triggerProjectChanged();
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
expect(postSave).toHaveBeenCalledTimes(1);
lifecycle.markAutosaveFailed(true);
lifecycle.flushQueuedSave();
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
expect(postSave).toHaveBeenCalledTimes(2);
expect(schedulerState.autosaveRetryUsed).toBe(true);
lifecycle.markAutosaveFailed(true);
lifecycle.flushQueuedSave();
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
expect(postSave).toHaveBeenCalledTimes(2);
expect(schedulerState.queued).toBe(false);
});
@@ -161,17 +161,17 @@ describe("scratchSaveLifecycle", () => {
const { postSave, triggerProjectChanged, lifecycle } = createLifecycle();
triggerProjectChanged();
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
lifecycle.markAutosaveFailed(true);
lifecycle.flushQueuedSave();
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
lifecycle.markAutosaveFailed(true);
lifecycle.flushQueuedSave();
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
expect(postSave).toHaveBeenCalledTimes(2);
triggerProjectChanged();
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
expect(postSave).toHaveBeenCalledTimes(3);
});
});
diff --git a/src/hooks/useScratchSave/useScratchSaveState.test.jsx b/src/hooks/useScratchSave/useScratchSaveState.test.jsx
index d971e2656..f011ee83c 100644
--- a/src/hooks/useScratchSave/useScratchSaveState.test.jsx
+++ b/src/hooks/useScratchSave/useScratchSaveState.test.jsx
@@ -14,12 +14,12 @@ import {
getAutoSaveHostApi,
} from "../../utils/save/autoSaveHostApi";
-jest.mock("../../utils/scratchIframe", () => ({
- getScratchAllowedOrigin: jest.fn(),
- postMessageToScratchIframe: jest.fn(),
+vi.mock("../../utils/scratchIframe", () => ({
+ getScratchAllowedOrigin: vi.fn(),
+ postMessageToScratchIframe: vi.fn(),
}));
-jest.useFakeTimers();
+vi.useFakeTimers();
const scratchOrigin = "https://scratch-frame.example.com";
const scratchProject = {
@@ -85,7 +85,7 @@ describe("useScratchSaveState", () => {
const originalScratchFrameUrl = process.env.REACT_APP_SCRATCH_FRAME_URL;
beforeEach(() => {
- jest.clearAllMocks();
+ vi.clearAllMocks();
process.env.REACT_APP_SCRATCH_FRAME_URL = scratchOrigin;
getScratchAllowedOrigin.mockReturnValue(scratchOrigin);
});
@@ -94,7 +94,7 @@ describe("useScratchSaveState", () => {
scratchSaveUnmount?.();
scratchSaveUnmount = null;
clearScratchAutoSaveHostApi();
- jest.clearAllTimers();
+ vi.clearAllTimers();
process.env.REACT_APP_SCRATCH_FRAME_URL = originalScratchFrameUrl;
});
@@ -128,7 +128,7 @@ describe("useScratchSaveState", () => {
dispatchScratchMessage("scratch-gui-project-changed");
act(() => {
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
});
expect(postMessageToScratchIframe).not.toHaveBeenCalled();
@@ -141,7 +141,7 @@ describe("useScratchSaveState", () => {
dispatchScratchMessage("scratch-gui-ready");
act(() => {
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
});
expect(postMessageToScratchIframe).toHaveBeenCalledWith({
@@ -155,13 +155,13 @@ describe("useScratchSaveState", () => {
dispatchScratchUserEdit();
act(() => {
- jest.advanceTimersByTime(1999);
+ vi.advanceTimersByTime(1999);
});
expect(postMessageToScratchIframe).not.toHaveBeenCalled();
act(() => {
- jest.advanceTimersByTime(1);
+ vi.advanceTimersByTime(1);
});
expect(postMessageToScratchIframe).toHaveBeenCalledWith({
@@ -175,19 +175,19 @@ describe("useScratchSaveState", () => {
dispatchScratchUserEdit();
act(() => {
- jest.advanceTimersByTime(1000);
+ vi.advanceTimersByTime(1000);
});
dispatchScratchMessage("scratch-gui-project-changed");
act(() => {
- jest.advanceTimersByTime(999);
+ vi.advanceTimersByTime(999);
});
expect(postMessageToScratchIframe).not.toHaveBeenCalled();
act(() => {
- jest.advanceTimersByTime(1);
+ vi.advanceTimersByTime(1);
});
expect(postMessageToScratchIframe).toHaveBeenCalledTimes(1);
@@ -203,19 +203,19 @@ describe("useScratchSaveState", () => {
dispatchScratchUserEdit();
act(() => {
- jest.advanceTimersByTime(1000);
+ vi.advanceTimersByTime(1000);
});
dispatchScratchMessage("scratch-gui-saving-succeeded");
act(() => {
- jest.advanceTimersByTime(999);
+ vi.advanceTimersByTime(999);
});
expect(postMessageToScratchIframe).not.toHaveBeenCalled();
act(() => {
- jest.advanceTimersByTime(1);
+ vi.advanceTimersByTime(1);
});
expect(postMessageToScratchIframe).toHaveBeenCalledWith({
@@ -232,7 +232,7 @@ describe("useScratchSaveState", () => {
dispatchScratchUserEdit();
act(() => {
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
});
dispatchScratchMessage("scratch-gui-saving-started");
@@ -291,19 +291,19 @@ describe("useScratchSaveState", () => {
dispatchScratchUserEdit();
act(() => {
- jest.advanceTimersByTime(1000);
+ vi.advanceTimersByTime(1000);
});
dispatchScratchMessage("scratch-gui-saving-failed");
act(() => {
- jest.advanceTimersByTime(999);
+ vi.advanceTimersByTime(999);
});
expect(postMessageToScratchIframe).not.toHaveBeenCalled();
act(() => {
- jest.advanceTimersByTime(1);
+ vi.advanceTimersByTime(1);
});
expect(postMessageToScratchIframe).toHaveBeenCalledWith({
@@ -339,7 +339,7 @@ describe("useScratchSaveState", () => {
dispatchScratchUserEdit();
act(() => {
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
});
dispatchScratchMessage("scratch-gui-saving-started");
@@ -348,13 +348,13 @@ describe("useScratchSaveState", () => {
dispatchScratchMessage("scratch-gui-project-changed");
act(() => {
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
});
expect(postMessageToScratchIframe).toHaveBeenCalledTimes(1);
act(() => {
- jest.advanceTimersByTime(10000);
+ vi.advanceTimersByTime(10000);
});
expect(postMessageToScratchIframe).toHaveBeenCalledTimes(2);
@@ -366,7 +366,7 @@ describe("useScratchSaveState", () => {
dispatchScratchUserEdit();
act(() => {
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
});
dispatchScratchMessage("scratch-gui-saving-started");
@@ -375,7 +375,7 @@ describe("useScratchSaveState", () => {
dispatchScratchMessage("scratch-gui-project-changed");
act(() => {
- jest.advanceTimersByTime(2000);
+ vi.advanceTimersByTime(2000);
});
expect(postMessageToScratchIframe).toHaveBeenCalledTimes(1);
@@ -414,7 +414,7 @@ describe("useScratchSaveState", () => {
dispatchScratchUserEdit();
act(() => {
- jest.advanceTimersByTime(1000);
+ vi.advanceTimersByTime(1000);
});
expect(postMessageToScratchIframe).not.toHaveBeenCalled();
diff --git a/src/redux/EditorSlice.test.js b/src/redux/EditorSlice.test.js
index 3237afccb..ec785f862 100644
--- a/src/redux/EditorSlice.test.js
+++ b/src/redux/EditorSlice.test.js
@@ -25,20 +25,28 @@ import reducer, {
setFriendlyError,
} from "./EditorSlice";
-const mockCreateRemix = jest.fn();
-const mockDeleteProject = jest.fn();
-const mockLoadAssets = jest.fn();
-const mockReadProject = jest.fn();
-const mockCreateOrUpdateProject = jest.fn();
-
-jest.mock("../utils/apiCallHandler", () => () => ({
- createRemix: jest.fn(mockCreateRemix),
- deleteProject: jest.fn(mockDeleteProject),
- loadAssets: jest.fn(mockLoadAssets),
- readProject: jest.fn(mockReadProject),
- createOrUpdateProject: jest.fn(mockCreateOrUpdateProject),
+const mockCreateRemix = vi.fn();
+const mockDeleteProject = vi.fn();
+const mockLoadAssets = vi.fn();
+const mockReadProject = vi.fn();
+const mockCreateOrUpdateProject = vi.fn();
+
+vi.mock("../utils/apiCallHandler", () => ({
+ default: () => ({
+ createRemix: vi.fn(mockCreateRemix),
+ deleteProject: vi.fn(mockDeleteProject),
+ loadAssets: vi.fn(mockLoadAssets),
+ readProject: vi.fn(mockReadProject),
+ createOrUpdateProject: vi.fn(mockCreateOrUpdateProject),
+ }),
}));
+const originalDateNow = Date.now;
+
+afterEach(() => {
+ Date.now = originalDateNow;
+});
+
const friendlyErrorHtml =
'Friendly error title
' +
'A friendly summary of the error
';
@@ -301,7 +309,7 @@ test("Action setFriendlyError sets friendlyError", () => {
});
describe("When project has no identifier", () => {
- const dispatch = jest.fn();
+ const dispatch = vi.fn();
const project = {
name: "hello world",
project_type: "python",
@@ -329,7 +337,7 @@ describe("When project has no identifier", () => {
let saveAction;
beforeEach(() => {
- Date.now = jest.fn(() => 1669808953);
+ Date.now = vi.fn(() => 1669808953);
saveThunk = syncProject("save");
saveAction = saveThunk({
project,
@@ -387,7 +395,7 @@ describe("When project has no identifier", () => {
});
describe("When project has an identifier", () => {
- const dispatch = jest.fn();
+ const dispatch = vi.fn();
const project = {
name: "hello world",
project_type: "python",
@@ -420,6 +428,7 @@ describe("When project has an identifier", () => {
beforeEach(() => {
localStorage.clear();
+ Date.now = vi.fn(() => 1669808953);
saveThunk = syncProject("save");
saveAction = saveThunk({
@@ -463,6 +472,7 @@ describe("When project has an identifier", () => {
const expectedState = {
project: project,
saving: "success",
+ lastSavedTime: 1669808953,
initialComponents: [
{
name: "main",
@@ -540,7 +550,7 @@ describe("When project has an identifier", () => {
});
describe("When deleting a project", () => {
- const dispatch = jest.fn();
+ const dispatch = vi.fn();
let project = { identifier: "my-amazing-project", name: "hello world" };
const access_token = "myToken";
const initialState = {
@@ -730,7 +740,7 @@ describe("Updating file name", () => {
});
describe("Loading a project", () => {
- const dispatch = jest.fn();
+ const dispatch = vi.fn();
const identifier = "my-project-identifier";
const accessToken = "myToken";
const locale = "es-LA";
@@ -989,7 +999,7 @@ describe("initialComponents snapshot", () => {
});
test("Scratch save lifecycle actions update editor save state", () => {
- Date.now = jest.fn(() => 1669808953);
+ Date.now = vi.fn(() => 1669808953);
const initialState = reducer(
undefined,
setProject({
diff --git a/src/redux/reducers/loadProjectReducers.test.js b/src/redux/reducers/loadProjectReducers.test.js
index 95c50c2c4..07ddde7d4 100644
--- a/src/redux/reducers/loadProjectReducers.test.js
+++ b/src/redux/reducers/loadProjectReducers.test.js
@@ -3,13 +3,15 @@ import produce from "immer";
import reducer, { syncProject } from "../../redux/EditorSlice";
import { loadProjectRejected } from "./loadProjectReducers";
-const mockReadProject = jest.fn();
-jest.mock("../../utils/apiCallHandler", () => () => ({
- readProject: jest.fn(mockReadProject),
+const mockReadProject = vi.fn();
+vi.mock("../../utils/apiCallHandler", () => ({
+ default: () => ({
+ readProject: vi.fn(mockReadProject),
+ }),
}));
const requestingAProject = function (project, projectFile) {
- const dispatch = jest.fn();
+ const dispatch = vi.fn();
const initialState = {
editor: {
project: {},
diff --git a/src/utils/Notifications.test.js b/src/utils/Notifications.test.js
index 4548661f1..6e921e91a 100644
--- a/src/utils/Notifications.test.js
+++ b/src/utils/Notifications.test.js
@@ -5,10 +5,10 @@ import {
showSavePrompt,
} from "./Notifications";
-jest.mock("./i18n", () => ({
- t: (string) => string,
+vi.mock("./i18n", () => ({
+ default: { t: (string) => string },
}));
-jest.mock("react-toastify");
+vi.mock("react-toastify");
test("Calling showSavedMessage calls toast with correct string", () => {
showSavedMessage();
diff --git a/src/utils/ResizableWithHandle.test.jsx b/src/utils/ResizableWithHandle.test.jsx
index 27a4593a9..ca1aa10d0 100644
--- a/src/utils/ResizableWithHandle.test.jsx
+++ b/src/utils/ResizableWithHandle.test.jsx
@@ -4,7 +4,7 @@ import ResizableWithHandle from "./ResizableWithHandle";
let mockResizeStop;
-jest.mock("re-resizable", () => ({
+vi.mock("re-resizable", () => ({
Resizable: ({
children,
handleComponent,
diff --git a/src/utils/SelectButtons.test.jsx b/src/utils/SelectButtons.test.jsx
index 8fc6a5c91..1dbbc7c3c 100644
--- a/src/utils/SelectButtons.test.jsx
+++ b/src/utils/SelectButtons.test.jsx
@@ -2,7 +2,7 @@ import { fireEvent, render, screen } from "@testing-library/react";
import React from "react";
import SelectButtons from "./SelectButtons";
-const setValue = jest.fn();
+const setValue = vi.fn();
beforeEach(() => {
render(
diff --git a/src/utils/ToastCloseButton.test.jsx b/src/utils/ToastCloseButton.test.jsx
index 88fd9fd48..044b82b11 100644
--- a/src/utils/ToastCloseButton.test.jsx
+++ b/src/utils/ToastCloseButton.test.jsx
@@ -2,7 +2,7 @@ import React from "react";
import { fireEvent, render, screen } from "@testing-library/react";
import ToastCloseButton from "./ToastCloseButton";
-const closeToast = jest.fn();
+const closeToast = vi.fn();
beforeEach(() => {
render();
diff --git a/src/utils/apiCallHandler.test.js b/src/utils/apiCallHandler.test.js
index d478e73fa..e5fb96d14 100644
--- a/src/utils/apiCallHandler.test.js
+++ b/src/utils/apiCallHandler.test.js
@@ -2,7 +2,7 @@ import axios from "axios";
import ApiCallHandler from "./apiCallHandler";
-jest.mock("axios");
+vi.mock("axios");
const host = "http://localhost:3009";
const defaultHeaders = { headers: { Accept: "application/json" } };
const accessToken = "39a09671-be55-4847-baf5-8919a0c24a25";
diff --git a/src/utils/save/autoSaveHostApi.test.js b/src/utils/save/autoSaveHostApi.test.js
index f68fc20ca..8146994d5 100644
--- a/src/utils/save/autoSaveHostApi.test.js
+++ b/src/utils/save/autoSaveHostApi.test.js
@@ -24,8 +24,8 @@ describe("autoSaveHostApi", () => {
});
test("flushes project and scratch saves in sequence", async () => {
- const projectFlush = jest.fn(() => Promise.resolve());
- const scratchFlush = jest.fn(() => Promise.resolve());
+ const projectFlush = vi.fn(() => Promise.resolve());
+ const scratchFlush = vi.fn(() => Promise.resolve());
registerAutoSaveHostApi({
flushPendingAutoSave: projectFlush,
diff --git a/src/utils/save/autoSaveLifecycle.test.js b/src/utils/save/autoSaveLifecycle.test.js
index 195b68e38..c2620172b 100644
--- a/src/utils/save/autoSaveLifecycle.test.js
+++ b/src/utils/save/autoSaveLifecycle.test.js
@@ -1,12 +1,12 @@
import { syncProject } from "../../redux/EditorSlice";
import { createAutoSaveLifecycle } from "./autoSaveLifecycle";
-jest.mock("../../redux/EditorSlice", () => ({
- ...jest.requireActual("../../redux/EditorSlice"),
- syncProject: jest.fn((_) => jest.fn()),
+vi.mock("../../redux/EditorSlice", async () => ({
+ ...(await vi.importActual("../../redux/EditorSlice")),
+ syncProject: vi.fn((_) => vi.fn()),
}));
-jest.useFakeTimers();
+vi.useFakeTimers();
const user1 = {
access_token: "myAccessToken1",
@@ -30,7 +30,7 @@ const editedProject = {
};
const saveAction = { type: "SAVE_PROJECT" };
-const saveProject = jest.fn(() => saveAction);
+const saveProject = vi.fn(() => saveAction);
/** flushPendingAutoSave is async; yield so it reaches its next await. */
const awaitAsyncFlush = () => Promise.resolve();
@@ -56,7 +56,7 @@ const createLifecycle = ({
let resolveSave;
let rejectSave;
- const dispatch = jest.fn(() => {
+ const dispatch = vi.fn(() => {
const thunkPromise = new Promise((resolve) => {
resolveSave = resolve;
rejectSave = (error) =>
@@ -110,7 +110,7 @@ const createLifecycle = ({
};
beforeEach(() => {
- syncProject.mockImplementation(jest.fn((_) => saveProject));
+ syncProject.mockImplementation(vi.fn((_) => saveProject));
});
describe("autoSaveLifecycle", () => {
@@ -162,7 +162,7 @@ describe("autoSaveLifecycle", () => {
lifecycle.requestAutoSave();
expect(dispatch).toHaveBeenCalledTimes(1);
- jest.advanceTimersByTime(10000);
+ vi.advanceTimersByTime(10000);
expect(inFlightSavePromiseRef.current).not.toBeNull();
await completeInFlightSave({ inFlightSavePromiseRef, resolveSave });
diff --git a/src/utils/scratchIframe.test.js b/src/utils/scratchIframe.test.js
index e373a56b4..a523ab205 100644
--- a/src/utils/scratchIframe.test.js
+++ b/src/utils/scratchIframe.test.js
@@ -13,13 +13,13 @@ describe("scratchIframe", () => {
let originalQuerySelector;
beforeEach(() => {
- mockPostMessage = jest.fn();
+ mockPostMessage = vi.fn();
mockContentWindow = { postMessage: mockPostMessage };
- mockShadowQuerySelector = jest.fn(() => ({
+ mockShadowQuerySelector = vi.fn(() => ({
contentWindow: mockContentWindow,
}));
originalQuerySelector = document.querySelector;
- document.querySelector = jest.fn(() => ({
+ document.querySelector = vi.fn(() => ({
shadowRoot: {
querySelector: mockShadowQuerySelector,
},
@@ -91,7 +91,7 @@ describe("scratchIframe", () => {
});
it("calls the handler with the updated project id", () => {
- const handler = jest.fn();
+ const handler = vi.fn();
const unsubscribe = subscribeToScratchProjectIdentifierUpdates(handler);
window.dispatchEvent(
@@ -111,7 +111,7 @@ describe("scratchIframe", () => {
it("accepts updates when REACT_APP_SCRATCH_FRAME_URL contains a path", () => {
process.env.REACT_APP_SCRATCH_FRAME_URL =
"https://scratch-frame.example.com/branches/main";
- const handler = jest.fn();
+ const handler = vi.fn();
const unsubscribe = subscribeToScratchProjectIdentifierUpdates(handler);
window.dispatchEvent(
@@ -129,7 +129,7 @@ describe("scratchIframe", () => {
});
it("ignores unrelated messages", () => {
- const handler = jest.fn();
+ const handler = vi.fn();
const unsubscribe = subscribeToScratchProjectIdentifierUpdates(handler);
window.dispatchEvent(
diff --git a/src/utils/setupTests.vitest.js b/src/utils/setupTests.vitest.js
index b4716c0e1..7f1497d1d 100644
--- a/src/utils/setupTests.vitest.js
+++ b/src/utils/setupTests.vitest.js
@@ -1,3 +1,74 @@
// Vitest equivalent of setupTests.js, used by every file not listed in
// JEST_ONLY_TEST_FILES (test-runner-migration.js).
import "@testing-library/jest-dom";
+import { vi } from "vitest";
+
+class MemoryStorage {
+ #store = new Map();
+
+ getItem(key) {
+ return this.#store.has(key) ? this.#store.get(key) : null;
+ }
+
+ setItem(key, value) {
+ this.#store.set(key, String(value));
+ }
+
+ removeItem(key) {
+ this.#store.delete(key);
+ }
+
+ clear() {
+ this.#store.clear();
+ }
+
+ get length() {
+ return this.#store.size;
+ }
+
+ key(index) {
+ return Array.from(this.#store.keys())[index] ?? null;
+ }
+}
+
+Object.defineProperty(window, "localStorage", {
+ value: new MemoryStorage(),
+ configurable: true,
+});
+
+window.matchMedia = (query) => ({
+ matches: false,
+ media: query,
+ onchange: null,
+ addListener: vi.fn(), // Deprecated
+ removeListener: vi.fn(), // Deprecated
+ addEventListener: vi.fn(),
+ removeEventListener: vi.fn(),
+ dispatchEvent: vi.fn(),
+});
+
+vi.mock("@raspberrypifoundation/python-friendly-error-messages", () => ({
+ loadCopydeckFor: vi.fn(),
+ registerAdapter: vi.fn(),
+ cpythonAdapter: {},
+ friendlyExplain: vi.fn(),
+}));
+
+vi.mock("react-i18next", () => ({
+ useTranslation: () => ({
+ t: (str) => (str.includes("null") ? null : str),
+ i18n: {
+ changeLanguage: () => new Promise(() => {}),
+ language: "ja-JP",
+ options: {
+ locales: ["en", "es-LA", "fr-FR", "ja-JP"],
+ },
+ },
+ }),
+ Trans: ({ children, i18nKey }) => children || i18nKey,
+ initReactI18next: {},
+}));
+
+vi.mock("./i18n", () => ({
+ default: { t: (string) => string },
+}));
diff --git a/test-runner-migration.js b/test-runner-migration.js
index f53d49d09..198ab5ffd 100644
--- a/test-runner-migration.js
+++ b/test-runner-migration.js
@@ -6,68 +6,14 @@
// Vitest - anything not listed here runs under Vitest by default, including
// any new test file.
const JEST_ONLY_TEST_FILES = [
- "src/components/AstroPiModel/AstroPiControls/MotionInput.test.jsx",
- "src/components/AstroPiModel/FlightCase.test.jsx",
- "src/components/AstroPiModel/OrientationPanel/OrientationPanel.test.jsx",
- "src/components/AstroPiModel/OrientationPanel/OrientationResetButton.test.jsx",
- "src/components/AstroPiModel/Simulator.test.jsx",
- "src/components/DownloadButton/DownloadButton.test.jsx",
- "src/components/Editor/EditorInput/EditorInput.test.jsx",
- "src/components/Editor/EditorPanel/EditorPanel.test.jsx",
- "src/components/Editor/ErrorMessage/ErrorMessage.test.jsx",
- "src/components/Editor/Output/Output.test.jsx",
"src/components/Editor/Project/Project.test.jsx",
"src/components/Editor/Project/ScratchContainer.test.jsx",
- "src/components/Editor/Runners/HtmlRunner/HtmlRenderer.test.jsx",
"src/components/Editor/Runners/HtmlRunner/HtmlRunner.test.jsx",
"src/components/Editor/Runners/PythonRunner/PyodideRunner/PyodideRunner.test.jsx",
"src/components/Editor/Runners/PythonRunner/PyodideRunner/PyodideWorker.test.js",
"src/components/Editor/Runners/PythonRunner/PyodideRunner/VisualOutputPane.test.jsx",
"src/components/Editor/Runners/PythonRunner/PythonRunner.test.jsx",
"src/components/Editor/Runners/PythonRunner/SkulptRunner/SkulptRunner.test.jsx",
- "src/components/Menus/ContextMenu/ContextMenu.test.jsx",
- "src/components/Menus/FileMenu/FileMenu.test.jsx",
- "src/components/Menus/Sidebar/DownloadPanel/DownloadPanel.test.jsx",
- "src/components/Menus/Sidebar/FilePanel/FilePanel.test.jsx",
- "src/components/Menus/Sidebar/InstructionsPanel/InstructionsPanel.test.jsx",
- "src/components/Menus/Sidebar/InstructionsPanel/ProgressBar/ProgressBar.test.jsx",
- "src/components/Menus/Sidebar/ProjectsPanel/ProjectsPanel.test.jsx",
- "src/components/Menus/Sidebar/SettingsPanel/SettingsPanel.test.jsx",
- "src/components/Menus/Sidebar/SettingsPanel/ThemeToggle/ThemeToggle.test.jsx",
- "src/components/Menus/Sidebar/Sidebar.test.jsx",
- "src/components/Menus/Sidebar/SidebarBar.test.jsx",
- "src/components/Menus/Sidebar/SidebarBarOption.test.jsx",
- "src/components/Mobile/MobileProject/MobileProject.test.jsx",
- "src/components/Modals/ErrorModal.test.jsx",
- "src/components/Modals/GeneralModal.test.jsx",
- "src/components/ProjectBar/ProjectBar.test.jsx",
- "src/components/ProjectBar/ScratchProjectBar.test.jsx",
- "src/components/ProjectName/ProjectName.test.jsx",
- "src/components/RunButton/StopButton.test.jsx",
- "src/components/SaveButton/SaveButton.test.jsx",
- "src/components/SaveStatus/SaveStatus.test.jsx",
- "src/components/UploadButton/UploadButton.test.jsx",
- "src/components/WebComponentProject/WebComponentProject.integration.test.jsx",
- "src/components/WebComponentProject/WebComponentProject.test.jsx",
- "src/components/WebComponentProject/runEventCodeSnapshot.test.js",
- "src/containers/WebComponentLoader.test.jsx",
- "src/hooks/useAutoSave/useAutoSave.test.js",
- "src/hooks/useContainerMinWidth.test.js",
- "src/hooks/useIsOnline.test.js",
- "src/hooks/useProject.test.jsx",
- "src/hooks/useProjectPersistence.test.js",
- "src/hooks/useScratchSave/scratchSaveLifecycle.test.js",
- "src/hooks/useScratchSave/useScratchSaveState.test.jsx",
- "src/redux/EditorSlice.test.js",
- "src/redux/reducers/loadProjectReducers.test.js",
- "src/utils/Notifications.test.js",
- "src/utils/ResizableWithHandle.test.jsx",
- "src/utils/SelectButtons.test.jsx",
- "src/utils/ToastCloseButton.test.jsx",
- "src/utils/apiCallHandler.test.js",
- "src/utils/save/autoSaveHostApi.test.js",
- "src/utils/save/autoSaveLifecycle.test.js",
- "src/utils/scratchIframe.test.js",
];
module.exports = { JEST_ONLY_TEST_FILES };
diff --git a/vite.config.js b/vite.config.js
index 8d151382b..369e45770 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -170,6 +170,7 @@ export default defineConfig(async ({ mode }) => {
test: {
environment: "jsdom",
globals: true,
+ mockReset: true,
setupFiles: [path.resolve(__dirname, "src/utils/setupTests.vitest.js")],
include: [
"src/**/__tests__/**/*.{js,jsx,ts,tsx}",