From 9a2e8031bcc40808d61a7a147155faf3695116c9 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 1 Aug 2024 11:43:37 +0100 Subject: [PATCH] Fix plugin.spec.ts's reliance on the node-fetch mock. --- .../src/api/controllers/plugin/index.ts | 18 +-- .../src/api/routes/tests/plugin.spec.ts | 116 +++++++++++------- .../integrations/tests/googlesheets.spec.ts | 22 ++++ .../server/src/tests/utilities/api/index.ts | 3 + .../server/src/tests/utilities/api/plugin.ts | 11 ++ packages/types/src/api/web/index.ts | 1 + packages/types/src/api/web/plugins.ts | 12 ++ 7 files changed, 129 insertions(+), 54 deletions(-) create mode 100644 packages/server/src/tests/utilities/api/plugin.ts create mode 100644 packages/types/src/api/web/plugins.ts diff --git a/packages/server/src/api/controllers/plugin/index.ts b/packages/server/src/api/controllers/plugin/index.ts index c7d4912db3..e1c51f0219 100644 --- a/packages/server/src/api/controllers/plugin/index.ts +++ b/packages/server/src/api/controllers/plugin/index.ts @@ -1,6 +1,13 @@ import { npmUpload, urlUpload, githubUpload } from "./uploaders" import { plugins as pluginCore } from "@budibase/backend-core" -import { PluginType, FileType, PluginSource } from "@budibase/types" +import { + PluginType, + FileType, + PluginSource, + Ctx, + CreatePluginRequest, + CreatePluginResponse, +} from "@budibase/types" import env from "../../../environment" import { clientAppSocket } from "../../../websockets" import sdk from "../../../sdk" @@ -29,7 +36,9 @@ export async function upload(ctx: any) { } } -export async function create(ctx: any) { +export async function create( + ctx: Ctx +) { const { source, url, headers, githubToken } = ctx.request.body try { @@ -75,14 +84,9 @@ export async function create(ctx: any) { const doc = await pro.plugins.storePlugin(metadata, directory, source) clientAppSocket?.emit("plugins-update", { name, hash: doc.hash }) - ctx.body = { - message: "Plugin uploaded successfully", - plugins: [doc], - } ctx.body = { plugin: doc } } catch (err: any) { const errMsg = err?.message ? err?.message : err - ctx.throw(400, `Failed to import plugin: ${errMsg}`) } } diff --git a/packages/server/src/api/routes/tests/plugin.spec.ts b/packages/server/src/api/routes/tests/plugin.spec.ts index 788d3cf349..e592772909 100644 --- a/packages/server/src/api/routes/tests/plugin.spec.ts +++ b/packages/server/src/api/routes/tests/plugin.spec.ts @@ -15,6 +15,8 @@ jest.mock("@budibase/backend-core", () => { import { events, objectStore } from "@budibase/backend-core" import * as setup from "./utilities" +import nock from "nock" +import { PluginSource } from "@budibase/types" const mockUploadDirectory = objectStore.uploadDirectory as jest.Mock const mockDeleteFolder = objectStore.deleteFolder as jest.Mock @@ -28,6 +30,7 @@ describe("/plugins", () => { beforeEach(async () => { await config.init() jest.clearAllMocks() + nock.cleanAll() }) const createPlugin = async (status?: number) => { @@ -112,67 +115,86 @@ describe("/plugins", () => { }) describe("github", () => { - const createGithubPlugin = async (status?: number, url?: string) => { - return await request - .post(`/api/plugin`) - .send({ - source: "Github", - url, - githubToken: "token", + beforeEach(async () => { + nock("https://api.github.com") + .get("/repos/my-repo/budibase-comment-box") + .reply(200, { + name: "budibase-comment-box", + releases_url: + "https://api.github.com/repos/my-repo/budibase-comment-box{/id}", }) - .set(config.defaultHeaders()) - .expect("Content-Type", /json/) - .expect(status ? status : 200) - } - it("should be able to create a plugin from github", async () => { - const res = await createGithubPlugin( - 200, - "https://github.com/my-repo/budibase-comment-box.git" - ) - expect(res.body).toBeDefined() - expect(res.body.plugin).toBeDefined() - expect(res.body.plugin._id).toEqual("plg_comment-box") + .get("/repos/my-repo/budibase-comment-box/latest") + .reply(200, { + assets: [ + { + content_type: "application/gzip", + browser_download_url: + "https://github.com/my-repo/budibase-comment-box/releases/download/v1.0.2/comment-box-1.0.2.tar.gz", + }, + ], + }) + + nock("https://github.com") + .get( + "/my-repo/budibase-comment-box/releases/download/v1.0.2/comment-box-1.0.2.tar.gz" + ) + .replyWithFile( + 200, + "src/api/routes/tests/data/comment-box-1.0.2.tar.gz" + ) }) + + it("should be able to create a plugin from github", async () => { + const { plugin } = await config.api.plugin.create({ + source: PluginSource.GITHUB, + url: "https://github.com/my-repo/budibase-comment-box.git", + githubToken: "token", + }) + expect(plugin._id).toEqual("plg_comment-box") + }) + it("should fail if the url is not from github", async () => { - const res = await createGithubPlugin( - 400, - "https://notgithub.com/my-repo/budibase-comment-box" - ) - expect(res.body.message).toEqual( - "Failed to import plugin: The plugin origin must be from Github" + await config.api.plugin.create( + { + source: PluginSource.GITHUB, + url: "https://notgithub.com/my-repo/budibase-comment-box", + githubToken: "token", + }, + { + status: 400, + body: { + message: + "Failed to import plugin: The plugin origin must be from Github", + }, + } ) }) }) describe("npm", () => { it("should be able to create a plugin from npm", async () => { - const res = await request - .post(`/api/plugin`) - .send({ - source: "NPM", - url: "https://www.npmjs.com/package/budibase-component", - }) - .set(config.defaultHeaders()) - .expect("Content-Type", /json/) - .expect(200) - expect(res.body).toBeDefined() - expect(res.body.plugin._id).toEqual("plg_budibase-component") + const { plugin } = await config.api.plugin.create({ + source: PluginSource.NPM, + url: "https://www.npmjs.com/package/budibase-component", + }) + expect(plugin._id).toEqual("plg_budibase-component") expect(events.plugin.imported).toHaveBeenCalled() }) }) describe("url", () => { it("should be able to create a plugin from a URL", async () => { - const res = await request - .post(`/api/plugin`) - .send({ - source: "URL", - url: "https://www.someurl.com/comment-box/comment-box-1.0.2.tar.gz", - }) - .set(config.defaultHeaders()) - .expect("Content-Type", /json/) - .expect(200) - expect(res.body).toBeDefined() - expect(res.body.plugin._id).toEqual("plg_comment-box") + nock("https://www.someurl.com") + .get("/comment-box/comment-box-1.0.2.tar.gz") + .replyWithFile( + 200, + "src/api/routes/tests/data/comment-box-1.0.2.tar.gz" + ) + + const { plugin } = await config.api.plugin.create({ + source: PluginSource.URL, + url: "https://www.someurl.com/comment-box/comment-box-1.0.2.tar.gz", + }) + expect(plugin._id).toEqual("plg_comment-box") expect(events.plugin.imported).toHaveBeenCalledTimes(1) }) }) diff --git a/packages/server/src/integrations/tests/googlesheets.spec.ts b/packages/server/src/integrations/tests/googlesheets.spec.ts index 97ac35787d..2252a8bb9b 100644 --- a/packages/server/src/integrations/tests/googlesheets.spec.ts +++ b/packages/server/src/integrations/tests/googlesheets.spec.ts @@ -64,6 +64,28 @@ describe("Google Sheets Integration", () => { jest.clearAllMocks() }) + // nock("https://www.googleapis.com/").post("/oauth2/v4/token").reply(200, { + // grant_type: "client_credentials", + // client_id: "your-client-id", + // client_secret: "your-client-secret", + // }) + + // nock("https://oauth2.googleapis.com").post("/token").reply(200, { + // access_token: "your-access-token", + // }) + + // nock("https://sheets.googleapis.com") + // .get("/v4/spreadsheets/randomId/") + // .reply(200, { + // sheets: [ + // { + // properties: { + // title: "test", + // }, + // }, + // ], + // }) + function createBasicTable(name: string, columns: string[]): Table { return { type: "table", diff --git a/packages/server/src/tests/utilities/api/index.ts b/packages/server/src/tests/utilities/api/index.ts index 36a6ed0222..79514d4ece 100644 --- a/packages/server/src/tests/utilities/api/index.ts +++ b/packages/server/src/tests/utilities/api/index.ts @@ -15,6 +15,7 @@ import { RoleAPI } from "./role" import { TemplateAPI } from "./template" import { RowActionAPI } from "./rowAction" import { AutomationAPI } from "./automation" +import { PluginAPI } from "./plugin" export default class API { table: TableAPI @@ -33,6 +34,7 @@ export default class API { templates: TemplateAPI rowAction: RowActionAPI automation: AutomationAPI + plugin: PluginAPI constructor(config: TestConfiguration) { this.table = new TableAPI(config) @@ -51,5 +53,6 @@ export default class API { this.templates = new TemplateAPI(config) this.rowAction = new RowActionAPI(config) this.automation = new AutomationAPI(config) + this.plugin = new PluginAPI(config) } } diff --git a/packages/server/src/tests/utilities/api/plugin.ts b/packages/server/src/tests/utilities/api/plugin.ts new file mode 100644 index 0000000000..c2b3a3269d --- /dev/null +++ b/packages/server/src/tests/utilities/api/plugin.ts @@ -0,0 +1,11 @@ +import { Expectations, TestAPI } from "./base" +import { CreatePluginRequest, CreatePluginResponse } from "@budibase/types" + +export class PluginAPI extends TestAPI { + create = async (body: CreatePluginRequest, expectations?: Expectations) => { + return await this._post(`/api/plugin`, { + body, + expectations, + }) + } +} diff --git a/packages/types/src/api/web/index.ts b/packages/types/src/api/web/index.ts index 8a091afdba..27d51ce1b7 100644 --- a/packages/types/src/api/web/index.ts +++ b/packages/types/src/api/web/index.ts @@ -15,3 +15,4 @@ export * from "./automation" export * from "./layout" export * from "./query" export * from "./role" +export * from "./plugins" diff --git a/packages/types/src/api/web/plugins.ts b/packages/types/src/api/web/plugins.ts new file mode 100644 index 0000000000..458ad3f6ce --- /dev/null +++ b/packages/types/src/api/web/plugins.ts @@ -0,0 +1,12 @@ +import { PluginSource } from "../../documents" + +export interface CreatePluginRequest { + source: PluginSource + url: string + githubToken?: string + headers?: { [key: string]: string } +} + +export interface CreatePluginResponse { + plugin: any +}