Got container reuse strategy in place, need to convert tests now.
This commit is contained in:
parent
df52b6937a
commit
158964c4d2
|
@ -16,7 +16,7 @@ import {
|
||||||
import _ from "lodash"
|
import _ from "lodash"
|
||||||
import { generator } from "@budibase/backend-core/tests"
|
import { generator } from "@budibase/backend-core/tests"
|
||||||
import { utils } from "@budibase/backend-core"
|
import { utils } from "@budibase/backend-core"
|
||||||
import { databaseTestProviders } from "../integrations/tests/utils"
|
import { DatabaseName, getDatasource } from "../integrations/tests/utils"
|
||||||
import { Client } from "pg"
|
import { Client } from "pg"
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
fetch.mockSearch()
|
fetch.mockSearch()
|
||||||
|
@ -41,18 +41,17 @@ describe("postgres integrations", () => {
|
||||||
makeRequest = generateMakeRequest(apiKey, true)
|
makeRequest = generateMakeRequest(apiKey, true)
|
||||||
|
|
||||||
postgresDatasource = await config.api.datasource.create(
|
postgresDatasource = await config.api.datasource.create(
|
||||||
await databaseTestProviders.postgres.datasource()
|
await getDatasource(DatabaseName.POSTGRES)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await databaseTestProviders.postgres.stop()
|
|
||||||
})
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
async function createAuxTable(prefix: string) {
|
async function createAuxTable(prefix: string) {
|
||||||
return await config.createTable({
|
return await config.createTable({
|
||||||
name: `${prefix}_${generator.word({ length: 6 })}`,
|
name: `${prefix}_${generator
|
||||||
|
.guid()
|
||||||
|
.replaceAll("-", "")
|
||||||
|
.substring(0, 6)}`,
|
||||||
type: "table",
|
type: "table",
|
||||||
primary: ["id"],
|
primary: ["id"],
|
||||||
primaryDisplay: "title",
|
primaryDisplay: "title",
|
||||||
|
@ -89,7 +88,7 @@ describe("postgres integrations", () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
primaryPostgresTable = await config.createTable({
|
primaryPostgresTable = await config.createTable({
|
||||||
name: `p_${generator.word({ length: 6 })}`,
|
name: `p_${generator.guid().replaceAll("-", "").substring(0, 6)}`,
|
||||||
type: "table",
|
type: "table",
|
||||||
primary: ["id"],
|
primary: ["id"],
|
||||||
schema: {
|
schema: {
|
||||||
|
@ -251,7 +250,7 @@ describe("postgres integrations", () => {
|
||||||
|
|
||||||
async function createDefaultPgTable() {
|
async function createDefaultPgTable() {
|
||||||
return await config.createTable({
|
return await config.createTable({
|
||||||
name: generator.word({ length: 10 }),
|
name: generator.guid().replaceAll("-", "").substring(0, 10),
|
||||||
type: "table",
|
type: "table",
|
||||||
primary: ["id"],
|
primary: ["id"],
|
||||||
schema: {
|
schema: {
|
||||||
|
@ -1043,7 +1042,7 @@ describe("postgres integrations", () => {
|
||||||
it("should be able to verify the connection", async () => {
|
it("should be able to verify the connection", async () => {
|
||||||
await config.api.datasource.verify(
|
await config.api.datasource.verify(
|
||||||
{
|
{
|
||||||
datasource: await databaseTestProviders.postgres.datasource(),
|
datasource: await getDatasource(DatabaseName.POSTGRES),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
body: {
|
body: {
|
||||||
|
@ -1054,7 +1053,7 @@ describe("postgres integrations", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should state an invalid datasource cannot connect", async () => {
|
it("should state an invalid datasource cannot connect", async () => {
|
||||||
const dbConfig = await databaseTestProviders.postgres.datasource()
|
const dbConfig = await getDatasource(DatabaseName.POSTGRES)
|
||||||
await config.api.datasource.verify(
|
await config.api.datasource.verify(
|
||||||
{
|
{
|
||||||
datasource: {
|
datasource: {
|
||||||
|
@ -1089,21 +1088,21 @@ describe("postgres integrations", () => {
|
||||||
|
|
||||||
describe("POST /api/datasources/:datasourceId/schema", () => {
|
describe("POST /api/datasources/:datasourceId/schema", () => {
|
||||||
let client: Client
|
let client: Client
|
||||||
|
let tableName: string
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
client = new Client(
|
tableName = generator.guid().replaceAll("-", "").substring(0, 10)
|
||||||
(await databaseTestProviders.postgres.datasource()).config!
|
client = new Client((await getDatasource(DatabaseName.POSTGRES)).config!)
|
||||||
)
|
|
||||||
await client.connect()
|
await client.connect()
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await client.query(`DROP TABLE IF EXISTS "table"`)
|
await client.query(`DROP TABLE IF EXISTS "${tableName}"`)
|
||||||
await client.end()
|
await client.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("recognises when a table has no primary key", async () => {
|
it("recognises when a table has no primary key", async () => {
|
||||||
await client.query(`CREATE TABLE "table" (id SERIAL)`)
|
await client.query(`CREATE TABLE "${tableName}" (id SERIAL)`)
|
||||||
|
|
||||||
const response = await makeRequest(
|
const response = await makeRequest(
|
||||||
"post",
|
"post",
|
||||||
|
@ -1111,12 +1110,14 @@ describe("postgres integrations", () => {
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(response.body.errors).toEqual({
|
expect(response.body.errors).toEqual({
|
||||||
table: "Table must have a primary key.",
|
[tableName]: "Table must have a primary key.",
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it("recognises when a table is using a reserved column name", async () => {
|
it("recognises when a table is using a reserved column name", async () => {
|
||||||
await client.query(`CREATE TABLE "table" (_id SERIAL PRIMARY KEY) `)
|
await client.query(
|
||||||
|
`CREATE TABLE "${tableName}" (_id SERIAL PRIMARY KEY) `
|
||||||
|
)
|
||||||
|
|
||||||
const response = await makeRequest(
|
const response = await makeRequest(
|
||||||
"post",
|
"post",
|
||||||
|
@ -1124,18 +1125,22 @@ describe("postgres integrations", () => {
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(response.body.errors).toEqual({
|
expect(response.body.errors).toEqual({
|
||||||
table: "Table contains invalid columns.",
|
[tableName]: "Table contains invalid columns.",
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("Integration compatibility with postgres search_path", () => {
|
describe("Integration compatibility with postgres search_path", () => {
|
||||||
let client: Client, pathDatasource: Datasource
|
let client: Client,
|
||||||
const schema1 = "test1",
|
pathDatasource: Datasource,
|
||||||
schema2 = "test-2"
|
schema1: string,
|
||||||
|
schema2: string
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeEach(async () => {
|
||||||
const dsConfig = await databaseTestProviders.postgres.datasource()
|
schema1 = generator.guid().replaceAll("-", "")
|
||||||
|
schema2 = generator.guid().replaceAll("-", "")
|
||||||
|
|
||||||
|
const dsConfig = await getDatasource(DatabaseName.POSTGRES)
|
||||||
const dbConfig = dsConfig.config!
|
const dbConfig = dsConfig.config!
|
||||||
|
|
||||||
client = new Client(dbConfig)
|
client = new Client(dbConfig)
|
||||||
|
@ -1153,7 +1158,7 @@ describe("postgres integrations", () => {
|
||||||
pathDatasource = await config.api.datasource.create(pathConfig)
|
pathDatasource = await config.api.datasource.create(pathConfig)
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterEach(async () => {
|
||||||
await client.query(`DROP SCHEMA "${schema1}" CASCADE;`)
|
await client.query(`DROP SCHEMA "${schema1}" CASCADE;`)
|
||||||
await client.query(`DROP SCHEMA "${schema2}" CASCADE;`)
|
await client.query(`DROP SCHEMA "${schema2}" CASCADE;`)
|
||||||
await client.end()
|
await client.end()
|
||||||
|
|
|
@ -1,19 +1,50 @@
|
||||||
jest.unmock("pg")
|
jest.unmock("pg")
|
||||||
|
|
||||||
import { Datasource } from "@budibase/types"
|
import { Datasource } from "@budibase/types"
|
||||||
import * as postgres from "./postgres"
|
import { postgres } from "./postgres"
|
||||||
import * as mongodb from "./mongodb"
|
import { mongodb } from "./mongodb"
|
||||||
import * as mysql from "./mysql"
|
import { mysql } from "./mysql"
|
||||||
import * as mssql from "./mssql"
|
import { mssql } from "./mssql"
|
||||||
import * as mariadb from "./mariadb"
|
import { mariadb } from "./mariadb"
|
||||||
import { StartedTestContainer } from "testcontainers"
|
|
||||||
|
|
||||||
jest.setTimeout(30000)
|
export type DatasourceProvider = () => Promise<Datasource>
|
||||||
|
|
||||||
export interface DatabaseProvider {
|
export enum DatabaseName {
|
||||||
start(): Promise<StartedTestContainer>
|
POSTGRES = "postgres",
|
||||||
stop(): Promise<void>
|
MONGODB = "mongodb",
|
||||||
datasource(): Promise<Datasource>
|
MYSQL = "mysql",
|
||||||
|
SQL_SERVER = "mssql",
|
||||||
|
MARIADB = "mariadb",
|
||||||
|
}
|
||||||
|
|
||||||
|
const providers: Record<DatabaseName, DatasourceProvider> = {
|
||||||
|
[DatabaseName.POSTGRES]: postgres,
|
||||||
|
[DatabaseName.MONGODB]: mongodb,
|
||||||
|
[DatabaseName.MYSQL]: mysql,
|
||||||
|
[DatabaseName.SQL_SERVER]: mssql,
|
||||||
|
[DatabaseName.MARIADB]: mariadb,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDatasourceProviders(
|
||||||
|
...sourceNames: DatabaseName[]
|
||||||
|
): Promise<Datasource>[] {
|
||||||
|
return sourceNames.map(sourceName => providers[sourceName]())
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDatasourceProvider(
|
||||||
|
sourceName: DatabaseName
|
||||||
|
): DatasourceProvider {
|
||||||
|
return providers[sourceName]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDatasource(sourceName: DatabaseName): Promise<Datasource> {
|
||||||
|
return providers[sourceName]()
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getDatasources(
|
||||||
|
...sourceNames: DatabaseName[]
|
||||||
|
): Promise<Datasource[]> {
|
||||||
|
return Promise.all(sourceNames.map(sourceName => providers[sourceName]()))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const databaseTestProviders = {
|
export const databaseTestProviders = {
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import { Datasource, SourceName } from "@budibase/types"
|
import { Datasource, SourceName } from "@budibase/types"
|
||||||
import { GenericContainer, Wait, StartedTestContainer } from "testcontainers"
|
import { GenericContainer, Wait } from "testcontainers"
|
||||||
import { AbstractWaitStrategy } from "testcontainers/build/wait-strategies/wait-strategy"
|
import { AbstractWaitStrategy } from "testcontainers/build/wait-strategies/wait-strategy"
|
||||||
|
|
||||||
let container: StartedTestContainer | undefined
|
|
||||||
|
|
||||||
class MariaDBWaitStrategy extends AbstractWaitStrategy {
|
class MariaDBWaitStrategy extends AbstractWaitStrategy {
|
||||||
async waitUntilReady(container: any, boundPorts: any, startTime?: Date) {
|
async waitUntilReady(container: any, boundPorts: any, startTime?: Date) {
|
||||||
// Because MariaDB first starts itself up, runs an init script, then restarts,
|
// Because MariaDB first starts itself up, runs an init script, then restarts,
|
||||||
|
@ -21,18 +19,15 @@ class MariaDBWaitStrategy extends AbstractWaitStrategy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function start(): Promise<StartedTestContainer> {
|
export async function mariadb(): Promise<Datasource> {
|
||||||
return await new GenericContainer("mariadb:lts")
|
const container = await new GenericContainer("mariadb:lts")
|
||||||
|
.withName("budibase-test-mariadb")
|
||||||
|
.withReuse()
|
||||||
.withExposedPorts(3306)
|
.withExposedPorts(3306)
|
||||||
.withEnvironment({ MARIADB_ROOT_PASSWORD: "password" })
|
.withEnvironment({ MARIADB_ROOT_PASSWORD: "password" })
|
||||||
.withWaitStrategy(new MariaDBWaitStrategy())
|
.withWaitStrategy(new MariaDBWaitStrategy())
|
||||||
.start()
|
.start()
|
||||||
}
|
|
||||||
|
|
||||||
export async function datasource(): Promise<Datasource> {
|
|
||||||
if (!container) {
|
|
||||||
container = await start()
|
|
||||||
}
|
|
||||||
const host = container.getHost()
|
const host = container.getHost()
|
||||||
const port = container.getMappedPort(3306)
|
const port = container.getMappedPort(3306)
|
||||||
|
|
||||||
|
@ -49,10 +44,3 @@ export async function datasource(): Promise<Datasource> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function stop() {
|
|
||||||
if (container) {
|
|
||||||
await container.stop()
|
|
||||||
container = undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Datasource, SourceName } from "@budibase/types"
|
import { Datasource, SourceName } from "@budibase/types"
|
||||||
import { GenericContainer, Wait, StartedTestContainer } from "testcontainers"
|
import { GenericContainer, Wait } from "testcontainers"
|
||||||
|
|
||||||
let container: StartedTestContainer | undefined
|
export async function mongodb(): Promise<Datasource> {
|
||||||
|
const container = await new GenericContainer("mongo:7.0-jammy")
|
||||||
export async function start(): Promise<StartedTestContainer> {
|
.withName("budibase-test-mongodb")
|
||||||
return await new GenericContainer("mongo:7.0-jammy")
|
.withReuse()
|
||||||
.withExposedPorts(27017)
|
.withExposedPorts(27017)
|
||||||
.withEnvironment({
|
.withEnvironment({
|
||||||
MONGO_INITDB_ROOT_USERNAME: "mongo",
|
MONGO_INITDB_ROOT_USERNAME: "mongo",
|
||||||
|
@ -16,14 +16,10 @@ export async function start(): Promise<StartedTestContainer> {
|
||||||
).withStartupTimeout(10000)
|
).withStartupTimeout(10000)
|
||||||
)
|
)
|
||||||
.start()
|
.start()
|
||||||
}
|
|
||||||
|
|
||||||
export async function datasource(): Promise<Datasource> {
|
|
||||||
if (!container) {
|
|
||||||
container = await start()
|
|
||||||
}
|
|
||||||
const host = container.getHost()
|
const host = container.getHost()
|
||||||
const port = container.getMappedPort(27017)
|
const port = container.getMappedPort(27017)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "datasource",
|
type: "datasource",
|
||||||
source: SourceName.MONGODB,
|
source: SourceName.MONGODB,
|
||||||
|
@ -34,10 +30,3 @@ export async function datasource(): Promise<Datasource> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function stop() {
|
|
||||||
if (container) {
|
|
||||||
await container.stop()
|
|
||||||
container = undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { Datasource, SourceName } from "@budibase/types"
|
import { Datasource, SourceName } from "@budibase/types"
|
||||||
import { GenericContainer, Wait, StartedTestContainer } from "testcontainers"
|
import { GenericContainer, Wait } from "testcontainers"
|
||||||
|
|
||||||
let container: StartedTestContainer | undefined
|
export async function mssql(): Promise<Datasource> {
|
||||||
|
const container = await new GenericContainer(
|
||||||
export async function start(): Promise<StartedTestContainer> {
|
|
||||||
return await new GenericContainer(
|
|
||||||
"mcr.microsoft.com/mssql/server:2022-latest"
|
"mcr.microsoft.com/mssql/server:2022-latest"
|
||||||
)
|
)
|
||||||
|
.withName("budibase-test-mssql")
|
||||||
|
.withReuse()
|
||||||
.withExposedPorts(1433)
|
.withExposedPorts(1433)
|
||||||
.withEnvironment({
|
.withEnvironment({
|
||||||
ACCEPT_EULA: "Y",
|
ACCEPT_EULA: "Y",
|
||||||
|
@ -23,12 +23,7 @@ export async function start(): Promise<StartedTestContainer> {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.start()
|
.start()
|
||||||
}
|
|
||||||
|
|
||||||
export async function datasource(): Promise<Datasource> {
|
|
||||||
if (!container) {
|
|
||||||
container = await start()
|
|
||||||
}
|
|
||||||
const host = container.getHost()
|
const host = container.getHost()
|
||||||
const port = container.getMappedPort(1433)
|
const port = container.getMappedPort(1433)
|
||||||
|
|
||||||
|
@ -47,10 +42,3 @@ export async function datasource(): Promise<Datasource> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function stop() {
|
|
||||||
if (container) {
|
|
||||||
await container.stop()
|
|
||||||
container = undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import { Datasource, SourceName } from "@budibase/types"
|
import { Datasource, SourceName } from "@budibase/types"
|
||||||
import { GenericContainer, Wait, StartedTestContainer } from "testcontainers"
|
import { GenericContainer, Wait } from "testcontainers"
|
||||||
import { AbstractWaitStrategy } from "testcontainers/build/wait-strategies/wait-strategy"
|
import { AbstractWaitStrategy } from "testcontainers/build/wait-strategies/wait-strategy"
|
||||||
|
|
||||||
let container: StartedTestContainer | undefined
|
|
||||||
|
|
||||||
class MySQLWaitStrategy extends AbstractWaitStrategy {
|
class MySQLWaitStrategy extends AbstractWaitStrategy {
|
||||||
async waitUntilReady(container: any, boundPorts: any, startTime?: Date) {
|
async waitUntilReady(container: any, boundPorts: any, startTime?: Date) {
|
||||||
// Because MySQL first starts itself up, runs an init script, then restarts,
|
// Because MySQL first starts itself up, runs an init script, then restarts,
|
||||||
|
@ -24,18 +22,14 @@ class MySQLWaitStrategy extends AbstractWaitStrategy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function start(): Promise<StartedTestContainer> {
|
export async function mysql(): Promise<Datasource> {
|
||||||
return await new GenericContainer("mysql:8.3")
|
const container = await new GenericContainer("mysql:8.3")
|
||||||
|
.withName("budibase-test-mysql")
|
||||||
|
.withReuse()
|
||||||
.withExposedPorts(3306)
|
.withExposedPorts(3306)
|
||||||
.withEnvironment({ MYSQL_ROOT_PASSWORD: "password" })
|
.withEnvironment({ MYSQL_ROOT_PASSWORD: "password" })
|
||||||
.withWaitStrategy(new MySQLWaitStrategy().withStartupTimeout(10000))
|
.withWaitStrategy(new MySQLWaitStrategy().withStartupTimeout(10000))
|
||||||
.start()
|
.start()
|
||||||
}
|
|
||||||
|
|
||||||
export async function datasource(): Promise<Datasource> {
|
|
||||||
if (!container) {
|
|
||||||
container = await start()
|
|
||||||
}
|
|
||||||
const host = container.getHost()
|
const host = container.getHost()
|
||||||
const port = container.getMappedPort(3306)
|
const port = container.getMappedPort(3306)
|
||||||
|
|
||||||
|
@ -52,10 +46,3 @@ export async function datasource(): Promise<Datasource> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function stop() {
|
|
||||||
if (container) {
|
|
||||||
await container.stop()
|
|
||||||
container = undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Datasource, SourceName } from "@budibase/types"
|
import { Datasource, SourceName } from "@budibase/types"
|
||||||
import { GenericContainer, Wait, StartedTestContainer } from "testcontainers"
|
import { GenericContainer, Wait } from "testcontainers"
|
||||||
|
|
||||||
let container: StartedTestContainer | undefined
|
export async function postgres(): Promise<Datasource> {
|
||||||
|
const container = await new GenericContainer("postgres:16.1-bullseye")
|
||||||
export async function start(): Promise<StartedTestContainer> {
|
.withName("budibase-test-postgres")
|
||||||
return await new GenericContainer("postgres:16.1-bullseye")
|
.withReuse()
|
||||||
.withExposedPorts(5432)
|
.withExposedPorts(5432)
|
||||||
.withEnvironment({ POSTGRES_PASSWORD: "password" })
|
.withEnvironment({ POSTGRES_PASSWORD: "password" })
|
||||||
.withWaitStrategy(
|
.withWaitStrategy(
|
||||||
|
@ -13,12 +13,6 @@ export async function start(): Promise<StartedTestContainer> {
|
||||||
).withStartupTimeout(10000)
|
).withStartupTimeout(10000)
|
||||||
)
|
)
|
||||||
.start()
|
.start()
|
||||||
}
|
|
||||||
|
|
||||||
export async function datasource(): Promise<Datasource> {
|
|
||||||
if (!container) {
|
|
||||||
container = await start()
|
|
||||||
}
|
|
||||||
const host = container.getHost()
|
const host = container.getHost()
|
||||||
const port = container.getMappedPort(5432)
|
const port = container.getMappedPort(5432)
|
||||||
|
|
||||||
|
@ -39,10 +33,3 @@ export async function datasource(): Promise<Datasource> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function stop() {
|
|
||||||
if (container) {
|
|
||||||
await container.stop()
|
|
||||||
container = undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue