Skip to content

Commit b44b362

Browse files
Updates
1 parent 6069d7b commit b44b362

File tree

15 files changed

+54
-109
lines changed

15 files changed

+54
-109
lines changed

docs/features/advanced.md

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,5 @@
11
# Advanced
22

3-
## Timeout parameter of APIs
4-
5-
Testcontainers library provides a set of classes and functions, and some of them expect a parameter named `timeout`, `ms`, or similar to be passed from the caller. This parameters are of type `number`, and the unit of measurement for this parameters across all public APIs is the same: millisecond. For example:
6-
7-
```js
8-
export interface TestContainer {
9-
...
10-
withStartupTimeout(ms: number): this; // timeout expected to be passed as milliseconds
11-
}
12-
```
13-
14-
The underlying docker APIs may expect different units for timeouts and intervals, and testcontainers library will do the needed conversion under the hood automatically. For example, consider the `stop` method of a container:
15-
16-
```javascript
17-
const container = await new GenericContainer("alpine").start();
18-
await container.stop({ timeout: 10_000 }); // testcontainers library expects the timeout to be passed as milliseconds
19-
```
20-
21-
The Docker API [expects seconds](https://docs.docker.com/reference/api/engine/version/v1.48/#tag/Container/operation/ContainerStop) to be passed to this API call. The 10_000 ms value will be converted to seconds by testontainers library.
22-
23-
Keep in mind that conversion from ms to seconds uses truncation to integer, for example:
24-
25-
```
26-
5000ms = 5s
27-
3800ms = 3s
28-
500ms = 0s
29-
```
30-
31-
You may also pass a *negative* value to function parameters, but this may lead to unexpedted results.
32-
333
## Container Runtime Client
344

355
Testcontainers configures an underlying container runtime to perform its tasks. This runtime works automatically with several providers like Docker, Podman, Colima, Rancher Desktop and Testcontainers Desktop. There are too many usage examples to list here, but here are some common examples:
@@ -69,4 +39,4 @@ const environment = await containerRuntimeClient.compose.up({ ... })
6939

7040
```js
7141
const network = await containerRuntimeClient.network.create({ ... })
72-
```
42+
```**
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
export { withFileLock } from "./file-lock";
22
export { hash } from "./hash";
33
export { buildLog, composeLog, containerLog, execLog, log, Logger, pullLog } from "./logger";
4-
export { Ms } from "./ms";
54
export { IntervalRetry, Retry } from "./retry";
65
export { streamToString } from "./streams";
6+
export * from "./time";
77
export * from "./type-guards";
88
export { RandomUuid, Uuid } from "./uuid";

packages/testcontainers/src/common/ms.test.ts

Lines changed: 0 additions & 36 deletions
This file was deleted.

packages/testcontainers/src/common/ms.ts

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { toNanos, toSeconds } from "./time";
2+
3+
test.for([
4+
[0, 0],
5+
[10, 0],
6+
[999, 0],
7+
[1010, 1],
8+
[1999, 1],
9+
[10_000, 10],
10+
[-10, -0],
11+
[-999, -0],
12+
[-1010, -1],
13+
[-1999, -1],
14+
[-10_000, -10],
15+
])("should convert %i ms to %i seconds", ([ms, s]) => {
16+
expect(toSeconds(ms)).toEqual(s);
17+
});
18+
19+
test.for([
20+
[0, 0],
21+
[1, 1_000_000],
22+
[-1, -1_000_000],
23+
])("should convert %i ms to %i ns", ([ms, ns]) => {
24+
expect(toNanos(ms)).toEqual(ns);
25+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const toSeconds = (ms: number) => Math.trunc(ms * 1e-3);
2+
3+
export const toNanos = (ms: number) => ms * 1e6;

packages/testcontainers/src/container-runtime/clients/compose/compose-client.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { default as dockerComposeV1, default as v1, v2 as dockerComposeV2, v2 } from "docker-compose";
2-
import { log, Ms, pullLog } from "../../../common";
2+
import { log, pullLog } from "../../../common";
3+
import { toSeconds } from "../../../common/time";
34
import { ComposeInfo } from "../types";
45
import { defaultComposeOptions } from "./default-compose-options";
56
import { ComposeDownOptions, ComposeOptions } from "./types";
@@ -222,7 +223,7 @@ function composeDownCommandOptions(options: ComposeDownOptions): string[] {
222223
result.push("-v");
223224
}
224225
if (options.timeout) {
225-
result.push("-t", `${new Ms(options.timeout).seconds()}`);
226+
result.push("-t", `${toSeconds(options.timeout)}`);
226227
}
227228
return result;
228229
}

packages/testcontainers/src/container-runtime/clients/container/docker-container-client.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Dockerode, {
99
} from "dockerode";
1010
import { IncomingMessage } from "http";
1111
import { PassThrough, Readable } from "stream";
12-
import { execLog, log, Ms, streamToString } from "../../../common";
12+
import { execLog, log, streamToString, toSeconds } from "../../../common";
1313
import { ContainerClient } from "./container-client";
1414
import { ContainerCommitOptions, ContainerStatus, ExecOptions, ExecResult } from "./types";
1515

@@ -120,8 +120,7 @@ export class DockerContainerClient implements ContainerClient {
120120

121121
async inspect(container: Dockerode.Container): Promise<ContainerInspectInfo> {
122122
try {
123-
const inspectInfo = await container.inspect();
124-
return inspectInfo;
123+
return await container.inspect();
125124
} catch (err) {
126125
log.error(`Failed to inspect container: ${err}`, { containerId: container.id });
127126
throw err;
@@ -131,8 +130,7 @@ export class DockerContainerClient implements ContainerClient {
131130
async stop(container: Container, opts?: { timeout: number }): Promise<void> {
132131
try {
133132
log.debug(`Stopping container...`, { containerId: container.id });
134-
const t = new Ms(opts?.timeout ?? 0).seconds();
135-
await container.stop({ t });
133+
await container.stop({ t: toSeconds(opts?.timeout ?? 0) });
136134
log.debug(`Stopped container`, { containerId: container.id });
137135
// eslint-disable-next-line @typescript-eslint/no-explicit-any
138136
} catch (err: any) {
@@ -257,8 +255,7 @@ export class DockerContainerClient implements ContainerClient {
257255
async restart(container: Container, opts?: { timeout: number }): Promise<void> {
258256
try {
259257
log.debug(`Restarting container...`, { containerId: container.id });
260-
const t = new Ms(opts?.timeout ?? 0).seconds();
261-
await container.restart({ t });
258+
await container.restart({ t: toSeconds(opts?.timeout ?? 0) });
262259
log.debug(`Restarted container`, { containerId: container.id });
263260
} catch (err) {
264261
log.error(`Failed to restart container: ${err}`, { containerId: container.id });

packages/testcontainers/src/docker-compose-environment/docker-compose-environment.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ export class DockerComposeEnvironment {
6868
return this;
6969
}
7070

71-
public withStartupTimeout(ms: number): this {
72-
this.startupTimeoutMs = ms;
71+
public withStartupTimeout(startupTimeoutMs: number): this {
72+
this.startupTimeoutMs = startupTimeoutMs;
7373
return this;
7474
}
7575

packages/testcontainers/src/generic-container/generic-container.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import archiver from "archiver";
22
import AsyncLock from "async-lock";
33
import { Container, ContainerCreateOptions, HostConfig } from "dockerode";
44
import { Readable } from "stream";
5-
import { containerLog, hash, log, Ms } from "../common";
5+
import { containerLog, hash, log, toNanos } from "../common";
66
import { ContainerRuntimeClient, getContainerRuntimeClient, ImageName } from "../container-runtime";
77
import { CONTAINER_STATUSES } from "../container-runtime/clients/container/types";
88
import { StartedNetwork } from "../network/network";
@@ -398,17 +398,17 @@ export class GenericContainer implements TestContainer {
398398
this.healthCheck = healthCheck;
399399
this.createOpts.Healthcheck = {
400400
Test: healthCheck.test,
401-
Interval: healthCheck.interval ? new Ms(healthCheck.interval).nanos() : 0,
402-
Timeout: healthCheck.timeout ? new Ms(healthCheck.timeout).nanos() : 0,
401+
Interval: healthCheck.interval ? toNanos(healthCheck.interval) : 0,
402+
Timeout: healthCheck.timeout ? toNanos(healthCheck.timeout) : 0,
403403
Retries: healthCheck.retries ?? 0,
404-
StartPeriod: healthCheck.startPeriod ? new Ms(healthCheck.startPeriod).nanos() : 0,
404+
StartPeriod: healthCheck.startPeriod ? toNanos(healthCheck.startPeriod) : 0,
405405
};
406406

407407
return this;
408408
}
409409

410-
public withStartupTimeout(ms: number): this {
411-
this.startupTimeoutMs = ms;
410+
public withStartupTimeout(startupTimeoutMs: number): this {
411+
this.startupTimeoutMs = startupTimeoutMs;
412412
return this;
413413
}
414414

0 commit comments

Comments
 (0)