1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-10 13:40:06 +00:00

Replay without refcount for app state values

This commit is contained in:
Matt Gibson
2023-10-05 08:41:55 -04:00
parent c13cc39da0
commit ef90d37a44
4 changed files with 44 additions and 3 deletions

View File

@@ -46,6 +46,16 @@ export const mockFromJson = (stub: any) => (stub + "_fromJSON") as any;
export function trackEmissions<T>(observable: Observable<T>): T[] {
const emissions: T[] = [];
observable.subscribe((value) => {
switch (value) {
case undefined:
case null:
emissions.push(value);
return;
default:
// process by type
break;
}
switch (typeof value) {
case "string":
case "number":

View File

@@ -30,6 +30,35 @@ describe("accountService", () => {
jest.resetAllMocks();
});
describe("activeAccount$", () => {
it("should emit undefined if no account is active", () => {
const emissions = trackEmissions(sut.activeAccount$);
expect(emissions).toEqual([undefined]);
});
it("should emit the active account and status", async () => {
const emissions = trackEmissions(sut.activeAccount$);
sut.addAccount(userId, userInfo(AuthenticationStatus.Unlocked));
sut.switchAccount(userId);
expect(emissions).toEqual([
undefined, // initial value
{ id: userId, ...userInfo(AuthenticationStatus.Unlocked) },
]);
});
it("should remember the last emitted value", async () => {
sut.addAccount(userId, userInfo(AuthenticationStatus.Unlocked));
sut.switchAccount(userId);
expect(await firstValueFrom(sut.activeAccount$)).toEqual({
id: userId,
...userInfo(AuthenticationStatus.Unlocked),
});
});
});
describe("addAccount", () => {
it("should throw if the account already exists", () => {
sut.addAccount(userId, userInfo(AuthenticationStatus.Unlocked));

View File

@@ -4,7 +4,7 @@ import {
combineLatestWith,
distinctUntilChanged,
map,
share,
shareReplay,
} from "rxjs";
import { AccountInfo, InternalAccountService } from "../../auth/abstractions/account.service";
@@ -24,7 +24,7 @@ export class AccountServiceImplementation implements InternalAccountService {
combineLatestWith(this.accounts$),
map(([id, accounts]) => (id ? { id, ...accounts[id] } : undefined)),
distinctUntilChanged(),
share()
shareReplay({ bufferSize: 1, refCount: false })
);
accountLock$ = this.lock.asObservable();
accountLogout$ = this.logout.asObservable();

View File

@@ -5,6 +5,7 @@ import {
firstValueFrom,
map,
share,
shareReplay,
switchMap,
tap,
} from "rxjs";
@@ -95,7 +96,8 @@ class DefaultUserState<T> implements UserState<T> {
account != null && account.id != null
? userKeyBuilder(account.id, this.keyDefinition)
: null
)
),
shareReplay({ bufferSize: 1, refCount: false })
);
const activeAccountData$ = this.formattedKey$.pipe(