chore: migrate a bunch of tests to vitest (#21514)

This commit is contained in:
ケイラ
2026-01-15 12:38:29 -07:00
committed by GitHub
parent d25d95231f
commit d2d7c0ee40
25 changed files with 86 additions and 89 deletions
@@ -17,7 +17,7 @@ describe(PaginationWidgetBase.name, () => {
]; ];
for (const props of sampleProps) { for (const props of sampleProps) {
const onPageChange = jest.fn(); const onPageChange = vi.fn();
const { unmount } = renderWithAuth( const { unmount } = renderWithAuth(
<PaginationWidgetBase {...props} onPageChange={onPageChange} />, <PaginationWidgetBase {...props} onPageChange={onPageChange} />,
); );
@@ -39,7 +39,7 @@ describe(PaginationWidgetBase.name, () => {
]; ];
for (const props of sampleProps) { for (const props of sampleProps) {
const onPageChange = jest.fn(); const onPageChange = vi.fn();
const { unmount } = renderWithAuth( const { unmount } = renderWithAuth(
<PaginationWidgetBase {...props} onPageChange={onPageChange} />, <PaginationWidgetBase {...props} onPageChange={onPageChange} />,
); );
@@ -61,7 +61,7 @@ describe(PaginationWidgetBase.name, () => {
]; ];
for (const props of sampleProps) { for (const props of sampleProps) {
const onPageChange = jest.fn(); const onPageChange = vi.fn();
const { unmount } = renderWithAuth( const { unmount } = renderWithAuth(
<PaginationWidgetBase {...props} onPageChange={onPageChange} />, <PaginationWidgetBase {...props} onPageChange={onPageChange} />,
); );
@@ -22,13 +22,12 @@ import {
} from "./ProxyContext"; } from "./ProxyContext";
import type * as ProxyLatency from "./useProxyLatency"; import type * as ProxyLatency from "./useProxyLatency";
// Mock useProxyLatency to use a hard-coded latency. 'jest.mock' must be called // Mock useProxyLatency to use a hard-coded latency.
// here and not inside a unit test. vi.mock("contexts/useProxyLatency", () => ({
jest.mock("contexts/useProxyLatency", () => ({
useProxyLatency: () => { useProxyLatency: () => {
return { return {
proxyLatencies: hardCodedLatencies, proxyLatencies: hardCodedLatencies,
refetch: jest.fn(), refetch: vi.fn(),
loaded: true, loaded: true,
}; };
}, },
@@ -48,9 +48,9 @@ const createAuthWrapper = (override: Partial<AuthContextValue>) => {
organizationIds: undefined, organizationIds: undefined,
signInError: undefined, signInError: undefined,
updateProfileError: undefined, updateProfileError: undefined,
signOut: jest.fn(), signOut: vi.fn(),
signIn: jest.fn(), signIn: vi.fn(),
updateProfile: jest.fn(), updateProfile: vi.fn(),
...override, ...override,
}; };
const Wrapper: FC<PropsWithChildren> = ({ children }) => { const Wrapper: FC<PropsWithChildren> = ({ children }) => {
@@ -66,7 +66,7 @@ const createAuthWrapper = (override: Partial<AuthContextValue>) => {
describe("useAuthenticated", () => { describe("useAuthenticated", () => {
it("throws an error if it is used outside of a context with user", () => { it("throws an error if it is used outside of a context with user", () => {
jest.spyOn(console, "error").mockImplementation(() => {}); vi.spyOn(console, "error").mockImplementation(() => {});
expect(() => { expect(() => {
renderHook(() => useAuthenticated(), { renderHook(() => useAuthenticated(), {
@@ -74,11 +74,11 @@ describe("useAuthenticated", () => {
}); });
}).toThrow("User is not authenticated."); }).toThrow("User is not authenticated.");
jest.restoreAllMocks(); vi.restoreAllMocks();
}); });
it("throws an error if it is used outside of a context with permissions", () => { it("throws an error if it is used outside of a context with permissions", () => {
jest.spyOn(console, "error").mockImplementation(() => {}); vi.spyOn(console, "error").mockImplementation(() => {});
expect(() => { expect(() => {
renderHook(() => useAuthenticated(), { renderHook(() => useAuthenticated(), {
@@ -86,7 +86,7 @@ describe("useAuthenticated", () => {
}); });
}).toThrow("Permissions are not available."); }).toThrow("Permissions are not available.");
jest.restoreAllMocks(); vi.restoreAllMocks();
}); });
it("returns auth context values for authenticated context", () => { it("returns auth context values for authenticated context", () => {
@@ -1,7 +1,7 @@
import { render, screen } from "@testing-library/react"; import { render, screen } from "@testing-library/react";
import { ClassicParameterFlowDeprecationWarning } from "./ClassicParameterFlowDeprecationWarning"; import { ClassicParameterFlowDeprecationWarning } from "./ClassicParameterFlowDeprecationWarning";
jest.mock("modules/navigation", () => ({ vi.mock("modules/navigation", () => ({
useLinks: () => () => "/mock-link", useLinks: () => () => "/mock-link",
linkToTemplate: () => "/mock-template-link", linkToTemplate: () => "/mock-template-link",
})); }));
@@ -48,7 +48,7 @@ const renderPage = async ({ filter, page }: RenderPageOptions = {}) => {
describe("AuditPage", () => { describe("AuditPage", () => {
beforeEach(() => { beforeEach(() => {
// Mocking the dayjs module within the createDayString file // Mocking the dayjs module within the createDayString file
const mock = jest.spyOn(CreateDayString, "createDayString"); const mock = vi.spyOn(CreateDayString, "createDayString");
mock.mockImplementation(() => "a minute ago"); mock.mockImplementation(() => "a minute ago");
// Mock the entitlements // Mock the entitlements
@@ -62,7 +62,7 @@ describe("AuditPage", () => {
it("renders page 5", async () => { it("renders page 5", async () => {
// Given // Given
const page = 5; const page = 5;
const getAuditLogsSpy = jest.spyOn(API, "getAuditLogs").mockResolvedValue({ const getAuditLogsSpy = vi.spyOn(API, "getAuditLogs").mockResolvedValue({
audit_logs: [MockAuditLog, MockAuditLog2], audit_logs: [MockAuditLog, MockAuditLog2],
count: 2, count: 2,
}); });
@@ -82,7 +82,7 @@ describe("AuditPage", () => {
describe("Filtering", () => { describe("Filtering", () => {
it("filters by URL", async () => { it("filters by URL", async () => {
const getAuditLogsSpy = jest const getAuditLogsSpy = vi
.spyOn(API, "getAuditLogs") .spyOn(API, "getAuditLogs")
.mockResolvedValue({ audit_logs: [MockAuditLog], count: 1 }); .mockResolvedValue({ audit_logs: [MockAuditLog], count: 1 });
@@ -99,7 +99,7 @@ describe("AuditPage", () => {
it("resets page to 1 when filter is changed", async () => { it("resets page to 1 when filter is changed", async () => {
await renderPage({ page: 2 }); await renderPage({ page: 2 });
const getAuditLogsSpy = jest.spyOn(API, "getAuditLogs"); const getAuditLogsSpy = vi.spyOn(API, "getAuditLogs");
getAuditLogsSpy.mockClear(); getAuditLogsSpy.mockClear();
const filterField = screen.getByLabelText("Filter"); const filterField = screen.getByLabelText("Filter");
@@ -47,7 +47,7 @@ const renderPage = async ({ filter, page }: RenderPageOptions = {}) => {
describe("ConnectionLogPage", () => { describe("ConnectionLogPage", () => {
beforeEach(() => { beforeEach(() => {
// Mocking the dayjs module within the createDayString file // Mocking the dayjs module within the createDayString file
const mock = jest.spyOn(CreateDayString, "createDayString"); const mock = vi.spyOn(CreateDayString, "createDayString");
mock.mockImplementation(() => "a minute ago"); mock.mockImplementation(() => "a minute ago");
// Mock the entitlements // Mock the entitlements
@@ -61,7 +61,7 @@ describe("ConnectionLogPage", () => {
it("renders page 5", async () => { it("renders page 5", async () => {
// Given // Given
const page = 5; const page = 5;
const getConnectionLogsSpy = jest const getConnectionLogsSpy = vi
.spyOn(API, "getConnectionLogs") .spyOn(API, "getConnectionLogs")
.mockResolvedValue({ .mockResolvedValue({
connection_logs: [ connection_logs: [
@@ -90,7 +90,7 @@ describe("ConnectionLogPage", () => {
describe("Filtering", () => { describe("Filtering", () => {
it("filters by URL", async () => { it("filters by URL", async () => {
const getConnectionLogsSpy = jest const getConnectionLogsSpy = vi
.spyOn(API, "getConnectionLogs") .spyOn(API, "getConnectionLogs")
.mockResolvedValue({ .mockResolvedValue({
connection_logs: [MockConnectedSSHConnectionLog], connection_logs: [MockConnectedSSHConnectionLog],
@@ -110,7 +110,7 @@ describe("ConnectionLogPage", () => {
it("resets page to 1 when filter is changed", async () => { it("resets page to 1 when filter is changed", async () => {
await renderPage({ page: 2 }); await renderPage({ page: 2 });
const getConnectionLogsSpy = jest.spyOn(API, "getConnectionLogs"); const getConnectionLogsSpy = vi.spyOn(API, "getConnectionLogs");
getConnectionLogsSpy.mockClear(); getConnectionLogsSpy.mockClear();
const filterField = screen.getByLabelText("Filter"); const filterField = screen.getByLabelText("Filter");
@@ -16,7 +16,7 @@ import type { SlimRole } from "api/typesGenerated";
import { HttpResponse, http } from "msw"; import { HttpResponse, http } from "msw";
import OrganizationMembersPage from "./OrganizationMembersPage"; import OrganizationMembersPage from "./OrganizationMembersPage";
jest.spyOn(console, "error").mockImplementation(() => {}); vi.spyOn(console, "error").mockImplementation(() => {});
beforeEach(() => { beforeEach(() => {
server.use( server.use(
@@ -12,7 +12,7 @@ import { screen } from "@testing-library/react";
import { HttpResponse, http } from "msw"; import { HttpResponse, http } from "msw";
import OrganizationRedirect from "./OrganizationRedirect"; import OrganizationRedirect from "./OrganizationRedirect";
jest.spyOn(console, "error").mockImplementation(() => {}); vi.spyOn(console, "error").mockImplementation(() => {});
const renderPage = async () => { const renderPage = async () => {
const { router } = renderWithOrganizationSettingsLayout( const { router } = renderWithOrganizationSettingsLayout(
@@ -124,7 +124,7 @@ describe("Setup Page", () => {
}); });
it("calls sendBeacon with telemetry", async () => { it("calls sendBeacon with telemetry", async () => {
const sendBeacon = jest.fn(); const sendBeacon = vi.fn();
Object.defineProperty(window.navigator, "sendBeacon", { Object.defineProperty(window.navigator, "sendBeacon", {
value: sendBeacon, value: sendBeacon,
}); });
@@ -24,9 +24,10 @@ it("redirects from multi-org to single-org", async () => {
}); });
it("redirects from single-org to multi-org", async () => { it("redirects from single-org to multi-org", async () => {
jest vi.spyOn(API, "getOrganizations").mockResolvedValueOnce([
.spyOn(API, "getOrganizations") M.MockDefaultOrganization,
.mockResolvedValueOnce([M.MockDefaultOrganization, M.MockOrganization2]); M.MockOrganization2,
]);
const { router } = renderTemplateRedirectController( const { router } = renderTemplateRedirectController(
`/templates/${M.MockTemplate.name}`, `/templates/${M.MockTemplate.name}`,
@@ -110,29 +110,27 @@ const fillAndSubmitForm = async ({
await user.click(confirmButton); await user.click(confirmButton);
}; };
// One problem with the waitFor function is that if no additional config options // By default, waitFor will lock until it succeeds or the test times out, and
// are passed in, it will hang indefinitely as it keeps retrying an assertion. // won't give a very informative error if the test times out. Setting a timeout
// Even if Jest runs out of time and kills the test, you won't get a good error // slightly shorter than the test timeout helps give a more informative error
// message. Adding options to force test to give up before test timeout // because Vitest will act as if something specific went wrong rather than
// vaguely handwaving about something taking too long.
function waitForWithCutoff(callback: () => void | Promise<void>) { function waitForWithCutoff(callback: () => void | Promise<void>) {
return waitFor(callback, { return waitFor(callback, {
// Defined to end 500ms before global cut-off time of 20s. Wanted to define timeout: 4_500,
// this in terms of an exported constant from jest.config, but since Jest
// is CJS-based, that would've involved weird CJS-ESM interop issues
timeout: 19_500,
}); });
} }
describe("TemplateSchedulePage", () => { describe("TemplateSchedulePage", () => {
beforeEach(() => { beforeEach(() => {
jest vi.spyOn(API, "getEntitlements").mockResolvedValue(
.spyOn(API, "getEntitlements") MockEntitlementsWithScheduling,
.mockResolvedValue(MockEntitlementsWithScheduling); );
}); });
it("Calls the API when user fills in and submits a form", async () => { it("Calls the API when user fills in and submits a form", async () => {
await renderTemplateSchedulePage(); await renderTemplateSchedulePage();
jest.spyOn(API, "updateTemplateMeta").mockResolvedValueOnce({ vi.spyOn(API, "updateTemplateMeta").mockResolvedValueOnce({
...MockTemplate, ...MockTemplate,
...validFormValues, ...validFormValues,
}); });
@@ -146,7 +144,7 @@ describe("TemplateSchedulePage", () => {
test("default is converted to and from hours", async () => { test("default is converted to and from hours", async () => {
await renderTemplateSchedulePage(); await renderTemplateSchedulePage();
jest.spyOn(API, "updateTemplateMeta").mockResolvedValueOnce({ vi.spyOn(API, "updateTemplateMeta").mockResolvedValueOnce({
...MockTemplate, ...MockTemplate,
...validFormValues, ...validFormValues,
}); });
@@ -169,7 +167,7 @@ describe("TemplateSchedulePage", () => {
test("failure, dormancy, and dormancy auto-deletion converted to and from days", async () => { test("failure, dormancy, and dormancy auto-deletion converted to and from days", async () => {
await renderTemplateSchedulePage(); await renderTemplateSchedulePage();
jest.spyOn(API, "updateTemplateMeta").mockResolvedValueOnce({ vi.spyOn(API, "updateTemplateMeta").mockResolvedValueOnce({
...MockTemplate, ...MockTemplate,
...validFormValues, ...validFormValues,
}); });
@@ -25,7 +25,7 @@ const fillAndSubmitForm = async () => {
describe("AccountPage", () => { describe("AccountPage", () => {
describe("when it is a success", () => { describe("when it is a success", () => {
it("shows the success message", async () => { it("shows the success message", async () => {
jest.spyOn(API, "updateProfile").mockImplementationOnce((userId, data) => vi.spyOn(API, "updateProfile").mockImplementationOnce((userId, data) =>
Promise.resolve({ Promise.resolve({
id: userId, id: userId,
email: "user@coder.com", email: "user@coder.com",
@@ -53,7 +53,7 @@ describe("AccountPage", () => {
describe("when the username is already taken", () => { describe("when the username is already taken", () => {
it("shows an error", async () => { it("shows an error", async () => {
jest.spyOn(API, "updateProfile").mockRejectedValueOnce( vi.spyOn(API, "updateProfile").mockRejectedValueOnce(
mockApiError({ mockApiError({
message: "Invalid profile", message: "Invalid profile",
validations: [ validations: [
@@ -76,7 +76,7 @@ describe("AccountPage", () => {
describe("when it is an unknown error", () => { describe("when it is an unknown error", () => {
it("shows a generic error message", async () => { it("shows a generic error message", async () => {
jest.spyOn(API, "updateProfile").mockRejectedValueOnce({ vi.spyOn(API, "updateProfile").mockRejectedValueOnce({
data: "unknown error", data: "unknown error",
}); });
@@ -9,7 +9,7 @@ describe("appearance page", () => {
it("does nothing when selecting current theme", async () => { it("does nothing when selecting current theme", async () => {
renderWithAuth(<AppearancePage />); renderWithAuth(<AppearancePage />);
jest.spyOn(API, "updateAppearanceSettings").mockResolvedValueOnce({ vi.spyOn(API, "updateAppearanceSettings").mockResolvedValueOnce({
...MockUserOwner, ...MockUserOwner,
theme_preference: "dark", theme_preference: "dark",
terminal_font: "fira-code", terminal_font: "fira-code",
@@ -25,7 +25,7 @@ describe("appearance page", () => {
it("changes theme to light", async () => { it("changes theme to light", async () => {
renderWithAuth(<AppearancePage />); renderWithAuth(<AppearancePage />);
jest.spyOn(API, "updateAppearanceSettings").mockResolvedValueOnce({ vi.spyOn(API, "updateAppearanceSettings").mockResolvedValueOnce({
...MockUserOwner, ...MockUserOwner,
terminal_font: "ibm-plex-mono", terminal_font: "ibm-plex-mono",
theme_preference: "light", theme_preference: "light",
@@ -45,7 +45,7 @@ describe("appearance page", () => {
it("changes font to fira code", async () => { it("changes font to fira code", async () => {
renderWithAuth(<AppearancePage />); renderWithAuth(<AppearancePage />);
jest.spyOn(API, "updateAppearanceSettings").mockResolvedValueOnce({ vi.spyOn(API, "updateAppearanceSettings").mockResolvedValueOnce({
...MockUserOwner, ...MockUserOwner,
terminal_font: "fira-code", terminal_font: "fira-code",
theme_preference: "dark", theme_preference: "dark",
@@ -66,8 +66,7 @@ describe("appearance page", () => {
renderWithAuth(<AppearancePage />); renderWithAuth(<AppearancePage />);
// given // given
jest vi.spyOn(API, "updateAppearanceSettings")
.spyOn(API, "updateAppearanceSettings")
.mockResolvedValueOnce({ .mockResolvedValueOnce({
...MockUserOwner, ...MockUserOwner,
terminal_font: "fira-code", terminal_font: "fira-code",
@@ -28,7 +28,7 @@ describe("SSH keys Page", () => {
const newUserSSHKey = const newUserSSHKey =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDSC/ouD/LqiT1Rd99vDv/MwUmqzJuinLTMTpk5kVy66"; "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDSC/ouD/LqiT1Rd99vDv/MwUmqzJuinLTMTpk5kVy66";
jest.spyOn(API, "regenerateUserSSHKey").mockResolvedValueOnce({ vi.spyOn(API, "regenerateUserSSHKey").mockResolvedValueOnce({
...MockGitSSHKey, ...MockGitSSHKey,
public_key: newUserSSHKey, public_key: newUserSSHKey,
}); });
@@ -57,7 +57,7 @@ describe("SSH keys Page", () => {
// Wait to the ssh be rendered on the screen // Wait to the ssh be rendered on the screen
await screen.findByText(MockGitSSHKey.public_key); await screen.findByText(MockGitSSHKey.public_key);
jest.spyOn(API, "regenerateUserSSHKey").mockRejectedValueOnce( vi.spyOn(API, "regenerateUserSSHKey").mockRejectedValueOnce(
mockApiError({ mockApiError({
message: SSHKeysPageLanguage.regenerationError, message: SSHKeysPageLanguage.regenerationError,
}), }),
@@ -50,7 +50,7 @@ const renderScheduleControls = async () => {
test("add 3 hours to deadline", async () => { test("add 3 hours to deadline", async () => {
const user = userEvent.setup(); const user = userEvent.setup();
const updateDeadlineSpy = jest const updateDeadlineSpy = vi
.spyOn(API, "putWorkspaceExtension") .spyOn(API, "putWorkspaceExtension")
.mockResolvedValue(); .mockResolvedValue();
@@ -79,7 +79,7 @@ test("add 3 hours to deadline", async () => {
test("remove 2 hours to deadline", async () => { test("remove 2 hours to deadline", async () => {
const user = userEvent.setup(); const user = userEvent.setup();
const updateDeadlineSpy = jest const updateDeadlineSpy = vi
.spyOn(API, "putWorkspaceExtension") .spyOn(API, "putWorkspaceExtension")
.mockResolvedValue(); .mockResolvedValue();
@@ -108,7 +108,7 @@ test("remove 2 hours to deadline", async () => {
test("rollback to previous deadline on error", async () => { test("rollback to previous deadline on error", async () => {
const user = userEvent.setup(); const user = userEvent.setup();
const initialScheduleMessage = "Stop in 3 hours"; const initialScheduleMessage = "Stop in 3 hours";
jest.spyOn(API, "putWorkspaceExtension").mockRejectedValue({}); vi.spyOn(API, "putWorkspaceExtension").mockRejectedValue({});
await renderScheduleControls(); await renderScheduleControls();
@@ -127,7 +127,7 @@ test("rollback to previous deadline on error", async () => {
test("request is only sent once when clicking multiple times", async () => { test("request is only sent once when clicking multiple times", async () => {
const user = userEvent.setup(); const user = userEvent.setup();
const updateDeadlineSpy = jest const updateDeadlineSpy = vi
.spyOn(API, "putWorkspaceExtension") .spyOn(API, "putWorkspaceExtension")
.mockResolvedValue(); .mockResolvedValue();
@@ -19,23 +19,23 @@ import WorkspaceParametersPage from "./WorkspaceParametersPage";
test("Submit the workspace settings page successfully", async () => { test("Submit the workspace settings page successfully", async () => {
// Mock the API calls that loads data // Mock the API calls that loads data
jest vi.spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValueOnce(
.spyOn(API, "getWorkspaceByOwnerAndName") MockWorkspace,
.mockResolvedValueOnce(MockWorkspace); );
jest.spyOn(API, "getTemplateVersionRichParameters").mockResolvedValueOnce([ vi.spyOn(API, "getTemplateVersionRichParameters").mockResolvedValueOnce([
MockTemplateVersionParameter1, MockTemplateVersionParameter1,
MockTemplateVersionParameter2, MockTemplateVersionParameter2,
// Immutable parameters // Immutable parameters
MockTemplateVersionParameter4, MockTemplateVersionParameter4,
]); ]);
jest.spyOn(API, "getWorkspaceBuildParameters").mockResolvedValueOnce([ vi.spyOn(API, "getWorkspaceBuildParameters").mockResolvedValueOnce([
MockWorkspaceBuildParameter1, MockWorkspaceBuildParameter1,
MockWorkspaceBuildParameter2, MockWorkspaceBuildParameter2,
// Immutable value // Immutable value
MockWorkspaceBuildParameter4, MockWorkspaceBuildParameter4,
]); ]);
// Mock the API calls that submit data // Mock the API calls that submit data
const postWorkspaceBuildSpy = jest const postWorkspaceBuildSpy = vi
.spyOn(API, "postWorkspaceBuild") .spyOn(API, "postWorkspaceBuild")
.mockResolvedValue(MockWorkspaceBuild); .mockResolvedValue(MockWorkspaceBuild);
// Setup event and rendering // Setup event and rendering
@@ -79,16 +79,16 @@ test("Submit the workspace settings page successfully", async () => {
test("Submit button is only enabled when changes are made", async () => { test("Submit button is only enabled when changes are made", async () => {
// Mock the API calls that loads data // Mock the API calls that loads data
jest vi.spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValueOnce(
.spyOn(API, "getWorkspaceByOwnerAndName") MockWorkspace,
.mockResolvedValueOnce(MockWorkspace); );
jest.spyOn(API, "getTemplateVersionRichParameters").mockResolvedValueOnce([ vi.spyOn(API, "getTemplateVersionRichParameters").mockResolvedValueOnce([
MockTemplateVersionParameter1, MockTemplateVersionParameter1,
MockTemplateVersionParameter2, MockTemplateVersionParameter2,
// Immutable parameters // Immutable parameters
MockTemplateVersionParameter4, MockTemplateVersionParameter4,
]); ]);
jest.spyOn(API, "getWorkspaceBuildParameters").mockResolvedValueOnce([ vi.spyOn(API, "getWorkspaceBuildParameters").mockResolvedValueOnce([
MockWorkspaceBuildParameter1, MockWorkspaceBuildParameter1,
MockWorkspaceBuildParameter2, MockWorkspaceBuildParameter2,
// Immutable value // Immutable value
@@ -270,7 +270,7 @@ const defaultFormProps: WorkspaceScheduleFormProps = {
describe("templateInheritance", () => { describe("templateInheritance", () => {
it("disables the entire autostart feature appropriately", async () => { it("disables the entire autostart feature appropriately", async () => {
jest.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate); vi.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate);
const props = { const props = {
...defaultFormProps, ...defaultFormProps,
template: { template: {
@@ -300,7 +300,7 @@ describe("templateInheritance", () => {
it("disables the autostart days of the week appropriately", async () => { it("disables the autostart days of the week appropriately", async () => {
const enabledDayLabels = ["Sat", "Sun"]; const enabledDayLabels = ["Sat", "Sun"];
jest.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate); vi.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate);
const props = { const props = {
...defaultFormProps, ...defaultFormProps,
template: { template: {
@@ -346,7 +346,7 @@ describe("templateInheritance", () => {
allow_user_autostop: false, allow_user_autostop: false,
}, },
}; };
jest.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate); vi.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate);
render(<WorkspaceScheduleForm {...props} />); render(<WorkspaceScheduleForm {...props} />);
const autoStopToggle = await screen.findByLabelText("Enable Autostop", { const autoStopToggle = await screen.findByLabelText("Enable Autostop", {
@@ -360,7 +360,7 @@ describe("templateInheritance", () => {
expect(ttlInput).toBeDisabled(); expect(ttlInput).toBeDisabled();
}); });
it("disables secondary autostart fields if main feature switch is toggled off", async () => { it("disables secondary autostart fields if main feature switch is toggled off", async () => {
jest.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate); vi.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate);
render( render(
<WorkspaceScheduleForm <WorkspaceScheduleForm
{...defaultFormProps} {...defaultFormProps}
@@ -384,7 +384,7 @@ describe("templateInheritance", () => {
} }
}); });
it("disables secondary autostop fields if main feature switch is toggled off", async () => { it("disables secondary autostop fields if main feature switch is toggled off", async () => {
jest.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate); vi.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate);
render( render(
<WorkspaceScheduleForm <WorkspaceScheduleForm
{...defaultFormProps} {...defaultFormProps}
@@ -403,7 +403,7 @@ describe("templateInheritance", () => {
}); });
test("form should be enabled when both auto stop and auto start features are disabled, given that the template permits these actions", async () => { test("form should be enabled when both auto stop and auto start features are disabled, given that the template permits these actions", async () => {
jest.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate); vi.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate);
render( render(
<WorkspaceScheduleForm <WorkspaceScheduleForm
{...defaultFormProps} {...defaultFormProps}
@@ -430,7 +430,7 @@ test("form should be disabled when both auto stop and auto start features are di
allow_user_autostop: false, allow_user_autostop: false,
}, },
}; };
jest.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate); vi.spyOn(API, "getTemplateByName").mockResolvedValue(MockTemplate);
render(<WorkspaceScheduleForm {...props} />); render(<WorkspaceScheduleForm {...props} />);
const submitButton = await screen.findByRole("button", { const submitButton = await screen.findByRole("button", {
@@ -10,13 +10,11 @@ import WorkspaceSettingsPage from "./WorkspaceSettingsPage";
test("Submit the workspace settings page successfully", async () => { test("Submit the workspace settings page successfully", async () => {
// Mock the API calls that loads data // Mock the API calls that loads data
jest vi.spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValueOnce({
.spyOn(API, "getWorkspaceByOwnerAndName") ...MockWorkspace,
.mockResolvedValueOnce({ ...MockWorkspace }); });
// Mock the API calls that submit data // Mock the API calls that submit data
const patchWorkspaceSpy = jest const patchWorkspaceSpy = vi.spyOn(API, "patchWorkspace").mockResolvedValue();
.spyOn(API, "patchWorkspace")
.mockResolvedValue();
// Setup event and rendering // Setup event and rendering
const user = userEvent.setup(); const user = userEvent.setup();
renderWithWorkspaceSettingsLayout(<WorkspaceSettingsPage />, { renderWithWorkspaceSettingsLayout(<WorkspaceSettingsPage />, {
@@ -42,9 +40,10 @@ test("Submit the workspace settings page successfully", async () => {
test("Name field is disabled if renames are disabled", async () => { test("Name field is disabled if renames are disabled", async () => {
// Mock the API calls that loads data // Mock the API calls that loads data
jest vi.spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValueOnce({
.spyOn(API, "getWorkspaceByOwnerAndName") ...MockWorkspace,
.mockResolvedValueOnce({ ...MockWorkspace, allow_renames: false }); allow_renames: false,
});
renderWithWorkspaceSettingsLayout(<WorkspaceSettingsPage />, { renderWithWorkspaceSettingsLayout(<WorkspaceSettingsPage />, {
route: "/@test-user/test-workspace/settings", route: "/@test-user/test-workspace/settings",
path: "/:username/:workspace/settings", path: "/:username/:workspace/settings",
@@ -12,7 +12,7 @@ interface TestType {
maxLengthOver: string; maxLengthOver: string;
} }
const mockHandleChange = jest.fn(); const mockHandleChange = vi.fn();
const form = { const form = {
errors: { errors: {
@@ -43,12 +43,12 @@ const form = {
maxLengthOver: "a".repeat(33), maxLengthOver: "a".repeat(33),
}, },
handleChange: mockHandleChange, handleChange: mockHandleChange,
handleBlur: jest.fn(), handleBlur: vi.fn(),
getFieldProps: (name: keyof TestType) => { getFieldProps: (name: keyof TestType) => {
return { return {
name, name,
onBlur: jest.fn(), onBlur: vi.fn(),
onChange: jest.fn(), onChange: vi.fn(),
value: form.values[name] ?? "", value: form.values[name] ?? "",
}; };
}, },
+2 -1
View File
@@ -2,5 +2,6 @@
globalThis.HTMLElement.prototype.hasPointerCapture = vi globalThis.HTMLElement.prototype.hasPointerCapture = vi
.fn() .fn()
.mockReturnValue(false); .mockReturnValue(false);
globalThis.HTMLElement.prototype.setPointerCapture = vi.fn();
globalThis.HTMLElement.prototype.releasePointerCapture = vi.fn(); globalThis.HTMLElement.prototype.releasePointerCapture = vi.fn();
globalThis.HTMLElement.prototype.scrollIntoView = vi.fn();
globalThis.HTMLElement.prototype.setPointerCapture = vi.fn();