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

additional tests; fix disabled semantic logger panic behavior

This commit is contained in:
✨ Audrey ✨
2025-03-07 17:36:26 -05:00
parent f12966fe7b
commit 4455278704
3 changed files with 45 additions and 19 deletions

View File

@@ -12,7 +12,11 @@ export class DisabledSemanticLogger implements SemanticLogger {
error<T>(_content: Jsonify<T>, _message?: string): void {}
panic<T>(_content: Jsonify<T>, message?: string): never {
throw new Error(message);
panic<T>(content: Jsonify<T>, message?: string): never {
if (typeof content === "string" && !message) {
throw new Error(content);
} else {
throw new Error(message);
}
}
}

View File

@@ -86,14 +86,14 @@ const SomeSite: SiteMetadata = Object.freeze({
const SomePolicyService = mock<PolicyService>();
const SomeExtensionService = mock<ExtensionService>();
const ApplicationProvider = {
/** Policy configured by the administrative console */
policy: SomePolicyService,
/** Client extension metadata and profile access */
extension: mock<ExtensionService>({
site: () => new ExtensionSite(SomeSite, new Map()),
}),
extension: SomeExtensionService,
/** Event monitoring and diagnostic interfaces */
log: disabledSemanticLoggerProvider,
@@ -102,6 +102,16 @@ const ApplicationProvider = {
describe("GeneratorMetadataProvider", () => {
beforeEach(() => {
jest.resetAllMocks();
SomeExtensionService.site.mockImplementation(() => new ExtensionSite(SomeSite, new Map()));
});
describe("constructor", () => {
it("throws when the forwarder site isn't defined by the extension service", () => {
SomeExtensionService.site.mockReturnValue(undefined);
expect(() => new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, [])).toThrow(
"forwarder extension site not found",
);
});
});
describe("metadata", () => {
@@ -354,6 +364,14 @@ describe("GeneratorMetadataProvider", () => {
await expect(firstValueFrom(algorithmResult)).resolves.toEqual([]);
await expect(firstValueFrom(categoryResult)).resolves.toEqual([password.id]);
});
it("panics when neither algorithm nor category are specified", () => {
const provider = new GeneratorMetadataProvider(SystemProvider, ApplicationProvider, []);
expect(() => provider.algorithms$({} as any, { account$: SomeAccount$ })).toThrow(
"algorithm or category required",
);
});
});
describe("preference$", () => {

View File

@@ -14,7 +14,7 @@ import { BoundDependency } from "@bitwarden/common/tools/dependencies";
import { ExtensionSite } from "@bitwarden/common/tools/extension";
import { SemanticLogger } from "@bitwarden/common/tools/log";
import { SystemServiceProvider } from "@bitwarden/common/tools/providers";
import { anyComplete } from "@bitwarden/common/tools/rx";
import { anyComplete, pin } from "@bitwarden/common/tools/rx";
import { UserStateSubject } from "@bitwarden/common/tools/state/user-state-subject";
import { UserStateSubjectDependencyProvider } from "@bitwarden/common/tools/state/user-state-subject-dependency-provider";
@@ -134,24 +134,28 @@ export class GeneratorMetadataProvider {
private isAvailable$(
dependencies: BoundDependency<"account", Account>,
): Observable<(a: CredentialAlgorithm) => boolean> {
const account$ = dependencies.account$.pipe(
distinctUntilChanged((previous, current) => previous.id === current.id),
const id$ = dependencies.account$.pipe(
map((account) => account.id),
pin(),
shareReplay({ bufferSize: 1, refCount: true }),
);
const available$ = account$.pipe(
switchMap((account) => {
const policies$ = this.application.policy
.getAll$(PolicyType.PasswordGenerator, account.id)
.pipe(
map((p) => availableAlgorithms_vNext(p).filter((a) => this._metadata.has(a))),
map((p) => new Set(p)),
// complete policy emissions otherwise `switchMap` holds `available$` open indefinitely
takeUntil(anyComplete(account$)),
);
const available$ = id$.pipe(
switchMap((id) => {
const policies$ = this.application.policy.getAll$(PolicyType.PasswordGenerator, id).pipe(
map((p) => availableAlgorithms_vNext(p).filter((a) => this._metadata.has(a))),
map((p) => new Set(p)),
// complete policy emissions otherwise `switchMap` holds `available$` open indefinitely
takeUntil(anyComplete(id$)),
);
return policies$;
}),
map((available) => (a: CredentialAlgorithm) => isForwarderExtensionId(a) || available.has(a)),
map(
(available) =>
function (a: CredentialAlgorithm) {
return isForwarderExtensionId(a) || available.has(a);
},
),
);
return available$;