diff --git a/biome.jsonc b/biome.jsonc index 10e0514f21..51b6936f6e 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -3,11 +3,13 @@ "enabled": true, "clientKind": "git", "useIgnoreFile": true, - "defaultBranch": "main", + "defaultBranch": "main" }, "files": { - "includes": ["**", "!**/pnpm-lock.yaml"], - "ignoreUnknown": true, + // static/*.html are Go templates with {{ }} directives that + // Biome's HTML parser does not support. + "includes": ["**", "!**/pnpm-lock.yaml", "!**/static/*.html"], + "ignoreUnknown": true }, "linter": { "rules": { @@ -15,7 +17,7 @@ "noSvgWithoutTitle": "off", "useButtonType": "off", "useSemanticElements": "off", - "noStaticElementInteractions": "off", + "noStaticElementInteractions": "off" }, "correctness": { "noUnusedImports": "warn", @@ -24,9 +26,9 @@ "noUnusedVariables": { "level": "warn", "options": { - "ignoreRestSiblings": true, - }, - }, + "ignoreRestSiblings": true + } + } }, "style": { "noNonNullAssertion": "off", @@ -47,7 +49,7 @@ "paths": { "react": { "message": "React 19 no longer requires forwardRef. Use ref as a prop instead.", - "importNames": ["forwardRef"], + "importNames": ["forwardRef"] }, // "@mui/material/Alert": "Use components/Alert/Alert instead.", // "@mui/material/AlertTitle": "Use components/Alert/Alert instead.", @@ -115,10 +117,10 @@ "@emotion/styled": "Use Tailwind CSS instead.", // "@emotion/cache": "Use Tailwind CSS instead.", // "components/Stack/Stack": "Use Tailwind flex utilities instead (e.g.,
).", - "lodash": "Use lodash/ instead.", - }, - }, - }, + "lodash": "Use lodash/ instead." + } + } + } }, "suspicious": { "noArrayIndexKey": "off", @@ -129,14 +131,21 @@ "noConsole": { "level": "error", "options": { - "allow": ["error", "info", "warn"], - }, - }, + "allow": ["error", "info", "warn"] + } + } }, "complexity": { - "noImportantStyles": "off", // TODO: check and fix !important styles - }, - }, + "noImportantStyles": "off" // TODO: check and fix !important styles + } + } }, - "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", + "css": { + "parser": { + // Biome 2.3+ requires opt-in for @apply and other + // Tailwind directives. + "tailwindDirectives": true + } + }, + "$schema": "./node_modules/@biomejs/biome/configuration_schema.json" } diff --git a/package.json b/package.json index b220803ad7..46c56d10e9 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "storybook": "pnpm run -C site/ storybook" }, "devDependencies": { - "@biomejs/biome": "2.2.0", + "@biomejs/biome": "2.4.10", "markdown-table-formatter": "^1.6.1", "markdownlint-cli2": "^0.16.0", "quicktype": "^23.0.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1e2921375a..35d88ae183 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: .: devDependencies: '@biomejs/biome': - specifier: 2.2.0 - version: 2.2.0 + specifier: 2.4.10 + version: 2.4.10 markdown-table-formatter: specifier: ^1.6.1 version: 1.6.1 @@ -26,55 +26,55 @@ importers: packages: - '@biomejs/biome@2.2.0': - resolution: {integrity: sha512-3On3RSYLsX+n9KnoSgfoYlckYBoU6VRM22cw1gB4Y0OuUVSYd/O/2saOJMrA4HFfA1Ff0eacOvMN1yAAvHtzIw==} + '@biomejs/biome@2.4.10': + resolution: {integrity: sha512-xxA3AphFQ1geij4JTHXv4EeSTda1IFn22ye9LdyVPoJU19fNVl0uzfEuhsfQ4Yue/0FaLs2/ccVi4UDiE7R30w==} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@2.2.0': - resolution: {integrity: sha512-zKbwUUh+9uFmWfS8IFxmVD6XwqFcENjZvEyfOxHs1epjdH3wyyMQG80FGDsmauPwS2r5kXdEM0v/+dTIA9FXAg==} + '@biomejs/cli-darwin-arm64@2.4.10': + resolution: {integrity: sha512-vuzzI1cWqDVzOMIkYyHbKqp+AkQq4K7k+UCXWpkYcY/HDn1UxdsbsfgtVpa40shem8Kax4TLDLlx8kMAecgqiw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@2.2.0': - resolution: {integrity: sha512-+OmT4dsX2eTfhD5crUOPw3RPhaR+SKVspvGVmSdZ9y9O/AgL8pla6T4hOn1q+VAFBHuHhsdxDRJgFCSC7RaMOw==} + '@biomejs/cli-darwin-x64@2.4.10': + resolution: {integrity: sha512-14fzASRo+BPotwp7nWULy2W5xeUyFnTaq1V13Etrrxkrih+ez/2QfgFm5Ehtf5vSjtgx/IJycMMpn5kPd5ZNaA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@2.2.0': - resolution: {integrity: sha512-egKpOa+4FL9YO+SMUMLUvf543cprjevNc3CAgDNFLcjknuNMcZ0GLJYa3EGTCR2xIkIUJDVneBV3O9OcIlCEZQ==} + '@biomejs/cli-linux-arm64-musl@2.4.10': + resolution: {integrity: sha512-WrJY6UuiSD/Dh+nwK2qOTu8kdMDlLV3dLMmychIghHPAysWFq1/DGC1pVZx8POE3ZkzKR3PUUnVrtZfMfaJjyQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-arm64@2.2.0': - resolution: {integrity: sha512-6eoRdF2yW5FnW9Lpeivh7Mayhq0KDdaDMYOJnH9aT02KuSIX5V1HmWJCQQPwIQbhDh68Zrcpl8inRlTEan0SXw==} + '@biomejs/cli-linux-arm64@2.4.10': + resolution: {integrity: sha512-7MH1CMW5uuxQ/s7FLST63qF8B3Hgu2HRdZ7tA1X1+mk+St4JOuIrqdhIBnnyqeyWJNI+Bww7Es5QZ0wIc1Cmkw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-x64-musl@2.2.0': - resolution: {integrity: sha512-I5J85yWwUWpgJyC1CcytNSGusu2p9HjDnOPAFG4Y515hwRD0jpR9sT9/T1cKHtuCvEQ/sBvx+6zhz9l9wEJGAg==} + '@biomejs/cli-linux-x64-musl@2.4.10': + resolution: {integrity: sha512-kDTi3pI6PBN6CiczsWYOyP2zk0IJI08EWEQyDMQWW221rPaaEz6FvjLhnU07KMzLv8q3qSuoB93ua6inSQ55Tw==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-linux-x64@2.2.0': - resolution: {integrity: sha512-5UmQx/OZAfJfi25zAnAGHUMuOd+LOsliIt119x2soA2gLggQYrVPA+2kMUxR6Mw5M1deUF/AWWP2qpxgH7Nyfw==} + '@biomejs/cli-linux-x64@2.4.10': + resolution: {integrity: sha512-tZLvEEi2u9Xu1zAqRjTcpIDGVtldigVvzug2fTuPG0ME/g8/mXpRPcNgLB22bGn6FvLJpHHnqLnwliOu8xjYrg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-win32-arm64@2.2.0': - resolution: {integrity: sha512-n9a1/f2CwIDmNMNkFs+JI0ZjFnMO0jdOyGNtihgUNFnlmd84yIYY2KMTBmMV58ZlVHjgmY5Y6E1hVTnSRieggA==} + '@biomejs/cli-win32-arm64@2.4.10': + resolution: {integrity: sha512-umwQU6qPzH+ISTf/eHyJ/QoQnJs3V9Vpjz2OjZXe9MVBZ7prgGafMy7yYeRGnlmDAn87AKTF3Q6weLoMGpeqdQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@2.2.0': - resolution: {integrity: sha512-Nawu5nHjP/zPKTIryh2AavzTc/KEg4um/MxWdXW0A6P/RZOyIpa7+QSjeXwAwX/utJGaCoXRPWtF3m5U/bB3Ww==} + '@biomejs/cli-win32-x64@2.4.10': + resolution: {integrity: sha512-aW/JU5GuyH4uxMrNYpoC2kjaHlyJGLgIa3XkhPEZI0uKhZhJZU8BuEyJmvgzSPQNGozBwWjC972RaNdcJ9KyJg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -778,39 +778,39 @@ packages: snapshots: - '@biomejs/biome@2.2.0': + '@biomejs/biome@2.4.10': optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.2.0 - '@biomejs/cli-darwin-x64': 2.2.0 - '@biomejs/cli-linux-arm64': 2.2.0 - '@biomejs/cli-linux-arm64-musl': 2.2.0 - '@biomejs/cli-linux-x64': 2.2.0 - '@biomejs/cli-linux-x64-musl': 2.2.0 - '@biomejs/cli-win32-arm64': 2.2.0 - '@biomejs/cli-win32-x64': 2.2.0 + '@biomejs/cli-darwin-arm64': 2.4.10 + '@biomejs/cli-darwin-x64': 2.4.10 + '@biomejs/cli-linux-arm64': 2.4.10 + '@biomejs/cli-linux-arm64-musl': 2.4.10 + '@biomejs/cli-linux-x64': 2.4.10 + '@biomejs/cli-linux-x64-musl': 2.4.10 + '@biomejs/cli-win32-arm64': 2.4.10 + '@biomejs/cli-win32-x64': 2.4.10 - '@biomejs/cli-darwin-arm64@2.2.0': + '@biomejs/cli-darwin-arm64@2.4.10': optional: true - '@biomejs/cli-darwin-x64@2.2.0': + '@biomejs/cli-darwin-x64@2.4.10': optional: true - '@biomejs/cli-linux-arm64-musl@2.2.0': + '@biomejs/cli-linux-arm64-musl@2.4.10': optional: true - '@biomejs/cli-linux-arm64@2.2.0': + '@biomejs/cli-linux-arm64@2.4.10': optional: true - '@biomejs/cli-linux-x64-musl@2.2.0': + '@biomejs/cli-linux-x64-musl@2.4.10': optional: true - '@biomejs/cli-linux-x64@2.2.0': + '@biomejs/cli-linux-x64@2.4.10': optional: true - '@biomejs/cli-win32-arm64@2.2.0': + '@biomejs/cli-win32-arm64@2.4.10': optional: true - '@biomejs/cli-win32-x64@2.2.0': + '@biomejs/cli-win32-x64@2.4.10': optional: true '@cspotcode/source-map-support@0.8.1': diff --git a/site/e2e/tests/externalAuth.spec.ts b/site/e2e/tests/externalAuth.spec.ts index f5c429dd53..796dd0644e 100644 --- a/site/e2e/tests/externalAuth.spec.ts +++ b/site/e2e/tests/externalAuth.spec.ts @@ -12,162 +12,164 @@ import { } from "../helpers"; import { beforeCoderTest, resetExternalAuthKey } from "../hooks"; -test.describe.skip("externalAuth", () => { - test.beforeAll(async ({ baseURL }) => { - const srv = await createServer(gitAuth.webPort); +test.describe + .skip("externalAuth", () => { + test.beforeAll(async ({ baseURL }) => { + const srv = await createServer(gitAuth.webPort); - // The GitHub validate endpoint returns the currently authenticated user! - srv.use(gitAuth.validatePath, (_req, res) => { - res.write(JSON.stringify(ghUser)); - res.end(); + // The GitHub validate endpoint returns the currently authenticated user! + srv.use(gitAuth.validatePath, (_req, res) => { + res.write(JSON.stringify(ghUser)); + res.end(); + }); + srv.use(gitAuth.tokenPath, (_req, res) => { + const r = (Math.random() + 1).toString(36).substring(7); + res.write(JSON.stringify({ access_token: r })); + res.end(); + }); + srv.use(gitAuth.authPath, (req, res) => { + res.redirect( + `${baseURL}/external-auth/${gitAuth.webProvider}/callback?code=1234&state=${req.query.state}`, + ); + }); }); - srv.use(gitAuth.tokenPath, (_req, res) => { - const r = (Math.random() + 1).toString(36).substring(7); - res.write(JSON.stringify({ access_token: r })); - res.end(); + + test.beforeEach(async ({ context, page }) => { + beforeCoderTest(page); + await login(page); + await resetExternalAuthKey(context); }); - srv.use(gitAuth.authPath, (req, res) => { - res.redirect( - `${baseURL}/external-auth/${gitAuth.webProvider}/callback?code=1234&state=${req.query.state}`, + + // Ensures that a Git auth provider with the device flow functions and completes! + test("external auth device", async ({ page }) => { + const device: ExternalAuthDevice = { + device_code: "1234", + user_code: "1234-5678", + expires_in: 900, + interval: 1, + verification_uri: "", + }; + + // Start a server to mock the GitHub API. + const srv = await createServer(gitAuth.devicePort); + srv.use(gitAuth.validatePath, (_req, res) => { + res.write(JSON.stringify(ghUser)); + res.end(); + }); + srv.use(gitAuth.codePath, (_req, res) => { + res.write(JSON.stringify(device)); + res.end(); + }); + srv.use(gitAuth.installationsPath, (_req, res) => { + res.write(JSON.stringify(ghInstall)); + res.end(); + }); + + const token = { + access_token: "", + error: "authorization_pending", + error_description: "", + }; + // First we send a result from the API that the token hasn't been + // authorized yet to ensure the UI reacts properly. + const sentPending = new Awaiter(); + srv.use(gitAuth.tokenPath, (_req, res) => { + res.write(JSON.stringify(token)); + res.end(); + sentPending.done(); + }); + + await page.goto(`/external-auth/${gitAuth.deviceProvider}`, { + waitUntil: "domcontentloaded", + }); + await page.getByText(device.user_code).isVisible(); + await sentPending.wait(); + // Update the token to be valid and ensure the UI updates! + token.error = ""; + token.access_token = "hello-world"; + await page.waitForSelector("text=1 organization authorized"); + }); + + test("external auth web", async ({ page }) => { + await page.goto(`/external-auth/${gitAuth.webProvider}`, { + waitUntil: "domcontentloaded", + }); + // This endpoint doesn't have the installations URL set intentionally! + await page.waitForSelector("text=You've authenticated with GitHub!"); + }); + + test("successful external auth from workspace", async ({ page }) => { + const templateName = await createTemplate( + page, + echoResponsesWithExternalAuth([ + { id: gitAuth.webProvider, optional: false }, + ]), ); + + await createWorkspace(page, templateName, { useExternalAuth: true }); }); - }); - test.beforeEach(async ({ context, page }) => { - beforeCoderTest(page); - await login(page); - await resetExternalAuthKey(context); - }); - - // Ensures that a Git auth provider with the device flow functions and completes! - test("external auth device", async ({ page }) => { - const device: ExternalAuthDevice = { - device_code: "1234", - user_code: "1234-5678", - expires_in: 900, - interval: 1, - verification_uri: "", + const ghUser: Endpoints["GET /user"]["response"]["data"] = { + login: "kylecarbs", + id: 7122116, + node_id: "MDQ6VXNlcjcxMjIxMTY=", + avatar_url: "https://avatars.githubusercontent.com/u/7122116?v=4", + gravatar_id: "", + url: "https://api.github.com/users/kylecarbs", + html_url: "https://github.com/kylecarbs", + followers_url: "https://api.github.com/users/kylecarbs/followers", + following_url: + "https://api.github.com/users/kylecarbs/following{/other_user}", + gists_url: "https://api.github.com/users/kylecarbs/gists{/gist_id}", + starred_url: + "https://api.github.com/users/kylecarbs/starred{/owner}{/repo}", + subscriptions_url: "https://api.github.com/users/kylecarbs/subscriptions", + organizations_url: "https://api.github.com/users/kylecarbs/orgs", + repos_url: "https://api.github.com/users/kylecarbs/repos", + events_url: "https://api.github.com/users/kylecarbs/events{/privacy}", + received_events_url: + "https://api.github.com/users/kylecarbs/received_events", + type: "User", + site_admin: false, + name: "Kyle Carberry", + company: "@coder", + blog: "https://carberry.com", + location: "Austin, TX", + email: "kyle@carberry.com", + hireable: null, + bio: "hey there", + twitter_username: "kylecarbs", + public_repos: 52, + public_gists: 9, + followers: 208, + following: 31, + created_at: "2014-04-01T02:24:41Z", + updated_at: "2023-06-26T13:03:09Z", }; - // Start a server to mock the GitHub API. - const srv = await createServer(gitAuth.devicePort); - srv.use(gitAuth.validatePath, (_req, res) => { - res.write(JSON.stringify(ghUser)); - res.end(); - }); - srv.use(gitAuth.codePath, (_req, res) => { - res.write(JSON.stringify(device)); - res.end(); - }); - srv.use(gitAuth.installationsPath, (_req, res) => { - res.write(JSON.stringify(ghInstall)); - res.end(); - }); - - const token = { - access_token: "", - error: "authorization_pending", - error_description: "", - }; - // First we send a result from the API that the token hasn't been - // authorized yet to ensure the UI reacts properly. - const sentPending = new Awaiter(); - srv.use(gitAuth.tokenPath, (_req, res) => { - res.write(JSON.stringify(token)); - res.end(); - sentPending.done(); - }); - - await page.goto(`/external-auth/${gitAuth.deviceProvider}`, { - waitUntil: "domcontentloaded", - }); - await page.getByText(device.user_code).isVisible(); - await sentPending.wait(); - // Update the token to be valid and ensure the UI updates! - token.error = ""; - token.access_token = "hello-world"; - await page.waitForSelector("text=1 organization authorized"); - }); - - test("external auth web", async ({ page }) => { - await page.goto(`/external-auth/${gitAuth.webProvider}`, { - waitUntil: "domcontentloaded", - }); - // This endpoint doesn't have the installations URL set intentionally! - await page.waitForSelector("text=You've authenticated with GitHub!"); - }); - - test("successful external auth from workspace", async ({ page }) => { - const templateName = await createTemplate( - page, - echoResponsesWithExternalAuth([ - { id: gitAuth.webProvider, optional: false }, - ]), - ); - - await createWorkspace(page, templateName, { useExternalAuth: true }); - }); - - const ghUser: Endpoints["GET /user"]["response"]["data"] = { - login: "kylecarbs", - id: 7122116, - node_id: "MDQ6VXNlcjcxMjIxMTY=", - avatar_url: "https://avatars.githubusercontent.com/u/7122116?v=4", - gravatar_id: "", - url: "https://api.github.com/users/kylecarbs", - html_url: "https://github.com/kylecarbs", - followers_url: "https://api.github.com/users/kylecarbs/followers", - following_url: - "https://api.github.com/users/kylecarbs/following{/other_user}", - gists_url: "https://api.github.com/users/kylecarbs/gists{/gist_id}", - starred_url: - "https://api.github.com/users/kylecarbs/starred{/owner}{/repo}", - subscriptions_url: "https://api.github.com/users/kylecarbs/subscriptions", - organizations_url: "https://api.github.com/users/kylecarbs/orgs", - repos_url: "https://api.github.com/users/kylecarbs/repos", - events_url: "https://api.github.com/users/kylecarbs/events{/privacy}", - received_events_url: - "https://api.github.com/users/kylecarbs/received_events", - type: "User", - site_admin: false, - name: "Kyle Carberry", - company: "@coder", - blog: "https://carberry.com", - location: "Austin, TX", - email: "kyle@carberry.com", - hireable: null, - bio: "hey there", - twitter_username: "kylecarbs", - public_repos: 52, - public_gists: 9, - followers: 208, - following: 31, - created_at: "2014-04-01T02:24:41Z", - updated_at: "2023-06-26T13:03:09Z", - }; - - const ghInstall: Endpoints["GET /user/installations"]["response"]["data"] = { - installations: [ + const ghInstall: Endpoints["GET /user/installations"]["response"]["data"] = { - id: 1, - access_tokens_url: "", - account: ghUser, - app_id: 1, - app_slug: "coder", - created_at: "2014-04-01T02:24:41Z", - events: [], - html_url: "", - permissions: {}, - repositories_url: "", - repository_selection: "all", - single_file_name: "", - suspended_at: null, - suspended_by: null, - target_id: 1, - target_type: "", - updated_at: "2023-06-26T13:03:09Z", - }, - ], - total_count: 1, - }; -}); + installations: [ + { + id: 1, + access_tokens_url: "", + account: ghUser, + app_id: 1, + app_slug: "coder", + created_at: "2014-04-01T02:24:41Z", + events: [], + html_url: "", + permissions: {}, + repositories_url: "", + repository_selection: "all", + single_file_name: "", + suspended_at: null, + suspended_by: null, + target_id: 1, + target_type: "", + updated_at: "2023-06-26T13:03:09Z", + }, + ], + total_count: 1, + }; + }); diff --git a/site/package.json b/site/package.json index 03246dbfbd..2a93c29633 100644 --- a/site/package.json +++ b/site/package.json @@ -127,7 +127,7 @@ "devDependencies": { "@babel/core": "7.29.0", "@babel/plugin-syntax-typescript": "7.28.6", - "@biomejs/biome": "2.2.4", + "@biomejs/biome": "2.4.10", "@chromatic-com/storybook": "5.0.1", "@octokit/types": "12.6.0", "@playwright/test": "1.50.1", diff --git a/site/pnpm-lock.yaml b/site/pnpm-lock.yaml index 444e9db902..9a7c84a006 100644 --- a/site/pnpm-lock.yaml +++ b/site/pnpm-lock.yaml @@ -276,8 +276,8 @@ importers: specifier: 7.28.6 version: 7.28.6(@babel/core@7.29.0) '@biomejs/biome': - specifier: 2.2.4 - version: 2.2.4 + specifier: 2.4.10 + version: 2.4.10 '@chromatic-com/storybook': specifier: 5.0.1 version: 5.0.1(storybook@10.3.3(@testing-library/dom@10.4.0)(prettier@3.4.1)(react-dom@19.2.2(react@19.2.2))(react@19.2.2)) @@ -469,7 +469,7 @@ importers: version: 8.0.2(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@20.19.25)(esbuild@0.25.12)(jiti@1.21.7)(yaml@2.7.0) vite-plugin-checker: specifier: 0.12.0 - version: 0.12.0(@biomejs/biome@2.2.4)(optionator@0.9.3)(typescript@6.0.2)(vite@8.0.2(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@20.19.25)(esbuild@0.25.12)(jiti@1.21.7)(yaml@2.7.0)) + version: 0.12.0(@biomejs/biome@2.4.10)(optionator@0.9.3)(typescript@6.0.2)(vite@8.0.2(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@20.19.25)(esbuild@0.25.12)(jiti@1.21.7)(yaml@2.7.0)) vitest: specifier: 4.1.1 version: 4.1.1(@types/node@20.19.25)(@vitest/browser-playwright@4.1.1)(jsdom@27.2.0)(msw@2.4.8(typescript@6.0.2))(vite@8.0.2(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@20.19.25)(esbuild@0.25.12)(jiti@1.21.7)(yaml@2.7.0)) @@ -708,55 +708,55 @@ packages: '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==, tarball: https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz} - '@biomejs/biome@2.2.4': - resolution: {integrity: sha512-TBHU5bUy/Ok6m8c0y3pZiuO/BZoY/OcGxoLlrfQof5s8ISVwbVBdFINPQZyFfKwil8XibYWb7JMwnT8wT4WVPg==, tarball: https://registry.npmjs.org/@biomejs/biome/-/biome-2.2.4.tgz} + '@biomejs/biome@2.4.10': + resolution: {integrity: sha512-xxA3AphFQ1geij4JTHXv4EeSTda1IFn22ye9LdyVPoJU19fNVl0uzfEuhsfQ4Yue/0FaLs2/ccVi4UDiE7R30w==, tarball: https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.10.tgz} engines: {node: '>=14.21.3'} hasBin: true - '@biomejs/cli-darwin-arm64@2.2.4': - resolution: {integrity: sha512-RJe2uiyaloN4hne4d2+qVj3d3gFJFbmrr5PYtkkjei1O9c+BjGXgpUPVbi8Pl8syumhzJjFsSIYkcLt2VlVLMA==, tarball: https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.2.4.tgz} + '@biomejs/cli-darwin-arm64@2.4.10': + resolution: {integrity: sha512-vuzzI1cWqDVzOMIkYyHbKqp+AkQq4K7k+UCXWpkYcY/HDn1UxdsbsfgtVpa40shem8Kax4TLDLlx8kMAecgqiw==, tarball: https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.10.tgz} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - '@biomejs/cli-darwin-x64@2.2.4': - resolution: {integrity: sha512-cFsdB4ePanVWfTnPVaUX+yr8qV8ifxjBKMkZwN7gKb20qXPxd/PmwqUH8mY5wnM9+U0QwM76CxFyBRJhC9tQwg==, tarball: https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.2.4.tgz} + '@biomejs/cli-darwin-x64@2.4.10': + resolution: {integrity: sha512-14fzASRo+BPotwp7nWULy2W5xeUyFnTaq1V13Etrrxkrih+ez/2QfgFm5Ehtf5vSjtgx/IJycMMpn5kPd5ZNaA==, tarball: https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.10.tgz} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - '@biomejs/cli-linux-arm64-musl@2.2.4': - resolution: {integrity: sha512-7TNPkMQEWfjvJDaZRSkDCPT/2r5ESFPKx+TEev+I2BXDGIjfCZk2+b88FOhnJNHtksbOZv8ZWnxrA5gyTYhSsQ==, tarball: https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.2.4.tgz} + '@biomejs/cli-linux-arm64-musl@2.4.10': + resolution: {integrity: sha512-WrJY6UuiSD/Dh+nwK2qOTu8kdMDlLV3dLMmychIghHPAysWFq1/DGC1pVZx8POE3ZkzKR3PUUnVrtZfMfaJjyQ==, tarball: https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.10.tgz} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-arm64@2.2.4': - resolution: {integrity: sha512-M/Iz48p4NAzMXOuH+tsn5BvG/Jb07KOMTdSVwJpicmhN309BeEyRyQX+n1XDF0JVSlu28+hiTQ2L4rZPvu7nMw==, tarball: https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.2.4.tgz} + '@biomejs/cli-linux-arm64@2.4.10': + resolution: {integrity: sha512-7MH1CMW5uuxQ/s7FLST63qF8B3Hgu2HRdZ7tA1X1+mk+St4JOuIrqdhIBnnyqeyWJNI+Bww7Es5QZ0wIc1Cmkw==, tarball: https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.10.tgz} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - '@biomejs/cli-linux-x64-musl@2.2.4': - resolution: {integrity: sha512-m41nFDS0ksXK2gwXL6W6yZTYPMH0LughqbsxInSKetoH6morVj43szqKx79Iudkp8WRT5SxSh7qVb8KCUiewGg==, tarball: https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.2.4.tgz} + '@biomejs/cli-linux-x64-musl@2.4.10': + resolution: {integrity: sha512-kDTi3pI6PBN6CiczsWYOyP2zk0IJI08EWEQyDMQWW221rPaaEz6FvjLhnU07KMzLv8q3qSuoB93ua6inSQ55Tw==, tarball: https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.10.tgz} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-linux-x64@2.2.4': - resolution: {integrity: sha512-orr3nnf2Dpb2ssl6aihQtvcKtLySLta4E2UcXdp7+RTa7mfJjBgIsbS0B9GC8gVu0hjOu021aU8b3/I1tn+pVQ==, tarball: https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.2.4.tgz} + '@biomejs/cli-linux-x64@2.4.10': + resolution: {integrity: sha512-tZLvEEi2u9Xu1zAqRjTcpIDGVtldigVvzug2fTuPG0ME/g8/mXpRPcNgLB22bGn6FvLJpHHnqLnwliOu8xjYrg==, tarball: https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.10.tgz} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - '@biomejs/cli-win32-arm64@2.2.4': - resolution: {integrity: sha512-NXnfTeKHDFUWfxAefa57DiGmu9VyKi0cDqFpdI+1hJWQjGJhJutHPX0b5m+eXvTKOaf+brU+P0JrQAZMb5yYaQ==, tarball: https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.2.4.tgz} + '@biomejs/cli-win32-arm64@2.4.10': + resolution: {integrity: sha512-umwQU6qPzH+ISTf/eHyJ/QoQnJs3V9Vpjz2OjZXe9MVBZ7prgGafMy7yYeRGnlmDAn87AKTF3Q6weLoMGpeqdQ==, tarball: https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.10.tgz} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - '@biomejs/cli-win32-x64@2.2.4': - resolution: {integrity: sha512-3Y4V4zVRarVh/B/eSHczR4LYoSVyv3Dfuvm3cWs5w/HScccS0+Wt/lHOcDTRYeHjQmMYVC3rIRWqyN2EI52+zg==, tarball: https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.2.4.tgz} + '@biomejs/cli-win32-x64@2.4.10': + resolution: {integrity: sha512-aW/JU5GuyH4uxMrNYpoC2kjaHlyJGLgIa3XkhPEZI0uKhZhJZU8BuEyJmvgzSPQNGozBwWjC972RaNdcJ9KyJg==, tarball: https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.10.tgz} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] @@ -7697,39 +7697,39 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} - '@biomejs/biome@2.2.4': + '@biomejs/biome@2.4.10': optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.2.4 - '@biomejs/cli-darwin-x64': 2.2.4 - '@biomejs/cli-linux-arm64': 2.2.4 - '@biomejs/cli-linux-arm64-musl': 2.2.4 - '@biomejs/cli-linux-x64': 2.2.4 - '@biomejs/cli-linux-x64-musl': 2.2.4 - '@biomejs/cli-win32-arm64': 2.2.4 - '@biomejs/cli-win32-x64': 2.2.4 + '@biomejs/cli-darwin-arm64': 2.4.10 + '@biomejs/cli-darwin-x64': 2.4.10 + '@biomejs/cli-linux-arm64': 2.4.10 + '@biomejs/cli-linux-arm64-musl': 2.4.10 + '@biomejs/cli-linux-x64': 2.4.10 + '@biomejs/cli-linux-x64-musl': 2.4.10 + '@biomejs/cli-win32-arm64': 2.4.10 + '@biomejs/cli-win32-x64': 2.4.10 - '@biomejs/cli-darwin-arm64@2.2.4': + '@biomejs/cli-darwin-arm64@2.4.10': optional: true - '@biomejs/cli-darwin-x64@2.2.4': + '@biomejs/cli-darwin-x64@2.4.10': optional: true - '@biomejs/cli-linux-arm64-musl@2.2.4': + '@biomejs/cli-linux-arm64-musl@2.4.10': optional: true - '@biomejs/cli-linux-arm64@2.2.4': + '@biomejs/cli-linux-arm64@2.4.10': optional: true - '@biomejs/cli-linux-x64-musl@2.2.4': + '@biomejs/cli-linux-x64-musl@2.4.10': optional: true - '@biomejs/cli-linux-x64@2.2.4': + '@biomejs/cli-linux-x64@2.4.10': optional: true - '@biomejs/cli-win32-arm64@2.2.4': + '@biomejs/cli-win32-arm64@2.4.10': optional: true - '@biomejs/cli-win32-x64@2.2.4': + '@biomejs/cli-win32-x64@2.4.10': optional: true '@blazediff/core@1.9.1': {} @@ -15034,7 +15034,7 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite-plugin-checker@0.12.0(@biomejs/biome@2.2.4)(optionator@0.9.3)(typescript@6.0.2)(vite@8.0.2(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@20.19.25)(esbuild@0.25.12)(jiti@1.21.7)(yaml@2.7.0)): + vite-plugin-checker@0.12.0(@biomejs/biome@2.4.10)(optionator@0.9.3)(typescript@6.0.2)(vite@8.0.2(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@20.19.25)(esbuild@0.25.12)(jiti@1.21.7)(yaml@2.7.0)): dependencies: '@babel/code-frame': 7.29.0 chokidar: 4.0.3 @@ -15046,7 +15046,7 @@ snapshots: vite: 8.0.2(@emnapi/core@1.7.1)(@emnapi/runtime@1.7.1)(@types/node@20.19.25)(esbuild@0.25.12)(jiti@1.21.7)(yaml@2.7.0) vscode-uri: 3.1.0 optionalDependencies: - '@biomejs/biome': 2.2.4 + '@biomejs/biome': 2.4.10 optionator: 0.9.3 typescript: 6.0.2 diff --git a/site/src/api/api.test.ts b/site/src/api/api.test.ts index e38e422c9f..a966f673e4 100644 --- a/site/src/api/api.test.ts +++ b/site/src/api/api.test.ts @@ -147,12 +147,9 @@ describe("api.ts", () => { { q: "owner:me" }, "/api/v2/workspaces?q=owner%3Ame", ], - ])( - "Workspaces - getURLWithSearchParams(%p, %p) returns %p", - (basePath, filter, expected) => { - expect(getURLWithSearchParams(basePath, filter)).toBe(expected); - }, - ); + ])("Workspaces - getURLWithSearchParams(%p, %p) returns %p", (basePath, filter, expected) => { + expect(getURLWithSearchParams(basePath, filter)).toBe(expected); + }); }); describe("getURLWithSearchParams - users", () => { @@ -164,12 +161,9 @@ describe("api.ts", () => { "/api/v2/users?q=status%3Aactive", ], ["/api/v2/users", { q: "" }, "/api/v2/users"], - ])( - "Users - getURLWithSearchParams(%p, %p) returns %p", - (basePath, filter, expected) => { - expect(getURLWithSearchParams(basePath, filter)).toBe(expected); - }, - ); + ])("Users - getURLWithSearchParams(%p, %p) returns %p", (basePath, filter, expected) => { + expect(getURLWithSearchParams(basePath, filter)).toBe(expected); + }); }); describe("update", () => { diff --git a/site/src/components/Collapsible/Collapsible.tsx b/site/src/components/Collapsible/Collapsible.tsx index 2ce8c12f63..40214f1b83 100644 --- a/site/src/components/Collapsible/Collapsible.tsx +++ b/site/src/components/Collapsible/Collapsible.tsx @@ -10,4 +10,4 @@ const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger; const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent; -export { Collapsible, CollapsibleTrigger, CollapsibleContent }; +export { Collapsible, CollapsibleContent, CollapsibleTrigger }; diff --git a/site/src/components/Dialogs/Dialog.tsx b/site/src/components/Dialogs/Dialog.tsx index 40d08f4b3b..f8fd9adce9 100644 --- a/site/src/components/Dialogs/Dialog.tsx +++ b/site/src/components/Dialogs/Dialog.tsx @@ -67,4 +67,4 @@ export const DialogActionButtons: FC = ({ * Re-export of MUI's Dialog component, for convenience. * @link See original documentation here: https://mui.com/material-ui/react-dialog/ */ -export { MuiDialog as Dialog, type DialogProps }; +export { type DialogProps, MuiDialog as Dialog }; diff --git a/site/src/components/Filter/Filter.tsx b/site/src/components/Filter/Filter.tsx index 1f0c1ba22a..f06f02b8f7 100644 --- a/site/src/components/Filter/Filter.tsx +++ b/site/src/components/Filter/Filter.tsx @@ -306,7 +306,7 @@ const PresetMenu: FC = ({ {(learnMoreLink || learnMoreLink2) && } {learnMoreLink && ( - + View advanced filtering @@ -314,7 +314,7 @@ const PresetMenu: FC = ({ )} {learnMoreLink2 && learnMoreLabel2 && ( - + {learnMoreLabel2} diff --git a/site/src/components/Kbd/Kbd.tsx b/site/src/components/Kbd/Kbd.tsx index ead6055542..3e5e0d6f07 100644 --- a/site/src/components/Kbd/Kbd.tsx +++ b/site/src/components/Kbd/Kbd.tsx @@ -24,4 +24,5 @@ function KbdGroup({ className, ...props }: React.ComponentProps<"div">) { /> ); } + export { Kbd, KbdGroup }; diff --git a/site/src/components/Markdown/Markdown.tsx b/site/src/components/Markdown/Markdown.tsx index 8c6637ec0a..1a197d7a0c 100644 --- a/site/src/components/Markdown/Markdown.tsx +++ b/site/src/components/Markdown/Markdown.tsx @@ -58,7 +58,7 @@ export const Markdown: FC = (props) => { }, pre: ({ node, children }) => { - if (!node || !node.children) { + if (!node?.children) { return
{children}
; } const firstChild = node.children[0]; diff --git a/site/src/contexts/ProxyContext.test.tsx b/site/src/contexts/ProxyContext.test.tsx index beb8d27df0..10d1284765 100644 --- a/site/src/contexts/ProxyContext.test.tsx +++ b/site/src/contexts/ProxyContext.test.tsx @@ -108,23 +108,11 @@ describe("ProxyContextGetURLs", () => { MockHealthyWildWorkspaceProxy.path_app_url, MockHealthyWildWorkspaceProxy.wildcard_hostname, ], - ])( - "%p", - ( - _, - regions, - latencies, - selected, - preferredPathAppURL, - preferredWildcardHostname, - ) => { - const preferred = getPreferredProxy(regions, selected, latencies, true); - expect(preferred.preferredPathAppURL).toBe(preferredPathAppURL); - expect(preferred.preferredWildcardHostname).toBe( - preferredWildcardHostname, - ); - }, - ); + ])("%p", (_, regions, latencies, selected, preferredPathAppURL, preferredWildcardHostname) => { + const preferred = getPreferredProxy(regions, selected, latencies, true); + expect(preferred.preferredPathAppURL).toBe(preferredPathAppURL); + expect(preferred.preferredWildcardHostname).toBe(preferredWildcardHostname); + }); }); const TestingComponent = () => { @@ -342,62 +330,56 @@ describe("ProxyContextSelection", () => { }, }, ], - ] as [string, ProxyContextSelectionTest][])( - "%s", - async ( - _, - { - expUserProxyID, - expProxyID: expSelectedProxyID, - regions, - storageProxy, - latencies = {}, - afterLoad, - }, - ) => { - // Mock the latencies - hardCodedLatencies = latencies; + ] as [string, ProxyContextSelectionTest][])("%s", async (_, { + expUserProxyID, + expProxyID: expSelectedProxyID, + regions, + storageProxy, + latencies = {}, + afterLoad, + }) => { + // Mock the latencies + hardCodedLatencies = latencies; - // Initial selection if present - if (storageProxy) { - saveUserSelectedProxy(storageProxy); - } + // Initial selection if present + if (storageProxy) { + saveUserSelectedProxy(storageProxy); + } - // Mock the API response - server.use( - http.get("/api/v2/regions", () => - HttpResponse.json({ - regions, - }), - ), - http.get("/api/v2/workspaceproxies", () => - HttpResponse.json({ regions }), - ), - ); + // Mock the API response + server.use( + http.get("/api/v2/regions", () => + HttpResponse.json({ + regions, + }), + ), + http.get("/api/v2/workspaceproxies", () => + HttpResponse.json({ regions }), + ), + ); - TestingComponent(); - await waitForLoaderToBeRemoved(); + TestingComponent(); + await waitForLoaderToBeRemoved(); - await screen.findByTestId("latenciesLoaded").then((x) => { - expect(x.title).toBe("true"); - }); + await screen.findByTestId("latenciesLoaded").then((x) => { + expect(x.title).toBe("true"); + }); - if (afterLoad) { - await afterLoad(); - } + if (afterLoad) { + await afterLoad(); + } - await screen.findByTestId("isFetched").then((x) => { - expect(x.title).toBe("true"); - }); - await screen.findByTestId("isLoading").then((x) => { - expect(x.title).toBe("false"); - }); - await screen.findByTestId("preferredProxy").then((x) => { - expect(x.title).toBe(expSelectedProxyID); - }); - await screen.findByTestId("userProxy").then((x) => { - expect(x.title).toBe(expUserProxyID || ""); - }); - }, - ); + await screen.findByTestId("isFetched").then((x) => { + expect(x.title).toBe("true"); + }); + await screen.findByTestId("isLoading").then((x) => { + expect(x.title).toBe("false"); + }); + await screen.findByTestId("preferredProxy").then((x) => { + expect(x.title).toBe(expSelectedProxyID); + }); + await screen.findByTestId("userProxy").then((x) => { + expect(x.title).toBe(expUserProxyID || ""); + }); + }); }); diff --git a/site/src/contexts/ProxyContext.tsx b/site/src/contexts/ProxyContext.tsx index a019de6770..bfbdb43c09 100644 --- a/site/src/contexts/ProxyContext.tsx +++ b/site/src/contexts/ProxyContext.tsx @@ -228,7 +228,7 @@ export const getPreferredProxy = ( ); // If no proxy is selected, or the selected proxy is unhealthy default to the primary proxy. - if (!selectedProxy || !selectedProxy.healthy) { + if (!selectedProxy?.healthy) { // Default to the primary proxy selectedProxy = proxies.find((proxy) => proxy.name === "primary"); diff --git a/site/src/hooks/useEmbeddedMetadata.ts b/site/src/hooks/useEmbeddedMetadata.ts index 5679760f5b..c9fa5a7f89 100644 --- a/site/src/hooks/useEmbeddedMetadata.ts +++ b/site/src/hooks/useEmbeddedMetadata.ts @@ -241,7 +241,7 @@ export function makeUseEmbeddedMetadata( metadata, clearMetadataByKey: manager.clearMetadataByKey, }; - }, [manager, metadata]); + }, [metadata]); return stableMetadataResult; }; diff --git a/site/src/modules/resources/AgentRowPreview.test.tsx b/site/src/modules/resources/AgentRowPreview.test.tsx index a49801d416..5b4ed61a39 100644 --- a/site/src/modules/resources/AgentRowPreview.test.tsx +++ b/site/src/modules/resources/AgentRowPreview.test.tsx @@ -87,54 +87,51 @@ describe("AgentRowPreviewApps", () => { workspaceAgent: EmptyAppPreview, testName: "EmptyAppPreview", }, - ])( - " displays appropriately", - ({ workspaceAgent }) => { - renderComponent(); - for (const app of workspaceAgent.apps) { - expect( - screen.getByText(app.display_name as string), - ).toBeInTheDocument(); - } + ])(" displays appropriately", ({ + workspaceAgent, + }) => { + renderComponent(); + for (const app of workspaceAgent.apps) { + expect(screen.getByText(app.display_name as string)).toBeInTheDocument(); + } - for (const app of workspaceAgent.display_apps) { - // These get special treatment - if (app === "vscode" || app === "vscode_insiders") { - continue; - } - expect(screen.getByText(DisplayAppNameMap[app])).toBeInTheDocument(); + for (const app of workspaceAgent.display_apps) { + // These get special treatment + if (app === "vscode" || app === "vscode_insiders") { + continue; } + expect(screen.getByText(DisplayAppNameMap[app])).toBeInTheDocument(); + } - // test VS Code display - if (workspaceAgent.display_apps.includes("vscode")) { - expect(screen.getByText(DisplayAppNameMap.vscode)).toBeInTheDocument(); - } else if (workspaceAgent.display_apps.includes("vscode_insiders")) { - expect( - screen.getByText(DisplayAppNameMap.vscode_insiders), - ).toBeInTheDocument(); - } else { - expect(screen.queryByText("vscode")).not.toBeInTheDocument(); - expect(screen.queryByText("vscode_insiders")).not.toBeInTheDocument(); - } + // test VS Code display + if (workspaceAgent.display_apps.includes("vscode")) { + expect(screen.getByText(DisplayAppNameMap.vscode)).toBeInTheDocument(); + } else if (workspaceAgent.display_apps.includes("vscode_insiders")) { + expect( + screen.getByText(DisplayAppNameMap.vscode_insiders), + ).toBeInTheDocument(); + } else { + expect(screen.queryByText("vscode")).not.toBeInTheDocument(); + expect(screen.queryByText("vscode_insiders")).not.toBeInTheDocument(); + } - // difference between all possible display apps and those displayed - const excludedApps = DisplayApps.filter( - (a) => !workspaceAgent.display_apps.includes(a), - ); + // difference between all possible display apps and those displayed + const excludedApps = DisplayApps.filter( + (a) => !workspaceAgent.display_apps.includes(a), + ); - for (const app of excludedApps) { - expect( - screen.queryByText(DisplayAppNameMap[app]), - ).not.toBeInTheDocument(); - } + for (const app of excludedApps) { + expect( + screen.queryByText(DisplayAppNameMap[app]), + ).not.toBeInTheDocument(); + } - // test empty state - if ( - workspaceAgent.display_apps.length === 0 && - workspaceAgent.apps.length === 0 - ) { - expect(screen.getByText("None")).toBeInTheDocument(); - } - }, - ); + // test empty state + if ( + workspaceAgent.display_apps.length === 0 && + workspaceAgent.apps.length === 0 + ) { + expect(screen.getByText("None")).toBeInTheDocument(); + } + }); }); diff --git a/site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx b/site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx index c31587cf4c..c415c536cc 100644 --- a/site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx +++ b/site/src/modules/workspaces/DynamicParameter/DynamicParameter.tsx @@ -859,7 +859,7 @@ export const useValidationSchemaForDynamicParameters = ( (v) => v.validation_regex !== null && v.validation_regex !== "", ); - if (!regex || !regex.validation_regex) { + if (!regex?.validation_regex) { return true; } diff --git a/site/src/pages/404Page/404Page.stories.tsx b/site/src/pages/404Page/404Page.stories.tsx index 8f1b52ab7b..3253f3c4ac 100644 --- a/site/src/pages/404Page/404Page.stories.tsx +++ b/site/src/pages/404Page/404Page.stories.tsx @@ -10,4 +10,5 @@ export default meta; type Story = StoryObj; const Example: Story = {}; + export { Example as NotFoundPage }; diff --git a/site/src/pages/AIBridgePage/JsonPrettyPrinter.tsx b/site/src/pages/AIBridgePage/JsonPrettyPrinter.tsx index 63a72159cf..99620aa439 100644 --- a/site/src/pages/AIBridgePage/JsonPrettyPrinter.tsx +++ b/site/src/pages/AIBridgePage/JsonPrettyPrinter.tsx @@ -34,7 +34,6 @@ const formatJSONValue = (value: unknown, depth: number): ReactNode => { if (entries.length === 0) return "{}"; return ( <> - {/* biome-ignore lint/style/useConsistentCurlyBraces: \n requires a JS string literal */} {"{\n"} {entries.map(([k, v], i) => ( diff --git a/site/src/pages/AgentsPage/components/ChatConversation/messageParsing.ts b/site/src/pages/AgentsPage/components/ChatConversation/messageParsing.ts index bbe980c49b..afece20da6 100644 --- a/site/src/pages/AgentsPage/components/ChatConversation/messageParsing.ts +++ b/site/src/pages/AgentsPage/components/ChatConversation/messageParsing.ts @@ -298,7 +298,7 @@ export const parseMessagesWithMergedTools = ( if (tool.name !== "process_signal") continue; const args = asRecord(tool.args); const result = asRecord(tool.result); - if (!args || !result || !result.success) continue; + if (!args || !result?.success) continue; const pid = asString(args.process_id); const sig = asString(args.signal); if (pid && (sig === "kill" || sig === "terminate")) diff --git a/site/src/pages/AgentsPage/utils/agentWorkspaceUtils.test.ts b/site/src/pages/AgentsPage/utils/agentWorkspaceUtils.test.ts index 9e13e64c04..e45ac3bb95 100644 --- a/site/src/pages/AgentsPage/utils/agentWorkspaceUtils.test.ts +++ b/site/src/pages/AgentsPage/utils/agentWorkspaceUtils.test.ts @@ -345,16 +345,18 @@ describe("shouldNavigateAfterArchive", () => { activeRootChatId: undefined, expected: false, }, - ])( - "$name → $expected", - ({ activeChatId, archivedChatId, activeRootChatId, expected }) => { - expect( - shouldNavigateAfterArchive( - activeChatId, - archivedChatId, - activeRootChatId, - ), - ).toBe(expected); - }, - ); + ])("$name → $expected", ({ + activeChatId, + archivedChatId, + activeRootChatId, + expected, + }) => { + expect( + shouldNavigateAfterArchive( + activeChatId, + archivedChatId, + activeRootChatId, + ), + ).toBe(expected); + }); }); diff --git a/site/src/pages/CreateTokenPage/utils.test.tsx b/site/src/pages/CreateTokenPage/utils.test.tsx index b09e72a812..c4532eb2fc 100644 --- a/site/src/pages/CreateTokenPage/utils.test.tsx +++ b/site/src/pages/CreateTokenPage/utils.test.tsx @@ -33,12 +33,12 @@ describe("unit/CreateTokenForm", () => { maxTokenLifetime: 100 * 24 * NANO_HOUR, expected: lifetimeDayPresets, }, - ])( - "filterByMaxTokenLifetime($maxTokenLifetime)", - ({ maxTokenLifetime, expected }) => { - expect(filterByMaxTokenLifetime(maxTokenLifetime)).toEqual(expected); - }, - ); + ])("filterByMaxTokenLifetime($maxTokenLifetime)", ({ + maxTokenLifetime, + expected, + }) => { + expect(filterByMaxTokenLifetime(maxTokenLifetime)).toEqual(expected); + }); }); describe("determineDefaultLtValue", () => { it.each<{ @@ -61,11 +61,11 @@ describe("unit/CreateTokenForm", () => { maxTokenLifetime: 2 * 24 * NANO_HOUR, expected: "custom", }, - ])( - "determineDefaultLtValue($maxTokenLifetime)", - ({ maxTokenLifetime, expected }) => { - expect(determineDefaultLtValue(maxTokenLifetime)).toEqual(expected); - }, - ); + ])("determineDefaultLtValue($maxTokenLifetime)", ({ + maxTokenLifetime, + expected, + }) => { + expect(determineDefaultLtValue(maxTokenLifetime)).toEqual(expected); + }); }); }); diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index 3477ca2518..a52d4c53db 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -266,7 +266,7 @@ export const CreateWorkspacePageView: FC = ({ } } - if (!selectedPreset || !selectedPreset.Parameters) { + if (!selectedPreset?.Parameters) { setPresetParameterNames([]); return; } diff --git a/site/src/pages/DeploymentSettingsPage/optionValue.test.ts b/site/src/pages/DeploymentSettingsPage/optionValue.test.ts index 3b52bf1dad..fe34e605e6 100644 --- a/site/src/pages/DeploymentSettingsPage/optionValue.test.ts +++ b/site/src/pages/DeploymentSettingsPage/optionValue.test.ts @@ -166,10 +166,11 @@ describe("optionValue", () => { }, expected: "", }, - ])( - "[$option.name]optionValue($option.value)", - ({ option, expected, additionalValues }) => { - expect(optionValue(option, additionalValues)).toEqual(expected); - }, - ); + ])("[$option.name]optionValue($option.value)", ({ + option, + expected, + additionalValues, + }) => { + expect(optionValue(option, additionalValues)).toEqual(expected); + }); }); diff --git a/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditorPage.test.tsx b/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditorPage.test.tsx index abc5955319..e84b2d15de 100644 --- a/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditorPage.test.tsx +++ b/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditorPage.test.tsx @@ -330,52 +330,49 @@ describe.each([ ], askForVariables: true, }, -])( - "Missing template variables", - ({ - testName, - initialVariables, - loadedVariables, - templateVersion, - askForVariables, - }) => { - it(testName, async () => { - vi.resetAllMocks(); - const queryClient = new QueryClient(); - queryClient.setQueryData( - templateVersionVariablesKey(MockTemplateVersion.id), - initialVariables, - ); +])("Missing template variables", ({ + testName, + initialVariables, + loadedVariables, + templateVersion, + askForVariables, +}) => { + it(testName, async () => { + vi.resetAllMocks(); + const queryClient = new QueryClient(); + queryClient.setQueryData( + templateVersionVariablesKey(MockTemplateVersion.id), + initialVariables, + ); + server.use( + http.get( + "/api/v2/organizations/:org/templates/:template/versions/:version", + () => { + return HttpResponse.json(templateVersion); + }, + ), + ); + + if (loadedVariables) { server.use( - http.get( - "/api/v2/organizations/:org/templates/:template/versions/:version", - () => { - return HttpResponse.json(templateVersion); - }, - ), + http.get("/api/v2/templateversions/:version/variables", () => { + return HttpResponse.json(loadedVariables); + }), ); + } - if (loadedVariables) { - server.use( - http.get("/api/v2/templateversions/:version/variables", () => { - return HttpResponse.json(loadedVariables); - }), - ); - } + renderEditorPage(queryClient); + await waitForLoaderToBeRemoved(); - renderEditorPage(queryClient); - await waitForLoaderToBeRemoved(); - - const dialogSelector = /template variables/i; - if (askForVariables) { - await screen.findByText(dialogSelector); - } else { - expect(screen.queryByText(dialogSelector)).not.toBeInTheDocument(); - } - }); - }, -); + const dialogSelector = /template variables/i; + if (askForVariables) { + await screen.findByText(dialogSelector); + } else { + expect(screen.queryByText(dialogSelector)).not.toBeInTheDocument(); + } + }); +}); test("display pending badge and update it to running when status changes", async () => { const MockPendingTemplateVersion = { diff --git a/site/src/pages/UserSettingsPage/SchedulePage/SchedulePage.test.tsx b/site/src/pages/UserSettingsPage/SchedulePage/SchedulePage.test.tsx index eda3420f22..fd0873bb5d 100644 --- a/site/src/pages/UserSettingsPage/SchedulePage/SchedulePage.test.tsx +++ b/site/src/pages/UserSettingsPage/SchedulePage/SchedulePage.test.tsx @@ -62,38 +62,36 @@ describe("SchedulePage", () => { }); describe("cron tests", () => { - it.each(cronTests)( - "case %# has the correct expected time", - async (test) => { - server.use( - http.put( - `/api/v2/users/${MockUserOwner.id}/quiet-hours`, - async ({ request }) => { - const data = - (await request.json()) as UpdateUserQuietHoursScheduleRequest; - return HttpResponse.json({ - raw_schedule: data.schedule, - user_set: true, - time: `${test.hour.toString().padStart(2, "0")}:${test.minute - .toString() - .padStart(2, "0")}`, - timezone: test.timezone, - next: "", // This value isn't used in the UI, the UI generates it. - }); - }, - ), - ); + it.each( + cronTests, + )("case %# has the correct expected time", async (test) => { + server.use( + http.put( + `/api/v2/users/${MockUserOwner.id}/quiet-hours`, + async ({ request }) => { + const data = + (await request.json()) as UpdateUserQuietHoursScheduleRequest; + return HttpResponse.json({ + raw_schedule: data.schedule, + user_set: true, + time: `${test.hour.toString().padStart(2, "0")}:${test.minute + .toString() + .padStart(2, "0")}`, + timezone: test.timezone, + next: "", // This value isn't used in the UI, the UI generates it. + }); + }, + ), + ); - renderWithAuth(); - await fillForm(test); - await submitForm(); - const successMessage = await screen.findByText( - "Schedule updated successfully.", - ); - expect(successMessage).toBeDefined(); - }, - 15_000, - ); + renderWithAuth(); + await fillForm(test); + await submitForm(); + const successMessage = await screen.findByText( + "Schedule updated successfully.", + ); + expect(successMessage).toBeDefined(); + }, 15_000); }); describe("when it is an unknown error", () => { diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx index 3dbf2ca915..db765b9221 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx @@ -190,7 +190,7 @@ const WorkspaceParametersPageExperimental: FC = () => { const handleSubmit = (values: { rich_parameter_values: WorkspaceBuildParameter[]; }) => { - if (!latestResponse || !latestResponse.parameters) { + if (!latestResponse?.parameters) { return; } diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.test.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.test.tsx index 22b14ebaea..0abfbcc092 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.test.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.test.tsx @@ -135,12 +135,9 @@ describe("WorkspaceSchedulePage", () => { schedule: "20 16 * * 1,3,5", }, ], - ] as const)( - "formValuesToAutostartRequest(%p) return %p", - (values, request) => { - expect(formValuesToAutostartRequest(values)).toEqual(request); - }, - ); + ] as const)("formValuesToAutostartRequest(%p) return %p", (values, request) => { + expect(formValuesToAutostartRequest(values)).toEqual(request); + }); }); describe("formValuesToTTLRequest", () => { diff --git a/site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx b/site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx index 3a4742c9b7..896f09742b 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPage.test.tsx @@ -369,53 +369,50 @@ describe("WorkspaceApps filtering", () => { ["disabled", true], ["unhealthy", false], ["initializing", false], - ])( - "apps with '%s' health status should be shown: %s", - async (health, shouldBeVisible) => { - const app: WorkspaceApp = { - ...MockWorkspaceApp, - id: `${health}-app`, - display_name: `${health} App`, - health, - hidden: false, - }; - const workspace: Workspace = { - ...MockWorkspace, - latest_build: { - ...MockWorkspace.latest_build, - status: "running", - resources: [ - { - ...MockWorkspace.latest_build.resources[0], - agents: [ - { - ...MockWorkspaceAgent, - apps: [app], - }, - ], - }, - ], - }, - }; - vi.spyOn(API, "getWorkspaces").mockResolvedValue({ - workspaces: [workspace], - count: 1, - }); + ])("apps with '%s' health status should be shown: %s", async (health, shouldBeVisible) => { + const app: WorkspaceApp = { + ...MockWorkspaceApp, + id: `${health}-app`, + display_name: `${health} App`, + health, + hidden: false, + }; + const workspace: Workspace = { + ...MockWorkspace, + latest_build: { + ...MockWorkspace.latest_build, + status: "running", + resources: [ + { + ...MockWorkspace.latest_build.resources[0], + agents: [ + { + ...MockWorkspaceAgent, + apps: [app], + }, + ], + }, + ], + }, + }; + vi.spyOn(API, "getWorkspaces").mockResolvedValue({ + workspaces: [workspace], + count: 1, + }); - renderWithAuth(); - await waitForLoaderToBeRemoved(); + renderWithAuth(); + await waitForLoaderToBeRemoved(); - const appLink = screen.queryByRole("link", { - name: (name) => - name.toLowerCase().includes(app.display_name!.toLowerCase()), - }); - if (shouldBeVisible) { - expect(appLink).toBeInTheDocument(); - } else { - expect(appLink).not.toBeInTheDocument(); - } - }, - ); + const appLink = screen.queryByRole("link", { + name: (name) => + name.toLowerCase().includes(app.display_name!.toLowerCase()), + }); + if (shouldBeVisible) { + expect(appLink).toBeInTheDocument(); + } else { + expect(appLink).not.toBeInTheDocument(); + } + }); it("does not show hidden apps regardless of health status", async () => { const hiddenApp: WorkspaceApp = { diff --git a/site/src/utils/dormant.test.ts b/site/src/utils/dormant.test.ts index 2dc3a28196..286ed77c1b 100644 --- a/site/src/utils/dormant.test.ts +++ b/site/src/utils/dormant.test.ts @@ -27,16 +27,13 @@ describe("displayDormantDeletion", () => { ], // today + 1 [new Date().toISOString(), true, true], // today + 0 [new Date().toISOString(), false, false], // Advanced Scheduling off - ])( - "deleting_at=%p, allowAdvancedScheduling=%p, shouldDisplay=%p", - (deleting_at, allowAdvancedScheduling, shouldDisplay) => { - const workspace: TypesGen.Workspace = { - ...Mocks.MockWorkspace, - deleting_at, - }; - expect(displayDormantDeletion(workspace, allowAdvancedScheduling)).toBe( - shouldDisplay, - ); - }, - ); + ])("deleting_at=%p, allowAdvancedScheduling=%p, shouldDisplay=%p", (deleting_at, allowAdvancedScheduling, shouldDisplay) => { + const workspace: TypesGen.Workspace = { + ...Mocks.MockWorkspace, + deleting_at, + }; + expect(displayDormantDeletion(workspace, allowAdvancedScheduling)).toBe( + shouldDisplay, + ); + }); }); diff --git a/site/src/utils/workspace.test.ts b/site/src/utils/workspace.test.ts index ee4c7c2b88..cb7480ed9e 100644 --- a/site/src/utils/workspace.test.ts +++ b/site/src/utils/workspace.test.ts @@ -35,23 +35,20 @@ describe("util > workspace", () => { ["start", "pending", false], ["start", "running", false], ["start", "succeeded", true], - ])( - "transition=%p, status=%p, isWorkspaceOn=%p", - (transition, status, isOn) => { - const workspace: TypesGen.Workspace = { - ...Mocks.MockWorkspace, - latest_build: { - ...Mocks.MockWorkspaceBuild, - job: { - ...Mocks.MockProvisionerJob, - status, - }, - transition, + ])("transition=%p, status=%p, isWorkspaceOn=%p", (transition, status, isOn) => { + const workspace: TypesGen.Workspace = { + ...Mocks.MockWorkspace, + latest_build: { + ...Mocks.MockWorkspaceBuild, + job: { + ...Mocks.MockProvisionerJob, + status, }, - }; - expect(isWorkspaceOn(workspace)).toBe(isOn); - }, - ); + transition, + }, + }; + expect(isWorkspaceOn(workspace)).toBe(isOn); + }); }); describe("defaultWorkspaceExtension", () => { @@ -100,12 +97,9 @@ describe("util > workspace", () => { }, "Coder", ], - ])( - "getDisplayWorkspaceBuildInitiatedBy(%p) returns %p", - (build, initiatedBy) => { - expect(getDisplayWorkspaceBuildInitiatedBy(build)).toEqual(initiatedBy); - }, - ); + ])("getDisplayWorkspaceBuildInitiatedBy(%p) returns %p", (build, initiatedBy) => { + expect(getDisplayWorkspaceBuildInitiatedBy(build)).toEqual(initiatedBy); + }); }); describe("getDisplayVersionStatus", () => { @@ -125,26 +119,16 @@ describe("util > workspace", () => { "v1.2.3", agentVersionStatus.Deprecated, ], - ])( - "getDisplayVersionStatus(theme, %p, %p, %p, %p) returns (%p, %p)", - ( + ])("getDisplayVersionStatus(theme, %p, %p, %p, %p) returns (%p, %p)", (agentVersion, serverVersion, agentAPIVersion, serverAPIVersion, expectedVersion, expectedStatus) => { + const { displayVersion, status } = getDisplayVersionStatus( agentVersion, serverVersion, agentAPIVersion, serverAPIVersion, - expectedVersion, - expectedStatus, - ) => { - const { displayVersion, status } = getDisplayVersionStatus( - agentVersion, - serverVersion, - agentAPIVersion, - serverAPIVersion, - ); - expect(displayVersion).toEqual(expectedVersion); - expect(status).toEqual(expectedStatus); - }, - ); + ); + expect(displayVersion).toEqual(expectedVersion); + expect(status).toEqual(expectedStatus); + }); }); describe("getDisplayWorkspaceTemplateName", () => {