|
1 | 1 | import {statusService} from '../src/app/status'; |
2 | 2 | import {SdkStatus} from '../src/models/models'; |
| 3 | +import {asperaSdk} from '../src/index'; |
3 | 4 |
|
4 | 5 | describe('StatusService', () => { |
5 | 6 | afterEach(() => { |
6 | 7 | statusService.reset(); |
| 8 | + asperaSdk.globals.httpGatewayVerified = false; |
| 9 | + asperaSdk.globals.asperaAppVerified = false; |
7 | 10 | jest.useRealTimers(); |
8 | 11 | }); |
9 | 12 |
|
@@ -47,6 +50,69 @@ describe('StatusService', () => { |
47 | 50 |
|
48 | 51 | expect(cb).toHaveBeenCalledWith('DISCONNECTED'); |
49 | 52 | }); |
| 53 | + |
| 54 | + test('remaps DISCONNECTED to DEGRADED when HTTP Gateway is ready', () => { |
| 55 | + asperaSdk.globals.httpGatewayVerified = true; |
| 56 | + statusService.setStatus('RUNNING'); |
| 57 | + |
| 58 | + statusService.setStatus('DISCONNECTED'); |
| 59 | + |
| 60 | + expect(statusService.getStatus()).toBe('DEGRADED'); |
| 61 | + }); |
| 62 | + |
| 63 | + test('keeps DISCONNECTED when HTTP Gateway is not ready', () => { |
| 64 | + statusService.setStatus('RUNNING'); |
| 65 | + |
| 66 | + statusService.setStatus('DISCONNECTED'); |
| 67 | + |
| 68 | + expect(statusService.getStatus()).toBe('DISCONNECTED'); |
| 69 | + }); |
| 70 | + |
| 71 | + test('resets asperaAppVerified on DISCONNECTED', () => { |
| 72 | + asperaSdk.globals.asperaAppVerified = true; |
| 73 | + statusService.setStatus('RUNNING'); |
| 74 | + |
| 75 | + statusService.setStatus('DISCONNECTED'); |
| 76 | + |
| 77 | + expect(asperaSdk.globals.asperaAppVerified).toBe(false); |
| 78 | + }); |
| 79 | + |
| 80 | + test('resets asperaAppVerified on DEGRADED', () => { |
| 81 | + asperaSdk.globals.asperaAppVerified = true; |
| 82 | + asperaSdk.globals.httpGatewayVerified = true; |
| 83 | + statusService.setStatus('RUNNING'); |
| 84 | + |
| 85 | + statusService.setStatus('DISCONNECTED'); // remapped to DEGRADED |
| 86 | + |
| 87 | + expect(asperaSdk.globals.asperaAppVerified).toBe(false); |
| 88 | + }); |
| 89 | + |
| 90 | + test('restores asperaAppVerified when transitioning from DEGRADED to RUNNING', () => { |
| 91 | + asperaSdk.globals.httpGatewayVerified = true; |
| 92 | + statusService.setStatus('DEGRADED'); |
| 93 | + expect(asperaSdk.globals.asperaAppVerified).toBe(false); |
| 94 | + |
| 95 | + statusService.setStatus('RUNNING'); |
| 96 | + |
| 97 | + expect(asperaSdk.globals.asperaAppVerified).toBe(true); |
| 98 | + }); |
| 99 | + |
| 100 | + test('restores asperaAppVerified when transitioning from DISCONNECTED to RUNNING', () => { |
| 101 | + statusService.setStatus('DISCONNECTED'); |
| 102 | + expect(asperaSdk.globals.asperaAppVerified).toBe(false); |
| 103 | + |
| 104 | + statusService.setStatus('RUNNING'); |
| 105 | + |
| 106 | + expect(asperaSdk.globals.asperaAppVerified).toBe(true); |
| 107 | + }); |
| 108 | + |
| 109 | + test('does not set asperaAppVerified when transitioning to RUNNING from other states', () => { |
| 110 | + statusService.setStatus('INITIALIZING'); |
| 111 | + |
| 112 | + statusService.setStatus('RUNNING'); |
| 113 | + |
| 114 | + expect(asperaSdk.globals.asperaAppVerified).toBe(false); |
| 115 | + }); |
50 | 116 | }); |
51 | 117 |
|
52 | 118 | describe('registerCallback', () => { |
@@ -162,6 +228,65 @@ describe('StatusService', () => { |
162 | 228 | expect(detectFn).toHaveBeenCalledTimes(1); |
163 | 229 | }); |
164 | 230 |
|
| 231 | + test('transitions to DEGRADED when HTTP Gateway is ready', async () => { |
| 232 | + jest.useFakeTimers(); |
| 233 | + asperaSdk.globals.httpGatewayVerified = true; |
| 234 | + |
| 235 | + const detectFn = jest.fn().mockRejectedValue(new Error('not found')); |
| 236 | + statusService.startPolling(detectFn, 2000, 5000); |
| 237 | + |
| 238 | + jest.advanceTimersByTime(5000); |
| 239 | + expect(statusService.getStatus()).toBe('DEGRADED'); |
| 240 | + }); |
| 241 | + |
| 242 | + test('transitions to FAILED when HTTP Gateway is not ready', async () => { |
| 243 | + jest.useFakeTimers(); |
| 244 | + |
| 245 | + const detectFn = jest.fn().mockRejectedValue(new Error('not found')); |
| 246 | + statusService.startPolling(detectFn, 2000, 5000); |
| 247 | + |
| 248 | + jest.advanceTimersByTime(5000); |
| 249 | + expect(statusService.getStatus()).toBe('FAILED'); |
| 250 | + }); |
| 251 | + |
| 252 | + test('transitions from DEGRADED to RUNNING when detectFn eventually resolves', async () => { |
| 253 | + jest.useFakeTimers(); |
| 254 | + asperaSdk.globals.httpGatewayVerified = true; |
| 255 | + |
| 256 | + let callCount = 0; |
| 257 | + const detectFn = jest.fn().mockImplementation(() => { |
| 258 | + callCount++; |
| 259 | + if (callCount <= 3) { |
| 260 | + return Promise.reject(new Error('not found')); |
| 261 | + } |
| 262 | + return Promise.resolve(); |
| 263 | + }); |
| 264 | + |
| 265 | + const statuses: SdkStatus[] = []; |
| 266 | + statusService.registerCallback((s) => statuses.push(s)); |
| 267 | + |
| 268 | + statusService.startPolling(detectFn, 2000, 5000); |
| 269 | + |
| 270 | + // First attempt fails |
| 271 | + await Promise.resolve(); |
| 272 | + expect(statusService.getStatus()).toBe('INITIALIZING'); |
| 273 | + |
| 274 | + // Advance past timeout |
| 275 | + jest.advanceTimersByTime(5000); |
| 276 | + await Promise.resolve(); |
| 277 | + expect(statusService.getStatus()).toBe('DEGRADED'); |
| 278 | + |
| 279 | + // Next poll interval triggers attempt that succeeds |
| 280 | + jest.advanceTimersByTime(2000); |
| 281 | + await Promise.resolve(); |
| 282 | + await Promise.resolve(); |
| 283 | + |
| 284 | + expect(statusService.getStatus()).toBe('RUNNING'); |
| 285 | + expect(statuses).toContain('INITIALIZING'); |
| 286 | + expect(statuses).toContain('DEGRADED'); |
| 287 | + expect(statuses).toContain('RUNNING'); |
| 288 | + }); |
| 289 | + |
165 | 290 | test('transitions from FAILED to RUNNING when detectFn eventually resolves', async () => { |
166 | 291 | jest.useFakeTimers(); |
167 | 292 |
|
|
0 commit comments