-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbooru.service.spec.ts
More file actions
167 lines (129 loc) · 5.66 KB
/
booru.service.spec.ts
File metadata and controls
167 lines (129 loc) · 5.66 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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import { Test, TestingModule } from '@nestjs/testing'
import { ConfigService } from '@nestjs/config'
import { BooruTypesStringEnum } from '@alejandroakbal/universal-booru-wrapper'
import * as UBW from '@alejandroakbal/universal-booru-wrapper'
import { BooruService } from './booru.service'
import { booruQueriesDTO } from './dto/booru-queries.dto'
import { BooruEndpointParamsDTO, SupportedBooruType } from './dto/request-booru.dto'
import { BooruAuthManagerService } from './services/booru-auth-manager.service'
describe('BooruService', () => {
let service: BooruService
let mockAuthManager: any
const mockConfigService = {
get: jest.fn()
}
const mockParams: BooruEndpointParamsDTO = {
booruType: BooruTypesStringEnum.GELBOORU_COM
}
const baseQueries: Partial<booruQueriesDTO> = {
baseEndpoint: 'https://gelbooru.com'
}
beforeEach(async () => {
mockAuthManager = {
getAvailableCredential: jest.fn()
}
const module: TestingModule = await Test.createTestingModule({
providers: [
BooruService,
{
provide: ConfigService,
useValue: mockConfigService
},
{
provide: BooruAuthManagerService,
useValue: mockAuthManager
}
]
}).compile()
service = module.get<BooruService>(BooruService)
jest.clearAllMocks()
})
describe('Authentication Resolution', () => {
it('should use query parameters when both auth_user and auth_pass are provided', () => {
const queries = {
...baseQueries,
auth_user: 'query_user',
auth_pass: 'query_pass'
} as booruQueriesDTO
const api = service.buildApiClass(mockParams, queries)
expect((api as any).options?.auth?.username).toBe('query_user')
expect((api as any).options?.auth?.apiKey).toBe('query_pass')
})
it('should fallback to environment variables when query parameters are missing or incomplete', () => {
mockAuthManager.getAvailableCredential.mockReturnValue({ user: 'env_user', password: 'env_pass' })
// Test with no query params
const queriesNoAuth = { ...baseQueries } as booruQueriesDTO
const apiNoAuth = service.buildApiClass(mockParams, queriesNoAuth)
expect(mockAuthManager.getAvailableCredential).toHaveBeenCalledWith('https://gelbooru.com')
expect((apiNoAuth as any).options?.auth?.username).toBe('env_user')
expect((apiNoAuth as any).options?.auth?.apiKey).toBe('env_pass')
// Test with partial query params (should still use env)
const queriesPartial = {
...baseQueries,
auth_user: 'partial_user' // Missing auth_pass
} as booruQueriesDTO
const apiPartial = service.buildApiClass(mockParams, queriesPartial)
expect((apiPartial as any).options?.auth?.username).toBe('env_user')
expect((apiPartial as any).options?.auth?.apiKey).toBe('env_pass')
})
it('should prioritize query parameters over environment variables', () => {
mockAuthManager.getAvailableCredential.mockReturnValue({ user: 'env_user', password: 'env_pass' })
const queries = {
...baseQueries,
auth_user: 'query_user',
auth_pass: 'query_pass'
} as booruQueriesDTO
const api = service.buildApiClass(mockParams, queries)
// Should use query credentials, not env credentials - auth manager should not be called
expect(mockAuthManager.getAvailableCredential).not.toHaveBeenCalled()
expect((api as any).options?.auth?.username).toBe('query_user')
expect((api as any).options?.auth?.apiKey).toBe('query_pass')
})
it('should create API without authentication when no credentials are available', () => {
mockAuthManager.getAvailableCredential.mockReturnValue(null)
const queries = { ...baseQueries } as booruQueriesDTO
const api = service.buildApiClass(mockParams, queries)
expect(mockAuthManager.getAvailableCredential).toHaveBeenCalledWith('https://gelbooru.com')
expect((api as any).options?.auth?.username).toBeUndefined()
expect((api as any).options?.auth?.apiKey).toBeUndefined()
})
it('should use auth manager for credential selection', () => {
mockAuthManager.getAvailableCredential.mockReturnValue({ user: 'managed_user', password: 'managed_pass' })
const queries = { ...baseQueries } as booruQueriesDTO
const api = service.buildApiClass(mockParams, queries)
expect(mockAuthManager.getAvailableCredential).toHaveBeenCalledWith('https://gelbooru.com')
expect((api as any).options?.auth?.username).toBe('managed_user')
expect((api as any).options?.auth?.apiKey).toBe('managed_pass')
})
})
describe('Booru type resolution', () => {
const queries = {
baseEndpoint: 'kemono.cr'
} as booruQueriesDTO
afterEach(() => {
if ((UBW as any).Kemono !== originalKemonoClass) {
;(UBW as any).Kemono = originalKemonoClass
}
})
const originalKemonoClass = (UBW as any).Kemono
it('should resolve kemono when the wrapper exports it', () => {
if (!originalKemonoClass) {
return
}
const params: BooruEndpointParamsDTO = {
booruType: 'kemono' as SupportedBooruType
}
const api = service.buildApiClass(params, queries)
expect(api).toBeInstanceOf(originalKemonoClass)
})
it('should fail clearly when the wrapper does not export kemono', () => {
;(UBW as any).Kemono = undefined
const params: BooruEndpointParamsDTO = {
booruType: 'kemono' as SupportedBooruType
}
expect(() => service.buildApiClass(params, queries)).toThrow(
'Kemono booru type requires @alejandroakbal/universal-booru-wrapper version that exports Kemono'
)
})
})
})