1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-06 03:33:30 +00:00

move trackEmissions and awaitAsync to core-test-utils

This commit is contained in:
addisonbeck
2025-07-30 16:32:37 -04:00
parent a8f869ee42
commit 3d365661c9
3 changed files with 61 additions and 56 deletions

View File

@@ -6,3 +6,4 @@ export * from "./fake-state";
export * from "./fake-account-service";
export * from "./fake-storage.service";
export * from "./observable-tracker";
export { awaitAsync, trackEmissions } from "@bitwarden/core-test-utils";

View File

@@ -1,7 +1,6 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { mock, MockProxy } from "jest-mock-extended";
import { Observable } from "rxjs";
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
@@ -77,58 +76,3 @@ export const mockFromSdk = (stub: any) => {
return `${stub}_fromSdk`;
};
/**
* Tracks the emissions of the given observable.
*
* Call this function before you expect any emissions and then use code that will cause the observable to emit values,
* then assert after all expected emissions have occurred.
* @param observable
* @returns An array that will be populated with all emissions of the observable.
*/
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":
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));
}
}
export async function awaitAsync(ms = 1) {
if (ms < 1) {
await Promise.resolve();
} else {
await new Promise((resolve) => setTimeout(resolve, ms));
}
}

View File

@@ -0,0 +1,60 @@
import { Observable } from "rxjs";
/**
* Tracks all emissions of a given observable and returns them as an array.
*
* Typically used for testing: Call before actions that trigger observable emissions,
* then assert that expected values have been emitted.
* @param observable The observable to track.
* @returns An array of all emitted values.
*/
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:
break;
}
switch (typeof value) {
case "string":
case "number":
case "boolean":
emissions.push(value);
break;
case "symbol":
// Symbols are converted to strings for storage
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));
}
}
/**
* Waits asynchronously for a given number of milliseconds.
*
* If ms < 1, yields to the event loop immediately.
* Useful in tests to await the next tick or introduce artificial delays.
* @param ms Milliseconds to wait (default: 1)
*/
export async function awaitAsync(ms = 1) {
if (ms < 1) {
await Promise.resolve();
} else {
await new Promise((resolve) => setTimeout(resolve, ms));
}
}