Docker Compose TestUtils
interface IDockerComposeProps { | |
cwd?: string; | |
dockerComposeFile: string; | |
} | |
class DockerCompose { | |
private readonly props: IDockerComposeProps; | |
private state: "unknown" | "pending-up" | "up" | "pending-down" | "down"; | |
public constructor(props: IDockerComposeProps) { | |
this.props = props; | |
this.state = "unknown"; | |
} | |
public readonly down = async () => { | |
ok( | |
this.state === "unknown" || this.state === "up", | |
`Invalid state: ${this.state}`, | |
); | |
this.state = "pending-down"; | |
const cwd = this.props.cwd || process.cwd(); | |
const cmd = `docker-compose -f ${this.props.dockerComposeFile.replace( | |
/ /g, | |
"\\ ", | |
)} down`; | |
return await new Promise((resolve, reject) => { | |
const childProcess = exec( | |
cmd, | |
{ | |
cwd, | |
}, | |
(error, _stdout, _stderr) => { | |
if (error) { | |
this.state = "unknown"; | |
return reject(error); | |
} | |
this.state = "down"; | |
return resolve(); | |
}, | |
); | |
childProcess.on("error", error => { | |
reject(error); | |
}); | |
}); | |
}; | |
public readonly up = async (): Promise<void> => { | |
ok(this.state === "down", `Invalid state: ${this.state}`); | |
this.state = "pending-up"; | |
return await new Promise((resolve, reject) => { | |
const childProcess = spawn( | |
"docker-compose", | |
"-f docker-compose.test.yml up --build".split(" "), | |
{ | |
cwd: this.props.cwd || process.cwd(), | |
}, | |
); | |
let readyForStartup = false; | |
// Declare both in the same statement to avoid use-before-declare | |
const [onStdOutChunk, onError] = [ | |
(chunk: Buffer): void => { | |
const data = chunk.toString("utf8"); | |
if (data.includes("ready for start up")) { | |
readyForStartup = true; | |
} | |
if (readyForStartup && data.includes("ready to accept connections")) { | |
childProcess.off("error", onError); | |
childProcess.stdout.off("data", onStdOutChunk); | |
this.state = "up"; | |
resolve(); | |
} | |
}, | |
(error: unknown): void => { | |
childProcess.off("error", onError); | |
childProcess.stdout.off("data", onStdOutChunk); | |
this.state = "unknown"; | |
reject(error); | |
}, | |
]; | |
childProcess.on("error", onError); | |
childProcess.stdout.on("data", onStdOutChunk); | |
}); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment