Skip to content

Commit

Permalink
setup all tests
Browse files Browse the repository at this point in the history
  • Loading branch information
maticzav committed Jun 10, 2023
1 parent 690fcaa commit 4bee8cd
Show file tree
Hide file tree
Showing 9 changed files with 314 additions and 108 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ jobs:
with:
version: 8.1.0

- name: Build Redis
uses: docker/build-push-action@v2
with:
context: .
file: ./docker/redis/Dockerfile
load: true
tags: my-redis:latest

- name: Run Redis
run: |
docker run -d --name redis -p 6379:6379 --env REDIS_PASSWORD=redis my-redis:latest
- name: Setup Node Environment
uses: actions/setup-node@v3
with:
Expand All @@ -35,5 +47,10 @@ jobs:
- name: Build Packages
run: pnpm run build

- name: Wait for Redis
uses: jakejarvis/wait-action@master
with:
time: '30s'

- name: Test Packages and Template
run: pnpm run test
2 changes: 1 addition & 1 deletion jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const config: Config = {
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
testRegex: '(/tests/.*|(\\.|/)test)\\.tsx?$',
testRegex: '/tests/.*\\.test\\.tsx?$',
testPathIgnorePatterns: ['/node_modules/', '/__fixtures__/', '/dist/'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
}
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
{
"name": "authsessions",
"version": "0.0.1",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"track": "changeset add",
"version": "changeset version",
Expand Down
154 changes: 154 additions & 0 deletions redis.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { RedisClientType, createClient } from 'redis'

import { RedisSessions } from '../../src/stores/redis'
import { SessionUtils } from '../../src/utils'
import { filter } from '../utils'

// RedisSessions (best for production environment).
const redis: RedisClientType = createClient({
socket: {
host: 'localhost',
port: 6379,
},
password: 'redis',
})

describe('reids', () => {
test('correctly finds user from a given session id', async () => {
const sessions = new RedisSessions<string, {}>({ redis })

const validSessionId = await sessions.createSession({
userId: 'user-id',
label: 'test',
meta: {},
})

await expect(sessions.getUserIdFromSession(validSessionId)).resolves.not.toBeNull()

const invalidSessionId = SessionUtils.toSessionId('invalid-session-id')

await expect(sessions.getUserIdFromSession(invalidSessionId)).resolves.toBeNull()
})

test('correctly parses userId from a given session id', async () => {
const sessions = new RedisSessions<string, {}>({ redis })

const userId = 'user-id'
const sessionId = await sessions.createSession({
userId,
label: 'test',
meta: {},
})

await expect(sessions.getUserIdFromSession(sessionId)).resolves.toEqual(userId)
})

test('correctly parses meta from a given session id', async () => {
// NOTE: We want to test all serializable types here.

const sessions = new RedisSessions<
string,
{
string: string
number: number
boolean: boolean
array: string[]
object: { [key: string]: string }
}
>({ redis })

const meta = {
string: 'string',
number: 1,
boolean: true,
array: ['string', 'string'],
object: {
string: 'string',
},
}

const sessionId = await sessions.createSession({
userId: 'user-id',
label: 'test',
meta,
})

await expect(sessions.getSessionMeta(sessionId)).resolves.toEqual(meta)
})

test('correctly destroys a session', async () => {
const sessions = new RedisSessions<string, {}>({ redis })

const sessionId = await sessions.createSession({
userId: 'user-id',
label: 'test',
meta: {},
})

await sessions.destroySession(sessionId)

await expect(sessions.getUserIdFromSession(sessionId)).resolves.toBeNull()
})

test('correctly lists all sessions', async () => {
const sessions = new RedisSessions<string, {}>({ redis })

await sessions.createSession({ userId: 'user-id', label: '#1', meta: {} })
await sessions.createSession({ userId: 'user-id', label: '#2', meta: {} })
await sessions.createSession({ userId: 'user-id', label: '#3', meta: {} })

await expect(
// We filter out random values and dates.
sessions.listSessions().then((r) => r.map((o) => filter(o, ['label', 'userId']))),
).resolves.toMatchInlineSnapshot(`
[
{
"label": "#1",
"userId": "user-id",
},
{
"label": "#2",
"userId": "user-id",
},
{
"label": "#3",
"userId": "user-id",
},
]
`)
})

test('correclty lists sessions for a given user', async () => {
const sessions = new RedisSessions<string, {}>({ redis })

const userId = 'user-id'

await sessions.createSession({ userId, label: '#1', meta: {} })
await sessions.createSession({ userId, label: '#2', meta: {} })
await sessions.createSession({ userId, label: '#3', meta: {} })

const otherUserId = 'other-user-id'
await sessions.createSession({ userId: otherUserId, label: '#1', meta: {} })
await sessions.createSession({ userId: otherUserId, label: '#2', meta: {} })

await expect(
// We filter out random values and dates.
sessions.getSessionsForUser(userId).then((r) => r.map((o) => filter(o, ['label', 'userId']))),
).resolves.toMatchInlineSnapshot(`
[
{
"label": "#1",
"userId": "user-id",
},
{
"label": "#2",
"userId": "user-id",
},
{
"label": "#3",
"userId": "user-id",
},
]
`)
})
})
5 changes: 3 additions & 2 deletions src/stores/inmemory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,12 @@ export class InMemorySessions<UserId = string, Meta = {}> implements ISessions<U
}
})

return sessions
return sessions.sort((a, b) => (a.lastUsedAt < b.lastUsedAt ? 1 : -1))
}

public async listSessions(): Promise<Session<UserId, Meta>[]> {
return Array.from(this.sessions.values())
// NOTE: The last accessed session needs to be at the top of the list.
return Array.from(this.sessions.values()).sort((a, b) => (a.lastUsedAt < b.lastUsedAt ? 1 : -1))
}

private getSessionId(): SessionId {
Expand Down
2 changes: 1 addition & 1 deletion src/stores/redis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export class RedisSessions<UserId extends string = string, Meta = {}> implements
})
}

return sessions
return sessions.sort((a, b) => b.lastUsedAt.toMillis() - a.lastUsedAt.toMillis())
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export interface ISessions<UserId, Meta = {}> {
destroySession(session: SessionId): Promise<void>

/**
* Lists all sessions in the system.
* Lists all sessions in the system starting with the least recently accessed one.
*/
listSessions(): Promise<Session<UserId, Meta>[]>
}
Loading

0 comments on commit 4bee8cd

Please sign in to comment.