mirror of
https://github.com/bitwarden/browser
synced 2026-02-10 21:50:15 +00:00
Prevent SDK from disposing withit debounce period (#18775)
This commit is contained in:
@@ -143,17 +143,44 @@ describe("DefaultSdkService", () => {
|
||||
});
|
||||
|
||||
it("destroys the internal SDK client when all subscriptions are closed", async () => {
|
||||
jest.useFakeTimers();
|
||||
const subject_1 = new BehaviorSubject<Rc<PasswordManagerClient> | undefined>(undefined);
|
||||
const subject_2 = new BehaviorSubject<Rc<PasswordManagerClient> | undefined>(undefined);
|
||||
const subscription_1 = service.userClient$(userId).subscribe(subject_1);
|
||||
const subscription_2 = service.userClient$(userId).subscribe(subject_2);
|
||||
await new Promise(process.nextTick);
|
||||
await jest.advanceTimersByTimeAsync(0);
|
||||
|
||||
subscription_1.unsubscribe();
|
||||
subscription_2.unsubscribe();
|
||||
|
||||
await new Promise(process.nextTick);
|
||||
await jest.advanceTimersByTimeAsync(0);
|
||||
expect(mockClient.free).not.toHaveBeenCalled();
|
||||
|
||||
await jest.advanceTimersByTimeAsync(1000);
|
||||
expect(mockClient.free).toHaveBeenCalledTimes(1);
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it("does not destroy the internal SDK client if resubscribed within 1 second", async () => {
|
||||
jest.useFakeTimers();
|
||||
const subject_1 = new BehaviorSubject<Rc<PasswordManagerClient> | undefined>(undefined);
|
||||
const subscription_1 = service.userClient$(userId).subscribe(subject_1);
|
||||
await jest.advanceTimersByTimeAsync(0);
|
||||
|
||||
subscription_1.unsubscribe();
|
||||
await jest.advanceTimersByTimeAsync(500);
|
||||
expect(mockClient.free).not.toHaveBeenCalled();
|
||||
|
||||
// Resubscribe before the 1 second delay
|
||||
const subject_2 = new BehaviorSubject<Rc<PasswordManagerClient> | undefined>(undefined);
|
||||
const subscription_2 = service.userClient$(userId).subscribe(subject_2);
|
||||
await jest.advanceTimersByTimeAsync(1000);
|
||||
|
||||
// Client should not be freed since we resubscribed
|
||||
expect(mockClient.free).not.toHaveBeenCalled();
|
||||
expect(sdkClientFactory.createSdkClient).toHaveBeenCalledTimes(1);
|
||||
subscription_2.unsubscribe();
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it("destroys the internal SDK client when the userKey is unset (i.e. lock or logout)", async () => {
|
||||
@@ -218,6 +245,7 @@ describe("DefaultSdkService", () => {
|
||||
});
|
||||
|
||||
it("destroys the internal client when an override is set", async () => {
|
||||
jest.useFakeTimers();
|
||||
const mockInternalClient = createMockClient();
|
||||
const mockOverrideClient = createMockClient();
|
||||
sdkClientFactory.createSdkClient.mockResolvedValue(mockInternalClient);
|
||||
@@ -227,7 +255,10 @@ describe("DefaultSdkService", () => {
|
||||
service.setClient(userId, mockOverrideClient);
|
||||
await userClientTracker.pauseUntilReceived(2);
|
||||
|
||||
expect(mockInternalClient.free).not.toHaveBeenCalled();
|
||||
await jest.advanceTimersByTimeAsync(1000);
|
||||
expect(mockInternalClient.free).toHaveBeenCalled();
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it("destroys the override client when explicitly setting the client to undefined", async () => {
|
||||
|
||||
@@ -2,7 +2,10 @@ import {
|
||||
combineLatest,
|
||||
concatMap,
|
||||
Observable,
|
||||
share,
|
||||
shareReplay,
|
||||
ReplaySubject,
|
||||
timer,
|
||||
map,
|
||||
distinctUntilChanged,
|
||||
tap,
|
||||
@@ -263,7 +266,10 @@ export class DefaultSdkService implements SdkService {
|
||||
},
|
||||
),
|
||||
tap({ finalize: () => this.sdkClientCache.delete(userId) }),
|
||||
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||
share({
|
||||
connector: () => new ReplaySubject(1),
|
||||
resetOnRefCountZero: () => timer(1000),
|
||||
}),
|
||||
);
|
||||
|
||||
this.sdkClientCache.set(userId, client$);
|
||||
|
||||
Reference in New Issue
Block a user