@@ -8,13 +8,16 @@ import { LoginState } from "../session/session-states/login-state.enum";
88import { KeycloakAuthService } from "../session/auth/keycloak/keycloak-auth.service" ;
99import { Subject } from "rxjs" ;
1010import { NAVIGATOR_TOKEN } from "../../utils/di-tokens" ;
11+ import { SyncState } from "../session/session-states/sync-state.enum" ;
1112
1213describe ( "SyncService" , ( ) => {
1314 let service : SyncService ;
1415 let loginState : LoginStateSubject ;
1516 let mockAuthService : jasmine . SpyObj < KeycloakAuthService > ;
1617 let mockNavigator ;
1718
19+ let mockSyncStateSubject : SyncStateSubject ;
20+
1821 beforeEach ( ( ) => {
1922 mockAuthService = jasmine . createSpyObj ( [ "login" , "addAuthHeader" ] ) ;
2023 mockNavigator = { onLine : true } ;
@@ -30,6 +33,7 @@ describe("SyncService", () => {
3033 } ) ;
3134 service = TestBed . inject ( SyncService ) ;
3235 loginState = TestBed . inject ( LoginStateSubject ) ;
36+ mockSyncStateSubject = TestBed . inject ( SyncStateSubject ) ;
3337 } ) ;
3438
3539 /**
@@ -45,18 +49,29 @@ describe("SyncService", () => {
4549 expect ( service ) . toBeTruthy ( ) ;
4650 } ) ;
4751
48- it ( "should restart the sync if it fails at one point" , fakeAsync ( ( ) => {
52+ /**
53+ * Set up a mocked db and localDb for tests and override the TestBed service provider.
54+ */
55+ function mockPouchDatabaseService ( ) : {
56+ mockLocalDb : jasmine . SpyObj < PouchDB . Database > ;
57+ db : PouchDatabase ;
58+ } {
59+ mockSyncStateSubject . next ( SyncState . UNSYNCED ) ;
4960 const mockLocalDb = jasmine . createSpyObj ( [ "sync" ] ) ;
50- spyOn (
51- TestBed . inject ( Database ) as PouchDatabase ,
52- "getPouchDB" ,
53- ) . and . returnValue ( mockLocalDb ) ;
61+ mockLocalDb . sync . and . resolveTo ( { } ) ;
62+
63+ const db = TestBed . inject ( Database ) as PouchDatabase ;
64+ spyOn ( db , "getPouchDB" ) . and . returnValue ( mockLocalDb ) ;
65+ return { mockLocalDb, db } ;
66+ }
67+
68+ it ( "should restart the sync if it fails at one point" , fakeAsync ( ( ) => {
69+ const { mockLocalDb } = mockPouchDatabaseService ( ) ;
5470
5571 loginState . next ( LoginState . LOGGED_IN ) ;
5672
5773 service . startSync ( ) ;
5874
59- mockLocalDb . sync . and . resolveTo ( { } ) ;
6075 tick ( 1000 ) ;
6176 expect ( mockLocalDb . sync ) . toHaveBeenCalled ( ) ;
6277
@@ -76,17 +91,14 @@ describe("SyncService", () => {
7691 } ) ) ;
7792
7893 it ( "should sync immediately when local db has changes" , fakeAsync ( ( ) => {
79- const mockLocalDb = jasmine . createSpyObj ( [ "sync" ] ) ;
80- const db = TestBed . inject ( Database ) as PouchDatabase ;
81- spyOn ( db , "getPouchDB" ) . and . returnValue ( mockLocalDb ) ;
94+ const { mockLocalDb, db } = mockPouchDatabaseService ( ) ;
8295 const mockChanges = new Subject ( ) ;
8396 spyOn ( db , "changes" ) . and . returnValue ( mockChanges ) ;
8497
8598 loginState . next ( LoginState . LOGGED_IN ) ;
8699
87100 service . startSync ( ) ;
88101
89- mockLocalDb . sync . and . resolveTo ( { } ) ;
90102 tick ( 1000 ) ;
91103 expect ( mockLocalDb . sync ) . toHaveBeenCalled ( ) ;
92104 mockLocalDb . sync . calls . reset ( ) ;
@@ -101,10 +113,7 @@ describe("SyncService", () => {
101113 } ) ) ;
102114
103115 it ( "should skip sync calls when offline" , fakeAsync ( ( ) => {
104- const mockLocalDb = jasmine . createSpyObj ( [ "sync" ] ) ;
105- mockLocalDb . sync . and . resolveTo ( { } ) ;
106- const db = TestBed . inject ( Database ) as PouchDatabase ;
107- spyOn ( db , "getPouchDB" ) . and . returnValue ( mockLocalDb ) ;
116+ const { mockLocalDb } = mockPouchDatabaseService ( ) ;
108117
109118 mockNavigator . onLine = false ;
110119
@@ -119,4 +128,29 @@ describe("SyncService", () => {
119128
120129 stopPeriodicTimer ( ) ;
121130 } ) ) ;
131+
132+ it ( "should not start additional syncs while a previous sync is still running" , fakeAsync ( ( ) => {
133+ const LONG_SYNC_TIME = 100000 ;
134+
135+ const { mockLocalDb } = mockPouchDatabaseService ( ) ;
136+ mockLocalDb . sync . and . callFake (
137+ // @ts -ignore
138+ async ( ) => await new Promise ( ( r ) => setTimeout ( r , LONG_SYNC_TIME ) ) ,
139+ ) ;
140+
141+ service . startSync ( ) ;
142+
143+ tick ( SyncService . SYNC_INTERVAL ) ;
144+ expect ( mockLocalDb . sync ) . toHaveBeenCalledTimes ( 1 ) ;
145+
146+ tick ( SyncService . SYNC_INTERVAL ) ;
147+ expect ( mockLocalDb . sync ) . toHaveBeenCalledTimes ( 1 ) ;
148+
149+ tick ( LONG_SYNC_TIME ) ;
150+ expect ( mockLocalDb . sync ) . toHaveBeenCalledTimes ( 2 ) ;
151+
152+ // stop periodic timer:
153+ service . liveSyncEnabled = false ;
154+ tick ( LONG_SYNC_TIME ) ;
155+ } ) ) ;
122156} ) ;
0 commit comments