@sailshq/connect-redis
Version:
Redis session store for your Sails app.
178 lines (142 loc) • 4.97 kB
JavaScript
const test = require("blue-tape")
const redisSrv = require("../test/redis-server")
const session = require("express-session")
const redisV3 = require("redis-v3")
const redisV4 = require("redis-v4")
const ioRedis = require("ioredis")
const redisMock = require("redis-mock")
let RedisStore = require("../")(session)
let p =
(ctx, method) =>
(...args) =>
new Promise((resolve, reject) => {
ctx[method](...args, (err, d) => {
if (err) reject(err)
resolve(d)
})
})
test("setup", redisSrv.connect)
test("defaults", async (t) => {
t.throws(() => new RedisStore(), "client is required")
var client = redisV3.createClient(redisSrv.port, "localhost")
var store = new RedisStore({ client })
t.equal(store.client, client, "stores client")
t.equal(store.prefix, "sess:", "defaults to sess:")
t.equal(store.ttl, 86400, "defaults to one day")
t.equal(store.scanCount, 100, "defaults SCAN count to 100")
t.equal(store.serializer, JSON, "defaults to JSON serialization")
t.equal(store.disableTouch, false, "defaults to having `touch` enabled")
t.equal(store.disableTTL, false, "defaults to having `ttl` enabled")
client.end(false)
})
test("node_redis v3", async (t) => {
var client = redisV3.createClient(redisSrv.port, "localhost")
var store = new RedisStore({ client })
await lifecycleTest(store, t)
client.end(false)
})
test("node_redis v4", async (t) => {
var client = redisV4.createClient({
url: `redis://localhost:${redisSrv.port}`,
legacyMode: true,
})
await client.connect()
var store = new RedisStore({ client })
await lifecycleTest(store, t)
await client.disconnect()
})
test("ioredis", async (t) => {
var client = ioRedis.createClient(redisSrv.port, "localhost")
var store = new RedisStore({ client })
await lifecycleTest(store, t)
client.disconnect()
})
test("redis-mock client", async (t) => {
var client = redisMock.createClient()
var store = new RedisStore({ client })
await lifecycleTest(store, t)
})
test("teardown", redisSrv.disconnect)
async function lifecycleTest(store, t) {
let res = await p(store, "set")("123", { foo: "bar" })
t.equal(res, "OK", "set value")
res = await p(store, "get")("123")
t.same(res, { foo: "bar" }, "get value")
res = await p(store.client, "ttl")("sess:123")
t.ok(res >= 86399, "check one day ttl")
let ttl = 60
let expires = new Date(Date.now() + ttl * 1000).toISOString()
res = await p(store, "set")("456", { cookie: { expires } })
t.equal(res, "OK", "set cookie expires")
res = await p(store.client, "ttl")("sess:456")
t.ok(res <= 60, "check expires ttl")
ttl = 90
let newExpires = new Date(Date.now() + ttl * 1000).toISOString()
// note: cookie.expires will not be updated on redis (see https://github.com/tj/connect-redis/pull/285)
res = await p(store, "touch")("456", { cookie: { expires: newExpires } })
t.equal(res, "OK", "set cookie expires touch")
res = await p(store.client, "ttl")("sess:456")
t.ok(res > 60, "check expires ttl touch")
res = await p(store, "length")()
t.equal(res, 2, "stored two keys length")
res = await p(store, "ids")()
res.sort()
t.same(res, ["123", "456"], "stored two keys ids")
res = await p(store, "all")()
res.sort((a, b) => (a.id > b.id ? 1 : -1))
t.same(
res,
[
{ id: "123", foo: "bar" },
{ id: "456", cookie: { expires } },
],
"stored two keys data"
)
res = await p(store, "destroy")("456")
t.equal(res, 1, "destroyed one")
res = await p(store, "length")()
t.equal(res, 1, "one key remains")
res = await p(store, "clear")()
t.equal(res, 1, "cleared remaining key")
res = await p(store, "length")()
t.equal(res, 0, "no key remains")
let count = 1000
await load(store, count)
res = await p(store, "length")()
t.equal(res, count, "bulk count")
res = await p(store, "clear")()
t.equal(res, count, "bulk clear")
expires = new Date(Date.now() + ttl * 1000).toISOString() // expires in the future
res = await p(store, "set")("789", { cookie: { expires } })
t.equal(res, "OK", "set value")
res = await p(store, "length")()
t.equal(res, 1, "one key exists (session 789)")
expires = new Date(Date.now() - ttl * 1000).toISOString() // expires in the past
res = await p(store, "set")("789", { cookie: { expires } })
t.equal(res, 1, "returns 1 because destroy was invoked")
res = await p(store, "length")()
t.equal(res, 0, "no key remains and that includes session 789")
}
function load(store, count) {
return new Promise((resolve, reject) => {
let set = (sid) => {
store.set(
"s" + sid,
{
cookie: { expires: new Date(Date.now() + 1000) },
data: "some data",
},
(err) => {
if (err) {
return reject(err)
}
if (sid === count) {
return resolve()
}
set(sid + 1)
}
)
}
set(1)
})
}