Got container reuse strategy in place, need to convert tests now.

This commit is contained in:
Sam Rose 2024-03-26 11:22:40 +00:00
parent df52b6937a
commit 158964c4d2
No known key found for this signature in database
7 changed files with 98 additions and 123 deletions

View File

@ -16,7 +16,7 @@ import {
import _ from "lodash"
import { generator } from "@budibase/backend-core/tests"
import { utils } from "@budibase/backend-core"
import { databaseTestProviders } from "../integrations/tests/utils"
import { DatabaseName, getDatasource } from "../integrations/tests/utils"
import { Client } from "pg"
// @ts-ignore
fetch.mockSearch()
@ -41,18 +41,17 @@ describe("postgres integrations", () => {
makeRequest = generateMakeRequest(apiKey, true)
postgresDatasource = await config.api.datasource.create(
await databaseTestProviders.postgres.datasource()
await getDatasource(DatabaseName.POSTGRES)
)
})
afterAll(async () => {
await databaseTestProviders.postgres.stop()
})
beforeEach(async () => {
async function createAuxTable(prefix: string) {
return await config.createTable({
name: `${prefix}_${generator.word({ length: 6 })}`,
name: `${prefix}_${generator
.guid()
.replaceAll("-", "")
.substring(0, 6)}`,
type: "table",
primary: ["id"],
primaryDisplay: "title",
@ -89,7 +88,7 @@ describe("postgres integrations", () => {
}
primaryPostgresTable = await config.createTable({
name: `p_${generator.word({ length: 6 })}`,
name: `p_${generator.guid().replaceAll("-", "").substring(0, 6)}`,
type: "table",
primary: ["id"],
schema: {
@ -251,7 +250,7 @@ describe("postgres integrations", () => {
async function createDefaultPgTable() {
return await config.createTable({
name: generator.word({ length: 10 }),
name: generator.guid().replaceAll("-", "").substring(0, 10),
type: "table",
primary: ["id"],
schema: {
@ -1043,7 +1042,7 @@ describe("postgres integrations", () => {
it("should be able to verify the connection", async () => {
await config.api.datasource.verify(
{
datasource: await databaseTestProviders.postgres.datasource(),
datasource: await getDatasource(DatabaseName.POSTGRES),
},
{
body: {
@ -1054,7 +1053,7 @@ describe("postgres integrations", () => {
})
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(
{
datasource: {
@ -1089,21 +1088,21 @@ describe("postgres integrations", () => {
describe("POST /api/datasources/:datasourceId/schema", () => {
let client: Client
let tableName: string
beforeEach(async () => {
client = new Client(
(await databaseTestProviders.postgres.datasource()).config!
)
tableName = generator.guid().replaceAll("-", "").substring(0, 10)
client = new Client((await getDatasource(DatabaseName.POSTGRES)).config!)
await client.connect()
})
afterEach(async () => {
await client.query(`DROP TABLE IF EXISTS "table"`)
await client.query(`DROP TABLE IF EXISTS "${tableName}"`)
await client.end()
})
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(
"post",
@ -1111,12 +1110,14 @@ describe("postgres integrations", () => {
)
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 () => {
await client.query(`CREATE TABLE "table" (_id SERIAL PRIMARY KEY) `)
await client.query(
`CREATE TABLE "${tableName}" (_id SERIAL PRIMARY KEY) `
)
const response = await makeRequest(
"post",
@ -1124,18 +1125,22 @@ describe("postgres integrations", () => {
)
expect(response.body.errors).toEqual({
table: "Table contains invalid columns.",
[tableName]: "Table contains invalid columns.",
})
})
})
describe("Integration compatibility with postgres search_path", () => {
let client: Client, pathDatasource: Datasource
const schema1 = "test1",
schema2 = "test-2"
let client: Client,
pathDatasource: Datasource,
schema1: string,
schema2: string
beforeAll(async () => {
const dsConfig = await databaseTestProviders.postgres.datasource()
beforeEach(async () => {
schema1 = generator.guid().replaceAll("-", "")
schema2 = generator.guid().replaceAll("-", "")
const dsConfig = await getDatasource(DatabaseName.POSTGRES)
const dbConfig = dsConfig.config!
client = new Client(dbConfig)
@ -1153,7 +1158,7 @@ describe("postgres integrations", () => {
pathDatasource = await config.api.datasource.create(pathConfig)
})
afterAll(async () => {
afterEach(async () => {
await client.query(`DROP SCHEMA "${schema1}" CASCADE;`)
await client.query(`DROP SCHEMA "${schema2}" CASCADE;`)
await client.end()

View File

@ -1,19 +1,50 @@
jest.unmock("pg")
import { Datasource } from "@budibase/types"
import * as postgres from "./postgres"
import * as mongodb from "./mongodb"
import * as mysql from "./mysql"
import * as mssql from "./mssql"
import * as mariadb from "./mariadb"
import { StartedTestContainer } from "testcontainers"
import { postgres } from "./postgres"
import { mongodb } from "./mongodb"
import { mysql } from "./mysql"
import { mssql } from "./mssql"
import { mariadb } from "./mariadb"
jest.setTimeout(30000)
export type DatasourceProvider = () => Promise<Datasource>
export interface DatabaseProvider {
start(): Promise<StartedTestContainer>
stop(): Promise<void>
datasource(): Promise<Datasource>
export enum DatabaseName {
POSTGRES = "postgres",
MONGODB = "mongodb",
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 = {

View File

@ -1,9 +1,7 @@
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"
let container: StartedTestContainer | undefined
class MariaDBWaitStrategy extends AbstractWaitStrategy {
async waitUntilReady(container: any, boundPorts: any, startTime?: Date) {
// 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> {
return await new GenericContainer("mariadb:lts")
export async function mariadb(): Promise<Datasource> {
const container = await new GenericContainer("mariadb:lts")
.withName("budibase-test-mariadb")
.withReuse()
.withExposedPorts(3306)
.withEnvironment({ MARIADB_ROOT_PASSWORD: "password" })
.withWaitStrategy(new MariaDBWaitStrategy())
.start()
}
export async function datasource(): Promise<Datasource> {
if (!container) {
container = await start()
}
const host = container.getHost()
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
}
}

View File

@ -1,10 +1,10 @@
import { Datasource, SourceName } from "@budibase/types"
import { GenericContainer, Wait, StartedTestContainer } from "testcontainers"
import { GenericContainer, Wait } from "testcontainers"
let container: StartedTestContainer | undefined
export async function start(): Promise<StartedTestContainer> {
return await new GenericContainer("mongo:7.0-jammy")
export async function mongodb(): Promise<Datasource> {
const container = await new GenericContainer("mongo:7.0-jammy")
.withName("budibase-test-mongodb")
.withReuse()
.withExposedPorts(27017)
.withEnvironment({
MONGO_INITDB_ROOT_USERNAME: "mongo",
@ -16,14 +16,10 @@ export async function start(): Promise<StartedTestContainer> {
).withStartupTimeout(10000)
)
.start()
}
export async function datasource(): Promise<Datasource> {
if (!container) {
container = await start()
}
const host = container.getHost()
const port = container.getMappedPort(27017)
return {
type: "datasource",
source: SourceName.MONGODB,
@ -34,10 +30,3 @@ export async function datasource(): Promise<Datasource> {
},
}
}
export async function stop() {
if (container) {
await container.stop()
container = undefined
}
}

View File

@ -1,12 +1,12 @@
import { Datasource, SourceName } from "@budibase/types"
import { GenericContainer, Wait, StartedTestContainer } from "testcontainers"
import { GenericContainer, Wait } from "testcontainers"
let container: StartedTestContainer | undefined
export async function start(): Promise<StartedTestContainer> {
return await new GenericContainer(
export async function mssql(): Promise<Datasource> {
const container = await new GenericContainer(
"mcr.microsoft.com/mssql/server:2022-latest"
)
.withName("budibase-test-mssql")
.withReuse()
.withExposedPorts(1433)
.withEnvironment({
ACCEPT_EULA: "Y",
@ -23,12 +23,7 @@ export async function start(): Promise<StartedTestContainer> {
)
)
.start()
}
export async function datasource(): Promise<Datasource> {
if (!container) {
container = await start()
}
const host = container.getHost()
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
}
}

View File

@ -1,9 +1,7 @@
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"
let container: StartedTestContainer | undefined
class MySQLWaitStrategy extends AbstractWaitStrategy {
async waitUntilReady(container: any, boundPorts: any, startTime?: Date) {
// 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> {
return await new GenericContainer("mysql:8.3")
export async function mysql(): Promise<Datasource> {
const container = await new GenericContainer("mysql:8.3")
.withName("budibase-test-mysql")
.withReuse()
.withExposedPorts(3306)
.withEnvironment({ MYSQL_ROOT_PASSWORD: "password" })
.withWaitStrategy(new MySQLWaitStrategy().withStartupTimeout(10000))
.start()
}
export async function datasource(): Promise<Datasource> {
if (!container) {
container = await start()
}
const host = container.getHost()
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
}
}

View File

@ -1,10 +1,10 @@
import { Datasource, SourceName } from "@budibase/types"
import { GenericContainer, Wait, StartedTestContainer } from "testcontainers"
import { GenericContainer, Wait } from "testcontainers"
let container: StartedTestContainer | undefined
export async function start(): Promise<StartedTestContainer> {
return await new GenericContainer("postgres:16.1-bullseye")
export async function postgres(): Promise<Datasource> {
const container = await new GenericContainer("postgres:16.1-bullseye")
.withName("budibase-test-postgres")
.withReuse()
.withExposedPorts(5432)
.withEnvironment({ POSTGRES_PASSWORD: "password" })
.withWaitStrategy(
@ -13,12 +13,6 @@ export async function start(): Promise<StartedTestContainer> {
).withStartupTimeout(10000)
)
.start()
}
export async function datasource(): Promise<Datasource> {
if (!container) {
container = await start()
}
const host = container.getHost()
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
}
}