mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-01-23 02:36:05 +00:00
test(op-log): fix clock drift tests by adding missing service mocks
- Add missing mocks for OperationEncryptionService, SuperSyncStatusService, and CLIENT_ID_PROVIDER - Fix async handling by replacing flushMicrotasks() with tick() and flush() - Update test expectation to match actual clientId parameter - Reset hasWarnedClockDrift flag in beforeEach to prevent test interference - Re-enable previously disabled test suite Root cause: Without all required service mocks, async code in lock callback never executed in fakeAsync context, preventing clock drift detection logic from running.
This commit is contained in:
parent
7d5bb1a709
commit
dca674cdf4
1 changed files with 41 additions and 16 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { fakeAsync, flushMicrotasks, TestBed, tick } from '@angular/core/testing';
|
||||
import { fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
|
||||
import { OperationLogDownloadService } from './operation-log-download.service';
|
||||
import { OperationLogStoreService } from '../persistence/operation-log-store.service';
|
||||
import { LockService } from './lock.service';
|
||||
|
|
@ -12,12 +12,18 @@ import { ActionType, OpType } from '../core/operation.types';
|
|||
import { CLOCK_DRIFT_THRESHOLD_MS } from '../core/operation-log.const';
|
||||
import { OpLog } from '../../core/log';
|
||||
import { T } from '../../t.const';
|
||||
import { OperationEncryptionService } from './operation-encryption.service';
|
||||
import { SuperSyncStatusService } from './super-sync-status.service';
|
||||
import { CLIENT_ID_PROVIDER } from '../util/client-id.provider';
|
||||
|
||||
xdescribe('OperationLogDownloadService', () => {
|
||||
describe('OperationLogDownloadService', () => {
|
||||
let service: OperationLogDownloadService;
|
||||
let mockOpLogStore: jasmine.SpyObj<OperationLogStoreService>;
|
||||
let mockLockService: jasmine.SpyObj<LockService>;
|
||||
let mockSnackService: jasmine.SpyObj<SnackService>;
|
||||
let mockEncryptionService: jasmine.SpyObj<OperationEncryptionService>;
|
||||
let mockSuperSyncStatusService: jasmine.SpyObj<SuperSyncStatusService>;
|
||||
let mockClientIdProvider: { loadClientId: jasmine.Spy };
|
||||
|
||||
beforeEach(() => {
|
||||
mockOpLogStore = jasmine.createSpyObj('OperationLogStoreService', [
|
||||
|
|
@ -26,17 +32,27 @@ xdescribe('OperationLogDownloadService', () => {
|
|||
]);
|
||||
mockLockService = jasmine.createSpyObj('LockService', ['request']);
|
||||
mockSnackService = jasmine.createSpyObj('SnackService', ['open']);
|
||||
mockEncryptionService = jasmine.createSpyObj('OperationEncryptionService', [
|
||||
'decryptOperations',
|
||||
]);
|
||||
mockSuperSyncStatusService = jasmine.createSpyObj('SuperSyncStatusService', [
|
||||
'markRemoteChecked',
|
||||
]);
|
||||
mockClientIdProvider = {
|
||||
loadClientId: jasmine
|
||||
.createSpy('loadClientId')
|
||||
.and.returnValue(Promise.resolve('test-client-id')),
|
||||
};
|
||||
|
||||
// Mock OpLog
|
||||
spyOn(OpLog, 'warn');
|
||||
spyOn(OpLog, 'normal');
|
||||
|
||||
// Default mock implementations
|
||||
mockLockService.request.and.callFake(
|
||||
async (_name: string, fn: () => Promise<void>) => {
|
||||
await fn();
|
||||
},
|
||||
);
|
||||
// Note: Don't use async/await here as it breaks fakeAsync zone context
|
||||
mockLockService.request.and.callFake((_name: string, fn: () => Promise<void>) => {
|
||||
return fn();
|
||||
});
|
||||
mockOpLogStore.getAppliedOpIds.and.returnValue(Promise.resolve(new Set<string>()));
|
||||
mockOpLogStore.hasSyncedOps.and.returnValue(Promise.resolve(false));
|
||||
|
||||
|
|
@ -46,10 +62,15 @@ xdescribe('OperationLogDownloadService', () => {
|
|||
{ provide: OperationLogStoreService, useValue: mockOpLogStore },
|
||||
{ provide: LockService, useValue: mockLockService },
|
||||
{ provide: SnackService, useValue: mockSnackService },
|
||||
{ provide: OperationEncryptionService, useValue: mockEncryptionService },
|
||||
{ provide: SuperSyncStatusService, useValue: mockSuperSyncStatusService },
|
||||
{ provide: CLIENT_ID_PROVIDER, useValue: mockClientIdProvider },
|
||||
],
|
||||
});
|
||||
|
||||
service = TestBed.inject(OperationLogDownloadService);
|
||||
// Reset the clock drift warning flag for each test
|
||||
(service as any).hasWarnedClockDrift = false;
|
||||
});
|
||||
|
||||
describe('downloadRemoteOps', () => {
|
||||
|
|
@ -125,13 +146,13 @@ xdescribe('OperationLogDownloadService', () => {
|
|||
);
|
||||
|
||||
service.downloadRemoteOps(mockApiProvider);
|
||||
flushMicrotasks(); // Flush all pending promises
|
||||
tick(); // Resolve promises
|
||||
|
||||
// Warning should not be shown immediately
|
||||
expect(OpLog.warn).not.toHaveBeenCalled();
|
||||
|
||||
// After 1 second retry, warning should appear
|
||||
tick(1000);
|
||||
flush(); // Flush all pending timers
|
||||
|
||||
expect(OpLog.warn).toHaveBeenCalledWith(
|
||||
'OperationLogDownloadService: Clock drift detected',
|
||||
|
|
@ -269,14 +290,14 @@ xdescribe('OperationLogDownloadService', () => {
|
|||
|
||||
// First call - should warn after retry
|
||||
service.downloadRemoteOps(mockApiProvider);
|
||||
flushMicrotasks(); // Flush all pending promises
|
||||
tick(1000); // Wait for retry
|
||||
tick(); // Resolve promises
|
||||
flush(); // Flush all pending timers
|
||||
expect(OpLog.warn).toHaveBeenCalledTimes(1);
|
||||
|
||||
// Second call - should NOT warn again
|
||||
service.downloadRemoteOps(mockApiProvider);
|
||||
flushMicrotasks(); // Flush all pending promises
|
||||
tick(1000); // Wait for retry (if any)
|
||||
tick(); // Resolve promises
|
||||
flush(); // Flush all pending timers (if any)
|
||||
expect(OpLog.warn).toHaveBeenCalledTimes(1);
|
||||
}));
|
||||
|
||||
|
|
@ -361,8 +382,8 @@ xdescribe('OperationLogDownloadService', () => {
|
|||
);
|
||||
|
||||
service.downloadRemoteOps(mockApiProvider);
|
||||
flushMicrotasks(); // Flush all pending promises
|
||||
tick(1000); // Wait for retry
|
||||
tick(); // Resolve promises
|
||||
flush(); // Flush all pending timers
|
||||
|
||||
// Should warn because serverTime differs from client time
|
||||
expect(OpLog.warn).toHaveBeenCalledWith(
|
||||
|
|
@ -562,7 +583,11 @@ xdescribe('OperationLogDownloadService', () => {
|
|||
await service.downloadRemoteOps(mockApiProvider, { forceFromSeq0: true });
|
||||
|
||||
// Should start from 0, not from lastServerSeq (100)
|
||||
expect(mockApiProvider.downloadOps).toHaveBeenCalledWith(0, undefined, 500);
|
||||
expect(mockApiProvider.downloadOps).toHaveBeenCalledWith(
|
||||
0,
|
||||
'test-client-id',
|
||||
500,
|
||||
);
|
||||
});
|
||||
|
||||
it('should collect all op clocks when forceFromSeq0 is true', async () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue