-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove jest testcontainers #13350
Remove jest testcontainers #13350
Changes from 9 commits
66cfb8e
db21542
b303592
d77b6f8
44d4e49
569f003
4a080e7
f68840a
0dba0ce
afacee9
f3e9e3d
5d7cd51
d85db6b
e5c7e65
415b27a
a4b940e
037becf
6ee8f42
06c3cc7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { GenericContainer, Wait } from "testcontainers" | ||
|
||
export default async function setup() { | ||
const container = await new GenericContainer("budibase/couchdb") | ||
.withExposedPorts(5984) | ||
.withEnvironment({ | ||
COUCHDB_PASSWORD: "budibase", | ||
COUCHDB_USER: "budibase", | ||
}) | ||
.withCopyFilesToContainer([ | ||
{ | ||
source: "./src/tests/test-couchdb.ini", | ||
target: "/opt/couchdb/etc/local.d/test-couchdb.ini", | ||
}, | ||
]) | ||
.withWaitStrategy( | ||
Wait.forSuccessfulCommand( | ||
"curl http://budibase:budibase@localhost:5984/_up" | ||
).withStartupTimeout(20000) | ||
) | ||
.start() | ||
|
||
// @ts-expect-error | ||
// eslint-disable-next-line no-undef | ||
globalThis.__COUCHDB_CONTAINER_ID__ = container.getId() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { getContainerRuntimeClient } from "testcontainers" | ||
|
||
export default async function teardown() { | ||
const client = await getContainerRuntimeClient() | ||
|
||
// @ts-expect-error | ||
// eslint-disable-next-line no-undef | ||
const containerId = globalThis.__COUCHDB_CONTAINER_ID__ | ||
const container = client.container.getById(containerId) | ||
await client.container.stop(container) | ||
mike12345567 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
await client.container.remove(container) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,66 @@ | ||
import { DatabaseImpl } from "../../../src/db" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've changed how this file works because when I moved away from The new code uses There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a nice improvement, I didn't even know you could get JSON out here, very handy! |
||
import { execSync } from "child_process" | ||
|
||
let dockerPsResult: string | undefined | ||
|
||
function formatDockerPsResult(serverName: string, port: number) { | ||
const lines = dockerPsResult?.split("\n") | ||
let first = true | ||
if (!lines) { | ||
return null | ||
} | ||
for (let line of lines) { | ||
if (first) { | ||
first = false | ||
continue | ||
} | ||
let toLookFor = serverName.split("-service")[0] | ||
if (!line.includes(toLookFor)) { | ||
continue | ||
} | ||
const regex = new RegExp(`0.0.0.0:([0-9]*)->${port}`, "g") | ||
const found = line.match(regex) | ||
if (found) { | ||
return found[0].split(":")[1].split("->")[0] | ||
} | ||
} | ||
return null | ||
interface ContainerInfo { | ||
Command: string | ||
CreatedAt: string | ||
ID: string | ||
Image: string | ||
Labels: string | ||
LocalVolumes: string | ||
Mounts: string | ||
Names: string | ||
Networks: string | ||
Ports: string | ||
RunningFor: string | ||
Size: string | ||
State: string | ||
Status: string | ||
} | ||
|
||
function getTestContainerSettings( | ||
serverName: string, | ||
key: string | ||
): string | null { | ||
const entry = Object.entries(global).find( | ||
([k]) => | ||
k.includes(`${serverName.toUpperCase()}`) && | ||
k.includes(`${key.toUpperCase()}`) | ||
) | ||
if (!entry) { | ||
return null | ||
} | ||
return entry[1] | ||
function getTestcontainers(): ContainerInfo[] { | ||
return execSync("docker ps --format json") | ||
.toString() | ||
.split("\n") | ||
.filter(x => x.length > 0) | ||
.map(x => JSON.parse(x) as ContainerInfo) | ||
.filter(x => x.Labels.includes("org.testcontainers=true")) | ||
} | ||
|
||
function getContainerInfo(containerName: string, port: number) { | ||
let assignedPort = getTestContainerSettings( | ||
containerName.toUpperCase(), | ||
`PORT_${port}` | ||
) | ||
if (!dockerPsResult) { | ||
try { | ||
const outputBuffer = execSync("docker ps") | ||
dockerPsResult = outputBuffer.toString("utf8") | ||
} catch (err) { | ||
//no-op | ||
} | ||
} | ||
const possiblePort = formatDockerPsResult(containerName, port) | ||
if (possiblePort) { | ||
assignedPort = possiblePort | ||
} | ||
const host = getTestContainerSettings(containerName.toUpperCase(), "IP") | ||
return { | ||
port: assignedPort, | ||
host, | ||
url: host && assignedPort && `http://${host}:${assignedPort}`, | ||
} | ||
function getContainerByImage(image: string) { | ||
return getTestcontainers().find(x => x.Image.startsWith(image)) | ||
} | ||
|
||
function getCouchConfig() { | ||
return getContainerInfo("couchdb", 5984) | ||
function getExposedPort(container: ContainerInfo, port: number) { | ||
const match = container.Ports.match(new RegExp(`0.0.0.0:(\\d+)->${port}/tcp`)) | ||
if (!match) { | ||
return undefined | ||
} | ||
return parseInt(match[1]) | ||
} | ||
|
||
export function setupEnv(...envs: any[]) { | ||
const couch = getCouchConfig() | ||
const couch = getContainerByImage("budibase/couchdb") | ||
if (!couch) { | ||
throw new Error("CouchDB container not found") | ||
} | ||
|
||
const couchPort = getExposedPort(couch, 5984) | ||
if (!couchPort) { | ||
throw new Error("CouchDB port not found") | ||
} | ||
|
||
const configs = [ | ||
{ key: "COUCH_DB_PORT", value: couch.port }, | ||
{ key: "COUCH_DB_URL", value: couch.url }, | ||
{ key: "COUCH_DB_PORT", value: `${couchPort}` }, | ||
{ key: "COUCH_DB_URL", value: `http://localhost:${couchPort}` }, | ||
] | ||
|
||
for (const config of configs.filter(x => !!x.value)) { | ||
for (const env of envs) { | ||
env._set(config.key, config.value) | ||
} | ||
} | ||
|
||
// @ts-expect-error | ||
DatabaseImpl.nano = undefined | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { GenericContainer, Wait } from "testcontainers" | ||
|
||
export default async function setup() { | ||
samwho marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const container = await new GenericContainer("budibase/couchdb") | ||
.withExposedPorts(5984) | ||
.withEnvironment({ | ||
COUCHDB_PASSWORD: "budibase", | ||
adrinr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
COUCHDB_USER: "budibase", | ||
}) | ||
.withCopyFilesToContainer([ | ||
{ | ||
source: "./src/tests/test-couchdb.ini", | ||
target: "/opt/couchdb/etc/local.d/test-couchdb.ini", | ||
}, | ||
]) | ||
.withWaitStrategy( | ||
Wait.forSuccessfulCommand( | ||
"curl http://budibase:budibase@localhost:5984/_up" | ||
).withStartupTimeout(20000) | ||
) | ||
.start() | ||
|
||
// @ts-expect-error | ||
// eslint-disable-next-line no-undef | ||
globalThis.__COUCHDB_CONTAINER_ID__ = container.getId() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { getContainerRuntimeClient } from "testcontainers" | ||
|
||
export default async function teardown() { | ||
const client = await getContainerRuntimeClient() | ||
|
||
// @ts-expect-error | ||
// eslint-disable-next-line no-undef | ||
const containerId = globalThis.__COUCHDB_CONTAINER_ID__ | ||
const container = client.container.getById(containerId) | ||
await client.container.stop(container) | ||
await client.container.remove(container) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[log] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've taken the opportunity here to calm the CouchDB logs down. By default they log every single HTTP request, which is an unbelievable amount of logging. This made |
||
level = warn |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { GenericContainer, Wait } from "testcontainers" | ||
|
||
export default async function setup() { | ||
const container = await new GenericContainer("budibase/couchdb") | ||
.withExposedPorts(5984) | ||
.withEnvironment({ | ||
COUCHDB_PASSWORD: "budibase", | ||
COUCHDB_USER: "budibase", | ||
}) | ||
.withCopyFilesToContainer([ | ||
{ | ||
source: "./src/tests/test-couchdb.ini", | ||
target: "/opt/couchdb/etc/local.d/test-couchdb.ini", | ||
}, | ||
]) | ||
.withWaitStrategy( | ||
Wait.forSuccessfulCommand( | ||
"curl http://budibase:budibase@localhost:5984/_up" | ||
).withStartupTimeout(20000) | ||
) | ||
.start() | ||
|
||
// @ts-expect-error | ||
// eslint-disable-next-line no-undef | ||
globalThis.__COUCHDB_CONTAINER_ID__ = container.getId() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { getContainerRuntimeClient } from "testcontainers" | ||
|
||
export default async function teardown() { | ||
const client = await getContainerRuntimeClient() | ||
|
||
// @ts-expect-error | ||
// eslint-disable-next-line no-undef | ||
const containerId = globalThis.__COUCHDB_CONTAINER_ID__ | ||
const container = client.container.getById(containerId) | ||
await client.container.stop(container) | ||
await client.container.remove(container) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This caused an error in a test while I was working on this change, and I moved to throwing the raw error in order to see the full stack trace. Decided to leave it as is because I feel this is more useful.