mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
refactor: improve test isolation for Axios API logic (#13125)
* wip: commit progress on code split-up * wip: commit more progress * wip: finish initial version of class implementation * chore: update all import paths to go through client instance * fix: remove temp comments * refactor: smoooooooosh the API * refactor: update import setup for tests
This commit is contained in:
+9
-8
@@ -1,7 +1,7 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { expect } from "@playwright/test";
|
||||
import { formatDuration, intervalToDuration } from "date-fns";
|
||||
import * as API from "api/api";
|
||||
import { type DeploymentConfig, API } from "api/api";
|
||||
import type { SerpentOption } from "api/typesGenerated";
|
||||
import { coderPort } from "./constants";
|
||||
import { findSessionToken, randomName } from "./helpers";
|
||||
@@ -15,6 +15,7 @@ export const setupApiCalls = async (page: Page) => {
|
||||
} catch {
|
||||
// If this fails, we have an unauthenticated client.
|
||||
}
|
||||
|
||||
API.setHost(`http://127.0.0.1:${coderPort}`);
|
||||
};
|
||||
|
||||
@@ -53,7 +54,7 @@ export const createGroup = async (orgId: string) => {
|
||||
|
||||
export async function verifyConfigFlagBoolean(
|
||||
page: Page,
|
||||
config: API.DeploymentConfig,
|
||||
config: DeploymentConfig,
|
||||
flag: string,
|
||||
) {
|
||||
const opt = findConfigOption(config, flag);
|
||||
@@ -68,7 +69,7 @@ export async function verifyConfigFlagBoolean(
|
||||
|
||||
export async function verifyConfigFlagNumber(
|
||||
page: Page,
|
||||
config: API.DeploymentConfig,
|
||||
config: DeploymentConfig,
|
||||
flag: string,
|
||||
) {
|
||||
const opt = findConfigOption(config, flag);
|
||||
@@ -80,7 +81,7 @@ export async function verifyConfigFlagNumber(
|
||||
|
||||
export async function verifyConfigFlagString(
|
||||
page: Page,
|
||||
config: API.DeploymentConfig,
|
||||
config: DeploymentConfig,
|
||||
flag: string,
|
||||
) {
|
||||
const opt = findConfigOption(config, flag);
|
||||
@@ -100,7 +101,7 @@ export async function verifyConfigFlagEmpty(page: Page, flag: string) {
|
||||
|
||||
export async function verifyConfigFlagArray(
|
||||
page: Page,
|
||||
config: API.DeploymentConfig,
|
||||
config: DeploymentConfig,
|
||||
flag: string,
|
||||
) {
|
||||
const opt = findConfigOption(config, flag);
|
||||
@@ -116,7 +117,7 @@ export async function verifyConfigFlagArray(
|
||||
|
||||
export async function verifyConfigFlagEntries(
|
||||
page: Page,
|
||||
config: API.DeploymentConfig,
|
||||
config: DeploymentConfig,
|
||||
flag: string,
|
||||
) {
|
||||
const opt = findConfigOption(config, flag);
|
||||
@@ -138,7 +139,7 @@ export async function verifyConfigFlagEntries(
|
||||
|
||||
export async function verifyConfigFlagDuration(
|
||||
page: Page,
|
||||
config: API.DeploymentConfig,
|
||||
config: DeploymentConfig,
|
||||
flag: string,
|
||||
) {
|
||||
const opt = findConfigOption(config, flag);
|
||||
@@ -157,7 +158,7 @@ export async function verifyConfigFlagDuration(
|
||||
}
|
||||
|
||||
export function findConfigOption(
|
||||
config: API.DeploymentConfig,
|
||||
config: DeploymentConfig,
|
||||
flag: string,
|
||||
): SerpentOption {
|
||||
const opt = config.options.find((option) => option.flag === flag);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { hasFirstUser } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { Language } from "pages/CreateUserPage/CreateUserForm";
|
||||
import { setupApiCalls } from "./api";
|
||||
import * as constants from "./constants";
|
||||
@@ -9,7 +9,7 @@ import { storageState } from "./playwright.config";
|
||||
test("setup deployment", async ({ page }) => {
|
||||
await page.goto("/", { waitUntil: "domcontentloaded" });
|
||||
await setupApiCalls(page);
|
||||
const exists = await hasFirstUser();
|
||||
const exists = await API.hasFirstUser();
|
||||
// First user already exists, abort early. All tests execute this as a dependency,
|
||||
// if you run multiple tests in the UI, this will fail unless we check this.
|
||||
if (exists) {
|
||||
|
||||
+2
-1
@@ -6,7 +6,7 @@ import capitalize from "lodash/capitalize";
|
||||
import path from "path";
|
||||
import * as ssh from "ssh2";
|
||||
import { Duplex } from "stream";
|
||||
import { axiosInstance } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type {
|
||||
WorkspaceBuildParameter,
|
||||
UpdateTemplateMeta,
|
||||
@@ -423,6 +423,7 @@ export const waitUntilUrlIsNotResponding = async (url: string) => {
|
||||
const retryIntervalMs = 1000;
|
||||
let retries = 0;
|
||||
|
||||
const axiosInstance = API.getAxiosInstance();
|
||||
while (retries < maxRetries) {
|
||||
try {
|
||||
await axiosInstance.get(url);
|
||||
|
||||
@@ -10,7 +10,7 @@ import type {
|
||||
} from "@playwright/test/reporter";
|
||||
import * as fs from "fs/promises";
|
||||
import type { Writable } from "stream";
|
||||
import { axiosInstance } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { coderdPProfPort, enterpriseLicense } from "./constants";
|
||||
|
||||
class CoderReporter implements Reporter {
|
||||
@@ -143,6 +143,7 @@ const logLines = (chunk: string | Buffer): string[] => {
|
||||
};
|
||||
|
||||
const exportDebugPprof = async (outputFile: string) => {
|
||||
const axiosInstance = API.getAxiosInstance();
|
||||
const response = await axiosInstance.get(
|
||||
`http://127.0.0.1:${coderdPProfPort}/debug/pprof/goroutine?debug=1`,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { setupApiCalls } from "../../api";
|
||||
import { e2eFakeExperiment1, e2eFakeExperiment2 } from "../../constants";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { test } from "@playwright/test";
|
||||
import { getDeploymentConfig } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import {
|
||||
setupApiCalls,
|
||||
verifyConfigFlagArray,
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
|
||||
test("enabled network settings", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
const config = await getDeploymentConfig();
|
||||
const config = await API.getDeploymentConfig();
|
||||
|
||||
await page.goto("/deployment/network", { waitUntil: "domcontentloaded" });
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { test } from "@playwright/test";
|
||||
import { getDeploymentConfig } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import {
|
||||
setupApiCalls,
|
||||
verifyConfigFlagArray,
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
|
||||
test("enabled observability settings", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
const config = await getDeploymentConfig();
|
||||
const config = await API.getDeploymentConfig();
|
||||
|
||||
await page.goto("/deployment/observability", {
|
||||
waitUntil: "domcontentloaded",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { expect, test } from "@playwright/test";
|
||||
import type * as API from "api/api";
|
||||
import { getDeploymentConfig } from "api/api";
|
||||
import { type DeploymentConfig, API } from "api/api";
|
||||
import {
|
||||
findConfigOption,
|
||||
setupApiCalls,
|
||||
@@ -12,7 +11,7 @@ import {
|
||||
|
||||
test("enabled security settings", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
const config = await getDeploymentConfig();
|
||||
const config = await API.getDeploymentConfig();
|
||||
|
||||
await page.goto("/deployment/security", { waitUntil: "domcontentloaded" });
|
||||
|
||||
@@ -31,7 +30,7 @@ test("enabled security settings", async ({ page }) => {
|
||||
|
||||
async function verifyStrictTransportSecurity(
|
||||
page: Page,
|
||||
config: API.DeploymentConfig,
|
||||
config: DeploymentConfig,
|
||||
) {
|
||||
const flag = "strict-transport-security";
|
||||
const opt = findConfigOption(config, flag);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { test } from "@playwright/test";
|
||||
import { getDeploymentConfig } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import {
|
||||
setupApiCalls,
|
||||
verifyConfigFlagArray,
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
|
||||
test("login with OIDC", async ({ page }) => {
|
||||
await setupApiCalls(page);
|
||||
const config = await getDeploymentConfig();
|
||||
const config = await API.getDeploymentConfig();
|
||||
|
||||
await page.goto("/deployment/userauth", { waitUntil: "domcontentloaded" });
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { test, expect, type Page } from "@playwright/test";
|
||||
import { createWorkspaceProxy } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { setupApiCalls } from "../../api";
|
||||
import { coderPort, workspaceProxyPort } from "../../constants";
|
||||
import { randomName, requiresEnterpriseLicense } from "../../helpers";
|
||||
@@ -34,7 +34,7 @@ test("custom proxy is online", async ({ page }) => {
|
||||
const proxyName = randomName();
|
||||
|
||||
// Register workspace proxy
|
||||
const proxyResponse = await createWorkspaceProxy({
|
||||
const proxyResponse = await API.createWorkspaceProxy({
|
||||
name: proxyName,
|
||||
display_name: "",
|
||||
icon: "/emojis/1f1e7-1f1f7.png",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import {
|
||||
createGroup,
|
||||
createUser,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { createTemplate, createTemplateVersion, getTemplate } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { getCurrentOrgId, setupApiCalls } from "../../api";
|
||||
import { beforeCoderTest } from "../../hooks";
|
||||
|
||||
@@ -11,14 +11,14 @@ test("update template schedule settings without override other settings", async
|
||||
}) => {
|
||||
await setupApiCalls(page);
|
||||
const orgId = await getCurrentOrgId();
|
||||
const templateVersion = await createTemplateVersion(orgId, {
|
||||
const templateVersion = await API.createTemplateVersion(orgId, {
|
||||
storage_method: "file" as const,
|
||||
provisioner: "echo",
|
||||
user_variable_values: [],
|
||||
example_id: "docker",
|
||||
tags: {},
|
||||
});
|
||||
const template = await createTemplate(orgId, {
|
||||
const template = await API.createTemplate(orgId, {
|
||||
name: "test-template",
|
||||
display_name: "Test Template",
|
||||
template_version_id: templateVersion.id,
|
||||
@@ -33,7 +33,7 @@ test("update template schedule settings without override other settings", async
|
||||
await page.getByRole("button", { name: "Submit" }).click();
|
||||
await expect(page.getByText("Template updated successfully")).toBeVisible();
|
||||
|
||||
const updatedTemplate = await getTemplate(template.id);
|
||||
const updatedTemplate = await API.getTemplate(template.id);
|
||||
// Validate that the template data remains consistent, with the exception of
|
||||
// the 'default_ttl_ms' field (updated during the test) and the 'updated at'
|
||||
// field (automatically updated by the backend).
|
||||
|
||||
+28
-27
@@ -6,10 +6,11 @@ import {
|
||||
MockWorkspaceBuild,
|
||||
MockWorkspaceBuildParameter1,
|
||||
} from "testHelpers/entities";
|
||||
import * as api from "./api";
|
||||
import { axiosInstance } from "./api";
|
||||
import { API, getURLWithSearchParams, MissingBuildParameters } from "./api";
|
||||
import type * as TypesGen from "./typesGenerated";
|
||||
|
||||
const axiosInstance = API.getAxiosInstance();
|
||||
|
||||
describe("api.ts", () => {
|
||||
describe("login", () => {
|
||||
it("should return LoginResponse", async () => {
|
||||
@@ -23,7 +24,7 @@ describe("api.ts", () => {
|
||||
.mockResolvedValueOnce({ data: loginResponse });
|
||||
|
||||
// when
|
||||
const result = await api.login("test", "123");
|
||||
const result = await API.login("test", "123");
|
||||
|
||||
// then
|
||||
expect(axiosInstance.post).toHaveBeenCalled();
|
||||
@@ -44,7 +45,7 @@ describe("api.ts", () => {
|
||||
axiosInstance.post = axiosMockPost;
|
||||
|
||||
try {
|
||||
await api.login("test", "123");
|
||||
await API.login("test", "123");
|
||||
} catch (error) {
|
||||
expect(error).toStrictEqual(expectedError);
|
||||
}
|
||||
@@ -60,7 +61,7 @@ describe("api.ts", () => {
|
||||
axiosInstance.post = axiosMockPost;
|
||||
|
||||
// when
|
||||
await api.logout();
|
||||
await API.logout();
|
||||
|
||||
// then
|
||||
expect(axiosMockPost).toHaveBeenCalled();
|
||||
@@ -80,7 +81,7 @@ describe("api.ts", () => {
|
||||
axiosInstance.post = axiosMockPost;
|
||||
|
||||
try {
|
||||
await api.logout();
|
||||
await API.logout();
|
||||
} catch (error) {
|
||||
expect(error).toStrictEqual(expectedError);
|
||||
}
|
||||
@@ -100,7 +101,7 @@ describe("api.ts", () => {
|
||||
axiosInstance.post = axiosMockPost;
|
||||
|
||||
// when
|
||||
const result = await api.getApiKey();
|
||||
const result = await API.getApiKey();
|
||||
|
||||
// then
|
||||
expect(axiosMockPost).toHaveBeenCalled();
|
||||
@@ -121,7 +122,7 @@ describe("api.ts", () => {
|
||||
axiosInstance.post = axiosMockPost;
|
||||
|
||||
try {
|
||||
await api.getApiKey();
|
||||
await API.getApiKey();
|
||||
} catch (error) {
|
||||
expect(error).toStrictEqual(expectedError);
|
||||
}
|
||||
@@ -147,7 +148,7 @@ describe("api.ts", () => {
|
||||
])(
|
||||
`Workspaces - getURLWithSearchParams(%p, %p) returns %p`,
|
||||
(basePath, filter, expected) => {
|
||||
expect(api.getURLWithSearchParams(basePath, filter)).toBe(expected);
|
||||
expect(getURLWithSearchParams(basePath, filter)).toBe(expected);
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -164,7 +165,7 @@ describe("api.ts", () => {
|
||||
])(
|
||||
`Users - getURLWithSearchParams(%p, %p) returns %p`,
|
||||
(basePath, filter, expected) => {
|
||||
expect(api.getURLWithSearchParams(basePath, filter)).toBe(expected);
|
||||
expect(getURLWithSearchParams(basePath, filter)).toBe(expected);
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -172,11 +173,11 @@ describe("api.ts", () => {
|
||||
describe("update", () => {
|
||||
it("creates a build with start and the latest template", async () => {
|
||||
jest
|
||||
.spyOn(api, "postWorkspaceBuild")
|
||||
.spyOn(API, "postWorkspaceBuild")
|
||||
.mockResolvedValueOnce(MockWorkspaceBuild);
|
||||
jest.spyOn(api, "getTemplate").mockResolvedValueOnce(MockTemplate);
|
||||
await api.updateWorkspace(MockWorkspace);
|
||||
expect(api.postWorkspaceBuild).toHaveBeenCalledWith(MockWorkspace.id, {
|
||||
jest.spyOn(API, "getTemplate").mockResolvedValueOnce(MockTemplate);
|
||||
await API.updateWorkspace(MockWorkspace);
|
||||
expect(API.postWorkspaceBuild).toHaveBeenCalledWith(MockWorkspace.id, {
|
||||
transition: "start",
|
||||
template_version_id: MockTemplate.active_version_id,
|
||||
rich_parameter_values: [],
|
||||
@@ -185,12 +186,12 @@ describe("api.ts", () => {
|
||||
|
||||
it("fails when having missing parameters", async () => {
|
||||
jest
|
||||
.spyOn(api, "postWorkspaceBuild")
|
||||
.spyOn(API, "postWorkspaceBuild")
|
||||
.mockResolvedValue(MockWorkspaceBuild);
|
||||
jest.spyOn(api, "getTemplate").mockResolvedValue(MockTemplate);
|
||||
jest.spyOn(api, "getWorkspaceBuildParameters").mockResolvedValue([]);
|
||||
jest.spyOn(API, "getTemplate").mockResolvedValue(MockTemplate);
|
||||
jest.spyOn(API, "getWorkspaceBuildParameters").mockResolvedValue([]);
|
||||
jest
|
||||
.spyOn(api, "getTemplateVersionRichParameters")
|
||||
.spyOn(API, "getTemplateVersionRichParameters")
|
||||
.mockResolvedValue([
|
||||
MockTemplateVersionParameter1,
|
||||
{ ...MockTemplateVersionParameter2, mutable: false },
|
||||
@@ -198,14 +199,14 @@ describe("api.ts", () => {
|
||||
|
||||
let error = new Error();
|
||||
try {
|
||||
await api.updateWorkspace(MockWorkspace);
|
||||
await API.updateWorkspace(MockWorkspace);
|
||||
} catch (e) {
|
||||
error = e as Error;
|
||||
}
|
||||
|
||||
expect(error).toBeInstanceOf(api.MissingBuildParameters);
|
||||
expect(error).toBeInstanceOf(MissingBuildParameters);
|
||||
// Verify if the correct missing parameters are being passed
|
||||
expect((error as api.MissingBuildParameters).parameters).toEqual([
|
||||
expect((error as MissingBuildParameters).parameters).toEqual([
|
||||
MockTemplateVersionParameter1,
|
||||
{ ...MockTemplateVersionParameter2, mutable: false },
|
||||
]);
|
||||
@@ -213,19 +214,19 @@ describe("api.ts", () => {
|
||||
|
||||
it("creates a build with the no parameters if it is already filled", async () => {
|
||||
jest
|
||||
.spyOn(api, "postWorkspaceBuild")
|
||||
.spyOn(API, "postWorkspaceBuild")
|
||||
.mockResolvedValueOnce(MockWorkspaceBuild);
|
||||
jest.spyOn(api, "getTemplate").mockResolvedValueOnce(MockTemplate);
|
||||
jest.spyOn(API, "getTemplate").mockResolvedValueOnce(MockTemplate);
|
||||
jest
|
||||
.spyOn(api, "getWorkspaceBuildParameters")
|
||||
.spyOn(API, "getWorkspaceBuildParameters")
|
||||
.mockResolvedValue([MockWorkspaceBuildParameter1]);
|
||||
jest
|
||||
.spyOn(api, "getTemplateVersionRichParameters")
|
||||
.spyOn(API, "getTemplateVersionRichParameters")
|
||||
.mockResolvedValue([
|
||||
{ ...MockTemplateVersionParameter1, required: true, mutable: false },
|
||||
]);
|
||||
await api.updateWorkspace(MockWorkspace);
|
||||
expect(api.postWorkspaceBuild).toHaveBeenCalledWith(MockWorkspace.id, {
|
||||
await API.updateWorkspace(MockWorkspace);
|
||||
expect(API.postWorkspaceBuild).toHaveBeenCalledWith(MockWorkspace.id, {
|
||||
transition: "start",
|
||||
template_version_id: MockTemplate.active_version_id,
|
||||
rich_parameter_values: [],
|
||||
|
||||
+1700
-1620
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
import type { QueryClient } from "react-query";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { AppearanceConfig } from "api/typesGenerated";
|
||||
import type { MetadataState } from "hooks/useEmbeddedMetadata";
|
||||
import { cachedQuery } from "./util";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getAuditLogs } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { AuditLogResponse } from "api/typesGenerated";
|
||||
import { useFilterParamsKey } from "components/Filter/filter";
|
||||
import type { UsePaginatedQueryOptions } from "hooks/usePaginatedQuery";
|
||||
@@ -13,7 +13,7 @@ export function paginatedAudits(
|
||||
return ["auditLogs", payload, pageNumber] as const;
|
||||
},
|
||||
queryFn: ({ payload, limit, offset }) => {
|
||||
return getAuditLogs({
|
||||
return API.getAuditLogs({
|
||||
offset,
|
||||
limit,
|
||||
q: payload,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { AuthorizationRequest } from "api/typesGenerated";
|
||||
|
||||
export const AUTHORIZATION_KEY = "authorization";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { BuildInfoResponse } from "api/typesGenerated";
|
||||
import type { MetadataState } from "hooks/useEmbeddedMetadata";
|
||||
import { cachedQuery } from "./util";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { QueryClient, UseMutationOptions } from "react-query";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { HealthSettings, UpdateHealthSettings } from "api/typesGenerated";
|
||||
|
||||
export const HEALTH_QUERY_KEY = ["health"];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
|
||||
export const deploymentConfig = () => {
|
||||
return {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { QueryClient } from "react-query";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { Entitlements } from "api/typesGenerated";
|
||||
import type { MetadataState } from "hooks/useEmbeddedMetadata";
|
||||
import { cachedQuery } from "./util";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { Experiments } from "api/typesGenerated";
|
||||
import type { MetadataState } from "hooks/useEmbeddedMetadata";
|
||||
import { cachedQuery } from "./util";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { QueryClient, UseMutationOptions } from "react-query";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { ExternalAuth } from "api/typesGenerated";
|
||||
|
||||
// Returns all configured external auths for a given user.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
|
||||
export const uploadFile = () => {
|
||||
return {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { QueryClient, UseQueryOptions } from "react-query";
|
||||
import * as API from "api/api";
|
||||
import { checkAuthorization } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type {
|
||||
CreateGroupRequest,
|
||||
Group,
|
||||
@@ -72,7 +71,7 @@ export const groupPermissions = (groupId: string) => {
|
||||
return {
|
||||
queryKey: [...getGroupQueryKey(groupId), "permissions"],
|
||||
queryFn: () =>
|
||||
checkAuthorization({
|
||||
API.checkAuthorization({
|
||||
checks: {
|
||||
canUpdateGroup: {
|
||||
object: {
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import * as API from "api/api";
|
||||
import { type InsightsParams, type InsightsTemplateParams, API } from "api/api";
|
||||
|
||||
export const insightsTemplate = (params: API.InsightsTemplateParams) => {
|
||||
export const insightsTemplate = (params: InsightsTemplateParams) => {
|
||||
return {
|
||||
queryKey: ["insights", "templates", params.template_ids, params],
|
||||
queryFn: () => API.getInsightsTemplate(params),
|
||||
};
|
||||
};
|
||||
|
||||
export const insightsUserLatency = (params: API.InsightsParams) => {
|
||||
export const insightsUserLatency = (params: InsightsParams) => {
|
||||
return {
|
||||
queryKey: ["insights", "userLatency", params.template_ids, params],
|
||||
queryFn: () => API.getInsightsUserLatency(params),
|
||||
};
|
||||
};
|
||||
|
||||
export const insightsUserActivity = (params: API.InsightsParams) => {
|
||||
export const insightsUserActivity = (params: InsightsParams) => {
|
||||
return {
|
||||
queryKey: ["insights", "userActivity", params.template_ids, params],
|
||||
queryFn: () => API.getInsightsUserActivity(params),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { GetJFrogXRayScanParams } from "api/api";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
|
||||
export const xrayScan = (params: GetJFrogXRayScanParams) => {
|
||||
return {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { QueryClient } from "react-query";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type * as TypesGen from "api/typesGenerated";
|
||||
|
||||
const appsKey = ["oauth2-provider", "apps"];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
|
||||
export const roles = () => {
|
||||
return {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { QueryClient, QueryOptions } from "react-query";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type {
|
||||
UpdateUserQuietHoursScheduleRequest,
|
||||
UserQuietHoursScheduleResponse,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { QueryClient } from "react-query";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { GitSSHKey } from "api/typesGenerated";
|
||||
|
||||
const getUserSSHKeyQueryKey = (userId: string) => [userId, "sshKey"];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { MutationOptions, QueryClient, QueryOptions } from "react-query";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type {
|
||||
CreateTemplateRequest,
|
||||
CreateTemplateVersionRequest,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
|
||||
export const updateCheck = () => {
|
||||
return {
|
||||
|
||||
@@ -3,7 +3,7 @@ import type {
|
||||
UseMutationOptions,
|
||||
UseQueryOptions,
|
||||
} from "react-query";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type {
|
||||
AuthorizationRequest,
|
||||
GetUsersResponse,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { QueryOptions, UseInfiniteQueryOptions } from "react-query";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type {
|
||||
WorkspaceBuild,
|
||||
WorkspaceBuildParameter,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
|
||||
export const getWorkspaceQuotaQueryKey = (username: string) => [
|
||||
username,
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import {
|
||||
deleteWorkspaceAgentSharedPort,
|
||||
getWorkspaceAgentSharedPorts,
|
||||
upsertWorkspaceAgentSharedPort,
|
||||
} from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type {
|
||||
DeleteWorkspaceAgentPortShareRequest,
|
||||
UpsertWorkspaceAgentPortShareRequest,
|
||||
@@ -11,14 +7,14 @@ import type {
|
||||
export const workspacePortShares = (workspaceId: string) => {
|
||||
return {
|
||||
queryKey: ["sharedPorts", workspaceId],
|
||||
queryFn: () => getWorkspaceAgentSharedPorts(workspaceId),
|
||||
queryFn: () => API.getWorkspaceAgentSharedPorts(workspaceId),
|
||||
};
|
||||
};
|
||||
|
||||
export const upsertWorkspacePortShare = (workspaceId: string) => {
|
||||
return {
|
||||
mutationFn: async (options: UpsertWorkspaceAgentPortShareRequest) => {
|
||||
await upsertWorkspaceAgentSharedPort(workspaceId, options);
|
||||
await API.upsertWorkspaceAgentSharedPort(workspaceId, options);
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -26,7 +22,7 @@ export const upsertWorkspacePortShare = (workspaceId: string) => {
|
||||
export const deleteWorkspacePortShare = (workspaceId: string) => {
|
||||
return {
|
||||
mutationFn: async (options: DeleteWorkspaceAgentPortShareRequest) => {
|
||||
await deleteWorkspaceAgentSharedPort(workspaceId, options);
|
||||
await API.deleteWorkspaceAgentSharedPort(workspaceId, options);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,8 +4,7 @@ import type {
|
||||
QueryOptions,
|
||||
UseMutationOptions,
|
||||
} from "react-query";
|
||||
import * as API from "api/api";
|
||||
import { putWorkspaceExtension } from "api/api";
|
||||
import { type DeleteWorkspaceOptions, API } from "api/api";
|
||||
import type {
|
||||
CreateWorkspaceRequest,
|
||||
ProvisionerLogLevel,
|
||||
@@ -28,7 +27,9 @@ export const workspaceByOwnerAndName = (owner: string, name: string) => {
|
||||
return {
|
||||
queryKey: workspaceByOwnerAndNameKey(owner, name),
|
||||
queryFn: () =>
|
||||
API.getWorkspaceByOwnerAndName(owner, name, { include_deleted: true }),
|
||||
API.getWorkspaceByOwnerAndName(owner, name, {
|
||||
include_deleted: true,
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -111,7 +112,7 @@ export const updateDeadline = (
|
||||
): UseMutationOptions<void, unknown, Dayjs> => {
|
||||
return {
|
||||
mutationFn: (deadline: Dayjs) => {
|
||||
return putWorkspaceExtension(workspace.id, deadline);
|
||||
return API.putWorkspaceExtension(workspace.id, deadline);
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -155,7 +156,7 @@ export const deleteWorkspace = (
|
||||
queryClient: QueryClient,
|
||||
) => {
|
||||
return {
|
||||
mutationFn: (options: API.DeleteWorkspaceOptions) => {
|
||||
mutationFn: (options: DeleteWorkspaceOptions) => {
|
||||
return API.deleteWorkspace(workspace.id, options);
|
||||
},
|
||||
onSuccess: async (build: WorkspaceBuild) => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { FC } from "react";
|
||||
import { getUsers } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { UserAvatar } from "../UserAvatar/UserAvatar";
|
||||
import { FilterSearchMenu, OptionItem } from "./filter";
|
||||
@@ -42,7 +42,7 @@ export const useUserFilterMenu = ({
|
||||
};
|
||||
}
|
||||
|
||||
const usersRes = await getUsers({ q: value, limit: 1 });
|
||||
const usersRes = await API.getUsers({ q: value, limit: 1 });
|
||||
const firstUser = usersRes.users.at(0);
|
||||
if (firstUser && firstUser.username === value) {
|
||||
return {
|
||||
@@ -54,7 +54,7 @@ export const useUserFilterMenu = ({
|
||||
return null;
|
||||
},
|
||||
getOptions: async (query) => {
|
||||
const usersRes = await getUsers({ q: query, limit: 25 });
|
||||
const usersRes = await API.getUsers({ q: query, limit: 25 });
|
||||
let options: UserOption[] = usersRes.users.map((user) => ({
|
||||
label: user.username,
|
||||
value: user.username,
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
useState,
|
||||
} from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { getWorkspaceProxies, getWorkspaceProxyRegions } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { cachedQuery } from "api/queries/util";
|
||||
import type { Region, WorkspaceProxy } from "api/typesGenerated";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
@@ -108,10 +108,11 @@ export const ProxyProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
metadata: metadata.regions,
|
||||
queryKey: ["get-proxies"],
|
||||
queryFn: async (): Promise<readonly Region[]> => {
|
||||
const endpoint = permissions.editWorkspaceProxies
|
||||
? getWorkspaceProxies
|
||||
: getWorkspaceProxyRegions;
|
||||
const resp = await endpoint();
|
||||
const apiCall = permissions.editWorkspaceProxies
|
||||
? API.getWorkspaceProxies
|
||||
: API.getWorkspaceProxyRegions;
|
||||
|
||||
const resp = await apiCall();
|
||||
return resp.regions;
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type FC, useEffect } from "react";
|
||||
import { Outlet, Navigate, useLocation } from "react-router-dom";
|
||||
import { axiosInstance } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { isApiError } from "api/errors";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { ProxyProvider } from "contexts/ProxyContext";
|
||||
@@ -18,6 +18,7 @@ export const RequireAuth: FC = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const axiosInstance = API.getAxiosInstance();
|
||||
const interceptorHandle = axiosInstance.interceptors.response.use(
|
||||
(okResponse) => okResponse,
|
||||
(error: unknown) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import PerformanceObserver from "@fastly/performance-observer-polyfill";
|
||||
import { useEffect, useReducer, useState } from "react";
|
||||
import { axiosInstance } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { Region } from "api/typesGenerated";
|
||||
import { generateRandomString } from "utils/random";
|
||||
|
||||
@@ -197,6 +197,7 @@ export const useProxyLatency = (
|
||||
// The resource requests include xmlhttp requests.
|
||||
observer.observe({ entryTypes: ["resource"] });
|
||||
|
||||
const axiosInstance = API.getAxiosInstance();
|
||||
const proxyRequests = Object.keys(proxyChecks).map((latencyURL) => {
|
||||
return axiosInstance.get(latencyURL, {
|
||||
withCredentials: false,
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
useState,
|
||||
} from "react";
|
||||
import { FixedSizeList as List } from "react-window";
|
||||
import * as API from "api/api";
|
||||
import { watchWorkspaceAgentLogs } from "api/api";
|
||||
import type { WorkspaceAgentLogSource } from "api/typesGenerated";
|
||||
import {
|
||||
AGENT_LOG_LINE_HEIGHT,
|
||||
@@ -193,7 +193,7 @@ export const useAgentLogs = (
|
||||
return;
|
||||
}
|
||||
|
||||
const socket = API.watchWorkspaceAgentLogs(agentId, {
|
||||
const socket = watchWorkspaceAgentLogs(agentId, {
|
||||
// Get all logs
|
||||
after: 0,
|
||||
onMessage: (logs) => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import CircularProgress from "@mui/material/CircularProgress";
|
||||
import Link from "@mui/material/Link";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import { type FC, useState } from "react";
|
||||
import { getApiKey } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type * as TypesGen from "api/typesGenerated";
|
||||
import { useProxy } from "contexts/ProxyContext";
|
||||
import { createAppLinkHref } from "utils/apps";
|
||||
@@ -145,7 +145,7 @@ export const AppLink: FC<AppLinkProps> = ({ app, workspace, agent }) => {
|
||||
let url = href;
|
||||
if (hasMagicToken !== -1) {
|
||||
setFetchingSessionToken(true);
|
||||
const key = await getApiKey();
|
||||
const key = await API.getApiKey();
|
||||
url = href.replaceAll(magicTokenString, key.key);
|
||||
setFetchingSessionToken(false);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import { type FormikContextType, useFormik } from "formik";
|
||||
import { useState, type FC } from "react";
|
||||
import { useQuery, useMutation } from "react-query";
|
||||
import * as Yup from "yup";
|
||||
import { getAgentListeningPorts } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import {
|
||||
deleteWorkspacePortShare,
|
||||
upsertWorkspacePortShare,
|
||||
@@ -70,7 +70,7 @@ export const PortForwardButton: FC<PortForwardButtonProps> = (props) => {
|
||||
|
||||
const portsQuery = useQuery({
|
||||
queryKey: ["portForward", agent.id],
|
||||
queryFn: () => getAgentListeningPorts(agent.id),
|
||||
queryFn: () => API.getAgentListeningPorts(agent.id),
|
||||
enabled: agent.status === "connected",
|
||||
refetchInterval: 5_000,
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import ButtonGroup from "@mui/material/ButtonGroup";
|
||||
import Menu from "@mui/material/Menu";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import { type FC, useState, useRef } from "react";
|
||||
import { getApiKey } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { DisplayApp } from "api/typesGenerated";
|
||||
import { VSCodeIcon } from "components/Icons/VSCodeIcon";
|
||||
import { VSCodeInsidersIcon } from "components/Icons/VSCodeInsidersIcon";
|
||||
@@ -119,7 +119,7 @@ const VSCodeButton: FC<VSCodeDesktopButtonProps> = ({
|
||||
disabled={loading}
|
||||
onClick={() => {
|
||||
setLoading(true);
|
||||
getApiKey()
|
||||
API.getApiKey()
|
||||
.then(({ key }) => {
|
||||
const query = new URLSearchParams({
|
||||
owner: userName,
|
||||
@@ -163,7 +163,7 @@ const VSCodeInsidersButton: FC<VSCodeDesktopButtonProps> = ({
|
||||
disabled={loading}
|
||||
onClick={() => {
|
||||
setLoading(true);
|
||||
getApiKey()
|
||||
API.getApiKey()
|
||||
.then(({ key }) => {
|
||||
const query = new URLSearchParams({
|
||||
owner: userName,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { screen, waitFor } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { HttpResponse, http } from "msw";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { DEFAULT_RECORDS_PER_PAGE } from "components/PaginationWidget/utils";
|
||||
import {
|
||||
MockAuditLog,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { screen, waitFor, within } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import {
|
||||
MockTemplateExample,
|
||||
MockTemplateVersion,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { screen, within } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import {
|
||||
renderWithAuth,
|
||||
waitForLoaderToBeRemoved,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { type FC, useState } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQuery } from "react-query";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { createToken, getTokenConfig } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { CodeExample } from "components/CodeExample/CodeExample";
|
||||
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
|
||||
@@ -28,7 +28,7 @@ export const CreateTokenPage: FC = () => {
|
||||
isError: creationFailed,
|
||||
isSuccess: creationSuccessful,
|
||||
data: newToken,
|
||||
} = useMutation(createToken);
|
||||
} = useMutation(API.createToken);
|
||||
const {
|
||||
data: tokenConfig,
|
||||
isLoading: fetchingTokenConfig,
|
||||
@@ -36,7 +36,7 @@ export const CreateTokenPage: FC = () => {
|
||||
error: tokenFetchError,
|
||||
} = useQuery({
|
||||
queryKey: ["tokenconfig"],
|
||||
queryFn: getTokenConfig,
|
||||
queryFn: API.getTokenConfig,
|
||||
});
|
||||
|
||||
const [formError, setFormError] = useState<unknown>(undefined);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fireEvent, screen, waitFor } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import {
|
||||
MockTemplate,
|
||||
MockUser,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { type FC, useCallback, useEffect, useState, useRef } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
|
||||
import { getUserParameters } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { ApiErrorResponse } from "api/errors";
|
||||
import { checkAuthorization } from "api/queries/authCheck";
|
||||
import {
|
||||
@@ -99,7 +99,7 @@ const CreateWorkspacePage: FC = () => {
|
||||
const autofillEnabled = experiments.includes("auto-fill-parameters");
|
||||
const userParametersQuery = useQuery({
|
||||
queryKey: ["userParameters"],
|
||||
queryFn: () => getUserParameters(templateQuery.data!.id),
|
||||
queryFn: () => API.getUserParameters(templateQuery.data!.id),
|
||||
enabled: autofillEnabled && templateQuery.isSuccess,
|
||||
});
|
||||
const autofillParameters = getAutofillParameters(
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation } from "react-query";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { createLicense } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { AddNewLicensePageView } from "./AddNewLicensePageView";
|
||||
@@ -14,7 +14,7 @@ const AddNewLicensePage: FC = () => {
|
||||
mutate: saveLicenseKeyApi,
|
||||
isLoading: isCreating,
|
||||
error: savingLicenseError,
|
||||
} = useMutation(createLicense, {
|
||||
} = useMutation(API.createLicense, {
|
||||
onSuccess: () => {
|
||||
displaySuccess("You have successfully added a license");
|
||||
navigate("/deployment/licenses?success=true");
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import useToggle from "react-use/lib/useToggle";
|
||||
import { getLicenses, removeLicense } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { getErrorMessage } from "api/errors";
|
||||
import { entitlements, refreshEntitlements } from "api/queries/entitlements";
|
||||
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
@@ -36,7 +36,7 @@ const LicensesSettingsPage: FC = () => {
|
||||
}, [entitlementsQuery.error]);
|
||||
|
||||
const { mutate: removeLicenseApi, isLoading: isRemovingLicense } =
|
||||
useMutation(removeLicense, {
|
||||
useMutation(API.removeLicense, {
|
||||
onSuccess: () => {
|
||||
displaySuccess("Successfully removed license");
|
||||
void queryClient.invalidateQueries(["licenses"]);
|
||||
@@ -48,7 +48,7 @@ const LicensesSettingsPage: FC = () => {
|
||||
|
||||
const { data: licenses, isLoading } = useQuery({
|
||||
queryKey: ["licenses"],
|
||||
queryFn: () => getLicenses(),
|
||||
queryFn: () => API.getLicenses(),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { TemplateLayout } from "pages/TemplatePage/TemplateLayout";
|
||||
import {
|
||||
MockTemplate,
|
||||
|
||||
@@ -7,7 +7,7 @@ import RadioGroup from "@mui/material/RadioGroup";
|
||||
import { type FC, useEffect, useState } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useQuery } from "react-query";
|
||||
import { getTemplateVersionRichParameters } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { Template, TemplateVersionParameter } from "api/typesGenerated";
|
||||
import { FormSection, VerticalForm } from "components/Form/Form";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
@@ -24,7 +24,8 @@ const TemplateEmbedPage: FC = () => {
|
||||
const { template } = useTemplateLayoutContext();
|
||||
const { data: templateParameters } = useQuery({
|
||||
queryKey: ["template", template.id, "embed"],
|
||||
queryFn: () => getTemplateVersionRichParameters(template.active_version_id),
|
||||
queryFn: () =>
|
||||
API.getTemplateVersionRichParameters(template.active_version_id),
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -7,11 +7,7 @@ import {
|
||||
} from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { Outlet, useLocation, useNavigate, useParams } from "react-router-dom";
|
||||
import {
|
||||
checkAuthorization,
|
||||
getTemplateByName,
|
||||
getTemplateVersion,
|
||||
} from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { AuthorizationRequest } from "api/typesGenerated";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
@@ -39,10 +35,11 @@ const templatePermissions = (
|
||||
});
|
||||
|
||||
const fetchTemplate = async (organizationId: string, templateName: string) => {
|
||||
const template = await getTemplateByName(organizationId, templateName);
|
||||
const template = await API.getTemplateByName(organizationId, templateName);
|
||||
|
||||
const [activeVersion, permissions] = await Promise.all([
|
||||
getTemplateVersion(template.active_version_id),
|
||||
checkAuthorization({
|
||||
API.getTemplateVersion(template.active_version_id),
|
||||
API.checkAuthorization({
|
||||
checks: templatePermissions(template.id),
|
||||
}),
|
||||
]);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useQuery } from "react-query";
|
||||
import { getTemplateVersionResources } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { useTemplateLayoutContext } from "pages/TemplatePage/TemplateLayout";
|
||||
import { getTemplatePageTitle } from "../utils";
|
||||
import { TemplateSummaryPageView } from "./TemplateSummaryPageView";
|
||||
@@ -10,7 +10,7 @@ export const TemplateSummaryPage: FC = () => {
|
||||
const { template, activeVersion } = useTemplateLayoutContext();
|
||||
const { data: resources } = useQuery({
|
||||
queryKey: ["templates", template.id, "resources"],
|
||||
queryFn: () => getTemplateVersionResources(activeVersion.id),
|
||||
queryFn: () => API.getTemplateVersionResources(activeVersion.id),
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import { useState } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQuery } from "react-query";
|
||||
import {
|
||||
archiveTemplateVersion,
|
||||
getTemplateVersions,
|
||||
updateActiveTemplateVersion,
|
||||
} from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { getErrorMessage } from "api/errors";
|
||||
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
|
||||
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
@@ -17,7 +13,7 @@ const TemplateVersionsPage = () => {
|
||||
const { template, permissions } = useTemplateLayoutContext();
|
||||
const { data } = useQuery({
|
||||
queryKey: ["template", "versions", template.id],
|
||||
queryFn: () => getTemplateVersions(template.id),
|
||||
queryFn: () => API.getTemplateVersions(template.id),
|
||||
});
|
||||
// We use this to update the active version in the UI without having to refetch the template
|
||||
const [latestActiveVersion, setLatestActiveVersion] = useState(
|
||||
@@ -25,7 +21,7 @@ const TemplateVersionsPage = () => {
|
||||
);
|
||||
const { mutate: promoteVersion, isLoading: isPromoting } = useMutation({
|
||||
mutationFn: (templateVersionId: string) => {
|
||||
return updateActiveTemplateVersion(template.id, {
|
||||
return API.updateActiveTemplateVersion(template.id, {
|
||||
id: templateVersionId,
|
||||
});
|
||||
},
|
||||
@@ -41,7 +37,7 @@ const TemplateVersionsPage = () => {
|
||||
|
||||
const { mutate: archiveVersion, isLoading: isArchiving } = useMutation({
|
||||
mutationFn: (templateVersionId: string) => {
|
||||
return archiveTemplateVersion(templateVersionId);
|
||||
return API.archiveTemplateVersion(templateVersionId);
|
||||
},
|
||||
onSuccess: async () => {
|
||||
// The reload is unfortunate. When a version is archived, we should hide
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { act, renderHook, waitFor } from "@testing-library/react";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { MockTemplate } from "testHelpers/entities";
|
||||
import { useDeletionDialogState } from "./useDeletionDialogState";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from "react";
|
||||
import { deleteTemplate } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { getErrorMessage } from "api/errors";
|
||||
import { displayError } from "components/GlobalSnackbar/utils";
|
||||
|
||||
@@ -27,7 +27,7 @@ export const useDeletionDialogState = (
|
||||
const confirmDelete = async () => {
|
||||
try {
|
||||
setState({ status: "deleting" });
|
||||
await deleteTemplate(templateId);
|
||||
await API.deleteTemplate(templateId);
|
||||
onDelete();
|
||||
} catch (e) {
|
||||
setState({ status: "confirming" });
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { screen, waitFor } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { http, HttpResponse } from "msw";
|
||||
import * as API from "api/api";
|
||||
import { API, withDefaultFeatures } from "api/api";
|
||||
import type { Template, UpdateTemplateMeta } from "api/typesGenerated";
|
||||
import { Language as FooterFormLanguage } from "components/FormFooter/FormFooter";
|
||||
import { MockEntitlements, MockTemplate } from "testHelpers/entities";
|
||||
@@ -138,7 +138,7 @@ describe("TemplateSettingsPage", () => {
|
||||
http.get("/api/v2/entitlements", () => {
|
||||
return HttpResponse.json({
|
||||
...MockEntitlements,
|
||||
features: API.withDefaultFeatures({
|
||||
features: withDefaultFeatures({
|
||||
access_control: { enabled: true, entitlement: "entitled" },
|
||||
}),
|
||||
});
|
||||
@@ -163,7 +163,7 @@ describe("TemplateSettingsPage", () => {
|
||||
http.get("/api/v2/entitlements", () => {
|
||||
return HttpResponse.json({
|
||||
...MockEntitlements,
|
||||
features: API.withDefaultFeatures({
|
||||
features: withDefaultFeatures({
|
||||
access_control: { enabled: false, entitlement: "not_entitled" },
|
||||
}),
|
||||
});
|
||||
|
||||
+4
-2
@@ -2,7 +2,7 @@ import type { FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQueryClient } from "react-query";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { updateTemplateMeta } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { templateByNameKey } from "api/queries/templates";
|
||||
import type { UpdateTemplateMeta } from "api/typesGenerated";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
@@ -30,7 +30,9 @@ export const TemplateSettingsPage: FC = () => {
|
||||
isLoading: isSubmitting,
|
||||
error: submitError,
|
||||
} = useMutation(
|
||||
(data: UpdateTemplateMeta) => updateTemplateMeta(template.id, data),
|
||||
(data: UpdateTemplateMeta) => {
|
||||
return API.updateTemplateMeta(template.id, data);
|
||||
},
|
||||
{
|
||||
onSuccess: async (data) => {
|
||||
// This update has a chance to return a 304 which means nothing was updated.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { screen, waitFor } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { Language as FooterFormLanguage } from "components/FormFooter/FormFooter";
|
||||
import {
|
||||
MockEntitlementsWithScheduling,
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQueryClient } from "react-query";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { updateTemplateMeta } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { templateByNameKey } from "api/queries/templates";
|
||||
import type { UpdateTemplateMeta } from "api/typesGenerated";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
@@ -27,7 +27,7 @@ const TemplateSchedulePage: FC = () => {
|
||||
isLoading: isSubmitting,
|
||||
error: submitError,
|
||||
} = useMutation(
|
||||
(data: UpdateTemplateMeta) => updateTemplateMeta(template.id, data),
|
||||
(data: UpdateTemplateMeta) => API.updateTemplateMeta(template.id, data),
|
||||
{
|
||||
onSuccess: async () => {
|
||||
await queryClient.invalidateQueries(
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { Language as FooterFormLanguage } from "components/FormFooter/FormFooter";
|
||||
import {
|
||||
MockTemplate,
|
||||
|
||||
@@ -4,7 +4,7 @@ import WS from "jest-websocket-mock";
|
||||
import { HttpResponse, http } from "msw";
|
||||
import { QueryClient } from "react-query";
|
||||
import { RouterProvider, createMemoryRouter } from "react-router-dom";
|
||||
import * as api from "api/api";
|
||||
import * as apiModule from "api/api";
|
||||
import { templateVersionVariablesKey } from "api/queries/templates";
|
||||
import type { TemplateVersion } from "api/typesGenerated";
|
||||
import { AppProviders } from "App";
|
||||
@@ -26,6 +26,8 @@ import type { MonacoEditorProps } from "./MonacoEditor";
|
||||
import { Language } from "./PublishTemplateVersionDialog";
|
||||
import TemplateVersionEditorPage from "./TemplateVersionEditorPage";
|
||||
|
||||
const { API } = apiModule;
|
||||
|
||||
// For some reason this component in Jest is throwing a MUI style warning so,
|
||||
// since we don't need it for this test, we can mock it out
|
||||
jest.mock(
|
||||
@@ -72,8 +74,8 @@ const buildTemplateVersion = async (
|
||||
user: UserEvent,
|
||||
topbar: HTMLElement,
|
||||
) => {
|
||||
jest.spyOn(api, "uploadFile").mockResolvedValueOnce({ hash: "hash" });
|
||||
jest.spyOn(api, "createTemplateVersion").mockResolvedValue({
|
||||
jest.spyOn(API, "uploadFile").mockResolvedValueOnce({ hash: "hash" });
|
||||
jest.spyOn(API, "createTemplateVersion").mockResolvedValue({
|
||||
...templateVersion,
|
||||
job: {
|
||||
...templateVersion.job,
|
||||
@@ -81,10 +83,10 @@ const buildTemplateVersion = async (
|
||||
},
|
||||
});
|
||||
jest
|
||||
.spyOn(api, "getTemplateVersionByName")
|
||||
.spyOn(API, "getTemplateVersionByName")
|
||||
.mockResolvedValue(templateVersion);
|
||||
jest
|
||||
.spyOn(api, "watchBuildLogsByTemplateVersionId")
|
||||
.spyOn(apiModule, "watchBuildLogsByTemplateVersionId")
|
||||
.mockImplementation((_, options) => {
|
||||
options.onMessage(MockWorkspaceBuildLogs[0]);
|
||||
options.onDone?.();
|
||||
@@ -116,10 +118,10 @@ test("Use custom name, message and set it as active when publishing", async () =
|
||||
|
||||
// Publish
|
||||
const patchTemplateVersion = jest
|
||||
.spyOn(api, "patchTemplateVersion")
|
||||
.spyOn(API, "patchTemplateVersion")
|
||||
.mockResolvedValue(newTemplateVersion);
|
||||
const updateActiveTemplateVersion = jest
|
||||
.spyOn(api, "updateActiveTemplateVersion")
|
||||
.spyOn(API, "updateActiveTemplateVersion")
|
||||
.mockResolvedValue({ message: "" });
|
||||
const publishButton = within(topbar).getByRole("button", {
|
||||
name: "Publish",
|
||||
@@ -162,10 +164,10 @@ test("Do not mark as active if promote is not checked", async () => {
|
||||
|
||||
// Publish
|
||||
const patchTemplateVersion = jest
|
||||
.spyOn(api, "patchTemplateVersion")
|
||||
.spyOn(API, "patchTemplateVersion")
|
||||
.mockResolvedValue(newTemplateVersion);
|
||||
const updateActiveTemplateVersion = jest
|
||||
.spyOn(api, "updateActiveTemplateVersion")
|
||||
.spyOn(API, "updateActiveTemplateVersion")
|
||||
.mockResolvedValue({ message: "" });
|
||||
const publishButton = within(topbar).getByRole("button", {
|
||||
name: "Publish",
|
||||
@@ -207,7 +209,7 @@ test("Patch request is not send when there are no changes", async () => {
|
||||
|
||||
// Publish
|
||||
const patchTemplateVersion = jest
|
||||
.spyOn(api, "patchTemplateVersion")
|
||||
.spyOn(API, "patchTemplateVersion")
|
||||
.mockResolvedValue(newTemplateVersion);
|
||||
const publishButton = within(topbar).getByRole("button", {
|
||||
name: "Publish",
|
||||
|
||||
@@ -2,7 +2,7 @@ import { type FC, useEffect, useState } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
|
||||
import { patchTemplateVersion, updateActiveTemplateVersion } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { file, uploadFile } from "api/queries/files";
|
||||
import {
|
||||
createTemplateVersion,
|
||||
@@ -323,12 +323,12 @@ const publishVersion = async (options: {
|
||||
const publishActions: Promise<unknown>[] = [];
|
||||
|
||||
if (haveChanges) {
|
||||
publishActions.push(patchTemplateVersion(version.id, data));
|
||||
publishActions.push(API.patchTemplateVersion(version.id, data));
|
||||
}
|
||||
|
||||
if (isActiveVersion) {
|
||||
publishActions.push(
|
||||
updateActiveTemplateVersion(version.template_id!, {
|
||||
API.updateActiveTemplateVersion(version.template_id!, {
|
||||
id: version.id,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@ import "jest-canvas-mock";
|
||||
import { waitFor } from "@testing-library/react";
|
||||
import WS from "jest-websocket-mock";
|
||||
import { HttpResponse, http } from "msw";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import {
|
||||
MockUser,
|
||||
MockWorkspace,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { fireEvent, screen, waitFor } from "@testing-library/react";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { mockApiError } from "testHelpers/entities";
|
||||
import { renderWithAuth } from "testHelpers/renderHelpers";
|
||||
import * as AccountForm from "./AccountForm";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { MockUser } from "testHelpers/entities";
|
||||
import { renderWithAuth } from "testHelpers/renderHelpers";
|
||||
import { AppearancePage } from "./AppearancePage";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { fireEvent, screen, within } from "@testing-library/react";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { MockGitSSHKey, mockApiError } from "testHelpers/entities";
|
||||
import { renderWithAuth } from "testHelpers/renderHelpers";
|
||||
import { Language as SSHKeysPageLanguage, SSHKeysPage } from "./SSHKeysPage";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { fireEvent, screen, waitFor, within } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { OAuthConversionResponse } from "api/typesGenerated";
|
||||
import { MockAuthMethodsAll, mockApiError } from "testHelpers/entities";
|
||||
import {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ComponentProps, FC } from "react";
|
||||
import { useMutation, useQuery } from "react-query";
|
||||
import { getUserLoginType } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { authMethods, updatePassword } from "api/queries/users";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
@@ -19,7 +19,7 @@ export const SecurityPage: FC = () => {
|
||||
const authMethodsQuery = useQuery(authMethods());
|
||||
const { data: userLoginType } = useQuery({
|
||||
queryKey: ["loginType"],
|
||||
queryFn: getUserLoginType,
|
||||
queryFn: API.getUserLoginType,
|
||||
});
|
||||
const singleSignOnSection = useSingleSignOnSection();
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import Link from "@mui/material/Link";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { type FC, useState } from "react";
|
||||
import { useMutation } from "react-query";
|
||||
import { convertToOAUTH } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { getErrorMessage } from "api/errors";
|
||||
import type {
|
||||
AuthMethods,
|
||||
@@ -52,7 +52,7 @@ export const useSingleSignOnSection = () => {
|
||||
const [loginTypeConfirmation, setLoginTypeConfirmation] =
|
||||
useState<LoginTypeConfirmation>({ open: false, selectedType: undefined });
|
||||
|
||||
const mutation = useMutation(convertToOAUTH, {
|
||||
const mutation = useMutation(API.convertToOAUTH, {
|
||||
onSuccess: (data) => {
|
||||
const loginTypeMsg =
|
||||
data.to_type === "github" ? "Github" : "OpenID Connect";
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
} from "react-query";
|
||||
import { getTokens, deleteToken } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { TokensFilter } from "api/typesGenerated";
|
||||
|
||||
// Load all tokens
|
||||
@@ -12,10 +12,7 @@ export const useTokensData = ({ include_all }: TokensFilter) => {
|
||||
const queryKey = ["tokens", include_all];
|
||||
const result = useQuery({
|
||||
queryKey,
|
||||
queryFn: () =>
|
||||
getTokens({
|
||||
include_all,
|
||||
}),
|
||||
queryFn: () => API.getTokens({ include_all }),
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -29,7 +26,7 @@ export const useDeleteToken = (queryKey: QueryKey) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: deleteToken,
|
||||
mutationFn: API.deleteToken,
|
||||
onSuccess: () => {
|
||||
// Invalidate and refetch
|
||||
void queryClient.invalidateQueries(queryKey);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { fireEvent, screen, within } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { HttpResponse, http } from "msw";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { Role } from "api/typesGenerated";
|
||||
import {
|
||||
MockUser,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { screen, waitFor } from "@testing-library/react";
|
||||
import WS from "jest-websocket-mock";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import {
|
||||
MockWorkspace,
|
||||
MockWorkspaceAgent,
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useQuery } from "react-query";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { getWorkspaceBuilds } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { workspaceBuildByNumber } from "api/queries/workspaceBuilds";
|
||||
import { useWorkspaceBuildLogs } from "hooks/useWorkspaceBuildLogs";
|
||||
import { pageTitle } from "utils/page";
|
||||
@@ -26,7 +26,7 @@ export const WorkspaceBuildPage: FC = () => {
|
||||
const buildsQuery = useQuery({
|
||||
queryKey: ["builds", username, build?.workspace_id],
|
||||
queryFn: () => {
|
||||
return getWorkspaceBuilds(build?.workspace_id ?? "", {
|
||||
return API.getWorkspaceBuilds(build?.workspace_id ?? "", {
|
||||
since: dayjs().add(-30, "day").toISOString(),
|
||||
});
|
||||
},
|
||||
|
||||
@@ -5,7 +5,7 @@ import visuallyHidden from "@mui/utils/visuallyHidden";
|
||||
import { useFormik } from "formik";
|
||||
import type { FC } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { getWorkspaceParameters } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type {
|
||||
TemplateVersionParameter,
|
||||
Workspace,
|
||||
@@ -49,7 +49,7 @@ export const BuildParametersPopover: FC<BuildParametersPopoverProps> = ({
|
||||
}) => {
|
||||
const { data: parameters } = useQuery({
|
||||
queryKey: ["workspace", workspace.id, "parameters"],
|
||||
queryFn: () => getWorkspaceParameters(workspace),
|
||||
queryFn: () => API.getWorkspaceParameters(workspace),
|
||||
});
|
||||
const ephemeralParameters = parameters
|
||||
? parameters.templateVersionRichParameters.filter((p) => p.ephemeral)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { screen, waitFor, within } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { HttpResponse, http } from "msw";
|
||||
import * as api from "api/api";
|
||||
import * as apiModule from "api/api";
|
||||
import type { TemplateVersionParameter, Workspace } from "api/typesGenerated";
|
||||
import EventSourceMock from "eventsourcemock";
|
||||
import {
|
||||
@@ -22,16 +22,18 @@ import { renderWithAuth } from "testHelpers/renderHelpers";
|
||||
import { server } from "testHelpers/server";
|
||||
import { WorkspacePage } from "./WorkspacePage";
|
||||
|
||||
const { API, MissingBuildParameters } = apiModule;
|
||||
|
||||
// Renders the workspace page and waits for it be loaded
|
||||
const renderWorkspacePage = async (workspace: Workspace) => {
|
||||
jest.spyOn(api, "getWorkspaceByOwnerAndName").mockResolvedValue(workspace);
|
||||
jest.spyOn(api, "getTemplate").mockResolvedValueOnce(MockTemplate);
|
||||
jest.spyOn(api, "getTemplateVersionRichParameters").mockResolvedValueOnce([]);
|
||||
jest.spyOn(API, "getWorkspaceByOwnerAndName").mockResolvedValue(workspace);
|
||||
jest.spyOn(API, "getTemplate").mockResolvedValueOnce(MockTemplate);
|
||||
jest.spyOn(API, "getTemplateVersionRichParameters").mockResolvedValueOnce([]);
|
||||
jest
|
||||
.spyOn(api, "getDeploymentConfig")
|
||||
.spyOn(API, "getDeploymentConfig")
|
||||
.mockResolvedValueOnce(MockDeploymentConfig);
|
||||
jest
|
||||
.spyOn(api, "watchWorkspaceAgentLogs")
|
||||
.spyOn(apiModule, "watchWorkspaceAgentLogs")
|
||||
.mockImplementation((_, options) => {
|
||||
options.onDone?.();
|
||||
return new WebSocket("");
|
||||
@@ -87,7 +89,7 @@ describe("WorkspacePage", () => {
|
||||
it("requests a delete job when the user presses Delete and confirms", async () => {
|
||||
const user = userEvent.setup({ delay: 0 });
|
||||
const deleteWorkspaceMock = jest
|
||||
.spyOn(api, "deleteWorkspace")
|
||||
.spyOn(API, "deleteWorkspace")
|
||||
.mockResolvedValueOnce(MockWorkspaceBuild);
|
||||
await renderWorkspacePage(MockWorkspace);
|
||||
|
||||
@@ -127,7 +129,7 @@ describe("WorkspacePage", () => {
|
||||
);
|
||||
|
||||
const deleteWorkspaceMock = jest
|
||||
.spyOn(api, "deleteWorkspace")
|
||||
.spyOn(API, "deleteWorkspace")
|
||||
.mockResolvedValueOnce(MockWorkspaceBuildDelete);
|
||||
await renderWorkspacePage(MockFailedWorkspace);
|
||||
|
||||
@@ -173,7 +175,7 @@ describe("WorkspacePage", () => {
|
||||
);
|
||||
|
||||
const startWorkspaceMock = jest
|
||||
.spyOn(api, "startWorkspace")
|
||||
.spyOn(API, "startWorkspace")
|
||||
.mockImplementation(() => Promise.resolve(MockWorkspaceBuild));
|
||||
|
||||
await testButton(MockStoppedWorkspace, "Start", startWorkspaceMock);
|
||||
@@ -181,7 +183,7 @@ describe("WorkspacePage", () => {
|
||||
|
||||
it("requests a stop job when the user presses Stop", async () => {
|
||||
const stopWorkspaceMock = jest
|
||||
.spyOn(api, "stopWorkspace")
|
||||
.spyOn(API, "stopWorkspace")
|
||||
.mockResolvedValueOnce(MockWorkspaceBuild);
|
||||
|
||||
await testButton(MockWorkspace, "Stop", stopWorkspaceMock);
|
||||
@@ -189,7 +191,7 @@ describe("WorkspacePage", () => {
|
||||
|
||||
it("requests a stop when the user presses Restart", async () => {
|
||||
const stopWorkspaceMock = jest
|
||||
.spyOn(api, "stopWorkspace")
|
||||
.spyOn(API, "stopWorkspace")
|
||||
.mockResolvedValueOnce(MockWorkspaceBuild);
|
||||
|
||||
// Render
|
||||
@@ -215,7 +217,7 @@ describe("WorkspacePage", () => {
|
||||
);
|
||||
|
||||
const cancelWorkspaceMock = jest
|
||||
.spyOn(api, "cancelWorkspaceBuild")
|
||||
.spyOn(API, "cancelWorkspaceBuild")
|
||||
.mockImplementation(() => Promise.resolve({ message: "job canceled" }));
|
||||
|
||||
await testButton(MockStartingWorkspace, "Cancel", cancelWorkspaceMock);
|
||||
@@ -224,11 +226,11 @@ describe("WorkspacePage", () => {
|
||||
it("requests an update when the user presses Update", async () => {
|
||||
// Mocks
|
||||
jest
|
||||
.spyOn(api, "getWorkspaceByOwnerAndName")
|
||||
.spyOn(API, "getWorkspaceByOwnerAndName")
|
||||
.mockResolvedValueOnce(MockOutdatedWorkspace);
|
||||
|
||||
const updateWorkspaceMock = jest
|
||||
.spyOn(api, "updateWorkspace")
|
||||
.spyOn(API, "updateWorkspace")
|
||||
.mockResolvedValueOnce(MockWorkspaceBuild);
|
||||
|
||||
// Render
|
||||
@@ -249,12 +251,12 @@ describe("WorkspacePage", () => {
|
||||
it("updates the parameters when they are missing during update", async () => {
|
||||
// Mocks
|
||||
jest
|
||||
.spyOn(api, "getWorkspaceByOwnerAndName")
|
||||
.spyOn(API, "getWorkspaceByOwnerAndName")
|
||||
.mockResolvedValueOnce(MockOutdatedWorkspace);
|
||||
const updateWorkspaceSpy = jest
|
||||
.spyOn(api, "updateWorkspace")
|
||||
.spyOn(API, "updateWorkspace")
|
||||
.mockRejectedValueOnce(
|
||||
new api.MissingBuildParameters(
|
||||
new MissingBuildParameters(
|
||||
[MockTemplateVersionParameter1, MockTemplateVersionParameter2],
|
||||
MockOutdatedWorkspace.template_active_version_id,
|
||||
),
|
||||
@@ -271,7 +273,7 @@ describe("WorkspacePage", () => {
|
||||
|
||||
// The update was called
|
||||
await waitFor(() => {
|
||||
expect(api.updateWorkspace).toBeCalled();
|
||||
expect(API.updateWorkspace).toBeCalled();
|
||||
updateWorkspaceSpy.mockClear();
|
||||
});
|
||||
|
||||
@@ -294,7 +296,7 @@ describe("WorkspacePage", () => {
|
||||
|
||||
// Check if the update was called using the values from the form
|
||||
await waitFor(() => {
|
||||
expect(api.updateWorkspace).toBeCalledWith(MockOutdatedWorkspace, [
|
||||
expect(API.updateWorkspace).toBeCalledWith(MockOutdatedWorkspace, [
|
||||
{
|
||||
name: MockTemplateVersionParameter1.name,
|
||||
value: "some-value",
|
||||
@@ -309,7 +311,7 @@ describe("WorkspacePage", () => {
|
||||
|
||||
it("restart the workspace with one time parameters when having the confirmation dialog", async () => {
|
||||
localStorage.removeItem(`${MockUser.id}_ignoredWarnings`);
|
||||
jest.spyOn(api, "getWorkspaceParameters").mockResolvedValue({
|
||||
jest.spyOn(API, "getWorkspaceParameters").mockResolvedValue({
|
||||
templateVersionRichParameters: [
|
||||
{
|
||||
...MockTemplateVersionParameter1,
|
||||
@@ -321,7 +323,7 @@ describe("WorkspacePage", () => {
|
||||
],
|
||||
buildParameters: [{ name: "rebuild", value: "false" }],
|
||||
});
|
||||
const restartWorkspaceSpy = jest.spyOn(api, "restartWorkspace");
|
||||
const restartWorkspaceSpy = jest.spyOn(API, "restartWorkspace");
|
||||
const user = userEvent.setup();
|
||||
await renderWorkspacePage(MockWorkspace);
|
||||
await user.click(screen.getByTestId("build-parameters-button"));
|
||||
@@ -351,7 +353,7 @@ describe("WorkspacePage", () => {
|
||||
const retryDebugButtonRe = /^Debug$/i;
|
||||
|
||||
describe("Retries a failed 'Start' transition", () => {
|
||||
const mockStart = jest.spyOn(api, "startWorkspace");
|
||||
const mockStart = jest.spyOn(API, "startWorkspace");
|
||||
const failedStart: Workspace = {
|
||||
...MockFailedWorkspace,
|
||||
latest_build: {
|
||||
@@ -384,7 +386,7 @@ describe("WorkspacePage", () => {
|
||||
});
|
||||
|
||||
describe("Retries a failed 'Stop' transition", () => {
|
||||
const mockStop = jest.spyOn(api, "stopWorkspace");
|
||||
const mockStop = jest.spyOn(API, "stopWorkspace");
|
||||
const failedStop: Workspace = {
|
||||
...MockFailedWorkspace,
|
||||
latest_build: {
|
||||
@@ -405,7 +407,7 @@ describe("WorkspacePage", () => {
|
||||
});
|
||||
|
||||
describe("Retries a failed 'Delete' transition", () => {
|
||||
const mockDelete = jest.spyOn(api, "deleteWorkspace");
|
||||
const mockDelete = jest.spyOn(API, "deleteWorkspace");
|
||||
const failedDelete: Workspace = {
|
||||
...MockFailedWorkspace,
|
||||
latest_build: {
|
||||
@@ -450,7 +452,7 @@ describe("WorkspacePage", () => {
|
||||
return HttpResponse.json([parameter]);
|
||||
}),
|
||||
);
|
||||
const startWorkspaceSpy = jest.spyOn(api, "startWorkspace");
|
||||
const startWorkspaceSpy = jest.spyOn(API, "startWorkspace");
|
||||
|
||||
await renderWorkspacePage(workspace);
|
||||
const retryWithBuildParametersButton = await screen.findByRole("button", {
|
||||
@@ -496,7 +498,7 @@ describe("WorkspacePage", () => {
|
||||
return HttpResponse.json([parameter]);
|
||||
}),
|
||||
);
|
||||
const startWorkspaceSpy = jest.spyOn(api, "startWorkspace");
|
||||
const startWorkspaceSpy = jest.spyOn(API, "startWorkspace");
|
||||
|
||||
await renderWorkspacePage(workspace);
|
||||
const retryWithBuildParametersButton = await screen.findByRole("button", {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { type FC, useEffect, useState } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { MissingBuildParameters, restartWorkspace } from "api/api";
|
||||
import { MissingBuildParameters, API } from "api/api";
|
||||
import { getErrorMessage } from "api/errors";
|
||||
import { buildInfo } from "api/queries/buildInfo";
|
||||
import { deploymentConfig, deploymentSSHConfig } from "api/queries/deployment";
|
||||
@@ -83,7 +83,7 @@ export const WorkspaceReadyPage: FC<WorkspaceReadyPageProps> = ({
|
||||
}>({ open: false });
|
||||
const { mutate: mutateRestartWorkspace, isLoading: isRestarting } =
|
||||
useMutation({
|
||||
mutationFn: restartWorkspace,
|
||||
mutationFn: API.restartWorkspace,
|
||||
});
|
||||
|
||||
// SSH Prefix
|
||||
|
||||
@@ -5,7 +5,7 @@ import { HttpResponse, http } from "msw";
|
||||
import type { FC } from "react";
|
||||
import { QueryClient, QueryClientProvider, useQuery } from "react-query";
|
||||
import { RouterProvider, createMemoryRouter } from "react-router-dom";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { workspaceByOwnerAndName } from "api/queries/workspaces";
|
||||
import { GlobalSnackbar } from "components/GlobalSnackbar/GlobalSnackbar";
|
||||
import { ThemeProvider } from "contexts/ThemeProvider";
|
||||
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
import { screen, waitFor, within } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import * as api from "api/api";
|
||||
import { API } from "api/api";
|
||||
import {
|
||||
MockWorkspace,
|
||||
MockTemplateVersionParameter1,
|
||||
@@ -20,15 +20,15 @@ import WorkspaceParametersPage from "./WorkspaceParametersPage";
|
||||
test("Submit the workspace settings page successfully", async () => {
|
||||
// Mock the API calls that loads data
|
||||
jest
|
||||
.spyOn(api, "getWorkspaceByOwnerAndName")
|
||||
.spyOn(API, "getWorkspaceByOwnerAndName")
|
||||
.mockResolvedValueOnce(MockWorkspace);
|
||||
jest.spyOn(api, "getTemplateVersionRichParameters").mockResolvedValueOnce([
|
||||
jest.spyOn(API, "getTemplateVersionRichParameters").mockResolvedValueOnce([
|
||||
MockTemplateVersionParameter1,
|
||||
MockTemplateVersionParameter2,
|
||||
// Immutable parameters
|
||||
MockTemplateVersionParameter4,
|
||||
]);
|
||||
jest.spyOn(api, "getWorkspaceBuildParameters").mockResolvedValueOnce([
|
||||
jest.spyOn(API, "getWorkspaceBuildParameters").mockResolvedValueOnce([
|
||||
MockWorkspaceBuildParameter1,
|
||||
MockWorkspaceBuildParameter2,
|
||||
// Immutable value
|
||||
@@ -36,7 +36,7 @@ test("Submit the workspace settings page successfully", async () => {
|
||||
]);
|
||||
// Mock the API calls that submit data
|
||||
const postWorkspaceBuildSpy = jest
|
||||
.spyOn(api, "postWorkspaceBuild")
|
||||
.spyOn(API, "postWorkspaceBuild")
|
||||
.mockResolvedValue(MockWorkspaceBuild);
|
||||
// Setup event and rendering
|
||||
const user = userEvent.setup();
|
||||
|
||||
+4
-4
@@ -4,7 +4,7 @@ import type { FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQuery } from "react-query";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { getWorkspaceParameters, postWorkspaceBuild } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { isApiValidationError } from "api/errors";
|
||||
import { checkAuthorization } from "api/queries/authCheck";
|
||||
import { templateByName } from "api/queries/templates";
|
||||
@@ -29,12 +29,12 @@ const WorkspaceParametersPage: FC = () => {
|
||||
const workspace = useWorkspaceSettings();
|
||||
const parameters = useQuery({
|
||||
queryKey: ["workspace", workspace.id, "parameters"],
|
||||
queryFn: () => getWorkspaceParameters(workspace),
|
||||
queryFn: () => API.getWorkspaceParameters(workspace),
|
||||
});
|
||||
const navigate = useNavigate();
|
||||
const updateParameters = useMutation({
|
||||
mutationFn: (buildParameters: WorkspaceBuildParameter[]) =>
|
||||
postWorkspaceBuild(workspace.id, {
|
||||
API.postWorkspaceBuild(workspace.id, {
|
||||
transition: "start",
|
||||
rich_parameter_values: buildParameters,
|
||||
}),
|
||||
@@ -93,7 +93,7 @@ const WorkspaceParametersPage: FC = () => {
|
||||
export type WorkspaceParametersPageViewProps = {
|
||||
workspace: Workspace;
|
||||
canChangeVersions: boolean;
|
||||
data: Awaited<ReturnType<typeof getWorkspaceParameters>> | undefined;
|
||||
data: Awaited<ReturnType<typeof API.getWorkspaceParameters>> | undefined;
|
||||
submitError: unknown;
|
||||
isSubmitting: boolean;
|
||||
onSubmit: (formValues: WorkspaceParametersFormValues) => void;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { screen } from "@testing-library/react";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { defaultSchedule } from "pages/WorkspaceSettingsPage/WorkspaceSchedulePage/schedule";
|
||||
import { MockTemplate } from "testHelpers/entities";
|
||||
import { render } from "testHelpers/renderHelpers";
|
||||
|
||||
+4
-8
@@ -3,11 +3,7 @@ import { type FC, useState } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import {
|
||||
putWorkspaceAutostart,
|
||||
putWorkspaceAutostop,
|
||||
startWorkspace,
|
||||
} from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { checkAuthorization } from "api/queries/authCheck";
|
||||
import { templateByName } from "api/queries/templates";
|
||||
import { workspaceByOwnerAndNameKey } from "api/queries/workspaces";
|
||||
@@ -72,7 +68,7 @@ export const WorkspaceSchedulePage: FC = () => {
|
||||
const [isConfirmingApply, setIsConfirmingApply] = useState(false);
|
||||
const { mutate: updateWorkspace } = useMutation({
|
||||
mutationFn: () =>
|
||||
startWorkspace(workspace.id, workspace.template_active_version_id),
|
||||
API.startWorkspace(workspace.id, workspace.template_active_version_id),
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -167,11 +163,11 @@ const submitSchedule = async (data: SubmitScheduleData) => {
|
||||
const actions: Promise<void>[] = [];
|
||||
|
||||
if (autostartChanged) {
|
||||
actions.push(putWorkspaceAutostart(workspace.id, autostart));
|
||||
actions.push(API.putWorkspaceAutostart(workspace.id, autostart));
|
||||
}
|
||||
|
||||
if (autostopChanged) {
|
||||
actions.push(putWorkspaceAutostop(workspace.id, ttl));
|
||||
actions.push(API.putWorkspaceAutostop(workspace.id, ttl));
|
||||
}
|
||||
|
||||
return Promise.all(actions);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { screen, waitFor, within } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import * as api from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { MockWorkspace } from "testHelpers/entities";
|
||||
import {
|
||||
renderWithWorkspaceSettingsLayout,
|
||||
@@ -11,11 +11,11 @@ import WorkspaceSettingsPage from "./WorkspaceSettingsPage";
|
||||
test("Submit the workspace settings page successfully", async () => {
|
||||
// Mock the API calls that loads data
|
||||
jest
|
||||
.spyOn(api, "getWorkspaceByOwnerAndName")
|
||||
.spyOn(API, "getWorkspaceByOwnerAndName")
|
||||
.mockResolvedValueOnce({ ...MockWorkspace });
|
||||
// Mock the API calls that submit data
|
||||
const patchWorkspaceSpy = jest
|
||||
.spyOn(api, "patchWorkspace")
|
||||
.spyOn(API, "patchWorkspace")
|
||||
.mockResolvedValue();
|
||||
// Setup event and rendering
|
||||
const user = userEvent.setup();
|
||||
@@ -43,7 +43,7 @@ test("Submit the workspace settings page successfully", async () => {
|
||||
test("Name field is disabled if renames are disabled", async () => {
|
||||
// Mock the API calls that loads data
|
||||
jest
|
||||
.spyOn(api, "getWorkspaceByOwnerAndName")
|
||||
.spyOn(API, "getWorkspaceByOwnerAndName")
|
||||
.mockResolvedValueOnce({ ...MockWorkspace, allow_renames: false });
|
||||
renderWithWorkspaceSettingsLayout(<WorkspaceSettingsPage />, {
|
||||
route: "/@test-user/test-workspace/settings",
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation } from "react-query";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { patchWorkspace, updateWorkspaceAutomaticUpdates } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { pageTitle } from "utils/page";
|
||||
import type { WorkspaceSettingsFormValues } from "./WorkspaceSettingsForm";
|
||||
@@ -22,8 +22,8 @@ const WorkspaceSettingsPage: FC = () => {
|
||||
const mutation = useMutation({
|
||||
mutationFn: async (formValues: WorkspaceSettingsFormValues) => {
|
||||
await Promise.all([
|
||||
patchWorkspace(workspace.id, { name: formValues.name }),
|
||||
updateWorkspaceAutomaticUpdates(
|
||||
API.patchWorkspace(workspace.id, { name: formValues.name }),
|
||||
API.updateWorkspaceAutomaticUpdates(
|
||||
workspace.id,
|
||||
formValues.automatic_updates,
|
||||
),
|
||||
|
||||
@@ -7,7 +7,7 @@ import dayjs from "dayjs";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import { type FC, type ReactNode, useMemo, useState, useEffect } from "react";
|
||||
import { useQueries } from "react-query";
|
||||
import { getTemplateVersion } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { TemplateVersion, Workspace } from "api/typesGenerated";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
|
||||
@@ -129,7 +129,7 @@ export const BatchUpdateConfirmation: FC<BatchUpdateConfirmationProps> = ({
|
||||
// ...but the query _also_ doesn't have everything we need, like the
|
||||
// template display name!
|
||||
...version,
|
||||
...(await getTemplateVersion(version.id)),
|
||||
...(await API.getTemplateVersion(version.id)),
|
||||
}),
|
||||
})),
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { screen, waitFor, within } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { HttpResponse, http } from "msw";
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { Workspace } from "api/typesGenerated";
|
||||
import {
|
||||
MockStoppedWorkspace,
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
import { useMutation } from "react-query";
|
||||
import {
|
||||
deleteWorkspace,
|
||||
deleteFavoriteWorkspace,
|
||||
putFavoriteWorkspace,
|
||||
startWorkspace,
|
||||
stopWorkspace,
|
||||
updateWorkspace,
|
||||
} from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { Workspace } from "api/typesGenerated";
|
||||
import { displayError } from "components/GlobalSnackbar/utils";
|
||||
|
||||
@@ -21,7 +14,7 @@ export function useBatchActions(options: UseBatchActionsProps) {
|
||||
mutationFn: (workspaces: readonly Workspace[]) => {
|
||||
return Promise.all(
|
||||
workspaces.map((w) =>
|
||||
startWorkspace(w.id, w.latest_build.template_version_id),
|
||||
API.startWorkspace(w.id, w.latest_build.template_version_id),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -33,7 +26,7 @@ export function useBatchActions(options: UseBatchActionsProps) {
|
||||
|
||||
const stopAllMutation = useMutation({
|
||||
mutationFn: (workspaces: readonly Workspace[]) => {
|
||||
return Promise.all(workspaces.map((w) => stopWorkspace(w.id)));
|
||||
return Promise.all(workspaces.map((w) => API.stopWorkspace(w.id)));
|
||||
},
|
||||
onSuccess,
|
||||
onError: () => {
|
||||
@@ -43,7 +36,7 @@ export function useBatchActions(options: UseBatchActionsProps) {
|
||||
|
||||
const deleteAllMutation = useMutation({
|
||||
mutationFn: (workspaces: readonly Workspace[]) => {
|
||||
return Promise.all(workspaces.map((w) => deleteWorkspace(w.id)));
|
||||
return Promise.all(workspaces.map((w) => API.deleteWorkspace(w.id)));
|
||||
},
|
||||
onSuccess,
|
||||
onError: () => {
|
||||
@@ -56,7 +49,7 @@ export function useBatchActions(options: UseBatchActionsProps) {
|
||||
return Promise.all(
|
||||
workspaces
|
||||
.filter((w) => w.outdated && !w.dormant_at)
|
||||
.map((w) => updateWorkspace(w)),
|
||||
.map((w) => API.updateWorkspace(w)),
|
||||
);
|
||||
},
|
||||
onSuccess,
|
||||
@@ -70,7 +63,7 @@ export function useBatchActions(options: UseBatchActionsProps) {
|
||||
return Promise.all(
|
||||
workspaces
|
||||
.filter((w) => !w.favorite)
|
||||
.map((w) => putFavoriteWorkspace(w.id)),
|
||||
.map((w) => API.putFavoriteWorkspace(w.id)),
|
||||
);
|
||||
},
|
||||
onSuccess,
|
||||
@@ -84,7 +77,7 @@ export function useBatchActions(options: UseBatchActionsProps) {
|
||||
return Promise.all(
|
||||
workspaces
|
||||
.filter((w) => w.favorite)
|
||||
.map((w) => deleteFavoriteWorkspace(w.id)),
|
||||
.map((w) => API.deleteFavoriteWorkspace(w.id)),
|
||||
);
|
||||
},
|
||||
onSuccess,
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
} from "react-query";
|
||||
import { getWorkspaces, updateWorkspaceVersion } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import { getErrorMessage } from "api/errors";
|
||||
import type {
|
||||
Workspace,
|
||||
@@ -30,7 +30,7 @@ export const useWorkspacesData = ({
|
||||
const result = useQuery({
|
||||
queryKey,
|
||||
queryFn: () =>
|
||||
getWorkspaces({
|
||||
API.getWorkspaces({
|
||||
q: query,
|
||||
limit: limit,
|
||||
offset: page <= 0 ? 0 : (page - 1) * limit,
|
||||
@@ -54,7 +54,7 @@ export const useWorkspaceUpdate = (queryKey: QueryKey) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: updateWorkspaceVersion,
|
||||
mutationFn: API.updateWorkspaceVersion,
|
||||
onMutate: async (workspace) => {
|
||||
await queryClient.cancelQueries({ queryKey });
|
||||
queryClient.setQueryData<WorkspacesResponse>(queryKey, (oldResponse) => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getTemplates } from "api/api";
|
||||
import { API } from "api/api";
|
||||
import type { WorkspaceStatus } from "api/typesGenerated";
|
||||
import {
|
||||
useFilterMenu,
|
||||
@@ -21,7 +21,7 @@ export const useTemplateFilterMenu = ({
|
||||
id: "template",
|
||||
getSelectedOption: async () => {
|
||||
// Show all templates including deprecated
|
||||
const templates = await getTemplates(organizationId);
|
||||
const templates = await API.getTemplates(organizationId);
|
||||
const template = templates.find((template) => template.name === value);
|
||||
if (template) {
|
||||
return {
|
||||
@@ -37,7 +37,7 @@ export const useTemplateFilterMenu = ({
|
||||
},
|
||||
getOptions: async (query) => {
|
||||
// Show all templates including deprecated
|
||||
const templates = await getTemplates(organizationId);
|
||||
const templates = await API.getTemplates(organizationId);
|
||||
const filteredTemplates = templates.filter(
|
||||
(template) =>
|
||||
template.name.toLowerCase().includes(query.toLowerCase()) ||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as API from "api/api";
|
||||
import { API } from "api/api";
|
||||
|
||||
export const terminalWebsocketUrl = async (
|
||||
baseUrl: string | undefined,
|
||||
|
||||
Reference in New Issue
Block a user