mirror your GitHub repos to tangled.org automatically
1import { afterEach, beforeEach, describe, expect, it } from 'vitest'
2import { readAccounts, sessionConfig } from '../../server/utils/server-session'
3
4const ORIGINAL_PASSWORD = process.env.NUXT_SESSION_PASSWORD
5const ORIGINAL_PUBLIC_URL = process.env.NUXT_PUBLIC_URL
6
7describe('server-session: sessionConfig', () => {
8 beforeEach(() => {
9 process.env.NUXT_SESSION_PASSWORD = 'a'.repeat(32)
10 process.env.NUXT_PUBLIC_URL = 'http://127.0.0.1:3000'
11 })
12
13 afterEach(() => {
14 if (ORIGINAL_PASSWORD === undefined) delete process.env.NUXT_SESSION_PASSWORD
15 else process.env.NUXT_SESSION_PASSWORD = ORIGINAL_PASSWORD
16 if (ORIGINAL_PUBLIC_URL === undefined) delete process.env.NUXT_PUBLIC_URL
17 else process.env.NUXT_PUBLIC_URL = ORIGINAL_PUBLIC_URL
18 })
19
20 it('throws if NUXT_SESSION_PASSWORD is missing', () => {
21 delete process.env.NUXT_SESSION_PASSWORD
22 expect(() => sessionConfig()).toThrow(/NUXT_SESSION_PASSWORD/)
23 })
24
25 it('throws if NUXT_SESSION_PASSWORD is too short', () => {
26 process.env.NUXT_SESSION_PASSWORD = 'short'
27 expect(() => sessionConfig()).toThrow(/32\+ characters/)
28 })
29
30 it('marks the cookie non-secure on 127.0.0.1 loopback dev', () => {
31 process.env.NUXT_PUBLIC_URL = 'http://127.0.0.1:3000'
32 const config = sessionConfig()
33 expect(config.cookie).toMatchObject({ secure: false, sameSite: 'lax', httpOnly: true, path: '/' })
34 expect(config.name).toBe('synchub-session')
35 expect(config.maxAge).toBe(60 * 60 * 24 * 30)
36 })
37
38 it('marks the cookie non-secure on localhost loopback dev', () => {
39 process.env.NUXT_PUBLIC_URL = 'http://localhost:3000'
40 const config = sessionConfig()
41 expect(config.cookie).toMatchObject({ secure: false })
42 })
43
44 it('marks the cookie secure when the deploy URL is not loopback', () => {
45 process.env.NUXT_PUBLIC_URL = 'https://synchub.to'
46 const config = sessionConfig()
47 expect(config.cookie).toMatchObject({ secure: true })
48 })
49})
50
51describe('server-session: readAccounts', () => {
52 const acct = (did: string, installationId: number) => ({ did, installationId })
53
54 it('returns null for empty or malformed cookie data', () => {
55 expect(readAccounts({})).toBeNull()
56 expect(readAccounts({ active: 'did:plc:1', accounts: [] })).toBeNull()
57 expect(readAccounts({ active: 'did:plc:1' })).toBeNull()
58 // eslint-disable-next-line ts/no-unsafe-type-assertion
59 expect(readAccounts({ active: 'did:plc:1', accounts: 'nope' as unknown as [] })).toBeNull()
60 })
61
62 it('keeps the active did when it names a present account', () => {
63 const result = readAccounts({ active: 'did:plc:2', accounts: [acct('did:plc:1', 1), acct('did:plc:2', 2)] })
64 expect(result).toEqual({ active: 'did:plc:2', accounts: [acct('did:plc:1', 1), acct('did:plc:2', 2)] })
65 })
66
67 it('falls back active to the first account when active is stale', () => {
68 const result = readAccounts({ active: 'did:plc:gone', accounts: [acct('did:plc:1', 1), acct('did:plc:2', 2)] })
69 expect(result?.active).toBe('did:plc:1')
70 })
71
72 it('drops malformed account entries', () => {
73 const accounts = [
74 acct('did:plc:1', 1),
75 // eslint-disable-next-line ts/no-unsafe-type-assertion
76 { did: 'did:plc:2' } as unknown as { did: string, installationId: number },
77 // eslint-disable-next-line ts/no-unsafe-type-assertion
78 { installationId: 3 } as unknown as { did: string, installationId: number },
79 ]
80 const result = readAccounts({ active: 'did:plc:1', accounts })
81 expect(result?.accounts).toEqual([acct('did:plc:1', 1)])
82 })
83})