rondo-framework/packages/server/src/session/SessionStore.test.ts

152 lines
3.6 KiB
TypeScript

import loggerFactory from '@rondo.dev/logger'
import express, { Application } from 'express'
import ExpressSession from 'express-session'
import request from 'supertest'
import { Column, Connection, createConnection, Entity, Index, PrimaryColumn, Repository } from 'typeorm'
import { DefaultSession } from './DefaultSession'
import { SessionStore } from './SessionStore'
@Entity()
class SessionEntity implements DefaultSession {
@PrimaryColumn()
id!: string
@Column()
json!: string
@Column()
extraData!: string
@Column()
@Index()
expiredAt: number = Date.now()
}
describe('SessionStore', () => {
let connection!: Connection
let repository!: Repository<SessionEntity>
beforeEach(async () => {
connection = await createConnection({
type: 'sqlite',
database: ':memory:',
entities: [SessionEntity],
synchronize: true,
})
repository = connection.getRepository(SessionEntity)
})
afterEach(() => connection!.close())
function createApp(maxAge = 10) {
const app = express()
app.use(ExpressSession({
saveUninitialized: false,
secret: 'test',
resave: false,
rolling: true,
cookie: {
maxAge: 10,
},
store: new SessionStore({
logger: loggerFactory.getLogger('api'),
cleanupDelay: 60 * 1000,
getRepository: () => repository,
ttl: 1,
buildSession: (sd, s) => ({...s, extraData: 'test'}),
}),
}))
app.post('/session/:param',
(req, res, next) => {
req.session!.param = req.params.param
req.session!.save(next)
},
(req, res) => res.json({
param: req.session!.param,
}),
)
app.get('/session', (req, res) => res.json({
param: req.session!.param,
}))
app.delete('/session',
(req, res, next) => req.session!.destroy(next),
(req, res) => res.end(),
)
return app
}
async function saveSession(app: Application) {
return await request(app)
.post('/session/value')
.expect(200)
}
function getSession(app: Application, cookie = '') {
return request(app)
.get('/session')
.set('cookie', cookie)
.expect(200)
}
describe('save session', () => {
it('saves a session to the database', async () => {
const app = createApp()
const response = await saveSession(app)
const param = response.body.param
expect(param).toEqual('value')
const result = await repository.findOne(response.body.sid)
expect(result).toBeTruthy()
const payload = JSON.parse(result!.json)
expect(payload.param).toEqual('value')
})
})
describe('retrieve session', () => {
it('retrieves a saved session via cookie', async () => {
const app = createApp()
const response = await saveSession(app)
const cookie = response.header['set-cookie']
expect(cookie).toBeTruthy()
await getSession(app)
.expect('{}')
await getSession(app, cookie)
.expect('{"param":"value"}')
})
})
describe('destroy session', () => {
it('destroys a saved session', async () => {
const app = createApp()
const response = await saveSession(app)
const cookie = response.header['set-cookie']
expect(cookie).toBeTruthy()
await request(app)
.delete('/session')
.set('cookie', cookie)
await getSession(app, cookie)
.expect('{}')
})
})
describe('error handling', () => {
it('handles errors', async () => {
(repository as any).save = () => Promise.reject(new Error('test'))
const app = createApp()
return await request(app)
.post('/session/value')
.expect(500)
})
})
})