152 lines
3.6 KiB
TypeScript
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)
|
|
})
|
|
})
|
|
|
|
})
|