|
18 | 18 | /* eslint-disable sonarjs/no-nested-functions */ |
19 | 19 |
|
20 | 20 | import type { ExtensionContext } from '@podman-desktop/api'; |
21 | | -import { authentication } from '@podman-desktop/api'; |
| 21 | +import { authentication, window } from '@podman-desktop/api'; |
22 | 22 | import type { BaseClient, TokenSet } from 'openid-client'; |
23 | 23 | import { Issuer } from 'openid-client'; |
24 | 24 | import { beforeEach, expect, test, vi } from 'vitest'; |
@@ -110,3 +110,100 @@ test('Authentication service loads tokens form secret storage during initializat |
110 | 110 | expect(extensionContext.secrets.get).toHaveBeenCalledOnce(); |
111 | 111 | expect((await service.getSessions(['scope1', 'scope3', 'scope4'])).length).toBe(0); |
112 | 112 | }); |
| 113 | + |
| 114 | +test('Authentication service handles decryption errors gracefully', async () => { |
| 115 | + const decryptionError = new Error('Error while decrypting the ciphertext provided to safeStorage.decryptString'); |
| 116 | + |
| 117 | + vi.mocked(window.showWarningMessage).mockResolvedValue('OK'); |
| 118 | + |
| 119 | + const onDidChangeCallback = vi.fn(); |
| 120 | + const extensionContext: ExtensionContext = { |
| 121 | + secrets: { |
| 122 | + get: vi.fn().mockRejectedValue(decryptionError), |
| 123 | + store: vi.fn(), |
| 124 | + delete: vi.fn().mockResolvedValue(undefined), |
| 125 | + onDidChange: onDidChangeCallback, |
| 126 | + }, |
| 127 | + subscriptions: [], |
| 128 | + } as unknown as ExtensionContext; |
| 129 | + |
| 130 | + const service = await RedHatAuthenticationService.build(extensionContext, getAuthConfig()); |
| 131 | + await service.initialize(); |
| 132 | + |
| 133 | + // Verify secrets.get was called |
| 134 | + expect(extensionContext.secrets.get).toHaveBeenCalledOnce(); |
| 135 | + |
| 136 | + // Verify warning message was shown to user |
| 137 | + expect(window.showWarningMessage).toHaveBeenCalledWith( |
| 138 | + expect.stringContaining('could not be restored'), |
| 139 | + 'OK', |
| 140 | + ); |
| 141 | + |
| 142 | + // Verify corrupted data was deleted |
| 143 | + expect(extensionContext.secrets.delete).toHaveBeenCalledOnce(); |
| 144 | + |
| 145 | + // Verify onDidChange listener was still registered |
| 146 | + expect(onDidChangeCallback).toHaveBeenCalledOnce(); |
| 147 | + |
| 148 | + // Verify no sessions exist after error |
| 149 | + expect((await service.getSessions()).length).toBe(0); |
| 150 | +}); |
| 151 | + |
| 152 | +test('Authentication service registers onDidChange listener even when no stored data exists', async () => { |
| 153 | + const onDidChangeCallback = vi.fn(); |
| 154 | + const extensionContext: ExtensionContext = { |
| 155 | + secrets: { |
| 156 | + get: vi.fn().mockResolvedValue(undefined), |
| 157 | + store: vi.fn(), |
| 158 | + delete: vi.fn(), |
| 159 | + onDidChange: onDidChangeCallback, |
| 160 | + }, |
| 161 | + subscriptions: [], |
| 162 | + } as unknown as ExtensionContext; |
| 163 | + |
| 164 | + const service = await RedHatAuthenticationService.build(extensionContext, getAuthConfig()); |
| 165 | + await service.initialize(); |
| 166 | + |
| 167 | + // Verify secrets.get was called |
| 168 | + expect(extensionContext.secrets.get).toHaveBeenCalledOnce(); |
| 169 | + |
| 170 | + // Verify onDidChange listener was registered even with no stored data |
| 171 | + expect(onDidChangeCallback).toHaveBeenCalledOnce(); |
| 172 | + |
| 173 | + // Verify no sessions exist |
| 174 | + expect((await service.getSessions()).length).toBe(0); |
| 175 | +}); |
| 176 | + |
| 177 | +test('Authentication service handles delete error during decryption error recovery', async () => { |
| 178 | + const decryptionError = new Error('Error while decrypting the ciphertext'); |
| 179 | + const deleteError = new Error('Failed to delete'); |
| 180 | + |
| 181 | + // Clear mock from previous tests |
| 182 | + vi.mocked(window.showWarningMessage).mockClear(); |
| 183 | + vi.mocked(window.showWarningMessage).mockResolvedValue('OK'); |
| 184 | + |
| 185 | + const onDidChangeCallback = vi.fn(); |
| 186 | + const extensionContext: ExtensionContext = { |
| 187 | + secrets: { |
| 188 | + get: vi.fn().mockRejectedValue(decryptionError), |
| 189 | + store: vi.fn(), |
| 190 | + delete: vi.fn().mockRejectedValue(deleteError), |
| 191 | + onDidChange: onDidChangeCallback, |
| 192 | + }, |
| 193 | + subscriptions: [], |
| 194 | + } as unknown as ExtensionContext; |
| 195 | + |
| 196 | + const service = await RedHatAuthenticationService.build(extensionContext, getAuthConfig()); |
| 197 | + |
| 198 | + // Should not throw even if delete fails |
| 199 | + await expect(service.initialize()).resolves.not.toThrow(); |
| 200 | + |
| 201 | + // Verify warning was still shown |
| 202 | + expect(window.showWarningMessage).toHaveBeenCalledOnce(); |
| 203 | + |
| 204 | + // Verify delete was attempted |
| 205 | + expect(extensionContext.secrets.delete).toHaveBeenCalledOnce(); |
| 206 | + |
| 207 | + // Verify onDidChange listener was still registered |
| 208 | + expect(onDidChangeCallback).toHaveBeenCalledOnce(); |
| 209 | +}); |
0 commit comments