mirror of
https://github.com/bitwarden/browser
synced 2025-12-21 18:53:29 +00:00
Conflict resolution
This commit is contained in:
@@ -70,6 +70,9 @@ export class FakeAccountService implements AccountService {
|
||||
}
|
||||
|
||||
async switchAccount(userId: UserId): Promise<void> {
|
||||
const next =
|
||||
userId == null ? null : { id: userId, ...this.accountsSubject["_buffer"]?.[0]?.[userId] };
|
||||
this.activeAccountSubject.next(next);
|
||||
await this.mock.switchAccount(userId);
|
||||
}
|
||||
}
|
||||
|
||||
54
libs/common/spec/matchers/to-almost-equal.spec.ts
Normal file
54
libs/common/spec/matchers/to-almost-equal.spec.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
describe("toAlmostEqual custom matcher", () => {
|
||||
it("matches identical Dates", () => {
|
||||
const date = new Date();
|
||||
expect(date).toAlmostEqual(date);
|
||||
});
|
||||
|
||||
it("matches when older but within default ms", () => {
|
||||
const date = new Date();
|
||||
const olderDate = new Date(date.getTime() - 5);
|
||||
expect(date).toAlmostEqual(olderDate);
|
||||
});
|
||||
|
||||
it("matches when newer but within default ms", () => {
|
||||
const date = new Date();
|
||||
const olderDate = new Date(date.getTime() + 5);
|
||||
expect(date).toAlmostEqual(olderDate);
|
||||
});
|
||||
|
||||
it("doesn't match if older than default ms", () => {
|
||||
const date = new Date();
|
||||
const olderDate = new Date(date.getTime() - 11);
|
||||
expect(date).not.toAlmostEqual(olderDate);
|
||||
});
|
||||
|
||||
it("doesn't match if newer than default ms", () => {
|
||||
const date = new Date();
|
||||
const olderDate = new Date(date.getTime() + 11);
|
||||
expect(date).not.toAlmostEqual(olderDate);
|
||||
});
|
||||
|
||||
it("matches when older but within custom ms", () => {
|
||||
const date = new Date();
|
||||
const olderDate = new Date(date.getTime() - 15);
|
||||
expect(date).toAlmostEqual(olderDate, 20);
|
||||
});
|
||||
|
||||
it("matches when newer but within custom ms", () => {
|
||||
const date = new Date();
|
||||
const olderDate = new Date(date.getTime() + 15);
|
||||
expect(date).toAlmostEqual(olderDate, 20);
|
||||
});
|
||||
|
||||
it("doesn't match if older than custom ms", () => {
|
||||
const date = new Date();
|
||||
const olderDate = new Date(date.getTime() - 21);
|
||||
expect(date).not.toAlmostEqual(olderDate, 20);
|
||||
});
|
||||
|
||||
it("doesn't match if newer than custom ms", () => {
|
||||
const date = new Date();
|
||||
const olderDate = new Date(date.getTime() + 21);
|
||||
expect(date).not.toAlmostEqual(olderDate, 20);
|
||||
});
|
||||
});
|
||||
20
libs/common/spec/matchers/to-almost-equal.ts
Normal file
20
libs/common/spec/matchers/to-almost-equal.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Matches the expected date within an optional ms precision
|
||||
* @param received The received date
|
||||
* @param expected The expected date
|
||||
* @param msPrecision The optional precision in milliseconds
|
||||
*/
|
||||
export const toAlmostEqual: jest.CustomMatcher = function (
|
||||
received: Date,
|
||||
expected: Date,
|
||||
msPrecision: number = 10,
|
||||
) {
|
||||
const receivedTime = received.getTime();
|
||||
const expectedTime = expected.getTime();
|
||||
const difference = Math.abs(receivedTime - expectedTime);
|
||||
return {
|
||||
pass: difference <= msPrecision,
|
||||
message: () =>
|
||||
`expected ${received} to be within ${msPrecision}ms of ${expected} (actual difference: ${difference}ms)`,
|
||||
};
|
||||
};
|
||||
86
libs/common/spec/observable-tracker.ts
Normal file
86
libs/common/spec/observable-tracker.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { Observable, Subscription, firstValueFrom, throwError, timeout } from "rxjs";
|
||||
|
||||
/** Test class to enable async awaiting of observable emissions */
|
||||
export class ObservableTracker<T> {
|
||||
private subscription: Subscription;
|
||||
emissions: T[] = [];
|
||||
constructor(private observable: Observable<T>) {
|
||||
this.emissions = this.trackEmissions(observable);
|
||||
}
|
||||
|
||||
/** Unsubscribes from the observable */
|
||||
unsubscribe() {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
|
||||
/**
|
||||
* Awaits the next emission from the observable, or throws if the timeout is exceeded
|
||||
* @param msTimeout The maximum time to wait for another emission before throwing
|
||||
*/
|
||||
async expectEmission(msTimeout = 50) {
|
||||
await firstValueFrom(
|
||||
this.observable.pipe(
|
||||
timeout({
|
||||
first: msTimeout,
|
||||
with: () => throwError(() => new Error("Timeout exceeded waiting for another emission.")),
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/** Awaits until the the total number of emissions observed by this tracker equals or exceeds {@link count}
|
||||
* @param count The number of emissions to wait for
|
||||
*/
|
||||
async pauseUntilReceived(count: number, msTimeout = 50): Promise<T[]> {
|
||||
for (let i = 0; i < count - this.emissions.length; i++) {
|
||||
await this.expectEmission(msTimeout);
|
||||
}
|
||||
return this.emissions;
|
||||
}
|
||||
|
||||
private trackEmissions<T>(observable: Observable<T>): T[] {
|
||||
const emissions: T[] = [];
|
||||
this.subscription = 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":
|
||||
case "boolean":
|
||||
emissions.push(value);
|
||||
break;
|
||||
case "symbol":
|
||||
// Cheating types to make symbols work at all
|
||||
emissions.push(value.toString() as T);
|
||||
break;
|
||||
default: {
|
||||
emissions.push(clone(value));
|
||||
}
|
||||
}
|
||||
});
|
||||
return emissions;
|
||||
}
|
||||
}
|
||||
function clone(value: any): any {
|
||||
if (global.structuredClone != undefined) {
|
||||
return structuredClone(value);
|
||||
} else {
|
||||
return JSON.parse(JSON.stringify(value));
|
||||
}
|
||||
}
|
||||
|
||||
/** A test helper that builds an @see{@link ObservableTracker}, which can be used to assert things about the
|
||||
* emissions of the given observable
|
||||
* @param observable The observable to track
|
||||
*/
|
||||
export function subscribeTo<T>(observable: Observable<T>) {
|
||||
return new ObservableTracker(observable);
|
||||
}
|
||||
Reference in New Issue
Block a user