diff --git a/extensions/ql-vscode/package-lock.json b/extensions/ql-vscode/package-lock.json index 02f8c984962..0000501907f 100644 --- a/extensions/ql-vscode/package-lock.json +++ b/extensions/ql-vscode/package-lock.json @@ -4392,9 +4392,9 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==" + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.2.tgz", + "integrity": "sha512-8li32fUDUeml/ACRp/njCWTsk5t17cfTM1jp9n08pBrqs5cDFJubtjsSnuz56r5Tad6jdEPJld7LxNp9dNcyjQ==" }, "node_modules/@octokit/plugin-paginate-rest": { "version": "9.0.0", @@ -35269,9 +35269,9 @@ } }, "@octokit/openapi-types": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", - "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==" + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.2.tgz", + "integrity": "sha512-8li32fUDUeml/ACRp/njCWTsk5t17cfTM1jp9n08pBrqs5cDFJubtjsSnuz56r5Tad6jdEPJld7LxNp9dNcyjQ==" }, "@octokit/plugin-paginate-rest": { "version": "9.0.0", diff --git a/extensions/ql-vscode/src/databases/database-fetcher.ts b/extensions/ql-vscode/src/databases/database-fetcher.ts index c71ebf41579..3a8e2290341 100644 --- a/extensions/ql-vscode/src/databases/database-fetcher.ts +++ b/extensions/ql-vscode/src/databases/database-fetcher.ts @@ -562,10 +562,10 @@ export async function convertGithubNwoToDatabaseUrl( try { const [owner, repo] = nwo.split("/"); - const response = await octokit.request( - "GET /repos/:owner/:repo/code-scanning/codeql/databases", - { owner, repo }, - ); + const response = await octokit.rest.codeScanning.listCodeqlDatabases({ + owner, + repo, + }); const languages = response.data.map((db: any) => db.language); @@ -584,12 +584,12 @@ export async function convertGithubNwoToDatabaseUrl( } return { - databaseUrl: `https://api.github.com/repos/${owner}/${repo}/code-scanning/codeql/databases/${language}`, + databaseUrl: databaseForLanguage.url, owner, name: repo, databaseId: databaseForLanguage.id, databaseCreatedAt: databaseForLanguage.created_at, - commitOid: databaseForLanguage.commit_oid, + commitOid: databaseForLanguage.commit_oid ?? null, }; } catch (e) { void extLogger.log(`Error: ${getErrorMessage(e)}`); diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/databases/database-fetcher.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/databases/database-fetcher.test.ts index f7f8e7b7046..71ac166734d 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/databases/database-fetcher.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/databases/database-fetcher.test.ts @@ -8,7 +8,11 @@ import { findDirWithFile, } from "../../../../src/databases/database-fetcher"; import * as Octokit from "@octokit/rest"; -import { mockedQuickPickItem } from "../../utils/mocking.helpers"; +import { + mockedObject, + mockedOctokitFunction, + mockedQuickPickItem, +} from "../../utils/mocking.helpers"; // These tests make API calls and may need extra time to complete. jest.setTimeout(10000); @@ -18,10 +22,17 @@ describe("database-fetcher", () => { let quickPickSpy: jest.SpiedFunction; const progressSpy = jest.fn(); - const mockRequest = jest.fn(); - const octokit: Octokit.Octokit = { - request: mockRequest, - } as unknown as Octokit.Octokit; + const mockListCodeqlDatabases = mockedOctokitFunction< + "codeScanning", + "listCodeqlDatabases" + >(); + const octokit = mockedObject({ + rest: { + codeScanning: { + listCodeqlDatabases: mockListCodeqlDatabases, + }, + }, + }); // We can't make the real octokit request (since we need credentials), so we mock the response. const successfullMockApiResponse = { @@ -72,7 +83,7 @@ describe("database-fetcher", () => { }); it("should convert a GitHub nwo to a database url", async () => { - mockRequest.mockResolvedValue(successfullMockApiResponse); + mockListCodeqlDatabases.mockResolvedValue(successfullMockApiResponse); quickPickSpy.mockResolvedValue( mockedQuickPickItem({ label: "JavaScript", @@ -93,7 +104,7 @@ describe("database-fetcher", () => { const { databaseUrl, name, owner } = result; expect(databaseUrl).toBe( - "https://api.github.com/repos/github/codeql/code-scanning/codeql/databases/javascript", + "https://api.github.com/repositories/143040428/code-scanning/codeql/databases/javascript", ); expect(name).toBe("codeql"); expect(owner).toBe("github"); @@ -128,7 +139,7 @@ describe("database-fetcher", () => { }, status: 404, }; - mockRequest.mockResolvedValue(mockApiResponse); + mockListCodeqlDatabases.mockResolvedValue(mockApiResponse); const githubRepo = "foo/bar-not-real"; await expect( convertGithubNwoToDatabaseUrl(githubRepo, octokit, progressSpy), @@ -142,7 +153,7 @@ describe("database-fetcher", () => { data: [], }; - mockRequest.mockResolvedValue(mockApiResponse); + mockListCodeqlDatabases.mockResolvedValue(mockApiResponse); const githubRepo = "foo/bar-with-no-dbs"; await expect( convertGithubNwoToDatabaseUrl(githubRepo, octokit, progressSpy), @@ -153,7 +164,7 @@ describe("database-fetcher", () => { describe("when language is already provided", () => { describe("when language is valid", () => { it("should not prompt the user", async () => { - mockRequest.mockResolvedValue(successfullMockApiResponse); + mockListCodeqlDatabases.mockResolvedValue(successfullMockApiResponse); const githubRepo = "github/codeql"; await convertGithubNwoToDatabaseUrl( githubRepo, @@ -167,7 +178,7 @@ describe("database-fetcher", () => { describe("when language is invalid", () => { it("should prompt for language", async () => { - mockRequest.mockResolvedValue(successfullMockApiResponse); + mockListCodeqlDatabases.mockResolvedValue(successfullMockApiResponse); const githubRepo = "github/codeql"; await convertGithubNwoToDatabaseUrl( githubRepo, @@ -182,7 +193,7 @@ describe("database-fetcher", () => { describe("when language is not provided", () => { it("should prompt for language", async () => { - mockRequest.mockResolvedValue(successfullMockApiResponse); + mockListCodeqlDatabases.mockResolvedValue(successfullMockApiResponse); const githubRepo = "github/codeql"; await convertGithubNwoToDatabaseUrl(githubRepo, octokit, progressSpy); expect(quickPickSpy).toHaveBeenCalled(); diff --git a/extensions/ql-vscode/test/vscode-tests/utils/mocking.helpers.ts b/extensions/ql-vscode/test/vscode-tests/utils/mocking.helpers.ts index 388e048b17f..bb826293ded 100644 --- a/extensions/ql-vscode/test/vscode-tests/utils/mocking.helpers.ts +++ b/extensions/ql-vscode/test/vscode-tests/utils/mocking.helpers.ts @@ -1,5 +1,6 @@ import type { QuickPickItem, window, Uri } from "vscode"; import { DatabaseItem } from "../../../src/databases/local-databases"; +import * as Octokit from "@octokit/rest"; export type DeepPartial = T extends object ? { @@ -57,6 +58,14 @@ export function mockedObject( }); } +export function mockedOctokitFunction< + Namespace extends keyof Octokit.Octokit["rest"], + Name extends keyof Octokit.Octokit["rest"][Namespace], +>(): Octokit.Octokit["rest"][Namespace][Name] & jest.Mock { + const fn = jest.fn(); + return fn as unknown as Octokit.Octokit["rest"][Namespace][Name] & jest.Mock; +} + export function mockDatabaseItem( props: DeepPartial = {}, ): DatabaseItem {