Skip to content

Commit db6ad5d

Browse files
committed
Clean up realtime docs
1 parent 8fd5875 commit db6ad5d

File tree

103 files changed

+1309
-635
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+1309
-635
lines changed

src/SIL.XForge.Scripture/ClientApp/src/app/app.component.spec.ts

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { ExternalUrlService } from 'xforge-common/external-url.service';
2525
import { FileService } from 'xforge-common/file.service';
2626
import { I18nService } from 'xforge-common/i18n.service';
2727
import { LocationService } from 'xforge-common/location.service';
28+
import { FETCH_WITHOUT_SUBSCRIBE } from 'xforge-common/models/realtime-doc';
2829
import { UserDoc } from 'xforge-common/models/user-doc';
2930
import { NoticeService } from 'xforge-common/notice.service';
3031
import { OnlineStatusService } from 'xforge-common/online-status.service';
@@ -678,11 +679,12 @@ class TestEnvironment {
678679
this.addProjectUserConfig('project01', 'user03');
679680
this.addProjectUserConfig('project01', 'user04');
680681

681-
when(mockedSFProjectService.getProfile(anything())).thenCall(projectId =>
682-
this.realtimeService.subscribe(SFProjectProfileDoc.COLLECTION, projectId)
682+
when(mockedSFProjectService.subscribeProfile(anything(), anything())).thenCall((projectId, subscription) =>
683+
this.realtimeService.subscribe(SFProjectProfileDoc.COLLECTION, projectId, subscription)
683684
);
684-
when(mockedSFProjectService.getUserConfig(anything(), anything())).thenCall((projectId, userId) =>
685-
this.realtimeService.subscribe(SFProjectUserConfigDoc.COLLECTION, `${projectId}:${userId}`)
685+
when(mockedSFProjectService.getUserConfig(anything(), anything(), anything())).thenCall(
686+
(projectId, userId, subscriber) =>
687+
this.realtimeService.subscribe(SFProjectUserConfigDoc.COLLECTION, `${projectId}:${userId}`, subscriber)
686688
);
687689
when(mockedLocationService.pathname).thenReturn('/projects/project01/checking');
688690

@@ -793,12 +795,14 @@ class TestEnvironment {
793795
}
794796

795797
get currentUserDoc(): UserDoc {
796-
return this.realtimeService.get(UserDoc.COLLECTION, 'user01');
798+
return this.realtimeService.get(UserDoc.COLLECTION, 'user01', FETCH_WITHOUT_SUBSCRIBE);
797799
}
798800

799801
setCurrentUser(userId: string): void {
800802
when(mockedUserService.currentUserId).thenReturn(userId);
801-
when(mockedUserService.getCurrentUser()).thenCall(() => this.realtimeService.subscribe(UserDoc.COLLECTION, userId));
803+
when(mockedUserService.subscribeCurrentUser(anything())).thenCall(subscriber =>
804+
this.realtimeService.subscribe(UserDoc.COLLECTION, userId, subscriber)
805+
);
802806
}
803807

804808
triggerLogin(): void {
@@ -866,33 +870,49 @@ class TestEnvironment {
866870
when(mockedUserService.currentProjectId(anything())).thenReturn(undefined);
867871
}
868872
this.ngZone.run(() => {
869-
const projectDoc = this.realtimeService.get(SFProjectProfileDoc.COLLECTION, projectId);
873+
const projectDoc = this.realtimeService.get(SFProjectProfileDoc.COLLECTION, projectId, FETCH_WITHOUT_SUBSCRIBE);
870874
projectDoc.delete();
871875
});
872876
this.wait();
873877
}
874878

875879
removeUserFromProject(projectId: string): void {
876-
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(SFProjectProfileDoc.COLLECTION, projectId);
880+
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(
881+
SFProjectProfileDoc.COLLECTION,
882+
projectId,
883+
FETCH_WITHOUT_SUBSCRIBE
884+
);
877885
projectDoc.submitJson0Op(op => op.unset<string>(p => p.userRoles['user01']), false);
878886
this.wait();
879887
}
880888

881889
updatePreTranslate(projectId: string): void {
882-
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(SFProjectProfileDoc.COLLECTION, projectId);
890+
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(
891+
SFProjectProfileDoc.COLLECTION,
892+
projectId,
893+
FETCH_WITHOUT_SUBSCRIBE
894+
);
883895
projectDoc.submitJson0Op(op => op.set<boolean>(p => p.translateConfig.preTranslate, true), false);
884896
this.wait();
885897
}
886898

887899
addUserToProject(projectId: string): void {
888-
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(SFProjectProfileDoc.COLLECTION, projectId);
900+
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(
901+
SFProjectProfileDoc.COLLECTION,
902+
projectId,
903+
FETCH_WITHOUT_SUBSCRIBE
904+
);
889905
projectDoc.submitJson0Op(op => op.set<string>(p => p.userRoles['user01'], SFProjectRole.CommunityChecker), false);
890906
this.currentUserDoc.submitJson0Op(op => op.add<string>(u => u.sites['sf'].projects, 'project04'), false);
891907
this.wait();
892908
}
893909

894910
changeUserRole(projectId: string, userId: string, role: SFProjectRole): void {
895-
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(SFProjectProfileDoc.COLLECTION, projectId);
911+
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(
912+
SFProjectProfileDoc.COLLECTION,
913+
projectId,
914+
FETCH_WITHOUT_SUBSCRIBE
915+
);
896916
projectDoc.submitJson0Op(op => op.set<string>(p => p.userRoles[userId], role), false);
897917
this.wait();
898918
}

src/SIL.XForge.Scripture/ClientApp/src/app/app.component.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
22
import { Component, DestroyRef, OnDestroy, OnInit } from '@angular/core';
3+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
34
import { NavigationEnd, Router } from '@angular/router';
45
import Bugsnag from '@bugsnag/js';
56
import { translate } from '@ngneat/transloco';
@@ -23,6 +24,7 @@ import { FileService } from 'xforge-common/file.service';
2324
import { I18nService } from 'xforge-common/i18n.service';
2425
import { LocationService } from 'xforge-common/location.service';
2526
import { Breakpoint, MediaBreakpointService } from 'xforge-common/media-breakpoints/media-breakpoint.service';
27+
import { DocSubscription } from 'xforge-common/models/realtime-doc';
2628
import { UserDoc } from 'xforge-common/models/user-doc';
2729
import { NoticeService } from 'xforge-common/notice.service';
2830
import { OnlineStatusService } from 'xforge-common/online-status.service';
@@ -31,11 +33,10 @@ import {
3133
BrowserIssue,
3234
SupportedBrowsersDialogComponent
3335
} from 'xforge-common/supported-browsers-dialog/supported-browsers-dialog.component';
36+
import { ThemeService } from 'xforge-common/theme.service';
3437
import { UserService } from 'xforge-common/user.service';
3538
import { quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
3639
import { issuesEmailTemplate, supportedBrowser } from 'xforge-common/utils';
37-
import { ThemeService } from 'xforge-common/theme.service';
38-
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3940
import versionData from '../../../version.json';
4041
import { environment } from '../environments/environment';
4142
import { SFProjectProfileDoc } from './core/models/sf-project-profile-doc';
@@ -241,7 +242,9 @@ export class AppComponent extends DataLoadingComponent implements OnInit, OnDest
241242
this.themeService.setDarkMode(enabled);
242243
});
243244
this.loadingStarted();
244-
this.currentUserDoc = await this.userService.getCurrentUser();
245+
this.currentUserDoc = await this.userService.subscribeCurrentUser(
246+
new DocSubscription('AppComponent', this.destroyRef)
247+
);
245248
const userData: User | undefined = cloneDeep(this.currentUserDoc.data);
246249
if (userData != null) {
247250
const userDataWithId = { ...userData, id: this.currentUserDoc.id };
@@ -280,7 +283,8 @@ export class AppComponent extends DataLoadingComponent implements OnInit, OnDest
280283
this.userService.setCurrentProjectId(this.currentUserDoc!, this._selectedProjectDoc.id);
281284
this.projectUserConfigDoc = await this.projectService.getUserConfig(
282285
this._selectedProjectDoc.id,
283-
this.currentUserDoc!.id
286+
this.currentUserDoc!.id,
287+
new DocSubscription('AppComponent', this.destroyRef)
284288
);
285289
if (this.selectedProjectDeleteSub != null) {
286290
this.selectedProjectDeleteSub.unsubscribe();

src/SIL.XForge.Scripture/ClientApp/src/app/app.module.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { OverlayContainer } from '@angular/cdk/overlay';
22
import { DatePipe } from '@angular/common';
33
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
4-
import { APP_ID, ErrorHandler, NgModule } from '@angular/core';
4+
import { APP_ID, APP_INITIALIZER, ErrorHandler, NgModule } from '@angular/core';
55
import { MatRipple } from '@angular/material/core';
66
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
77
import { ServiceWorkerModule } from '@angular/service-worker';
@@ -37,13 +37,19 @@ import { ProjectComponent } from './project/project.component';
3737
import { ScriptureChooserDialogComponent } from './scripture-chooser-dialog/scripture-chooser-dialog.component';
3838
import { DeleteProjectDialogComponent } from './settings/delete-project-dialog/delete-project-dialog.component';
3939
import { SettingsComponent } from './settings/settings.component';
40+
import { CacheService } from './shared/cache-service/cache.service';
4041
import { GlobalNoticesComponent } from './shared/global-notices/global-notices.component';
4142
import { SharedModule } from './shared/shared.module';
4243
import { TextNoteDialogComponent } from './shared/text/text-note-dialog/text-note-dialog.component';
4344
import { SyncComponent } from './sync/sync.component';
4445
import { TranslateModule } from './translate/translate.module';
4546
import { UsersModule } from './users/users.module';
4647

48+
/** Initialization function for any services that need to be run but are not depended on by any component. */
49+
function initializeGlobalServicesFactor(_cacheService: CacheService): () => Promise<any> {
50+
return () => Promise.resolve();
51+
}
52+
4753
@NgModule({
4854
declarations: [
4955
AppComponent,
@@ -93,7 +99,13 @@ import { UsersModule } from './users/users.module';
9399
defaultTranslocoMarkupTranspilers(),
94100
{ provide: ErrorHandler, useClass: ExceptionHandlingService },
95101
{ provide: OverlayContainer, useClass: InAppRootOverlayContainer },
96-
provideHttpClient(withInterceptorsFromDi())
102+
provideHttpClient(withInterceptorsFromDi()),
103+
{
104+
provide: APP_INITIALIZER,
105+
useFactory: initializeGlobalServicesFactor,
106+
deps: [CacheService],
107+
multi: true
108+
}
97109
]
98110
})
99111
export class AppModule {}

src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking-overview/checking-overview.component.spec.ts

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { TextInfo } from 'realtime-server/lib/esm/scriptureforge/models/text-inf
2727
import { of } from 'rxjs';
2828
import { anything, mock, resetCalls, verify, when } from 'ts-mockito';
2929
import { DialogService } from 'xforge-common/dialog.service';
30+
import { FETCH_WITHOUT_SUBSCRIBE } from 'xforge-common/models/realtime-doc';
3031
import { NoticeService } from 'xforge-common/notice.service';
3132
import { OnlineStatusService } from 'xforge-common/online-status.service';
3233
import { noopDestroyRef } from 'xforge-common/realtime.service';
@@ -408,7 +409,8 @@ describe('CheckingOverviewComponent', () => {
408409
const env = new TestEnvironment();
409410
const questionDoc: QuestionDoc = env.realtimeService.get(
410411
QuestionDoc.COLLECTION,
411-
getQuestionDocId('project01', 'q7Id')
412+
getQuestionDocId('project01', 'q7Id'),
413+
FETCH_WITHOUT_SUBSCRIBE
412414
);
413415
await questionDoc.submitJson0Op(op => {
414416
op.set(d => d.isArchived, false);
@@ -916,18 +918,26 @@ class TestEnvironment {
916918
when(mockedActivatedRoute.params).thenReturn(of({ projectId: 'project01' }));
917919
when(mockedQuestionDialogService.questionDialog(anything())).thenResolve();
918920
when(mockedDialogService.confirm(anything(), anything())).thenResolve(true);
919-
when(mockedProjectService.getProfile(anything())).thenCall(id =>
920-
this.realtimeService.subscribe(SFProjectProfileDoc.COLLECTION, id)
921+
when(mockedProjectService.subscribeProfile(anything(), anything())).thenCall((id, subscription) =>
922+
this.realtimeService.subscribe(SFProjectProfileDoc.COLLECTION, id, subscription)
921923
);
922-
when(mockedProjectService.getUserConfig(anything(), anything())).thenCall((id, userId) =>
923-
this.realtimeService.subscribe(SFProjectUserConfigDoc.COLLECTION, getSFProjectUserConfigDocId(id, userId))
924+
when(mockedProjectService.getUserConfig(anything(), anything(), anything())).thenCall((id, userId, subscriber) =>
925+
this.realtimeService.subscribe(
926+
SFProjectUserConfigDoc.COLLECTION,
927+
getSFProjectUserConfigDocId(id, userId),
928+
subscriber
929+
)
924930
);
925931
when(mockedQuestionsService.queryQuestions('project01', anything(), anything())).thenCall(() =>
926932
this.realtimeService.subscribeQuery(QuestionDoc.COLLECTION, {}, noopDestroyRef)
927933
);
928934
when(mockedProjectService.onlineDeleteAudioTimingData(anything(), anything(), anything())).thenCall(
929935
(projectId, book, chapter) => {
930-
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(SFProjectProfileDoc.COLLECTION, projectId);
936+
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(
937+
SFProjectProfileDoc.COLLECTION,
938+
projectId,
939+
FETCH_WITHOUT_SUBSCRIBE
940+
);
931941
const textIndex: number = projectDoc.data!.texts.findIndex(t => t.bookNum === book);
932942
const chapterIndex: number = projectDoc.data!.texts[textIndex].chapters.findIndex(c => c.number === chapter);
933943
projectDoc.submitJson0Op(op => op.set(p => p.texts[textIndex].chapters[chapterIndex].hasAudio, false), false);
@@ -1093,7 +1103,11 @@ class TestEnvironment {
10931103
}
10941104

10951105
setSeeOtherUserResponses(isEnabled: boolean): void {
1096-
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(SFProjectProfileDoc.COLLECTION, 'project01');
1106+
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(
1107+
SFProjectProfileDoc.COLLECTION,
1108+
'project01',
1109+
FETCH_WITHOUT_SUBSCRIBE
1110+
);
10971111
projectDoc.submitJson0Op(
10981112
op => op.set<boolean>(p => p.checkingConfig.usersSeeEachOthersResponses, isEnabled),
10991113
false
@@ -1103,7 +1117,11 @@ class TestEnvironment {
11031117

11041118
setCheckingEnabled(isEnabled: boolean): void {
11051119
this.ngZone.run(() => {
1106-
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(SFProjectProfileDoc.COLLECTION, 'project01');
1120+
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(
1121+
SFProjectProfileDoc.COLLECTION,
1122+
'project01',
1123+
FETCH_WITHOUT_SUBSCRIBE
1124+
);
11071125
projectDoc.submitJson0Op(op => op.set<boolean>(p => p.checkingConfig.checkingEnabled, isEnabled), false);
11081126
});
11091127
this.waitForProjectDocChanges();
@@ -1163,7 +1181,11 @@ class TestEnvironment {
11631181
],
11641182
permissions: {}
11651183
};
1166-
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(SFProjectProfileDoc.COLLECTION, 'project01');
1184+
const projectDoc = this.realtimeService.get<SFProjectProfileDoc>(
1185+
SFProjectProfileDoc.COLLECTION,
1186+
'project01',
1187+
FETCH_WITHOUT_SUBSCRIBE
1188+
);
11671189
const index: number = projectDoc.data!.texts.length - 1;
11681190
projectDoc.submitJson0Op(op => op.insert(p => p.texts, index, text), false);
11691191
this.addQuestion({

src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking-overview/checking-overview.component.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { DataLoadingComponent } from 'xforge-common/data-loading-component';
1111
import { DialogService } from 'xforge-common/dialog.service';
1212
import { I18nService } from 'xforge-common/i18n.service';
1313
import { L10nNumberPipe } from 'xforge-common/l10n-number.pipe';
14+
import { DocSubscription } from 'xforge-common/models/realtime-doc';
1415
import { RealtimeQuery } from 'xforge-common/models/realtime-query';
1516
import { NoticeService } from 'xforge-common/notice.service';
1617
import { OnlineStatusService } from 'xforge-common/online-status.service';
@@ -178,7 +179,10 @@ export class CheckingOverviewComponent extends DataLoadingComponent implements O
178179
const projectId$ = this.activatedRoute.params.pipe(
179180
tap(params => {
180181
this.loadingStarted();
181-
projectDocPromise = this.projectService.getProfile(params['projectId']);
182+
projectDocPromise = this.projectService.subscribeProfile(
183+
params['projectId'],
184+
new DocSubscription('CheckingOverviewComponent', this.destroyRef)
185+
);
182186
}),
183187
map(params => params['projectId'] as string)
184188
);
@@ -187,7 +191,11 @@ export class CheckingOverviewComponent extends DataLoadingComponent implements O
187191
this.projectId = projectId;
188192
try {
189193
this.projectDoc = await projectDocPromise;
190-
this.projectUserConfigDoc = await this.projectService.getUserConfig(projectId, this.userService.currentUserId);
194+
this.projectUserConfigDoc = await this.projectService.getUserConfig(
195+
projectId,
196+
this.userService.currentUserId,
197+
new DocSubscription('CheckingOverviewComponent', this.destroyRef)
198+
);
191199
this.questionsQuery?.dispose();
192200
this.questionsQuery = await this.checkingQuestionsService.queryQuestions(
193201
projectId,

src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-answers.component.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { DialogService } from 'xforge-common/dialog.service';
2323
import { FileService } from 'xforge-common/file.service';
2424
import { I18nService } from 'xforge-common/i18n.service';
2525
import { FileType } from 'xforge-common/models/file-offline-data';
26+
import { DocSubscription } from 'xforge-common/models/realtime-doc';
2627
import { NoticeService } from 'xforge-common/notice.service';
2728
import { OnlineStatusService } from 'xforge-common/online-status.service';
2829
import { UserService } from 'xforge-common/user.service';
@@ -489,7 +490,9 @@ export class CheckingAnswersComponent implements OnInit {
489490

490491
async submit(response: CheckingInput): Promise<void> {
491492
this.submittingAnswer = true;
492-
const userDoc = await this.userService.getCurrentUser();
493+
const userDoc = await this.userService.subscribeCurrentUser(
494+
new DocSubscription('CheckingAnswersComponent', this.destroyRef)
495+
);
493496
if (this.onlineStatusService.isOnline && userDoc.data?.isDisplayNameConfirmed !== true) {
494497
await this.userService.editDisplayName(true);
495498
}

src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-questions.service.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { VerseRefData } from 'realtime-server/lib/esm/scriptureforge/models/vers
77
import { Subject } from 'rxjs';
88
import { FileService } from 'xforge-common/file.service';
99
import { FileType } from 'xforge-common/models/file-offline-data';
10+
import { DocSubscriberInfo } from 'xforge-common/models/realtime-doc';
1011
import { RealtimeQuery } from 'xforge-common/models/realtime-query';
1112
import { ComparisonOperator, PropertyFilter, QueryParameters, Sort } from 'xforge-common/query-parameters';
1213
import { RealtimeService } from 'xforge-common/realtime.service';
@@ -180,6 +181,7 @@ export class CheckingQuestionsService {
180181
async createQuestion(
181182
id: string,
182183
question: Question,
184+
subscriber: DocSubscriberInfo,
183185
audioFileName?: string,
184186
audioBlob?: Blob
185187
): Promise<QuestionDoc | undefined> {
@@ -210,7 +212,7 @@ export class CheckingQuestionsService {
210212
});
211213

212214
return this.realtimeService
213-
.create<QuestionDoc>(QuestionDoc.COLLECTION, docId, question)
215+
.create<QuestionDoc>(QuestionDoc.COLLECTION, docId, question, subscriber)
214216
.then((questionDoc: QuestionDoc) => {
215217
this.afterQuestionCreated$.next(questionDoc);
216218
return questionDoc;

src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-text/checking-text.component.spec.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { createTestProjectProfile } from 'realtime-server/lib/esm/scriptureforge
88
import * as RichText from 'rich-text';
99
import { anything, mock, when } from 'ts-mockito';
1010
import { DialogService } from 'xforge-common/dialog.service';
11+
import { FETCH_WITHOUT_SUBSCRIBE } from 'xforge-common/models/realtime-doc';
1112
import { UserDoc } from 'xforge-common/models/user-doc';
1213
import { OnlineStatusService } from 'xforge-common/online-status.service';
1314
import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
@@ -208,13 +209,16 @@ class TestEnvironment {
208209
})
209210
});
210211
when(mockedSFProjectService.getProfile('project01')).thenCall(() =>
211-
this.realtimeService.subscribe(SFProjectProfileDoc.COLLECTION, 'project01')
212+
this.realtimeService.subscribe(SFProjectProfileDoc.COLLECTION, 'project01', FETCH_WITHOUT_SUBSCRIBE)
212213
);
213-
when(mockedSFProjectService.getText(anything())).thenCall(id =>
214-
this.realtimeService.subscribe(TextDoc.COLLECTION, id.toString())
214+
when(mockedSFProjectService.subscribeProfile('project01', anything())).thenCall((id, subscription) =>
215+
this.realtimeService.subscribe(SFProjectProfileDoc.COLLECTION, id, subscription)
215216
);
216-
when(mockedUserService.getCurrentUser()).thenCall(() =>
217-
this.realtimeService.subscribe(UserDoc.COLLECTION, 'user01')
217+
when(mockedSFProjectService.getText(anything(), anything())).thenCall((id, subscriber) =>
218+
this.realtimeService.subscribe(TextDoc.COLLECTION, id.toString(), subscriber)
219+
);
220+
when(mockedUserService.subscribeCurrentUser(anything())).thenCall(subscriber =>
221+
this.realtimeService.subscribe(UserDoc.COLLECTION, 'user01', subscriber)
218222
);
219223

220224
this.fixture = TestBed.createComponent(CheckingTextComponent);

0 commit comments

Comments
 (0)