Skip to content

Commit

Permalink
fix: correctly evaluate predicates in HttpWaitStrategy (#450)
Browse files Browse the repository at this point in the history
  • Loading branch information
abendi committed Feb 14, 2023
1 parent be1c14c commit af72dc1
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 6 deletions.
30 changes: 30 additions & 0 deletions src/http-wait-strategy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ describe("HttpWaitStrategy", () => {
await container.stop();
});

it("should timeout for mismatching status code", async () => {
await expect(() =>
new GenericContainer("cristianrgreco/testcontainer:1.1.14")
.withExposedPorts(8080)
.withStartupTimeout(3000)
.withWaitStrategy(Wait.forHttp("/unknown-path", 8080).forStatusCode(200))
.start()
).rejects.toThrowError("URL /unknown-path not accessible after 3000ms for");
});

it("should wait for status code matching", async () => {
const container = await new GenericContainer("cristianrgreco/testcontainer:1.1.14")
.withExposedPorts(8080)
Expand All @@ -42,6 +52,16 @@ describe("HttpWaitStrategy", () => {
await container.stop();
});

it("should timeout for falsy status code matching", async () => {
await expect(() =>
new GenericContainer("cristianrgreco/testcontainer:1.1.14")
.withExposedPorts(8080)
.withStartupTimeout(3000)
.withWaitStrategy(Wait.forHttp("/hello-world", 8080).forStatusCodeMatching(() => false))
.start()
).rejects.toThrowError("URL /hello-world not accessible after 3000ms for");
});

it("should wait for response body predicate", async () => {
const container = await new GenericContainer("cristianrgreco/testcontainer:1.1.14")
.withExposedPorts(8080)
Expand All @@ -55,6 +75,16 @@ describe("HttpWaitStrategy", () => {
await container.stop();
});

it("should timeout for falsy response body predicate", async () => {
await expect(() =>
new GenericContainer("cristianrgreco/testcontainer:1.1.14")
.withExposedPorts(8080)
.withStartupTimeout(3000)
.withWaitStrategy(Wait.forHttp("/hello-world", 8080).forResponsePredicate(() => false))
.start()
).rejects.toThrowError("URL /hello-world not accessible after 3000ms for");
});

it("should set method", async () => {
const container = await new GenericContainer("cristianrgreco/testcontainer:1.1.14")
.withExposedPorts(8080)
Expand Down
10 changes: 8 additions & 2 deletions src/http-wait-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,19 @@ export class HttpWaitStrategy extends AbstractWaitStrategy {
return undefined;
}
},
(response) => {
async (response) => {
if (response === undefined) {
return false;
} else if (!this.predicates.length) {
return response.ok;
} else {
return this.predicates.every((predicate) => predicate(response));
for (const predicate of this.predicates) {
const result = await predicate(response);
if (!result) {
return false;
}
}
return true;
}
},
() => {
Expand Down
8 changes: 4 additions & 4 deletions src/retry-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Clock, SystemClock, Time } from "./clock";
export interface RetryStrategy<T, U> {
retryUntil(
fn: () => Promise<T>,
predicate: (result: T) => boolean,
predicate: (result: T) => boolean | Promise<boolean>,
onTimeout: () => U,
timeout: number
): Promise<T | U>;
Expand All @@ -14,7 +14,7 @@ abstract class AbstractRetryStrategy<T, U> implements RetryStrategy<T, U> {

public abstract retryUntil(
fn: () => Promise<T>,
predicate: (result: T) => boolean,
predicate: (result: T) => boolean | Promise<boolean>,
onTimeout: () => U,
timeout: number
): Promise<T | U>;
Expand All @@ -35,7 +35,7 @@ export class IntervalRetryStrategy<T, U> extends AbstractRetryStrategy<T, U> {

public async retryUntil(
fn: (attempt: number) => Promise<T>,
predicate: (result: T) => boolean,
predicate: (result: T) => boolean | Promise<boolean>,
onTimeout: () => U,
timeout: number
): Promise<T | U> {
Expand All @@ -44,7 +44,7 @@ export class IntervalRetryStrategy<T, U> extends AbstractRetryStrategy<T, U> {
let attemptNumber = 0;
let result = await fn(attemptNumber++);

while (!predicate(result)) {
while (!(await predicate(result))) {
if (this.hasTimedOut(timeout, startTime)) {
return onTimeout();
}
Expand Down

0 comments on commit af72dc1

Please sign in to comment.