Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions docs/features/containers.md
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,24 @@ class CustomStartedContainer extends AbstractStartedContainer {
}
```

### Default wait strategy for custom containers

Custom containers can define a fallback wait strategy by overriding `getDefaultWaitStrategy`. Testcontainers uses this when the user has not explicitly set a wait strategy and neither the container nor its image defines a health check:

```ts
import { GenericContainer, Wait, WaitStrategy } from "testcontainers";

class CustomContainer extends GenericContainer {
constructor() {
super("custom/image:1.0.0");
}

protected override getDefaultWaitStrategy(): WaitStrategy {
return Wait.forLogMessage("ready");
}
}
```

## Exposing container ports

Specify which container ports you want accessible by the host:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ export class GenericContainer implements TestContainer {

protected containerStarting?(inspectResult: InspectResult, reused: boolean): Promise<void>;

protected getDefaultWaitStrategy?(): WaitStrategy;

public async start(): Promise<StartedTestContainer> {
const client = await getContainerRuntimeClient();
await client.image.pull(this.imageName, {
Expand Down Expand Up @@ -132,6 +134,7 @@ export class GenericContainer implements TestContainer {
waitStrategy,
healthCheck: this.healthCheck,
imageNames: [this.imageName.string],
defaultWaitStrategy: this.getDefaultWaitStrategy?.(),
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,19 @@ describe("wait strategy selector", () => {
).resolves.toBeInstanceOf(HostPortWaitStrategy);
});

it("should select the default wait strategy when no healthcheck is configured", async () => {
const defaultWaitStrategy = Wait.forLogMessage("ready");

await expect(
selectWaitStrategy({
client: client({} as ImageInspectInfo),
inspectResult: containerInspectResult(),
imageNames: ["image:latest"],
defaultWaitStrategy,
})
).resolves.toBe(defaultWaitStrategy);
});

it("should select image healthcheck when container inspect omits healthcheck config", async () => {
await expect(
selectWaitStrategy({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type WaitStrategySelectorOptions = {
waitStrategy?: WaitStrategy;
healthCheck?: HealthCheck;
imageNames?: string[];
defaultWaitStrategy?: WaitStrategy;
};

export const selectWaitStrategy = async ({
Expand All @@ -25,13 +26,14 @@ export const selectWaitStrategy = async ({
waitStrategy,
healthCheck,
imageNames = getImageNames(inspectResult),
defaultWaitStrategy = Wait.forListeningPorts(),
}: WaitStrategySelectorOptions): Promise<WaitStrategy> => {
if (waitStrategy) return waitStrategy;
if (hasHealthCheck(healthCheck)) return Wait.forHealthCheck();
if (hasDisabledHealthCheckConfig(inspectResult)) return Wait.forListeningPorts();
if (hasHealthCheckConfig(inspectResult) || hasHealthCheckStatus(inspectResult)) return Wait.forHealthCheck();
if (await imageHasHealthCheck(client, imageNames)) return Wait.forHealthCheck();
return Wait.forListeningPorts();
return defaultWaitStrategy;
};

const getImageNames = (inspectResult: ContainerInspectInfo): string[] => {
Expand Down
Loading