@@ -656,9 +656,12 @@ describe("VcsStatusBroadcaster", () => {
656656 } ,
657657 ) ;
658658
659- it . effect ( "an explicit refresh reads local totals after the fetch " , ( ) => {
659+ it . effect ( "a remote poll refreshes Changes totals when divergence counts stay the same " , ( ) => {
660660 const state : Parameters < typeof layerTestFor > [ 0 ] = {
661- currentLocalStatus : baseLocalStatus ,
661+ currentLocalStatus : {
662+ ...baseLocalStatus ,
663+ branchChanges : { baseRef : "origin/main" , insertions : 745 , deletions : 24 } ,
664+ } ,
662665 currentRemoteStatus : baseRemoteStatus ,
663666 localStatusCalls : 0 ,
664667 remoteStatusCalls : 0 ,
@@ -668,24 +671,79 @@ describe("VcsStatusBroadcaster", () => {
668671
669672 return Effect . gen ( function * ( ) {
670673 const broadcaster = yield * VcsStatusBroadcaster . VcsStatusBroadcaster ;
671- const fetchStarted = yield * Deferred . make < void > ( ) ;
672- const finishFetch = yield * Deferred . make < void > ( ) ;
673- state . beforeRemoteStatus = Deferred . succeed ( fetchStarted , undefined ) . pipe (
674- Effect . andThen ( Deferred . await ( finishFetch ) ) ,
674+ yield * broadcaster . getStatus ( { cwd : "/repo" } ) ;
675+ const subscribed = yield * Deferred . make < void > ( ) ;
676+ const polled = yield * Deferred . make < void > ( ) ;
677+ yield * broadcaster . streamStatus ( { cwd : "/repo" } ) . pipe (
678+ Stream . runForEach ( ( event ) => {
679+ if ( event . _tag === "snapshot" ) return Deferred . succeed ( subscribed , undefined ) ;
680+ if ( event . _tag === "remoteUpdated" ) return Deferred . succeed ( polled , undefined ) ;
681+ return Effect . void ;
682+ } ) ,
683+ Effect . forkScoped ,
675684 ) ;
676- const refresh = yield * broadcaster . refreshStatus ( "/repo" ) . pipe ( Effect . forkScoped ) ;
677- yield * Deferred . await ( fetchStarted ) ;
678-
679- const fetchedLocal : VcsStatusLocalResult = {
685+ yield * Deferred . await ( subscribed ) ;
686+ state . currentLocalStatus = {
680687 ...baseLocalStatus ,
681- branchChanges : { baseRef : "origin/main" , insertions : 0 , deletions : 0 } ,
688+ branchChanges : { baseRef : "origin/main" , insertions : 107 , deletions : 4 } ,
682689 } ;
683- state . currentLocalStatus = fetchedLocal ;
684- yield * Deferred . succeed ( finishFetch , undefined ) ;
690+ state . currentRemoteStatus = remoteStatusWithPr ;
691+ yield * TestClock . adjust ( "30 seconds" ) ;
692+ yield * Deferred . await ( polled ) ;
693+ const status = yield * broadcaster . getStatus ( { cwd : "/repo" } ) ;
694+ assert . deepStrictEqual ( status . branchChanges , state . currentLocalStatus . branchChanges ) ;
695+ } ) . pipe ( Effect . provide ( layerTestFor ( state ) ) , Effect . scoped ) ;
696+ } ) ;
685697
686- const status = yield * Fiber . join ( refresh ) ;
687- assert . deepStrictEqual ( status . branchChanges , fetchedLocal . branchChanges ) ;
688- } ) . pipe ( Effect . provide ( layerTestFor ( state ) ) ) ;
698+ it . effect ( "an explicit refresh reads local totals after the fetch" , ( ) => {
699+ return Effect . gen ( function * ( ) {
700+ const fetchStarted = yield * Deferred . make < void > ( ) ;
701+ const finishFetch = yield * Deferred . make < void > ( ) ;
702+ let local : VcsStatusLocalResult = {
703+ ...baseLocalStatus ,
704+ branchChanges : { baseRef : "origin/main" , insertions : 745 , deletions : 24 } ,
705+ } ;
706+ let cachedLocal : VcsStatusLocalResult | undefined ;
707+ const readLocalStatus = ( ) => Effect . sync ( ( ) => ( cachedLocal ??= local ) ) ;
708+ const layerTest = VcsStatusBroadcaster . layer . pipe (
709+ Layer . provideMerge ( NodeServices . layer ) ,
710+ Layer . provide ( layerBackgroundPolicy ( ( ) => true ) ) ,
711+ Layer . provide (
712+ Layer . mock ( GitWorkflowService . GitWorkflowService ) ( {
713+ localStatus : readLocalStatus ,
714+ invalidateStatus : ( ) =>
715+ Effect . sync ( ( ) => {
716+ cachedLocal = undefined ;
717+ } ) ,
718+ invalidateLocalStatus : ( ) =>
719+ Effect . sync ( ( ) => {
720+ cachedLocal = undefined ;
721+ } ) ,
722+ currentBranch : ( ) => Effect . succeed ( baseLocalStatus . refName ) ,
723+ invalidateRemoteStatus : ( ) => Effect . void ,
724+ remoteStatus : ( ) =>
725+ Deferred . succeed ( fetchStarted , undefined ) . pipe (
726+ Effect . andThen ( Deferred . await ( finishFetch ) ) ,
727+ Effect . as ( baseRemoteStatus ) ,
728+ ) ,
729+ } ) ,
730+ ) ,
731+ ) ;
732+ yield * Effect . gen ( function * ( ) {
733+ const broadcaster = yield * VcsStatusBroadcaster . VcsStatusBroadcaster ;
734+ const refresh = yield * broadcaster . refreshStatus ( "/repo" ) . pipe ( Effect . forkScoped ) ;
735+ yield * Deferred . await ( fetchStarted ) ;
736+ // Another reader can refill the local cache while fetch is still running.
737+ yield * readLocalStatus ( ) ;
738+ local = {
739+ ...baseLocalStatus ,
740+ branchChanges : { baseRef : "origin/main" , insertions : 0 , deletions : 0 } ,
741+ } ;
742+ yield * Deferred . succeed ( finishFetch , undefined ) ;
743+ const status = yield * Fiber . join ( refresh ) ;
744+ assert . deepStrictEqual ( status . branchChanges , local . branchChanges ) ;
745+ } ) . pipe ( Effect . provide ( layerTest ) ) ;
746+ } ) ;
689747 } ) ;
690748
691749 it . effect ( "publishes local status while an earlier lookup holds the remote lock" , ( ) => {
0 commit comments