Improvements on types, helpers and assertions

This commit is contained in:
Pedro Silva 2023-04-12 18:18:28 +01:00
parent 322f25c7f0
commit a8460169d1
14 changed files with 251 additions and 85 deletions

View File

@ -56,3 +56,11 @@ export interface RestConfig {
} }
] ]
} }
export interface CreateDatasourceResponse {
datasource: Datasource
}
export interface UpdatedDatasourceResponse {
datasource: Datasource
}

View File

@ -42,3 +42,7 @@ export interface PaginationValues {
page: string | number | null page: string | number | null
limit: number | null limit: number | null
} }
export interface PreviewQueryRequest extends Omit<Query, "parameters"> {
parameters: {}
}

View File

@ -13,6 +13,20 @@ const env = {
ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL, ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL,
BB_ADMIN_USER_EMAIL: process.env.BB_ADMIN_USER_EMAIL, BB_ADMIN_USER_EMAIL: process.env.BB_ADMIN_USER_EMAIL,
BB_ADMIN_USER_PASSWORD: process.env.BB_ADMIN_USER_PASSWORD, BB_ADMIN_USER_PASSWORD: process.env.BB_ADMIN_USER_PASSWORD,
POSTGRES_HOST: process.env.POSTGRES_HOST,
POSTGRES_PORT: process.env.POSTGRES_PORT,
POSTGRES_DB: process.env.POSTGRES_DB,
POSTGRES_USER: process.env.POSTGRES_USER,
POSTGRES_PASSWORD: process.env.POSTGRES_PASSWORD,
MONGODB_CONNECTION_STRING: process.env.MONGODB_CONNECTION_STRING,
MONGODB_DB: process.env.MONGODB_DB,
REST_API_BASE_URL: process.env.REST_API_BASE_URL,
REST_API_KEY: process.env.REST_API_KEY,
MARIADB_HOST: process.env.MARIADB_HOST,
MARIADB_PORT: process.env.MARIADB_PORT,
MARIADB_DB: process.env.MARIADB_DB,
MARIADB_USER: process.env.MARIADB_USER,
MARIADB_PASSWORD: process.env.MARIADB_PASSWORD,
} }
export = env export = env

View File

@ -8,6 +8,9 @@ import SelfAPI from "./apis/SelfAPI"
import TableAPI from "./apis/TableAPI" import TableAPI from "./apis/TableAPI"
import UserAPI from "./apis/UserAPI" import UserAPI from "./apis/UserAPI"
import DatasourcesAPI from "./apis/DatasourcesAPI" import DatasourcesAPI from "./apis/DatasourcesAPI"
import IntegrationsAPI from "./apis/IntegrationsAPI"
import QueriesAPI from "./apis/QueriesAPI"
import PermissionsAPI from "./apis/PermissionsAPI"
import BudibaseInternalAPIClient from "./BudibaseInternalAPIClient" import BudibaseInternalAPIClient from "./BudibaseInternalAPIClient"
import { State } from "../../types" import { State } from "../../types"
@ -24,6 +27,9 @@ export default class BudibaseInternalAPI {
tables: TableAPI tables: TableAPI
users: UserAPI users: UserAPI
datasources: DatasourcesAPI datasources: DatasourcesAPI
integrations: IntegrationsAPI
queries: QueriesAPI
permissions: PermissionsAPI
constructor(state: State) { constructor(state: State) {
this.client = new BudibaseInternalAPIClient(state) this.client = new BudibaseInternalAPIClient(state)
@ -38,5 +44,8 @@ export default class BudibaseInternalAPI {
this.tables = new TableAPI(this.client) this.tables = new TableAPI(this.client)
this.users = new UserAPI(this.client) this.users = new UserAPI(this.client)
this.datasources = new DatasourcesAPI(this.client) this.datasources = new DatasourcesAPI(this.client)
this.integrations = new IntegrationsAPI(this.client)
this.queries = new QueriesAPI(this.client)
this.permissions = new PermissionsAPI(this.client)
} }
} }

View File

