mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 00:33:44 +00:00
refactor: introduce @bitwarden/state and other common libs (#15772)
* refactor: introduce @bitwarden/serialization * refactor: introduce @bitwarden/guid * refactor: introduce @bitwaren/client-type * refactor: introduce @bitwarden/core-test-utils * refactor: introduce @bitwarden/state and @bitwarden/state-test-utils Creates initial project structure for centralized application state management. Part of modularization effort to extract state code from common. * Added state provider documentation to README. * Changed callouts to Github format. * Fixed linting on file name. * Forced git to accept rename --------- Co-authored-by: Todd Martin <tmartin@bitwarden.com>
This commit is contained in:
60
libs/core-test-utils/src/index.ts
Normal file
60
libs/core-test-utils/src/index.ts
Normal 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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user