forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauthStore.test.ts
More file actions
103 lines (88 loc) · 3.48 KB
/
Copy pathauthStore.test.ts
File metadata and controls
103 lines (88 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { describe, it, expect, beforeEach, afterAll, vi } from 'vitest'
import { mkdtempSync, rmSync, existsSync, readFileSync } from 'fs'
import { tmpdir } from 'os'
import { join } from 'path'
const dir = mkdtempSync(join(tmpdir(), 'auth-store-test-'))
// Mock Electron: a temp userData dir plus an identity-ish safeStorage so the
// encrypt→base64→decrypt round-trip is exercised without real DPAPI. ipcMain and
// webContents are stubbed so the module imports (registerAuthStoreHandlers pulls
// them in), even though these tests only exercise the store class directly.
vi.mock('electron', () => ({
app: { getPath: (): string => dir },
ipcMain: { handle: (): void => {} },
webContents: { getAllWebContents: (): unknown[] => [] },
safeStorage: {
isEncryptionAvailable: (): boolean => true,
encryptString: (s: string): Buffer => Buffer.from(s, 'utf8'),
decryptString: (b: Buffer): string => b.toString('utf8')
}
}))
import { safeStorage } from 'electron'
import { AuthTokenStore } from './authStore'
afterAll(() => rmSync(dir, { recursive: true, force: true }))
let store: AuthTokenStore
let filePath: string
beforeEach(() => {
filePath = join(dir, `auth-${Math.random().toString(36).slice(2)}.json`)
store = new AuthTokenStore(filePath)
})
const KEY = 'firebase:authUser:AIzaTest:[DEFAULT]'
const VALUE = JSON.stringify({ uid: 'u1', stsTokenManager: { accessToken: 'id-tok' } })
describe('AuthTokenStore', () => {
it('set → get round-trips a value under a namespaced firebase key', () => {
store.set(KEY, VALUE)
expect(store.get(KEY)).toBe(VALUE)
expect(store.get('firebase:authUser:other')).toBeNull()
})
it('get returns null when the file is missing', () => {
expect(store.get(KEY)).toBeNull()
expect(existsSync(filePath)).toBe(false)
})
it('set persists ciphertext, not plaintext, on disk', () => {
store.set(KEY, VALUE)
const raw = readFileSync(filePath, 'utf8')
// The base64-of-"utf8-bytes" fake still must not contain the raw token text.
expect(raw).not.toContain('id-tok')
expect(raw).not.toContain('accessToken')
})
it('remove clears one entry and deletes the file when it empties', () => {
store.set(KEY, VALUE)
expect(existsSync(filePath)).toBe(true)
store.remove(KEY)
expect(store.get(KEY)).toBeNull()
expect(existsSync(filePath)).toBe(false)
})
it('remove leaves other entries intact', () => {
store.set(KEY, VALUE)
store.set('firebase:authUser:second', 'v2')
store.remove(KEY)
expect(store.get(KEY)).toBeNull()
expect(store.get('firebase:authUser:second')).toBe('v2')
expect(existsSync(filePath)).toBe(true)
})
it('set throws and get returns null when encryption is unavailable', () => {
store.set(KEY, VALUE)
const spy = vi.spyOn(safeStorage, 'isEncryptionAvailable').mockReturnValue(false)
try {
expect(() => store.set('firebase:authUser:x', 'v')).toThrow('Secure storage is unavailable')
expect(store.get(KEY)).toBeNull()
} finally {
spy.mockRestore()
}
})
it('isAvailable reflects safeStorage', () => {
expect(store.isAvailable()).toBe(true)
const spy = vi.spyOn(safeStorage, 'isEncryptionAvailable').mockReturnValue(false)
try {
expect(store.isAvailable()).toBe(false)
} finally {
spy.mockRestore()
}
})
it('defaults the file path to userData when constructed with no args', () => {
const dflt = new AuthTokenStore()
dflt.set(KEY, VALUE)
expect(dflt.get(KEY)).toBe(VALUE)
dflt.remove(KEY)
})
})