diff --git a/docs/modules/cassandra.md b/docs/modules/cassandra.md index 877071ba2..77917efc8 100644 --- a/docs/modules/cassandra.md +++ b/docs/modules/cassandra.md @@ -21,7 +21,7 @@ npm install @testcontainers/cassandra --save-dev -[With custom datacenter / rack](../../packages/modules/cassandra/src/cassandra-container.test.ts) inside_block:customDataSenterAndRack +[With custom datacenter / rack](../../packages/modules/cassandra/src/cassandra-container.test.ts) inside_block:customDataCenterAndRack diff --git a/packages/modules/cassandra/src/cassandra-container.test.ts b/packages/modules/cassandra/src/cassandra-container.test.ts index ababeb160..e403af9e1 100644 --- a/packages/modules/cassandra/src/cassandra-container.test.ts +++ b/packages/modules/cassandra/src/cassandra-container.test.ts @@ -5,7 +5,7 @@ import { CassandraContainer } from "./cassandra-container"; const IMAGE = getImage(__dirname); -describe("Cassandra", { timeout: 240_000 }, () => { +describe.sequential("Cassandra", { timeout: 240_000 }, () => { // connectWithDefaultCredentials { it("should connect and execute a query with default credentials", async () => { const container = await new CassandraContainer(IMAGE).start(); @@ -50,7 +50,7 @@ describe("Cassandra", { timeout: 240_000 }, () => { }); // } - // customDataSenterAndRack { + // customDataCenterAndRack { it("should set datacenter and rack", async () => { const customDataCenter = "customDC"; const customRack = "customRack"; diff --git a/packages/modules/gcloud/src/cloudstorage-emulator-container.test.ts b/packages/modules/gcloud/src/cloudstorage-emulator-container.test.ts index 8ffd6a581..297d30ccd 100644 --- a/packages/modules/gcloud/src/cloudstorage-emulator-container.test.ts +++ b/packages/modules/gcloud/src/cloudstorage-emulator-container.test.ts @@ -30,7 +30,7 @@ async function getRequestBodyFromReadableStream(stream: ReadableStream { +describe.sequential("CloudStorageEmulatorContainer", { timeout: 240_000 }, () => { const server = setupServer(); beforeAll(() => { diff --git a/packages/modules/gcloud/src/firestore-emulator-container.test.ts b/packages/modules/gcloud/src/firestore-emulator-container.test.ts index 6f8796c60..8353ed8de 100644 --- a/packages/modules/gcloud/src/firestore-emulator-container.test.ts +++ b/packages/modules/gcloud/src/firestore-emulator-container.test.ts @@ -1,14 +1,11 @@ import admin from "firebase-admin"; +import { randomUuid } from "testcontainers"; import { getImage } from "../../../testcontainers/src/utils/test-helper"; import { FirestoreEmulatorContainer, StartedFirestoreEmulatorContainer } from "./firestore-emulator-container"; const IMAGE = getImage(__dirname); describe("FirestoreEmulatorContainer", { timeout: 240_000 }, () => { - afterEach(async () => { - await admin.app().delete(); - }); - // firestore4 { it("should work using default version", async () => { const firestoreEmulatorContainer = await new FirestoreEmulatorContainer(IMAGE).start(); @@ -35,10 +32,11 @@ describe("FirestoreEmulatorContainer", { timeout: 240_000 }, () => { async function checkFirestore(firestoreEmulatorContainer: StartedFirestoreEmulatorContainer) { expect(firestoreEmulatorContainer).toBeDefined(); const testProjectId = "test-project"; + const testAppName = `test-app-${randomUuid()}`; const testCollection = "test-collection"; const testDocument = "test-doc"; const firebaseConfig = { projectId: testProjectId }; - const firestore = admin.initializeApp(firebaseConfig).firestore(); + const firestore = admin.initializeApp(firebaseConfig, testAppName).firestore(); firestore.settings({ host: firestoreEmulatorContainer.getEmulatorEndpoint(), ssl: false }); const docRef = firestore.collection(testCollection).doc(testDocument); diff --git a/packages/modules/kurrentdb/src/kurrentdb-container.test.ts b/packages/modules/kurrentdb/src/kurrentdb-container.test.ts index f8cf0d10a..544e7618b 100644 --- a/packages/modules/kurrentdb/src/kurrentdb-container.test.ts +++ b/packages/modules/kurrentdb/src/kurrentdb-container.test.ts @@ -4,7 +4,7 @@ import { KurrentDbContainer } from "./kurrentdb-container"; const IMAGE = getImage(__dirname); -describe("KurrentDbContainer", { timeout: 240_000 }, () => { +describe.sequential("KurrentDbContainer", { timeout: 240_000 }, () => { // startContainer { it("should execute write and read", async () => { const container = await new KurrentDbContainer(IMAGE).start(); @@ -42,6 +42,7 @@ describe("KurrentDbContainer", { timeout: 240_000 }, () => { ]); await container.stop(); + await client.dispose(); }); // } @@ -86,6 +87,7 @@ describe("KurrentDbContainer", { timeout: 240_000 }, () => { ); await stream.unsubscribe(); await container.stop(); + await client.dispose(); }); // } }); diff --git a/packages/testcontainers/src/common/index.ts b/packages/testcontainers/src/common/index.ts index e03676525..594e54477 100644 --- a/packages/testcontainers/src/common/index.ts +++ b/packages/testcontainers/src/common/index.ts @@ -5,4 +5,4 @@ export { IntervalRetry, Retry } from "./retry"; export { streamToString } from "./streams"; export * from "./time"; export * from "./type-guards"; -export { RandomUuid, Uuid } from "./uuid"; +export { RandomUuid, Uuid, randomUuid } from "./uuid"; diff --git a/packages/testcontainers/src/container-runtime/auth/cred-helpers.ts b/packages/testcontainers/src/container-runtime/auth/cred-helpers.ts index 982572c0c..022d2dc40 100644 --- a/packages/testcontainers/src/container-runtime/auth/cred-helpers.ts +++ b/packages/testcontainers/src/container-runtime/auth/cred-helpers.ts @@ -7,7 +7,7 @@ export class CredHelpers extends CredentialProvider { } public getCredentialProviderName(registry: string, dockerConfig: ContainerRuntimeConfig): string | undefined { - if (dockerConfig.credHelpers !== undefined && dockerConfig.credHelpers[registry] !== undefined) { + if (dockerConfig.credHelpers?.[registry] !== undefined) { return dockerConfig.credHelpers[registry]; } } diff --git a/packages/testcontainers/src/container-runtime/auth/credential-provider.test.ts b/packages/testcontainers/src/container-runtime/auth/credential-provider.test.ts index b84f1e99b..feb541c29 100644 --- a/packages/testcontainers/src/container-runtime/auth/credential-provider.test.ts +++ b/packages/testcontainers/src/container-runtime/auth/credential-provider.test.ts @@ -11,7 +11,7 @@ vi.mock("child_process", () => ({ spawn: (...args: unknown[]) => mockSpawn(...args), })); -describe("CredentialProvider", () => { +describe.sequential("CredentialProvider", () => { let credentialProvider: CredentialProvider; let containerRuntimeConfig: ContainerRuntimeConfig; diff --git a/packages/testcontainers/src/container-runtime/auth/get-auth-config.test.ts b/packages/testcontainers/src/container-runtime/auth/get-auth-config.test.ts index bb9e8887d..1a691bce8 100644 --- a/packages/testcontainers/src/container-runtime/auth/get-auth-config.test.ts +++ b/packages/testcontainers/src/container-runtime/auth/get-auth-config.test.ts @@ -1,6 +1,6 @@ -import { Mock } from "vitest"; +import type { Mock } from "vitest"; -describe("get auth config", () => { +describe.sequential("get auth config", () => { let mockExistsSync: Mock; let mockReadFile: Mock; diff --git a/packages/testcontainers/src/container-runtime/image-name.test.ts b/packages/testcontainers/src/container-runtime/image-name.test.ts index 4f87519cc..75e6ba264 100644 --- a/packages/testcontainers/src/container-runtime/image-name.test.ts +++ b/packages/testcontainers/src/container-runtime/image-name.test.ts @@ -1,6 +1,6 @@ import { ImageName } from "./image-name"; -describe("ContainerImage", () => { +describe.sequential("ContainerImage", () => { it("should return whether two image names are equal", () => { const imageName = new ImageName("registry", "image", "tag"); @@ -10,7 +10,7 @@ describe("ContainerImage", () => { expect(imageName.equals(new ImageName("anotherRegistry", "image", "tag"))).toBe(false); }); - describe("string", () => { + describe.sequential("string", () => { it("should work with registry", () => { const imageName = new ImageName("registry", "image", "tag"); expect(imageName.string).toBe("registry/image:tag"); @@ -67,7 +67,7 @@ describe("ContainerImage", () => { ); }); - describe("fromString", () => { + describe.sequential("fromString", () => { it("should work", () => { const imageName = ImageName.fromString("image:latest"); @@ -154,7 +154,7 @@ describe("ContainerImage", () => { }); }); - describe.each([ + describe.sequential.each([ { customRegistry: "custom.com/registry", expectedRegistry: "custom.com", expectedImagePrefix: "registry/" }, { customRegistry: "custom.com/registry/", expectedRegistry: "custom.com", expectedImagePrefix: "registry/" }, { customRegistry: "custom.com", expectedRegistry: "custom.com", expectedImagePrefix: "" }, diff --git a/packages/testcontainers/src/container-runtime/strategies/configuration-strategy.test.ts b/packages/testcontainers/src/container-runtime/strategies/configuration-strategy.test.ts index c7f027c9b..6e6c0e3f7 100644 --- a/packages/testcontainers/src/container-runtime/strategies/configuration-strategy.test.ts +++ b/packages/testcontainers/src/container-runtime/strategies/configuration-strategy.test.ts @@ -8,7 +8,7 @@ vi.mock("fs/promises"); const mockGetContainerRuntimeConfig = vi.mocked(getContainerRuntimeConfig); const mockReadFile = vi.mocked(readFile); -describe("ConfigurationStrategy", () => { +describe.sequential("ConfigurationStrategy", () => { it("should return undefined if no docker host is set", async () => { mockGetContainerRuntimeConfig.mockResolvedValueOnce({ dockerHost: undefined }); diff --git a/packages/testcontainers/src/container-runtime/strategies/rootless-unix-socket-strategy.test.ts b/packages/testcontainers/src/container-runtime/strategies/rootless-unix-socket-strategy.test.ts index 6f84e5225..9be20caa4 100644 --- a/packages/testcontainers/src/container-runtime/strategies/rootless-unix-socket-strategy.test.ts +++ b/packages/testcontainers/src/container-runtime/strategies/rootless-unix-socket-strategy.test.ts @@ -5,7 +5,7 @@ import { RootlessUnixSocketStrategy } from "./rootless-unix-socket-strategy"; vi.mock("fs", () => ({ existsSync: vi.fn() })); -describe("RootlessUnixSocketStrategy", () => { +describe.sequential("RootlessUnixSocketStrategy", () => { const mockExistsSync = vi.mocked(existsSync); it("should return undefined for non-linux and non-darwin platforms", async () => { diff --git a/packages/testcontainers/src/container-runtime/strategies/testcontainers-host-strategy.test.ts b/packages/testcontainers/src/container-runtime/strategies/testcontainers-host-strategy.test.ts index 4c499320c..dc792bf23 100644 --- a/packages/testcontainers/src/container-runtime/strategies/testcontainers-host-strategy.test.ts +++ b/packages/testcontainers/src/container-runtime/strategies/testcontainers-host-strategy.test.ts @@ -5,7 +5,7 @@ vi.mock("./utils/config", () => ({ getContainerRuntimeConfig: () => mockGetContainerRuntimeConfig(), })); -describe("TestcontainersHostStrategy", () => { +describe.sequential("TestcontainersHostStrategy", () => { it("should return undefined when tc.host property is not set", async () => { mockGetContainerRuntimeConfig.mockResolvedValue({}); diff --git a/packages/testcontainers/src/container-runtime/strategies/unix-socket-strategy.test.ts b/packages/testcontainers/src/container-runtime/strategies/unix-socket-strategy.test.ts index d18c5faca..2e6113c9a 100644 --- a/packages/testcontainers/src/container-runtime/strategies/unix-socket-strategy.test.ts +++ b/packages/testcontainers/src/container-runtime/strategies/unix-socket-strategy.test.ts @@ -4,7 +4,7 @@ import { UnixSocketStrategy } from "./unix-socket-strategy"; vi.mock("fs"); const mockExistsSync = vi.mocked(existsSync); -describe("UnixSocketStrategy", () => { +describe.sequential("UnixSocketStrategy", () => { beforeEach(() => { mockExistsSync.mockReturnValue(true); }); diff --git a/packages/testcontainers/src/container-runtime/strategies/utils/config.test.ts b/packages/testcontainers/src/container-runtime/strategies/utils/config.test.ts index 07d0eb33f..7fd593495 100644 --- a/packages/testcontainers/src/container-runtime/strategies/utils/config.test.ts +++ b/packages/testcontainers/src/container-runtime/strategies/utils/config.test.ts @@ -5,122 +5,124 @@ vi.mock("fs", () => ({ existsSync: mockExistsSync })); const mockReadFile = vi.fn(); vi.mock("fs/promises", () => ({ readFile: mockReadFile })); -let getContainerRuntimeConfig: GetContainerRuntimeConfig; +describe.sequential("Config", () => { + let getContainerRuntimeConfig: GetContainerRuntimeConfig; -beforeEach(async () => { - getContainerRuntimeConfig = (await import("./config")).getContainerRuntimeConfig; -}); - -afterEach(() => { - vi.resetModules(); -}); - -test("should not set anything", async () => { - const dockerClientConfig = await getContainerRuntimeConfig({}); - - expect(dockerClientConfig.dockerHost).toBeUndefined(); - expect(dockerClientConfig.dockerTlsVerify).toBeUndefined(); - expect(dockerClientConfig.dockerCertPath).toBeUndefined(); -}); + beforeEach(async () => { + getContainerRuntimeConfig = (await import("./config")).getContainerRuntimeConfig; + }); -describe("environment", () => { - beforeEach(() => { - mockExistsSync.mockReturnValue(false); + afterEach(() => { + vi.resetModules(); }); - test("should set the host", async () => { - const dockerClientConfig = await getContainerRuntimeConfig({ - DOCKER_HOST: "tcp://my.docker.host:1234", - }); + it("should not set anything", async () => { + const dockerClientConfig = await getContainerRuntimeConfig({}); - expect(dockerClientConfig.dockerHost).toBe("tcp://my.docker.host:1234"); + expect(dockerClientConfig.dockerHost).toBeUndefined(); expect(dockerClientConfig.dockerTlsVerify).toBeUndefined(); expect(dockerClientConfig.dockerCertPath).toBeUndefined(); }); - test("should set TLS verify", async () => { - const dockerClientConfig = await getContainerRuntimeConfig({ - DOCKER_HOST: "tcp://my.docker.host:1234", - DOCKER_TLS_VERIFY: "1", + describe("environment", () => { + beforeEach(() => { + mockExistsSync.mockReturnValue(false); }); - expect(dockerClientConfig.dockerHost).toBe("tcp://my.docker.host:1234"); - expect(dockerClientConfig.dockerTlsVerify).toBe("1"); - expect(dockerClientConfig.dockerCertPath).toBeUndefined(); - }); + it("should set the host", async () => { + const dockerClientConfig = await getContainerRuntimeConfig({ + DOCKER_HOST: "tcp://my.docker.host:1234", + }); - test("should set the cert path", async () => { - const dockerClientConfig = await getContainerRuntimeConfig({ - DOCKER_HOST: "tcp://my.docker.host:1234", - DOCKER_TLS_VERIFY: "1", - DOCKER_CERT_PATH: "/some/path", + expect(dockerClientConfig.dockerHost).toBe("tcp://my.docker.host:1234"); + expect(dockerClientConfig.dockerTlsVerify).toBeUndefined(); + expect(dockerClientConfig.dockerCertPath).toBeUndefined(); }); - expect(dockerClientConfig.dockerHost).toBe("tcp://my.docker.host:1234"); - expect(dockerClientConfig.dockerTlsVerify).toBe("1"); - expect(dockerClientConfig.dockerCertPath).toBe("/some/path"); - }); -}); + it("should set TLS verify", async () => { + const dockerClientConfig = await getContainerRuntimeConfig({ + DOCKER_HOST: "tcp://my.docker.host:1234", + DOCKER_TLS_VERIFY: "1", + }); -describe("testcontainers.properties file", () => { - beforeEach(() => { - mockExistsSync.mockReturnValue(true); + expect(dockerClientConfig.dockerHost).toBe("tcp://my.docker.host:1234"); + expect(dockerClientConfig.dockerTlsVerify).toBe("1"); + expect(dockerClientConfig.dockerCertPath).toBeUndefined(); + }); + + it("should set the cert path", async () => { + const dockerClientConfig = await getContainerRuntimeConfig({ + DOCKER_HOST: "tcp://my.docker.host:1234", + DOCKER_TLS_VERIFY: "1", + DOCKER_CERT_PATH: "/some/path", + }); + + expect(dockerClientConfig.dockerHost).toBe("tcp://my.docker.host:1234"); + expect(dockerClientConfig.dockerTlsVerify).toBe("1"); + expect(dockerClientConfig.dockerCertPath).toBe("/some/path"); + }); }); - test("should set the tc host", async () => { - mockReadFile.mockResolvedValueOnce("tc.host=tcp://my.docker.host:1234"); + describe("testcontainers.properties file", () => { + beforeEach(() => { + mockExistsSync.mockReturnValue(true); + }); - const dockerClientConfig = await getContainerRuntimeConfig({}); + it("should set the tc host", async () => { + mockReadFile.mockResolvedValueOnce("tc.host=tcp://my.docker.host:1234"); - expect(dockerClientConfig.tcHost).toBe("tcp://my.docker.host:1234"); - }); + const dockerClientConfig = await getContainerRuntimeConfig({}); - test("should set the host", async () => { - mockReadFile.mockResolvedValueOnce("docker.host=tcp://my.docker.host:1234"); + expect(dockerClientConfig.tcHost).toBe("tcp://my.docker.host:1234"); + }); - const dockerClientConfig = await getContainerRuntimeConfig({}); + it("should set the host", async () => { + mockReadFile.mockResolvedValueOnce("docker.host=tcp://my.docker.host:1234"); - expect(dockerClientConfig.dockerHost).toBe("tcp://my.docker.host:1234"); - expect(dockerClientConfig.dockerTlsVerify).toBeUndefined(); - expect(dockerClientConfig.dockerCertPath).toBeUndefined(); - }); + const dockerClientConfig = await getContainerRuntimeConfig({}); + + expect(dockerClientConfig.dockerHost).toBe("tcp://my.docker.host:1234"); + expect(dockerClientConfig.dockerTlsVerify).toBeUndefined(); + expect(dockerClientConfig.dockerCertPath).toBeUndefined(); + }); - test("should set TLS verify", async () => { - mockReadFile.mockResolvedValueOnce(` + it("should set TLS verify", async () => { + mockReadFile.mockResolvedValueOnce(` docker.host=tcp://my.docker.host:1234 docker.tls.verify=1 `); - const dockerClientConfig = await getContainerRuntimeConfig({}); + const dockerClientConfig = await getContainerRuntimeConfig({}); - expect(dockerClientConfig.dockerHost).toBe("tcp://my.docker.host:1234"); - expect(dockerClientConfig.dockerTlsVerify).toBe("1"); - expect(dockerClientConfig.dockerCertPath).toBeUndefined(); - }); + expect(dockerClientConfig.dockerHost).toBe("tcp://my.docker.host:1234"); + expect(dockerClientConfig.dockerTlsVerify).toBe("1"); + expect(dockerClientConfig.dockerCertPath).toBeUndefined(); + }); - test("should set the cert path", async () => { - mockReadFile.mockResolvedValueOnce(` + it("should set the cert path", async () => { + mockReadFile.mockResolvedValueOnce(` docker.host=tcp://my.docker.host:1234 docker.tls.verify=1 docker.cert.path=/some/path `); - const dockerClientConfig = await getContainerRuntimeConfig({}); + const dockerClientConfig = await getContainerRuntimeConfig({}); - expect(dockerClientConfig.dockerHost).toBe("tcp://my.docker.host:1234"); - expect(dockerClientConfig.dockerTlsVerify).toBe("1"); - expect(dockerClientConfig.dockerCertPath).toBe("/some/path"); + expect(dockerClientConfig.dockerHost).toBe("tcp://my.docker.host:1234"); + expect(dockerClientConfig.dockerTlsVerify).toBe("1"); + expect(dockerClientConfig.dockerCertPath).toBe("/some/path"); + }); }); -}); -test("should cache the result", async () => { - mockExistsSync.mockReturnValue(true); - mockReadFile.mockResolvedValueOnce("tc.host=tcp://my.docker.host:1234"); + it("should cache the result", async () => { + mockExistsSync.mockReturnValue(true); + mockReadFile.mockResolvedValueOnce("tc.host=tcp://my.docker.host:1234"); - await getContainerRuntimeConfig({}); - const dockerClientConfig = await getContainerRuntimeConfig({}); + await getContainerRuntimeConfig({}); + const dockerClientConfig = await getContainerRuntimeConfig({}); - expect(dockerClientConfig.tcHost).toBe("tcp://my.docker.host:1234"); - expect(mockExistsSync).toHaveBeenCalledTimes(1); - expect(mockReadFile).toHaveBeenCalledTimes(1); + expect(dockerClientConfig.tcHost).toBe("tcp://my.docker.host:1234"); + expect(mockExistsSync).toHaveBeenCalledTimes(1); + expect(mockReadFile).toHaveBeenCalledTimes(1); + }); }); diff --git a/packages/testcontainers/src/container-runtime/utils/image-exists.test.ts b/packages/testcontainers/src/container-runtime/utils/image-exists.test.ts index d9743fa15..1f3fa0944 100644 --- a/packages/testcontainers/src/container-runtime/utils/image-exists.test.ts +++ b/packages/testcontainers/src/container-runtime/utils/image-exists.test.ts @@ -12,46 +12,48 @@ vi.mock("dockerode", () => { }; }); -afterEach(() => { - vi.resetModules(); -}); +describe.sequential("imageExists", () => { + afterEach(() => { + vi.resetModules(); + }); -test("returns true when image exists", async () => { - const { imageExists } = await import("./image-exists"); - mockImageInspect.mockResolvedValue({}); + it("returns true when image exists", async () => { + const { imageExists } = await import("./image-exists"); + mockImageInspect.mockResolvedValue({}); - const imageName = ImageName.fromString("imageName"); - const result = await imageExists(new Dockerode(), imageName); + const imageName = ImageName.fromString("imageName"); + const result = await imageExists(new Dockerode(), imageName); - expect(result).toBe(true); -}); + expect(result).toBe(true); + }); -test("returns previous result from cache", async () => { - const { imageExists } = await import("./image-exists"); - mockImageInspect.mockResolvedValue({}); + it("returns previous result from cache", async () => { + const { imageExists } = await import("./image-exists"); + mockImageInspect.mockResolvedValue({}); - const imageName = ImageName.fromString("imageName"); - await imageExists(new Dockerode(), imageName); - const result = await imageExists(new Dockerode(), imageName); + const imageName = ImageName.fromString("imageName"); + await imageExists(new Dockerode(), imageName); + const result = await imageExists(new Dockerode(), imageName); - expect(result).toBe(true); - expect(mockImageInspect).toHaveBeenCalledTimes(1); -}); + expect(result).toBe(true); + expect(mockImageInspect).toHaveBeenCalledTimes(1); + }); -test("returns false when image inspect fails because image does not exist", async () => { - const { imageExists } = await import("./image-exists"); - mockImageInspect.mockRejectedValue(new Error("no such image")); + it("returns false when image inspect fails because image does not exist", async () => { + const { imageExists } = await import("./image-exists"); + mockImageInspect.mockRejectedValue(new Error("no such image")); - const imageName = ImageName.fromString("imageName"); - const result = await imageExists(new Dockerode(), imageName); + const imageName = ImageName.fromString("imageName"); + const result = await imageExists(new Dockerode(), imageName); - expect(result).toBe(false); -}); + expect(result).toBe(false); + }); -test("throws when unable to inspect image", async () => { - const { imageExists } = await import("./image-exists"); - mockImageInspect.mockRejectedValue(new Error("unknown error")); + it("throws when unable to inspect image", async () => { + const { imageExists } = await import("./image-exists"); + mockImageInspect.mockRejectedValue(new Error("unknown error")); - const imageName = ImageName.fromString("imageName"); - await expect(() => imageExists(new Dockerode(), imageName)).rejects.toThrowError("unknown error"); + const imageName = ImageName.fromString("imageName"); + await expect(() => imageExists(new Dockerode(), imageName)).rejects.toThrowError("unknown error"); + }); }); diff --git a/packages/testcontainers/src/container-runtime/utils/lookup-host-ips.test.ts b/packages/testcontainers/src/container-runtime/utils/lookup-host-ips.test.ts index ef56a59b1..07a53662e 100644 --- a/packages/testcontainers/src/container-runtime/utils/lookup-host-ips.test.ts +++ b/packages/testcontainers/src/container-runtime/utils/lookup-host-ips.test.ts @@ -8,7 +8,7 @@ vi.mock("dns/promises", () => { }; }); -describe("lookupHostIps", () => { +describe.sequential("lookupHostIps", () => { it("should return a list of resolved host IPs when host is not an IP", async () => { const hostIps: HostIp[] = [{ address: "127.0.0.1", family: 4 }]; mockDnsLookup.mockResolvedValueOnce(hostIps); diff --git a/packages/testcontainers/src/container-runtime/utils/resolve-host.test.ts b/packages/testcontainers/src/container-runtime/utils/resolve-host.test.ts index b2c029363..057af9698 100644 --- a/packages/testcontainers/src/container-runtime/utils/resolve-host.test.ts +++ b/packages/testcontainers/src/container-runtime/utils/resolve-host.test.ts @@ -27,161 +27,163 @@ vi.mock("./run-in-container", () => ({ runInContainer: () => runInContainerMock(), })); -test("should return TESTCONTAINERS_HOST_OVERRIDE from environment", async () => { - const strategyResult = { - uri: "tcp://another:2375", - allowUserOverrides: true, - } as ContainerRuntimeClientStrategyResult; - - const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", { - TESTCONTAINERS_HOST_OVERRIDE: "tcp://another:2375", +describe.sequential("resolveHost", () => { + it("should return TESTCONTAINERS_HOST_OVERRIDE from environment", async () => { + const strategyResult = { + uri: "tcp://another:2375", + allowUserOverrides: true, + } as ContainerRuntimeClientStrategyResult; + + const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", { + TESTCONTAINERS_HOST_OVERRIDE: "tcp://another:2375", + }); + + expect(host).toEqual("tcp://another:2375"); }); - expect(host).toEqual("tcp://another:2375"); -}); + it("should return hostname for TCP protocols", async () => { + for (const uri of ["tcp://docker:2375", "http://docker:2375", "https://docker:2375"]) { + const strategyResult = { + uri, + allowUserOverrides: true, + } as ContainerRuntimeClientStrategyResult; -test("should return hostname for TCP protocols", async () => { - for (const uri of ["tcp://docker:2375", "http://docker:2375", "https://docker:2375"]) { + const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); + + expect(host).toEqual("docker"); + } + }); + + it("should not return TESTCONTAINERS_HOST_OVERRIDE when allow user override is false", async () => { const strategyResult = { - uri, - allowUserOverrides: true, + uri: "tcp://docker:2375", + allowUserOverrides: false, } as ContainerRuntimeClientStrategyResult; - const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); + const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", { + TESTCONTAINERS_HOST_OVERRIDE: "tcp://another:2375", + }); expect(host).toEqual("docker"); - } -}); + }); -test("should not return TESTCONTAINERS_HOST_OVERRIDE when allow user override is false", async () => { - const strategyResult = { - uri: "tcp://docker:2375", - allowUserOverrides: false, - } as ContainerRuntimeClientStrategyResult; + it("should return localhost for unix and npipe protocols when not running in a container", async () => { + mockExistsSync.mockReturnValue(false); - const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", { - TESTCONTAINERS_HOST_OVERRIDE: "tcp://another:2375", - }); + for (const uri of ["unix://docker:2375", "npipe://docker:2375"]) { + const strategyResult = { + uri, + allowUserOverrides: true, + } as ContainerRuntimeClientStrategyResult; - expect(host).toEqual("docker"); -}); + const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); -test("should return localhost for unix and npipe protocols when not running in a container", async () => { - mockExistsSync.mockReturnValue(false); + expect(host).toEqual("localhost"); + } + }); - for (const uri of ["unix://docker:2375", "npipe://docker:2375"]) { - const strategyResult = { - uri, - allowUserOverrides: true, - } as ContainerRuntimeClientStrategyResult; + it("should return host from gateway when running in a container", async () => { + mockExistsSync.mockReturnValue(true); + mockInspectNetwork.mockResolvedValue({ + IPAM: { + Config: [{ Gateway: "172.0.0.1" }], + }, + }); - const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); + for (const uri of ["unix://docker:2375", "npipe://docker:2375"]) { + const strategyResult = { + uri, + allowUserOverrides: true, + } as ContainerRuntimeClientStrategyResult; - expect(host).toEqual("localhost"); - } -}); + const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); -test("should return host from gateway when running in a container", async () => { - mockExistsSync.mockReturnValue(true); - mockInspectNetwork.mockResolvedValue({ - IPAM: { - Config: [{ Gateway: "172.0.0.1" }], - }, + expect(host).toEqual("172.0.0.1"); + } }); - for (const uri of ["unix://docker:2375", "npipe://docker:2375"]) { - const strategyResult = { - uri, - allowUserOverrides: true, - } as ContainerRuntimeClientStrategyResult; + it("should use bridge network as gateway for Docker provider", async () => { + mockExistsSync.mockReturnValue(true); + mockInspectNetwork.mockResolvedValue({ + IPAM: { + Config: [{ Gateway: "172.0.0.1" }], + }, + }); - const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); + for (const uri of ["unix://docker:2375", "npipe://docker:2375"]) { + const strategyResult = { + uri, + allowUserOverrides: true, + } as ContainerRuntimeClientStrategyResult; - expect(host).toEqual("172.0.0.1"); - } -}); + await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); -test("should use bridge network as gateway for Docker provider", async () => { - mockExistsSync.mockReturnValue(true); - mockInspectNetwork.mockResolvedValue({ - IPAM: { - Config: [{ Gateway: "172.0.0.1" }], - }, + expect(mockGetNetwork).toHaveBeenCalledWith("bridge"); + } }); - for (const uri of ["unix://docker:2375", "npipe://docker:2375"]) { - const strategyResult = { - uri, - allowUserOverrides: true, - } as ContainerRuntimeClientStrategyResult; + it("should use podman network as gateway for Podman provider", async () => { + mockExistsSync.mockReturnValue(true); + mockInspectNetwork.mockResolvedValue({ + IPAM: { + Config: [{ Gateway: "172.0.0.1" }], + }, + }); - await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); + for (const uri of ["unix://podman.sock", "npipe://podman.sock"]) { + const strategyResult = { + uri, + allowUserOverrides: true, + } as ContainerRuntimeClientStrategyResult; - expect(mockGetNetwork).toHaveBeenCalledWith("bridge"); - } -}); + await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); -test("should use podman network as gateway for Podman provider", async () => { - mockExistsSync.mockReturnValue(true); - mockInspectNetwork.mockResolvedValue({ - IPAM: { - Config: [{ Gateway: "172.0.0.1" }], - }, + expect(mockGetNetwork).toHaveBeenCalledWith("podman"); + } }); - for (const uri of ["unix://podman.sock", "npipe://podman.sock"]) { - const strategyResult = { - uri, - allowUserOverrides: true, - } as ContainerRuntimeClientStrategyResult; + it("should return host from default gateway when running in a container", async () => { + mockExistsSync.mockReturnValue(true); + mockInspectNetwork.mockResolvedValue({}); + runInContainerMock.mockResolvedValue("172.0.0.2"); - await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); + for (const uri of ["unix://docker:2375", "npipe://docker:2375"]) { + const strategyResult = { + uri, + allowUserOverrides: true, + } as ContainerRuntimeClientStrategyResult; - expect(mockGetNetwork).toHaveBeenCalledWith("podman"); - } -}); + const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); -test("should return host from default gateway when running in a container", async () => { - mockExistsSync.mockReturnValue(true); - mockInspectNetwork.mockResolvedValue({}); - runInContainerMock.mockResolvedValue("172.0.0.2"); + expect(host).toEqual("172.0.0.2"); + } + }); - for (const uri of ["unix://docker:2375", "npipe://docker:2375"]) { - const strategyResult = { - uri, - allowUserOverrides: true, - } as ContainerRuntimeClientStrategyResult; + it("should return localhost if unable to find gateway", async () => { + mockExistsSync.mockReturnValue(true); + mockInspectNetwork.mockResolvedValue({}); + runInContainerMock.mockResolvedValue(undefined); - const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); + for (const uri of ["unix://docker:2375", "npipe://docker:2375"]) { + const strategyResult = { + uri, + allowUserOverrides: true, + } as ContainerRuntimeClientStrategyResult; - expect(host).toEqual("172.0.0.2"); - } -}); + const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); -test("should return localhost if unable to find gateway", async () => { - mockExistsSync.mockReturnValue(true); - mockInspectNetwork.mockResolvedValue({}); - runInContainerMock.mockResolvedValue(undefined); + expect(host).toEqual("localhost"); + } + }); - for (const uri of ["unix://docker:2375", "npipe://docker:2375"]) { + it("should throw for unsupported protocol", async () => { const strategyResult = { - uri, + uri: "invalid://unknown", allowUserOverrides: true, } as ContainerRuntimeClientStrategyResult; - const host = await resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {}); - - expect(host).toEqual("localhost"); - } -}); - -test("should throw for unsupported protocol", async () => { - const strategyResult = { - uri: "invalid://unknown", - allowUserOverrides: true, - } as ContainerRuntimeClientStrategyResult; - - await expect(() => resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {})).rejects.toThrowError( - "Unsupported protocol: invalid" - ); + await expect(() => resolveHost(new Dockerode(), strategyResult, "indexServerAddress", {})).rejects.toThrowError( + "Unsupported protocol: invalid" + ); + }); }); diff --git a/packages/testcontainers/src/generic-container/generic-container-lifecycle.test.ts b/packages/testcontainers/src/generic-container/generic-container-lifecycle.test.ts index 9003df48e..d8bac8f85 100644 --- a/packages/testcontainers/src/generic-container/generic-container-lifecycle.test.ts +++ b/packages/testcontainers/src/generic-container/generic-container-lifecycle.test.ts @@ -1,7 +1,7 @@ import { Mock } from "vitest"; import { AbstractStartedContainer, GenericContainer, InspectResult, StartedTestContainer } from "../index"; -describe("GenericContainer lifecycle", { timeout: 180_000 }, () => { +describe.sequential("GenericContainer lifecycle", { timeout: 180_000 }, () => { let beforeContainerCreated: Mock; let containerCreated: Mock; let containerStarting: Mock; diff --git a/packages/testcontainers/src/index.ts b/packages/testcontainers/src/index.ts index 9131ea89e..71e65489f 100644 --- a/packages/testcontainers/src/index.ts +++ b/packages/testcontainers/src/index.ts @@ -1,4 +1,4 @@ -export { IntervalRetry, RandomUuid, Retry, Uuid, log } from "./common"; +export { IntervalRetry, RandomUuid, Retry, Uuid, log, randomUuid } from "./common"; export { ContainerRuntimeClient, ImageName, getContainerRuntimeClient } from "./container-runtime"; export { DockerComposeEnvironment } from "./docker-compose-environment/docker-compose-environment"; export { DownedDockerComposeEnvironment } from "./docker-compose-environment/downed-docker-compose-environment"; diff --git a/packages/testcontainers/src/port-forwarder/port-forwarder-reuse.test.ts b/packages/testcontainers/src/port-forwarder/port-forwarder-reuse.test.ts index 4f62961b7..905e6db3b 100644 --- a/packages/testcontainers/src/port-forwarder/port-forwarder-reuse.test.ts +++ b/packages/testcontainers/src/port-forwarder/port-forwarder-reuse.test.ts @@ -2,7 +2,7 @@ import { GenericContainer } from "../generic-container/generic-container"; import { RandomPortGenerator } from "../utils/port-generator"; import { createTestServer } from "../utils/test-helper"; -describe("Port Forwarder reuse", { timeout: 180_000 }, () => { +describe.sequential("Port Forwarder reuse", { timeout: 180_000 }, () => { const portGen = new RandomPortGenerator(); it("should expose additional ports", async () => { diff --git a/packages/testcontainers/src/port-forwarder/port-forwarder.test.ts b/packages/testcontainers/src/port-forwarder/port-forwarder.test.ts index c28ef7480..23a97b97a 100644 --- a/packages/testcontainers/src/port-forwarder/port-forwarder.test.ts +++ b/packages/testcontainers/src/port-forwarder/port-forwarder.test.ts @@ -1,4 +1,3 @@ -import { Server } from "http"; import { GenericContainer } from "../generic-container/generic-container"; import { Network } from "../network/network"; import { TestContainers } from "../test-containers"; @@ -6,19 +5,11 @@ import { RandomPortGenerator } from "../utils/port-generator"; import { createTestServer } from "../utils/test-helper"; describe("PortForwarder", { timeout: 180_000 }, () => { - let randomPort: number; - let server: Server; - - beforeEach(async () => { - randomPort = await new RandomPortGenerator().generatePort(); - server = await createTestServer(randomPort); - }); - - afterEach(async () => { - await new Promise((resolve) => server.close(resolve)); - }); + const portGen = new RandomPortGenerator(); it("should expose host ports to the container", async () => { + const randomPort = await portGen.generatePort(); + const server = await createTestServer(randomPort); await TestContainers.exposeHostPorts(randomPort); const container = await new GenericContainer("cristianrgreco/testcontainer:1.1.14").start(); @@ -27,9 +18,12 @@ describe("PortForwarder", { timeout: 180_000 }, () => { expect(output).toEqual(expect.stringContaining("hello world")); await container.stop(); + server.close(); }); it("should expose host ports to the container with custom network", async () => { + const randomPort = await portGen.generatePort(); + const server = await createTestServer(randomPort); await TestContainers.exposeHostPorts(randomPort); const network = await new Network().start(); @@ -40,9 +34,12 @@ describe("PortForwarder", { timeout: 180_000 }, () => { await container.stop(); await network.stop(); + server.close(); }); it("should expose host ports to the container with custom network and network alias", async () => { + const randomPort = await portGen.generatePort(); + const server = await createTestServer(randomPort); await TestContainers.exposeHostPorts(randomPort); const network = await new Network().start(); @@ -56,5 +53,6 @@ describe("PortForwarder", { timeout: 180_000 }, () => { await container.stop(); await network.stop(); + server.close(); }); }); diff --git a/packages/testcontainers/src/reaper/reaper.test.ts b/packages/testcontainers/src/reaper/reaper.test.ts index 1227f5368..d3ad73bb3 100644 --- a/packages/testcontainers/src/reaper/reaper.test.ts +++ b/packages/testcontainers/src/reaper/reaper.test.ts @@ -1,7 +1,7 @@ import { ContainerRuntimeClient, getContainerRuntimeClient } from "../container-runtime"; import { RandomPortGenerator } from "../utils/port-generator"; -describe("Reaper", { timeout: 120_000 }, () => { +describe.sequential("Reaper", { timeout: 120_000 }, () => { let client: ContainerRuntimeClient; const getReaper = async () => await (await import("./reaper")).getReaper(client); diff --git a/packages/testcontainers/src/wait-strategies/utils/port-check.test.ts b/packages/testcontainers/src/wait-strategies/utils/port-check.test.ts index 54808a760..b40bf4766 100644 --- a/packages/testcontainers/src/wait-strategies/utils/port-check.test.ts +++ b/packages/testcontainers/src/wait-strategies/utils/port-check.test.ts @@ -19,8 +19,8 @@ vi.mock("../../container-runtime", () => { }; }); -describe("PortCheck", () => { - describe("InternalPortCheck", () => { +describe.sequential("PortCheck", () => { + describe.sequential("InternalPortCheck", () => { let client: ContainerRuntimeClient; let mockContainer: Container; let portCheck: InternalPortCheck; diff --git a/vitest.config.ts b/vitest.config.ts index 525260a7a..c20a8b6f0 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -12,6 +12,9 @@ export default defineConfig({ restoreMocks: true, unstubEnvs: true, retry: process.env.CI ? 3 : 0, + sequence: { + concurrent: true, + }, alias: { testcontainers: path.resolve(__dirname, "packages/testcontainers/src"), },