Skip to content

Commit 9271e97

Browse files
authored
Add CouchDB module (#1136)
1 parent 885e117 commit 9271e97

File tree

10 files changed

+249
-0
lines changed

10 files changed

+249
-0
lines changed

docs/modules/couchdb.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# CouchDB
2+
3+
## Install
4+
5+
```bash
6+
npm install @testcontainers/couchdb --save-dev
7+
```
8+
9+
## Examples
10+
11+
These examples use the following libraries:
12+
13+
- [nano](https://www.npmjs.com/package/nano)
14+
15+
npm install nano
16+
17+
Choose an image from the [container registry](https://hub.docker.com/_/couchdb) and substitute `IMAGE`.
18+
19+
### Execute a query
20+
21+
<!--codeinclude-->
22+
[](../../packages/modules/couchdb/src/couchdb-container.test.ts) inside_block:startContainer
23+
<!--/codeinclude-->
24+
25+
### With credentials
26+
27+
By default, this module uses `root:root` as credentials.
28+
29+
<!--codeinclude-->
30+
[](../../packages/modules/couchdb/src/couchdb-container.test.ts) inside_block:customCredentials
31+
<!--/codeinclude-->

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ nav:
6161
- CockroachDB: modules/cockroachdb.md
6262
- CosmosDB: modules/cosmosdb.md
6363
- Couchbase: modules/couchbase.md
64+
- CouchDB: modules/couchdb.md
6465
- Elasticsearch: modules/elasticsearch.md
6566
- Etcd: modules/etcd.md
6667
- GCloud: modules/gcloud.md

package-lock.json

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FROM couchdb:3.5
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "@testcontainers/couchdb",
3+
"version": "11.5.1",
4+
"license": "MIT",
5+
"keywords": [
6+
"couchdb",
7+
"testing",
8+
"docker",
9+
"testcontainers"
10+
],
11+
"description": "CouchDB module for Testcontainers",
12+
"homepage": "https://github.com/testcontainers/testcontainers-node#readme",
13+
"repository": {
14+
"type": "git",
15+
"url": "git+https://github.com/testcontainers/testcontainers-node.git"
16+
},
17+
"bugs": {
18+
"url": "https://github.com/testcontainers/testcontainers-node/issues"
19+
},
20+
"main": "build/index.js",
21+
"files": [
22+
"build"
23+
],
24+
"publishConfig": {
25+
"access": "public"
26+
},
27+
"scripts": {
28+
"prepack": "shx cp ../../../README.md . && shx cp ../../../LICENSE .",
29+
"build": "tsc --project tsconfig.build.json"
30+
},
31+
"dependencies": {
32+
"testcontainers": "^11.5.1"
33+
},
34+
"devDependencies": {
35+
"nano": "^11.0.0"
36+
}
37+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import nano from "nano";
2+
import { expect } from "vitest";
3+
import { getImage } from "../../../testcontainers/src/utils/test-helper";
4+
import { CouchDBContainer } from "./couchdb-container";
5+
6+
const IMAGE = getImage(__dirname);
7+
8+
type User = {
9+
username: string;
10+
email: string;
11+
};
12+
13+
describe("CouchDBContainer", { timeout: 240_000 }, () => {
14+
it("should write and read a collection", async () => {
15+
// startContainer {
16+
await using container = await new CouchDBContainer(IMAGE).start();
17+
18+
const client = nano({
19+
url: container.getUrl(),
20+
});
21+
await client.db.create("users");
22+
const db = client.use<User>("users");
23+
24+
const document = await db.insert({
25+
username: "j-doe",
26+
27+
});
28+
29+
expect(await db.get(document.id)).toEqual({
30+
_id: document.id,
31+
_rev: document.rev,
32+
username: "j-doe",
33+
34+
});
35+
// }
36+
});
37+
38+
it("should use custom credentials", async function () {
39+
// customCredentials {
40+
await using container = await new CouchDBContainer(IMAGE).withUsername("admin").withPassword("foo").start();
41+
42+
const client = nano({
43+
url: container.getUrl(),
44+
});
45+
await client.db.create("users");
46+
const db = client.use<User>("users");
47+
48+
const document = await db.insert({
49+
username: "j-doe",
50+
51+
});
52+
53+
expect(container.getUrl()).toBe(`http://admin:foo@${container.getHost()}:${container.getPort()}`);
54+
expect(await db.get(document.id)).toEqual({
55+
_id: document.id,
56+
_rev: document.rev,
57+
username: "j-doe",
58+
59+
});
60+
// }
61+
});
62+
});
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { AbstractStartedContainer, GenericContainer, StartedTestContainer, Wait } from "testcontainers";
2+
3+
const COUCHDB_PORT = 5984;
4+
5+
export class CouchDBContainer extends GenericContainer {
6+
private username: string = "root";
7+
private password: string = "root";
8+
9+
constructor(image: string) {
10+
super(image);
11+
this.withExposedPorts(COUCHDB_PORT)
12+
.withStartupTimeout(120_000)
13+
.withWaitStrategy(Wait.forHttp("/_up", COUCHDB_PORT).forStatusCode(200).withStartupTimeout(60_000));
14+
}
15+
16+
public withUsername(username: string): this {
17+
this.username = username;
18+
return this;
19+
}
20+
21+
public withPassword(password: string): this {
22+
this.password = password;
23+
return this;
24+
}
25+
26+
public override async start(): Promise<StartedCouchDBContainer> {
27+
this.withEnvironment({
28+
COUCHDB_USER: this.username,
29+
COUCHDB_PASSWORD: this.password,
30+
});
31+
return new StartedCouchDBContainer(await super.start(), this.username, this.password);
32+
}
33+
}
34+
35+
export class StartedCouchDBContainer extends AbstractStartedContainer {
36+
constructor(
37+
startedTestContainer: StartedTestContainer,
38+
private readonly username: string,
39+
private readonly password: string
40+
) {
41+
super(startedTestContainer);
42+
}
43+
44+
public getPort(): number {
45+
return this.getMappedPort(COUCHDB_PORT);
46+
}
47+
48+
public getUsername(): string {
49+
return this.username;
50+
}
51+
52+
public getPassword(): string {
53+
return this.password;
54+
}
55+
56+
public getUrl(): string {
57+
return `http://${this.username}:${this.password}@${this.getHost()}:${this.getPort()}`;
58+
}
59+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { CouchDBContainer, StartedCouchDBContainer } from "./couchdb-container";
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"exclude": [
4+
"build",
5+
"src/**/*.test.ts"
6+
],
7+
"references": [
8+
{
9+
"path": "../../testcontainers"
10+
}
11+
]
12+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"extends": "../../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"rootDir": "src",
5+
"outDir": "build",
6+
"paths": {
7+
"testcontainers": [
8+
"../../testcontainers/src"
9+
]
10+
}
11+
},
12+
"exclude": [
13+
"build"
14+
],
15+
"references": [
16+
{
17+
"path": "../../testcontainers"
18+
}
19+
]
20+
}

0 commit comments

Comments
 (0)