import { expect } from "chai" ; import * as lolex from "lolex" ; import * as sinon from "sinon" ; import * as moq from "typemoq" ; import { using } from "@itwin/core-bentley" ; import { IModelDb , IpcHost } from "@itwin/core-backend" ; import { PresentationIpcEvents , UpdateInfoJSON } from "@itwin/presentation-common" ; import { NativePlatformDefinition } from "../presentation-backend/NativePlatform" ; import { UpdatesTracker } from "../presentation-backend/UpdatesTracker" ; describe ( "UpdatesTracker" , ( ) => { const nativePlatformMock = moq . Mock . ofType < NativePlatformDefinition > ( ) ; const imodelDbMock = moq . Mock . ofType < IModelDb > ( ) ; let clock ; beforeEach ( ( ) => { nativePlatformMock . reset ( ) ; imodelDbMock . reset ( ) ; clock = lolex . install ( ) ; } ) ; afterEach ( ( ) => { clock . uninstall ( ) ; } ) ; describe ( "constructor" , ( ) => { it ( "sets up timer callback with specified `pollInterval`" , ( ) => { const s = sinon . spy ( clock , "setInterval" ) ; using ( UpdatesTracker . create ( { nativePlatformGetter : ( ) => nativePlatformMock . object , pollInterval : 123 } ) , ( _r ) => { expect ( s ) . to . be . calledOnce ; expect ( s . firstCall . args [ 1 ] ) . to . eq ( 123 ) ; } ) ; } ) ; } ) ; describe ( "dispose" , ( ) => { it ( "stops tracking on dispose" , ( ) => { const s = sinon . spy ( clock , "clearInterval" ) ; const tracker = UpdatesTracker . create ( { nativePlatformGetter : ( ) => nativePlatformMock . object , pollInterval : 123 } ) ; tracker . dispose ( ) ; expect ( s ) . to . be . calledOnce ; } ) ; } ) ; describe ( "tracking" , ( ) => { let spy ; let tracker ; beforeEach ( ( ) => { spy = sinon . stub ( IpcHost , "send" ) ; tracker = UpdatesTracker . create ( { nativePlatformGetter : ( ) => nativePlatformMock . object , pollInterval : 1 } ) ; } ) ; afterEach ( ( ) => { tracker . dispose ( ) ; } ) ; it ( "doesn't emit events if there are no updates" , ( ) => { nativePlatformMock . setup ( ( x ) => x . getUpdateInfo ( ) ) . returns ( ( ) => ( { result : undefined } ) ) ; clock . tick ( 1 ) ; nativePlatformMock . verify ( ( x ) => x . getUpdateInfo ( ) , moq . Times . once ( ) ) ; expect ( spy ) . to . not . be . called ; } ) ; it ( "emits events if there are updates" , ( ) => { const updates = { [ "imodel-File-Path" ] : { "a-ruleset" : { hierarchy : [ ] } , "b-ruleset" : { hierarchy : "FULL" } , "c-ruleset" : { content : "FULL" } } } ; nativePlatformMock . setup ( ( x ) => x . getUpdateInfo ( ) ) . returns ( ( ) => ( { result : updates } ) ) ; const findDbStub = sinon . stub ( IModelDb , "findByFilename" ) ; findDbStub . returns ( imodelDbMock . object ) ; imodelDbMock . setup ( ( x ) => x . getRpcProps ( ) ) . returns ( ( ) => ( { key : "imodelKey" } ) ) ; clock . tick ( 1 ) ; nativePlatformMock . verify ( ( x ) => x . getUpdateInfo ( ) , moq . Times . once ( ) ) ; const expectedUpdateInfo = { [ "imodelKey" ] : updates [ "imodel-File-Path" ] } ; expect ( spy ) . to . be . calledOnceWithExactly ( PresentationIpcEvents . Update , expectedUpdateInfo ) ; } ) ; it ( "does not emit events if imodelDb is not found" , ( ) => { const updates = { [ "imodel-File-Path" ] : { "a-ruleset" : { hierarchy : "FULL" } } } ; nativePlatformMock . setup ( ( x ) => x . getUpdateInfo ( ) ) . returns ( ( ) => ( { result : updates } ) ) ; const findDbStub = sinon . stub ( IModelDb , "findByFilename" ) ; findDbStub . returns ( undefined ) ; clock . tick ( 1 ) ; nativePlatformMock . verify ( ( x ) => x . getUpdateInfo ( ) , moq . Times . once ( ) ) ; expect ( spy ) . to . not . be . called ; } ) ; } ) ; } ) ;