diff --git a/qa-core/src/internal-api/api/BudibaseInternalAPI.ts b/qa-core/src/internal-api/api/BudibaseInternalAPI.ts index 5bb6b72ef0..4796799396 100644 --- a/qa-core/src/internal-api/api/BudibaseInternalAPI.ts +++ b/qa-core/src/internal-api/api/BudibaseInternalAPI.ts @@ -7,6 +7,7 @@ import ScreenAPI from "./apis/ScreenAPI" import SelfAPI from "./apis/SelfAPI" import TableAPI from "./apis/TableAPI" import UserAPI from "./apis/UserAPI" +import DatasourcesAPI from "./apis/DatasourcesAPI" import BudibaseInternalAPIClient from "./BudibaseInternalAPIClient" import { State } from "../../types" @@ -22,6 +23,7 @@ export default class BudibaseInternalAPI { self: SelfAPI tables: TableAPI users: UserAPI + datasources: DatasourcesAPI constructor(state: State) { this.client = new BudibaseInternalAPIClient(state) @@ -35,5 +37,6 @@ export default class BudibaseInternalAPI { this.self = new SelfAPI(this.client) this.tables = new TableAPI(this.client) this.users = new UserAPI(this.client) + this.datasources = new DatasourcesAPI(this.client) } } diff --git a/qa-core/src/internal-api/api/apis/AppAPI.ts b/qa-core/src/internal-api/api/apis/AppAPI.ts index 992728899e..bdbf5ba85d 100644 --- a/qa-core/src/internal-api/api/apis/AppAPI.ts +++ b/qa-core/src/internal-api/api/apis/AppAPI.ts @@ -60,6 +60,7 @@ export default class AppAPI { const [response, json] = await this.client.post(`/applications`, { body }) expect(response).toHaveStatusCode(200) expect(json._id).toBeDefined() + this.client.state.appId = json._id return json } diff --git a/qa-core/src/internal-api/api/apis/DatasourcesAPI.ts b/qa-core/src/internal-api/api/apis/DatasourcesAPI.ts new file mode 100644 index 0000000000..15215b7ba4 --- /dev/null +++ b/qa-core/src/internal-api/api/apis/DatasourcesAPI.ts @@ -0,0 +1,87 @@ +import { Response } from "node-fetch" +import { Datasource } from "@budibase/types" +import { AddedDatasource } from "../../../types" +import BudibaseInternalAPIClient from "../BudibaseInternalAPIClient" + +export default class DatasourcesAPI { + client: BudibaseInternalAPIClient + + constructor(client: BudibaseInternalAPIClient) { + this.client = client + } + + async getIntegrations(): Promise<[Response, any]> { + const [response, json] = await this.client.get(`/integrations`) + expect(response).toHaveStatusCode(200) + const integrationsCount = Object.keys(json).length + expect(integrationsCount).toBe(16) + return [response, json] + } + + async getAll(): Promise<[Response, Datasource[]]> { + const [response, json] = await this.client.get(`/datasources`) + expect(response).toHaveStatusCode(200) + expect(json.length).toBeGreaterThan(0) + return [response, json] + } + + async getTable(dataSourceId: string): Promise<[Response, Datasource]> { + const [response, json] = await this.client.get( + `/datasources/${dataSourceId}` + ) + expect(response).toHaveStatusCode(200) + expect(json._id).toEqual(dataSourceId) + return [response, json] + } + + async add(body: any): Promise<[Response, AddedDatasource]> { + //temporarily using a hard coded datasource to test 500 error + const [response, json] = await this.client.post(`/datasources`, { body }) + expect(response).toHaveStatusCode(200) + expect(json.datasource._id).toBeDefined() + expect(json.datasource._rev).toBeDefined() + + return [response, json] + } + + async update(body: any): Promise<[Response, AddedDatasource]> { + const [response, json] = await this.client.put(`/datasources/${body._id}`, { + body, + }) + expect(response).toHaveStatusCode(200) + expect(json.datasource._id).toBeDefined() + expect(json.datasource._rev).toBeDefined() + + return [response, json] + } + + async previewQuery(body: any): Promise<[Response, any]> { + const [response, json] = await this.client.post(`/queries/preview`, { + body, + }) + expect(response).toHaveStatusCode(200) + return [response, json] + } + + async saveQuery(body: any): Promise<[Response, any]> { + const [response, json] = await this.client.post(`/queries`, { + body, + }) + expect(response).toHaveStatusCode(200) + return [response, json] + } + + async getQuery(queryId: string): Promise<[Response, any]> { + const [response, json] = await this.client.get(`/queries/${queryId}`) + expect(response).toHaveStatusCode(200) + return [response, json] + } + + async delete(dataSourceId: string, revId: string): Promise { + const [response, json] = await this.client.del( + `/datasources/${dataSourceId}/${revId}` + ) + expect(response).toHaveStatusCode(200) + return response + } +} diff --git a/qa-core/src/internal-api/fixtures/datasources.ts b/qa-core/src/internal-api/fixtures/datasources.ts new file mode 100644 index 0000000000..feb51add32 --- /dev/null +++ b/qa-core/src/internal-api/fixtures/datasources.ts @@ -0,0 +1,37 @@ +// Add information about the data source to the fixtures file from 1password + +export const mongoDB = () => { + return { + datasource: { + name: "MongoDB", + source: "MONGODB", + type: "datasource", + config: { + connectionString: "", + db: "", + }, + }, + + fetchSchema: false, + } +} + +export const postgresSQL = () => { + return { + datasource: { + name: "PostgresSQL", + plus: true, + source: "POSTGRES", + type: "datasource", + config: { + database: "", + host: "", + password: "", + port: 1111, + schema: "public", + user: "", + }, + }, + fetchSchema: true, + } +} diff --git a/qa-core/src/internal-api/fixtures/index.ts b/qa-core/src/internal-api/fixtures/index.ts index d97c5f76b7..880ff8d3d9 100644 --- a/qa-core/src/internal-api/fixtures/index.ts +++ b/qa-core/src/internal-api/fixtures/index.ts @@ -4,3 +4,4 @@ export * as rows from "./rows" export * as screens from "./screens" export * as tables from "./tables" export * as users from "./users" +export * as datasources from "./datasources" diff --git a/qa-core/src/internal-api/tests/dataSources/postgresSQL.spec.ts b/qa-core/src/internal-api/tests/dataSources/postgresSQL.spec.ts new file mode 100644 index 0000000000..b244cbde4b --- /dev/null +++ b/qa-core/src/internal-api/tests/dataSources/postgresSQL.spec.ts @@ -0,0 +1,60 @@ +import TestConfiguration from "../../config/TestConfiguration" +import * as fixtures from "../../fixtures" + +describe("Internal API - Data Sources: PostgresSQL", () => { + const config = new TestConfiguration() + + beforeAll(async () => { + await config.beforeAll() + }) + + afterAll(async () => { + await config.afterAll() + }) + + it("Create an app with a data source - PostgresSQL", async () => { + // Create app + const app = await config.api.apps.create({ + ...fixtures.apps.generateApp(), + useTemplate: "false", + }) + + // Add data source + const [dataSourceResponse, dataSourceJson] = + await config.api.datasources.add(fixtures.datasources.postgresSQL()) + const newDataSourceInfo = { + ...dataSourceJson.datasource, + name: "PostgresSQL2", + } + const [updatedDataSourceResponse, updatedDataSourceJson] = + await config.api.datasources.update(newDataSourceInfo) + + const dataSourceQuery = { + datasourceId: updatedDataSourceJson.datasource._id, + fields: { + sql: "SELECT * FROM categories;", + }, + name: "Query 1", + parameters: {}, + queryVerb: "read", + schema: {}, + transformer: "return data", + } + // Query data source + + const [queryResponse, queryJson] = + await config.api.datasources.previewQuery(dataSourceQuery) + + // Save query + const [saveQueryResponse, saveQueryJson] = + await config.api.datasources.saveQuery(dataSourceQuery) + // Get Query + const [getQueryResponse, getQueryJson] = + await config.api.datasources.getQuery(saveQueryJson._id) + // Delete data source + const deleteResponse = await config.api.datasources.delete( + updatedDataSourceJson.datasource._id, + updatedDataSourceJson.datasource._rev + ) + }) +}) diff --git a/qa-core/src/types/addedDatasource.ts b/qa-core/src/types/addedDatasource.ts new file mode 100644 index 0000000000..65f51fd1bd --- /dev/null +++ b/qa-core/src/types/addedDatasource.ts @@ -0,0 +1,5 @@ +import { Datasource } from "@budibase/types" + +export interface AddedDatasource { + datasource: Datasource +} diff --git a/qa-core/src/types/index.ts b/qa-core/src/types/index.ts index bc75da46f8..6c3740200c 100644 --- a/qa-core/src/types/index.ts +++ b/qa-core/src/types/index.ts @@ -8,6 +8,7 @@ export * from "./responseMessage" export * from "./routing" export * from "./state" export * from "./unpublishAppResponse" +export * from "./addedDatasource" // re-export public api types export * from "@budibase/server/api/controllers/public/mapping/types"