@ -1,6 +1,9 @@
import { Response } from "node-fetch" import { Response } from "node-fetch"
import { Datasource } from "@budibase/types" import {
import { AddedDatasource } from "../../../types" Datasource,
CreateDatasourceResponse,
UpdatedDatasourceResponse,
} from "@budibase/types"
import BudibaseInternalAPIClient from "../BudibaseInternalAPIClient" import BudibaseInternalAPIClient from "../BudibaseInternalAPIClient"
export default class DatasourcesAPI { export default class DatasourcesAPI {
@ -34,7 +37,7 @@ export default class DatasourcesAPI {
return [response, json] return [response, json]
} }
async add(body: any): Promise<[Response, AddedDatasource]> { async add(body: any): Promise<[Response, CreateDatasourceResponse]> {
const [response, json] = await this.client.post(`/datasources`, { body }) const [response, json] = await this.client.post(`/datasources`, { body })
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(json.datasource._id).toBeDefined() expect(json.datasource._id).toBeDefined()
@ -43,7 +46,7 @@ export default class DatasourcesAPI {
return [response, json] return [response, json]
} }
async update(body: any): Promise<[Response, AddedDatasource]> { async update(body: any): Promise<[Response, UpdatedDatasourceResponse]> {
const [response, json] = await this.client.put(`/datasources/${body._id}`, { const [response, json] = await this.client.put(`/datasources/${body._id}`, {
body, body,
}) })

View File

@ -0,0 +1,18 @@
import { Response } from "node-fetch"
import BudibaseInternalAPIClient from "../BudibaseInternalAPIClient"
export default class IntegrationsAPI {
client: BudibaseInternalAPIClient
constructor(client: BudibaseInternalAPIClient) {
this.client = client
}
async getAll(): 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]
}
}

View File

@ -0,0 +1,16 @@
import { Response } from "node-fetch"
import BudibaseInternalAPIClient from "../BudibaseInternalAPIClient"
export default class PermissionsAPI {
client: BudibaseInternalAPIClient
constructor(client: BudibaseInternalAPIClient) {
this.client = client
}
async getAll(id: string): Promise<[Response, any]> {
const [response, json] = await this.client.get(`/permissions/${id}`)
expect(response).toHaveStatusCode(200)
return [response, json]
}
}

View File

@ -0,0 +1,33 @@
import { Response } from "node-fetch"
import BudibaseInternalAPIClient from "../BudibaseInternalAPIClient"
import { PreviewQueryRequest, Query } from "@budibase/types"
export default class DatasourcesAPI {
client: BudibaseInternalAPIClient
constructor(client: BudibaseInternalAPIClient) {
this.client = client
}
async preview(body: PreviewQueryRequest): Promise<[Response, any]> {
const [response, json] = await this.client.post(`/queries/preview`, {
body,
})
expect(response).toHaveStatusCode(200)
return [response, json]
}
async save(body: Query): Promise<[Response, any]> {
const [response, json] = await this.client.post(`/queries`, {
body,
})
expect(response).toHaveStatusCode(200)
return [response, json]
}
async get(queryId: string): Promise<[Response, any]> {
const [response, json] = await this.client.get(`/queries/${queryId}`)
expect(response).toHaveStatusCode(200)
return [response, json]
}
}

View File

@ -5,3 +5,4 @@ export * as screens from "./screens"
export * as tables from "./tables" export * as tables from "./tables"
export * as users from "./users" export * as users from "./users"
export * as datasources from "./datasources" export * as datasources from "./datasources"
export * as queries from "./queries"

View File

@ -0,0 +1,75 @@
import { PreviewQueryRequest } from "@budibase/types"
const query = (datasourceId: string, fields: any): any => {
return {
datasourceId: datasourceId,
fields: fields,
name: "Query 1",
parameters: {},
queryVerb: "read",
schema: {},
transformer: "return data",
}
}
export const mariaDB = (datasourceId: string): PreviewQueryRequest => {
const fields = {
sql: "SELECT * FROM employees LIMIT 10;",
}
return query(datasourceId, fields)
}
export const mongoDB = (datasourceId: string): PreviewQueryRequest => {
const fields = {
extra: {
collection: "movies",
actionType: "find",
},
json: "",
}
return query(datasourceId, fields)
}
export const postgres = (datasourceId: string): PreviewQueryRequest => {
const fields = {
sql: "SELECT * FROM customers;",
}
return query(datasourceId, fields)
}
export const expectedSchemaFields = {
mariaDB: {
birth_date: "string",
emp_no: "number",
first_name: "string",
gender: "string",
hire_date: "string",
last_name: "string",
},
mongoDB: {
directors: "array",
genres: "array",
image: "string",
plot: "string",
rank: "number",
rating: "number",
release_date: "string",
running_time_secs: "number",
title: "string",
year: "number",
_id: "json",
},
postgres: {
address: "string",
city: "string",
company_name: "string",
contact_name: "string",
contact_title: "string",
country: "string",
customer_id: "string",
fax: "string",
phone: "string",
postal_code: "string",
region: "string",
},
}

View File

@ -1,5 +1,6 @@
import TestConfiguration from "../../config/TestConfiguration" import TestConfiguration from "../../config/TestConfiguration"
import * as fixtures from "../../fixtures" import * as fixtures from "../../fixtures"
import { Query } from "@budibase/types"
describe("Internal API - Data Sources: MariaDB", () => { describe("Internal API - Data Sources: MariaDB", () => {
const config = new TestConfiguration() const config = new TestConfiguration()
@ -16,6 +17,9 @@ describe("Internal API - Data Sources: MariaDB", () => {
// Create app // Create app
await config.createApp() await config.createApp()
// Get all integrations
await config.api.integrations.getAll()
// Add data source // Add data source
const [dataSourceResponse, dataSourceJson] = const [dataSourceResponse, dataSourceJson] =
await config.api.datasources.add(fixtures.datasources.mariaDB()) await config.api.datasources.add(fixtures.datasources.mariaDB())
@ -28,44 +32,38 @@ describe("Internal API - Data Sources: MariaDB", () => {
const [updatedDataSourceResponse, updatedDataSourceJson] = const [updatedDataSourceResponse, updatedDataSourceJson] =
await config.api.datasources.update(newDataSourceInfo) await config.api.datasources.update(newDataSourceInfo)
const dataSourceQuery = {
datasourceId: updatedDataSourceJson.datasource._id,
fields: {
sql: "SELECT * FROM employees;",
},
name: "Query 1",
parameters: {},
queryVerb: "read",
schema: {},
transformer: "return data",
}
// Query data source // Query data source
const [queryResponse, queryJson] = await config.api.queries.preview(
fixtures.queries.mariaDB(updatedDataSourceJson.datasource._id!)
)
const [queryResponse, queryJson] = expect(queryJson.rows.length).toEqual(10)
await config.api.datasources.previewQuery(dataSourceQuery) expect(queryJson.schemaFields).toEqual(
fixtures.queries.expectedSchemaFields.mariaDB
)
// Save query // Save query
const datasourcetoSave = { const datasourcetoSave: Query = {
...dataSourceQuery, ...fixtures.queries.mariaDB(updatedDataSourceJson.datasource._id!),
parameters: [], parameters: [],
} }
const [saveQueryResponse, saveQueryJson] = const [saveQueryResponse, saveQueryJson] = await config.api.queries.save(
await config.api.datasources.saveQuery(datasourcetoSave) datasourcetoSave
)
// Get Query // Get Query
const [getQueryResponse, getQueryJson] = const [getQueryResponse, getQueryJson] = await config.api.queries.get(
await config.api.datasources.getQuery(<string>saveQueryJson._id) <string>saveQueryJson._id
)
// Get Query permissions // Get Query permissions
const [getQueryPermissionsResponse, getQueryPermissionsJson] = const [getQueryPermissionsResponse, getQueryPermissionsJson] =
await config.api.datasources.getQueryPermissions( await config.api.permissions.getAll(saveQueryJson._id!)
<string>saveQueryJson._id
)
// Delete data source // Delete data source
const deleteResponse = await config.api.datasources.delete( const deleteResponse = await config.api.datasources.delete(
<string>updatedDataSourceJson.datasource._id, updatedDataSourceJson.datasource._id!,
<string>updatedDataSourceJson.datasource._rev updatedDataSourceJson.datasource._rev!
) )
}) })
}) })

View File

@ -1,5 +1,6 @@
import TestConfiguration from "../../config/TestConfiguration" import TestConfiguration from "../../config/TestConfiguration"
import * as fixtures from "../../fixtures" import * as fixtures from "../../fixtures"
import { Query } from "@budibase/types"
describe("Internal API - Data Sources: MongoDB", () => { describe("Internal API - Data Sources: MongoDB", () => {
const config = new TestConfiguration() const config = new TestConfiguration()
@ -16,6 +17,9 @@ describe("Internal API - Data Sources: MongoDB", () => {
// Create app // Create app
await config.createApp() await config.createApp()
// Get all integrations
await config.api.integrations.getAll()
// Add data source // Add data source
const [dataSourceResponse, dataSourceJson] = const [dataSourceResponse, dataSourceJson] =
await config.api.datasources.add(fixtures.datasources.mongoDB()) await config.api.datasources.add(fixtures.datasources.mongoDB())
@ -28,48 +32,38 @@ describe("Internal API - Data Sources: MongoDB", () => {
const [updatedDataSourceResponse, updatedDataSourceJson] = const [updatedDataSourceResponse, updatedDataSourceJson] =
await config.api.datasources.update(newDataSourceInfo) await config.api.datasources.update(newDataSourceInfo)
const dataSourceQuery = {
datasourceId: updatedDataSourceJson.datasource._id,
fields: {
extra: {
collection: "movies",
actionType: "find",
},
json: "",
},
name: "Test Query",
parameters: {},
queryVerb: "read",
schema: {},
transformer: "return data",
}
// Query data source // Query data source
const [queryResponse, queryJson] = await config.api.queries.preview(
fixtures.queries.mongoDB(updatedDataSourceJson.datasource._id!)
)
const [queryResponse, queryJson] = expect(queryJson.rows.length).toBeGreaterThan(10)
await config.api.datasources.previewQuery(dataSourceQuery) expect(queryJson.schemaFields).toEqual(
fixtures.queries.expectedSchemaFields.mongoDB
)
// Save query // Save query
const datasourcetoSave = { const datasourcetoSave: Query = {
...dataSourceQuery, ...fixtures.queries.mongoDB(updatedDataSourceJson.datasource._id!),
parameters: [], parameters: [],
} }
const [saveQueryResponse, saveQueryJson] = const [saveQueryResponse, saveQueryJson] = await config.api.queries.save(
await config.api.datasources.saveQuery(datasourcetoSave) datasourcetoSave
)
// Get Query // Get Query
const [getQueryResponse, getQueryJson] = const [getQueryResponse, getQueryJson] = await config.api.queries.get(
await config.api.datasources.getQuery(<string>saveQueryJson._id) <string>saveQueryJson._id
)
// Get Query permissions // Get Query permissions
const [getQueryPermissionsResponse, getQueryPermissionsJson] = const [getQueryPermissionsResponse, getQueryPermissionsJson] =
await config.api.datasources.getQueryPermissions( await config.api.permissions.getAll(saveQueryJson._id!)
<string>saveQueryJson._id
)
// Delete data source // Delete data source
const deleteResponse = await config.api.datasources.delete( const deleteResponse = await config.api.datasources.delete(
<string>updatedDataSourceJson.datasource._id, updatedDataSourceJson.datasource._id!,
<string>updatedDataSourceJson.datasource._rev updatedDataSourceJson.datasource._rev!
) )
}) })
}) })

View File

@ -1,5 +1,6 @@
import TestConfiguration from "../../config/TestConfiguration" import TestConfiguration from "../../config/TestConfiguration"
import * as fixtures from "../../fixtures" import * as fixtures from "../../fixtures"
import { Query } from "@budibase/types"
describe("Internal API - Data Sources: PostgresSQL", () => { describe("Internal API - Data Sources: PostgresSQL", () => {
const config = new TestConfiguration() const config = new TestConfiguration()
@ -16,6 +17,9 @@ describe("Internal API - Data Sources: PostgresSQL", () => {
// Create app // Create app
await config.createApp() await config.createApp()
// Get all integrations
await config.api.integrations.getAll()
// Add data source // Add data source
const [dataSourceResponse, dataSourceJson] = const [dataSourceResponse, dataSourceJson] =
await config.api.datasources.add(fixtures.datasources.postgresSQL()) await config.api.datasources.add(fixtures.datasources.postgresSQL())
@ -28,44 +32,38 @@ describe("Internal API - Data Sources: PostgresSQL", () => {
const [updatedDataSourceResponse, updatedDataSourceJson] = const [updatedDataSourceResponse, updatedDataSourceJson] =
await config.api.datasources.update(newDataSourceInfo) 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 // Query data source
const [queryResponse, queryJson] = await config.api.queries.preview(
fixtures.queries.postgres(updatedDataSourceJson.datasource._id!)
)
const [queryResponse, queryJson] = expect(queryJson.rows.length).toEqual(91)
await config.api.datasources.previewQuery(dataSourceQuery) expect(queryJson.schemaFields).toEqual(
fixtures.queries.expectedSchemaFields.postgres
)
// Save query // Save query
const datasourcetoSave = { const datasourcetoSave: Query = {
...dataSourceQuery, ...fixtures.queries.postgres(updatedDataSourceJson.datasource._id!),
parameters: [], parameters: [],
} }
const [saveQueryResponse, saveQueryJson] = const [saveQueryResponse, saveQueryJson] = await config.api.queries.save(
await config.api.datasources.saveQuery(datasourcetoSave) datasourcetoSave
)
// Get Query // Get Query
const [getQueryResponse, getQueryJson] = const [getQueryResponse, getQueryJson] = await config.api.queries.get(
await config.api.datasources.getQuery(<string>saveQueryJson._id) saveQueryJson._id!
)
// Get Query permissions // Get Query permissions
const [getQueryPermissionsResponse, getQueryPermissionsJson] = const [getQueryPermissionsResponse, getQueryPermissionsJson] =
await config.api.datasources.getQueryPermissions( await config.api.permissions.getAll(saveQueryJson._id!)
<string>saveQueryJson._id
)
// Delete data source // Delete data source
const deleteResponse = await config.api.datasources.delete( const deleteResponse = await config.api.datasources.delete(
<string>updatedDataSourceJson.datasource._id, updatedDataSourceJson.datasource._id!,
<string>updatedDataSourceJson.datasource._rev updatedDataSourceJson.datasource._rev!
) )
}) })
}) })

View File

@ -1,5 +0,0 @@
import { Datasource } from "@budibase/types"
export interface AddedDatasource {
datasource: Datasource
}