Skip to content

Commit f150058

Browse files
authored
Add Redis module (#642)
1 parent 916b02f commit f150058

File tree

13 files changed

+464
-0
lines changed

13 files changed

+464
-0
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ jobs:
9090
- nats
9191
- neo4j
9292
- postgresql
93+
- redis
9394
- selenium
9495
uses: ./.github/workflows/test-template.yml
9596
with:

docs/modules/redis.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Redis Module
2+
3+
[Redis](https://redis.io/) The open source, in-memory data store used by millions of developers as a database, cache, streaming engine, and message broker.
4+
5+
## Install
6+
7+
```bash
8+
npm install @testcontainers/redis --save-dev
9+
```
10+
11+
## Examples
12+
13+
<!--codeinclude-->
14+
[Start container:](../../packages/modules/redis/src/redis-container.test.ts) inside_block:startContainer
15+
<!--/codeinclude-->
16+
17+
<!--codeinclude-->
18+
[Connect redis client to container:](../../packages/modules/redis/src/redis-container.test.ts) inside_block:simpleConnect
19+
<!--/codeinclude-->
20+
21+
<!--codeinclude-->
22+
[Start container with password authentication:](../../packages/modules/redis/src/redis-container.test.ts) inside_block:startWithCredentials
23+
<!--/codeinclude-->
24+
25+
<!--codeinclude-->
26+
[Define volume for persistent/predefined data:](../../packages/modules/redis/src/redis-container.test.ts) inside_block:persistentData
27+
<!--/codeinclude-->
28+
29+
<!--codeinclude-->
30+
[Execute a command inside the container:](../../packages/modules/redis/src/redis-container.test.ts) inside_block:executeCommand
31+
<!--/codeinclude-->

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,5 @@ nav:
5252
- Neo4J: modules/neo4j.md
5353
- PostgreSQL: modules/postgresql.md
5454
- Selenium: modules/selenium.md
55+
- Redis: modules/redis.md
5556
- Configuration: configuration.md

package-lock.json

Lines changed: 123 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { Config } from "jest";
2+
import * as path from "path";
3+
4+
const config: Config = {
5+
preset: "ts-jest",
6+
moduleNameMapper: {
7+
"^testcontainers$": path.resolve(__dirname, "../../testcontainers/src"),
8+
},
9+
};
10+
11+
export default config;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "@testcontainers/redis",
3+
"version": "10.2.1",
4+
"license": "MIT",
5+
"keywords": [
6+
"redis",
7+
"testing",
8+
"docker",
9+
"testcontainers"
10+
],
11+
"description": "Redis module for Testcontainers",
12+
"homepage": "https://github.com/testcontainers/testcontainers-node#readme",
13+
"repository": {
14+
"type": "git",
15+
"url": "https://github.com/testcontainers/testcontainers-node"
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+
"devDependencies": {
32+
"@types/redis": "^4.0.11",
33+
"redis": "^4.6.7"
34+
},
35+
"dependencies": {
36+
"testcontainers": "^10.2.1"
37+
}
38+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/env bash
2+
set -e
3+
redis-cli $([[ -n "$1" ]] && echo "-a $1") < "/tmp/import.redis"
4+
echo "Imported"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { RedisContainer, StartedRedisContainer } from "./redis-container";
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
SET "user:001" '{"first_name":"John","last_name":"Doe","dob":"12-JUN-1970"}'
2+
SET "user:002" '{"first_name":"David","last_name":"Bloom","dob":"03-MAR-1981"}'
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { createClient } from "redis";
2+
import { RedisContainer, StartedRedisContainer } from "./redis-container";
3+
import * as os from "os";
4+
import * as path from "path";
5+
import * as fs from "fs";
6+
7+
describe("RedisContainer", () => {
8+
jest.setTimeout(240_000);
9+
10+
// startContainer {
11+
it("should connect and execute set-get", async () => {
12+
const container = await new RedisContainer().start();
13+
14+
const client = await connectTo(container);
15+
16+
await client.set("key", "val");
17+
expect(await client.get("key")).toBe("val");
18+
19+
await client.disconnect();
20+
await container.stop();
21+
});
22+
// }
23+
24+
it("should connect with password and execute set-get", async () => {
25+
const container = await new RedisContainer().withPassword("test").start();
26+
27+
const client = await connectTo(container);
28+
29+
await client.set("key", "val");
30+
expect(await client.get("key")).toBe("val");
31+
32+
await client.disconnect();
33+
await container.stop();
34+
});
35+
36+
// persistentData {
37+
it("should reconnect with volume and persistence data", async () => {
38+
const sourcePath = fs.mkdtempSync(path.join(os.tmpdir(), "redis-"));
39+
const container = await new RedisContainer().withPassword("test").withPersistence(sourcePath).start();
40+
let client = await connectTo(container);
41+
42+
await client.set("key", "val");
43+
await client.disconnect();
44+
await container.restart();
45+
client = await connectTo(container);
46+
expect(await client.get("key")).toBe("val");
47+
48+
await client.disconnect();
49+
await container.stop();
50+
try {
51+
fs.rmSync(sourcePath, { force: true, recursive: true });
52+
} catch (e) {
53+
//Ignore clean up, when have no access on fs.
54+
console.log(e);
55+
}
56+
});
57+
// }
58+
59+
// initial data import {
60+
it("should load initial data and can read it", async () => {
61+
const container = await new RedisContainer()
62+
.withPassword("test")
63+
.withInitialData(path.join(__dirname, "initData.redis"))
64+
.start();
65+
const client = await connectTo(container);
66+
const user = {
67+
first_name: "David",
68+
last_name: "Bloom",
69+
dob: "03-MAR-1981",
70+
};
71+
expect(await client.get("user:002")).toBe(JSON.stringify(user));
72+
73+
await client.disconnect();
74+
await container.stop();
75+
});
76+
// }
77+
78+
// startWithCredentials {
79+
it("should start with credentials and login", async () => {
80+
const password = "testPassword";
81+
82+
// Test authentication
83+
const container = await new RedisContainer().withPassword(password).start();
84+
expect(container.getConnectionUrl()).toEqual(`redis://:${password}@${container.getHost()}:${container.getPort()}`);
85+
86+
const client = await connectTo(container);
87+
88+
await client.set("key", "val");
89+
expect(await client.get("key")).toBe("val");
90+
91+
await client.disconnect();
92+
await container.stop();
93+
});
94+
// }
95+
96+
// executeCommand {
97+
it("should execute container cmd and return the result", async () => {
98+
const container = await new RedisContainer().start();
99+
100+
const queryResult = await container.executeCliCmd("info", ["clients"]);
101+
expect(queryResult).toEqual(expect.stringContaining("connected_clients:1"));
102+
103+
await container.stop();
104+
});
105+
// }
106+
107+
// simpleConnect {
108+
async function connectTo(container: StartedRedisContainer) {
109+
const client = createClient({
110+
url: container.getConnectionUrl(),
111+
});
112+
await client.connect();
113+
expect(client.isOpen).toBeTruthy();
114+
return client;
115+
}
116+
// }
117+
});

0 commit comments

Comments
 (0)