diff --git a/extensions/ql-vscode/package-lock.json b/extensions/ql-vscode/package-lock.json index 4e76616e43b..0ca9ca928cf 100644 --- a/extensions/ql-vscode/package-lock.json +++ b/extensions/ql-vscode/package-lock.json @@ -15,7 +15,7 @@ "@octokit/plugin-retry": "^8.1.0", "@octokit/plugin-throttling": "^9.6.0", "@octokit/rest": "^22.0.1", - "@vscode-elements/react-elements": "^0.9.0", + "@vscode-elements/react-elements": "^2.4.0", "@vscode/codicons": "^0.0.44", "@vscode/debugadapter": "^1.68.0", "@vscode/debugprotocol": "^1.68.0", @@ -5142,11 +5142,20 @@ } }, "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.3.0.tgz", - "integrity": "sha512-nQIWonJ6eFAvUUrSlwyHDm/aE8PBDu5kRpL0vHMg6K8fK3Diq1xdPjTnsJSwxABhaZ+5eBi1btQB5ShUTKo4nQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.6.0.tgz", + "integrity": "sha512-VHb0ALPMTlgKjM6yIxxoQNnpKyUKLD04VzeQdsiXkMqkvYlAHxq9glGLmgbb889/1GsohSOAjvQYoiBppXFqrQ==", "license": "BSD-3-Clause" }, + "node_modules/@lit/context": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@lit/context/-/context-1.1.6.tgz", + "integrity": "sha512-M26qDE6UkQbZA2mQ3RjJ3Gzd8TxP+/0obMgE5HfkfLhEEyYE3Bui4A5XHiGPjy0MUGAyxB3QgVuw2ciS0kHn6A==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit/reactive-element": "^1.6.2 || ^2.1.0" + } + }, "node_modules/@lit/react": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/@lit/react/-/react-1.0.7.tgz", @@ -5157,12 +5166,12 @@ } }, "node_modules/@lit/reactive-element": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz", - "integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.2.tgz", + "integrity": "sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==", "license": "BSD-3-Clause", "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.2.0" + "@lit-labs/ssr-dom-shim": "^1.5.0" } }, "node_modules/@mdx-js/react": { @@ -10222,25 +10231,30 @@ ] }, "node_modules/@vscode-elements/elements": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/@vscode-elements/elements/-/elements-1.14.0.tgz", - "integrity": "sha512-fUOP8O/Pwy8zbD8hGSy1plBg/764hdM9jIMu8uG7GQJOrOB+uQ/ystYxkiUcN6P7OBHvqkBKO1j6vDrkaOJg6Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@vscode-elements/elements/-/elements-2.5.1.tgz", + "integrity": "sha512-HiKgIj9GwlfYkw1LrxG7dM5bMQUr8/GkOqG1HU1+npGHd51nRKCF6ZZ9FtnfoC2wujNN0lc+m0emH/wMpAseYQ==", "license": "MIT", "dependencies": { + "@lit/context": "^1.1.3", "lit": "^3.2.1" + }, + "peerDependencies": { + "@vscode/codicons": ">=0.0.40" } }, "node_modules/@vscode-elements/react-elements": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@vscode-elements/react-elements/-/react-elements-0.9.0.tgz", - "integrity": "sha512-pGWp6OBDAZXJ0tZqN+2SCiKhvhW3/cE4XJyiVHXH4Ft6KteuNVg20oexFv0M66U9iAZElQjPF8M9pBBABLaUZg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@vscode-elements/react-elements/-/react-elements-2.4.0.tgz", + "integrity": "sha512-gDLHE+JE0ViYN+Bzp0obUKBA+guc8Vk0X3n1157z9J+X9GCwHo5ZNziDmiNXyd3QA4IE/kkcg5+3RsemYLlZqg==", "license": "ISC", "dependencies": { - "@lit/react": "^1.0.6", - "@vscode-elements/elements": "^1.13.0" + "@lit/react": "^1.0.7", + "@vscode-elements/elements": "^2.4.0" }, "peerDependencies": { - "react": "^18.0.0" + "react": "17 || 18 || 19", + "react-dom": "17 || 18 || 19" } }, "node_modules/@vscode/codicons": { @@ -21869,31 +21883,31 @@ } }, "node_modules/lit": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/lit/-/lit-3.2.1.tgz", - "integrity": "sha512-1BBa1E/z0O9ye5fZprPtdqnc0BFzxIxTTOO/tQFmyC/hj1O3jL4TfmLBw0WEwjAokdLwpclkvGgDJwTIh0/22w==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.3.tgz", + "integrity": "sha512-fycuvZg/hkpozL00lm1pEJH5nN/lr9ZXd6mJI2HSN4+Bzc+LDNdEApJ6HFbPkdFNHLvOplIIuJvxkS4XUxqirw==", "license": "BSD-3-Clause", "dependencies": { - "@lit/reactive-element": "^2.0.4", - "lit-element": "^4.1.0", - "lit-html": "^3.2.0" + "@lit/reactive-element": "^2.1.0", + "lit-element": "^4.2.0", + "lit-html": "^3.3.0" } }, "node_modules/lit-element": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.1.1.tgz", - "integrity": "sha512-HO9Tkkh34QkTeUmEdNYhMT8hzLid7YlMlATSi1q4q17HE5d9mrrEHJ/o8O2D0cMi182zK1F3v7x0PWFjrhXFew==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.2.tgz", + "integrity": "sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==", "license": "BSD-3-Clause", "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.2.0", - "@lit/reactive-element": "^2.0.4", - "lit-html": "^3.2.0" + "@lit-labs/ssr-dom-shim": "^1.5.0", + "@lit/reactive-element": "^2.1.0", + "lit-html": "^3.3.0" } }, "node_modules/lit-html": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.2.1.tgz", - "integrity": "sha512-qI/3lziaPMSKsrwlxH/xMgikhQ0EGOX2ICU73Bi/YHFvz2j/yMCIrw4+puF2IpQ4+upd3EWbvnHM9+PnJn48YA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.3.tgz", + "integrity": "sha512-el8M6jK2o3RXBnrSHX3ZKrsN8zEV63pSExTO1wYJz7QndGYZ8353e2a5PPX+qHe2aGayfnchQmkAojaWAREOIA==", "license": "BSD-3-Clause", "dependencies": { "@types/trusted-types": "^2.0.2" diff --git a/extensions/ql-vscode/package.json b/extensions/ql-vscode/package.json index ec241601de5..cf4dd3727e7 100644 --- a/extensions/ql-vscode/package.json +++ b/extensions/ql-vscode/package.json @@ -2073,7 +2073,7 @@ "@octokit/plugin-retry": "^8.1.0", "@octokit/plugin-throttling": "^9.6.0", "@octokit/rest": "^22.0.1", - "@vscode-elements/react-elements": "^0.9.0", + "@vscode-elements/react-elements": "^2.4.0", "@vscode/codicons": "^0.0.44", "@vscode/debugadapter": "^1.68.0", "@vscode/debugprotocol": "^1.68.0", diff --git a/extensions/ql-vscode/src/view/jest.setup.ts b/extensions/ql-vscode/src/view/jest.setup.ts index 31dc6657d40..66bafd99fe6 100644 --- a/extensions/ql-vscode/src/view/jest.setup.ts +++ b/extensions/ql-vscode/src/view/jest.setup.ts @@ -18,6 +18,14 @@ Object.defineProperty(window, "matchMedia", { // Used by Primer React window.CSS.supports = jest.fn().mockResolvedValue(false); +// ResizeObserver is not implemented in jsdom but is used by some +// @vscode-elements/elements components (e.g. vscode-table, vscode-form-container). +window.ResizeObserver = class ResizeObserver { + observe = jest.fn(); + unobserve = jest.fn(); + disconnect = jest.fn(); +}; + // Functions that are not implemented in jsdom window.CSSStyleSheet.prototype.replaceSync = jest .fn() diff --git a/extensions/ql-vscode/src/view/variant-analysis/__tests__/RepoRow.spec.tsx b/extensions/ql-vscode/src/view/variant-analysis/__tests__/RepoRow.spec.tsx index 1c89400615d..617d0284f67 100644 --- a/extensions/ql-vscode/src/view/variant-analysis/__tests__/RepoRow.spec.tsx +++ b/extensions/ql-vscode/src/view/variant-analysis/__tests__/RepoRow.spec.tsx @@ -1,4 +1,9 @@ -import { act, render as reactRender, screen } from "@testing-library/react"; +import { + act, + render as reactRender, + screen, + waitFor, +} from "@testing-library/react"; import { VariantAnalysisRepoStatus, VariantAnalysisScannedRepositoryDownloadStatus, @@ -24,6 +29,29 @@ describe(RepoRow.name, () => { ); }; + // The `vscode-checkbox` web component no longer exposes a `checkbox` ARIA role + // on its host element (the role now lives on an inside its shadow DOM, + // which testing-library cannot reach), so find it by tag name instead. The + // `disabled` property is reflected to a `disabled` attribute asynchronously by + // Lit, so wait for the expected state. + const findCheckbox = async ( + container: HTMLElement, + expected: "enabled" | "disabled", + ): Promise => { + return waitFor(() => { + const checkbox = container.querySelector("vscode-checkbox"); + if (!checkbox) { + throw new Error("Unable to find a vscode-checkbox element"); + } + if (expected === "disabled") { + expect(checkbox).toBeDisabled(); + } else { + expect(checkbox).toBeEnabled(); + } + return checkbox as HTMLElement; + }); + }; + it("renders the pending state", () => { render(); @@ -394,25 +422,23 @@ describe(RepoRow.name, () => { }); it("does not allow selecting the item if the item has not succeeded", async () => { - render({ + const { container } = render({ status: VariantAnalysisRepoStatus.InProgress, }); - const checkbox = await screen.findByRole("checkbox"); - expect(checkbox).toBeDisabled(); + await findCheckbox(container, "disabled"); }); it("does not allow selecting the item if the item has not been downloaded", async () => { - render({ + const { container } = render({ status: VariantAnalysisRepoStatus.Succeeded, }); - const checkbox = await screen.findByRole("checkbox"); - expect(checkbox).toBeDisabled(); + await findCheckbox(container, "disabled"); }); it("does not allow selecting the item if the item has not been downloaded successfully", async () => { - render({ + const { container } = render({ status: VariantAnalysisRepoStatus.Succeeded, downloadState: { repositoryId: 1, @@ -420,12 +446,11 @@ describe(RepoRow.name, () => { }, }); - const checkbox = await screen.findByRole("checkbox"); - expect(checkbox).toBeDisabled(); + await findCheckbox(container, "disabled"); }); it("allows selecting the item if the item has been downloaded", async () => { - render({ + const { container } = render({ status: VariantAnalysisRepoStatus.Succeeded, downloadState: { repositoryId: 1, @@ -434,7 +459,6 @@ describe(RepoRow.name, () => { }, }); - const checkbox = await screen.findByRole("checkbox"); - expect(checkbox).toBeEnabled(); + await findCheckbox(container, "enabled"); }); });