Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ describe("OverlayBackground", () => {

beforeEach(() => {
configService = mock<ConfigService>();
configService.getFeatureFlag$.mockImplementation(() => of(true));
configService.getFeatureFlag$.mockReturnValue(of(true));
accountService = mockAccountServiceWith(mockUserId);
fakeStateProvider = new FakeStateProvider(accountService);
showFaviconsMock$ = new BehaviorSubject(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing

exports[`AutofillInlineMenuIframeService initMenuIframe sets up the iframe's attributes 1`] = `
<iframe
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing

exports[`AutofillInlineMenuButton initAutofillInlineMenuButton creates the button element with the locked icon when the user's auth status is not Unlocked 1`] = `
<button
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing

exports[`AutofillInlineMenuList initAutofillInlineMenuList creates the build save login item view 1`] = `
<div
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing

exports[`OverlayNotificationsContentService opening the notification bar creates the notification bar elements and appends them to the body within a shadow root 1`] = `
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ describe("AutofillService", () => {

beforeEach(() => {
configService = mock<ConfigService>();
configService.getFeatureFlag$.mockImplementation(() => of(false));
configService.getFeatureFlag$.mockReturnValue(of(false));

const mockEnvironment = mock<Environment>();
mockEnvironment.getApiUrl.mockReturnValue("https://api.bitwarden.com");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,9 @@ describe("LocalBackedSessionStorage", () => {
});

it("returns the cached value when cache is populated during storage retrieval", async () => {
localStorage.get.mockImplementation(async () => {
localStorage.get.mockImplementation(<T>(): Promise<T> => {
sut["cache"]["test"] = "cached-during-read";
return encString.encryptedString;
return Promise.resolve(encString.encryptedString) as Promise<T>;
});
encryptService.decryptString.mockResolvedValue(JSON.stringify("decrypted-from-storage"));

Expand All @@ -157,9 +157,9 @@ describe("LocalBackedSessionStorage", () => {
});

it("returns the cached value when storage returns null but cache was filled", async () => {
localStorage.get.mockImplementation(async () => {
localStorage.get.mockImplementation(<T>(): Promise<T> => {
sut["cache"]["test"] = "cached-during-read";
return null;
return Promise.resolve(null) as Promise<T>;
});

const result = await sut.get("test");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,9 +305,7 @@ describe("Browser Utils Service", () => {
BrowserApi.sendMessageWithResponse = jest.fn();
offscreenDocumentService.offscreenApiSupported.mockReturnValue(true);
getManifestVersionSpy.mockReturnValue(3);
offscreenDocumentService.withDocument.mockImplementationOnce((_, __, callback) =>
Promise.resolve("test"),
);
offscreenDocumentService.withDocument.mockResolvedValueOnce("test");

await browserPlatformUtilsService.readFromClipboard();

Expand All @@ -328,9 +326,7 @@ describe("Browser Utils Service", () => {
.mockReturnValue(DeviceType.ChromeExtension);
getManifestVersionSpy.mockReturnValue(3);
jest.spyOn(BrowserApi, "sendMessageWithResponse").mockResolvedValue(1);
offscreenDocumentService.withDocument.mockImplementationOnce((_, __, callback) =>
Promise.resolve(1),
);
offscreenDocumentService.withDocument.mockResolvedValueOnce(1);

const result = await browserPlatformUtilsService.readFromClipboard();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,7 @@ describe("VaultPopupItemsService", () => {
};

// Assume all ciphers are autofill ciphers to test sorting
cipherServiceMock.filterCiphersForUrl.mockImplementation(async () =>
Object.values(allCiphers),
);
cipherServiceMock.filterCiphersForUrl.mockResolvedValue(Object.values(allCiphers));

service.autoFillCiphers$.subscribe((ciphers) => {
expect(ciphers.length).toBe(10);
Expand Down Expand Up @@ -317,11 +315,10 @@ describe("VaultPopupItemsService", () => {
const cipherList = Object.values(allCiphers);
const searchText = "Login";

searchService.searchCiphers.mockImplementation(async () => {
return cipherList.filter((cipher) => {
return cipher.name.includes(searchText);
});
const searchResult = cipherList.filter((cipher) => {
return cipher.name.includes(searchText);
});
searchService.searchCiphers.mockResolvedValue(searchResult);

service.filteredCiphers$.subscribe((ciphers) => {
// There are 10 ciphers but only 3 with "Login" in the name
Expand All @@ -344,11 +341,10 @@ describe("VaultPopupItemsService", () => {
const cipherList = Object.values(allCiphers);
const searchText = "Card 2";

searchService.searchCiphers.mockImplementation(async () => {
return cipherList.filter((cipher) => {
return cipher.name === searchText;
});
const searchResult = cipherList.filter((cipher) => {
return cipher.name.includes(searchText);
});
searchService.searchCiphers.mockResolvedValue(searchResult);

service.favoriteCiphers$.subscribe((ciphers) => {
// There are 2 favorite items but only one Card 2
Expand Down Expand Up @@ -404,7 +400,7 @@ describe("VaultPopupItemsService", () => {
});

it("should return true when there are zero filteredResults", (done) => {
searchService.searchCiphers.mockImplementation(async () => []);
searchService.searchCiphers.mockResolvedValue([]);
service.noFilteredResults$.subscribe((noResults) => {
expect(noResults).toBe(true);
done();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { Component, Input } from "@angular/core";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { By } from "@angular/platform-browser";
import { mock } from "jest-mock-extended";
import { BehaviorSubject, of } from "rxjs";
import { BehaviorSubject, Observable, of } from "rxjs";

import { AccountService, Account } from "@bitwarden/common/auth/abstractions/account.service";
import { BadgeSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/badge-settings.service";
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { FeatureFlag, FeatureFlagValueType } from "@bitwarden/common/enums/feature-flag.enum";
import { AnimationControlService } from "@bitwarden/common/platform/abstractions/animation-control.service";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
Expand Down Expand Up @@ -88,12 +88,14 @@ describe("AppearanceComponent", () => {
setShowAtRiskPasswordNotifications.mockClear();

const configService = mock<ConfigService>();
configService.getFeatureFlag$.mockImplementation((flag: FeatureFlag) => {
if (flag === FeatureFlag.PM31039ItemActionInExtension) {
return featureFlag$.asObservable();
}
return of(false);
});
configService.getFeatureFlag$.mockImplementation(
<Flag extends FeatureFlag>(flag: Flag): Observable<FeatureFlagValueType<Flag>> => {
if (flag === FeatureFlag.PM31039ItemActionInExtension) {
return featureFlag$.asObservable() as Observable<FeatureFlagValueType<Flag>>;
}
return of(false) as Observable<FeatureFlagValueType<Flag>>;
},
);

await TestBed.configureTestingModule({
imports: [AppearanceComponent],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing

exports[`WebRegistrationFinishService finishRegistration() when feature flag is OFF (old API) it registers the user with org invite when given an org invite 1`] = `
RegisterFinishRequest {
Expand Down
20 changes: 13 additions & 7 deletions libs/angular/src/platform/guard/feature-flag.guard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { CanActivateFn, Router } from "@angular/router";
import { RouterTestingModule } from "@angular/router/testing";
import { mock, MockProxy } from "jest-mock-extended";

import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { FeatureFlag, FeatureFlagValueType } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
Expand All @@ -31,16 +31,22 @@ describe("canAccessFeature", () => {

// Mock the correct getter based on the type of flagValue; also mock default values if one is not provided
if (typeof flagValue === "boolean") {
mockConfigService.getFeatureFlag.mockImplementation((flag, defaultValue = false) =>
flag == testFlag ? Promise.resolve(flagValue) : Promise.resolve(defaultValue),
mockConfigService.getFeatureFlag.mockImplementation(<Flag extends FeatureFlag>(flag: Flag) =>
Promise.resolve(
(flag === testFlag ? flagValue : false) as unknown as FeatureFlagValueType<Flag>,
),
);
} else if (typeof flagValue === "string") {
mockConfigService.getFeatureFlag.mockImplementation((flag) =>
flag == testFlag ? Promise.resolve(flagValue as any) : Promise.resolve(""),
mockConfigService.getFeatureFlag.mockImplementation(<Flag extends FeatureFlag>(flag: Flag) =>
Promise.resolve(
(flag === testFlag ? flagValue : "") as unknown as FeatureFlagValueType<Flag>,
),
);
} else if (typeof flagValue === "number") {
mockConfigService.getFeatureFlag.mockImplementation((flag) =>
flag == testFlag ? Promise.resolve(flagValue as any) : Promise.resolve(0),
mockConfigService.getFeatureFlag.mockImplementation(<Flag extends FeatureFlag>(flag: Flag) =>
Promise.resolve(
(flag === testFlag ? flagValue : 0) as unknown as FeatureFlagValueType<Flag>,
),
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing

exports[`DefaultRegistrationFinishService finishRegistration() when feature flag is OFF (old API) registers the user with KDF fields when given valid email verification input 1`] = `
RegisterFinishRequest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ describe("PasswordLoginStrategy", () => {
environmentService = mock<EnvironmentService>();
configService = mock<ConfigService>();
accountCryptographicStateService = mock<AccountCryptographicStateService>();
configService.getFeatureFlag.mockResolvedValue(false);
configService.getFeatureFlag
.calledWith(FeatureFlag.UseUnlockServiceForPasswordLogin)
.mockResolvedValue(false);

appIdService.getAppId.mockResolvedValue(deviceId);
tokenService.decodeAccessToken.mockResolvedValue({
Expand Down Expand Up @@ -222,12 +224,9 @@ describe("PasswordLoginStrategy", () => {
});

it("uses master password unlock service when feature flag is enabled", async () => {
configService.getFeatureFlag.mockImplementation(async (flag: FeatureFlag) => {
if (flag === FeatureFlag.UseUnlockServiceForPasswordLogin) {
return true;
}
return false;
});
configService.getFeatureFlag
.calledWith(FeatureFlag.UseUnlockServiceForPasswordLogin)
.mockResolvedValue(true);

// Re-create he strategy and wait a bit to settle the feature flag
passwordLoginStrategy = new PasswordLoginStrategy(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,9 @@ describe("DefaultDomainSettingsService", () => {
};

beforeEach(() => {
configService.getFeatureFlag.mockImplementation((flag: string) => {
if (flag === FeatureFlag.FillAssistTargetingRules) {
return Promise.resolve(true);
}
return Promise.resolve(false);
});
configService.getFeatureFlag
.calledWith(FeatureFlag.FillAssistTargetingRules)
.mockResolvedValue(true);
accountService.activeAccountSubject.next({ id: mockUserId } as any);
});

Expand Down Expand Up @@ -639,7 +636,7 @@ describe("DefaultDomainSettingsService", () => {

describe("handles state gates", () => {
it("returns null when feature flag is disabled", async () => {
configService.getFeatureFlag.mockImplementation(() => Promise.resolve(false));
configService.getFeatureFlag.mockResolvedValue(false);
await domainSettingsService.setEnableFillAssist(true);
await setupRules(mockRules);

Expand All @@ -651,7 +648,7 @@ describe("DefaultDomainSettingsService", () => {
});

it("returns null when fill assist setting is disabled", async () => {
configService.getFeatureFlag.mockImplementation(() => Promise.resolve(true));
configService.getFeatureFlag.mockResolvedValue(true);
await domainSettingsService.setEnableFillAssist(false);
await domainSettingsService.setTargetingRules(mockRules);

Expand All @@ -663,7 +660,7 @@ describe("DefaultDomainSettingsService", () => {
});

it("returns null when no active account (logged out)", async () => {
configService.getFeatureFlag.mockImplementation(() => Promise.resolve(true));
configService.getFeatureFlag.mockResolvedValue(true);
await domainSettingsService.setEnableFillAssist(true);
accountService.activeAccountSubject.next(null);
await setupRules(mockRules);
Expand All @@ -676,7 +673,7 @@ describe("DefaultDomainSettingsService", () => {
});

it("returns null when no rules exist in state", async () => {
configService.getFeatureFlag.mockImplementation(() => Promise.resolve(true));
configService.getFeatureFlag.mockResolvedValue(true);
await domainSettingsService.setEnableFillAssist(true);
await domainSettingsService.setTargetingRules({});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe("NotificationsService", () => {
autoConfirmService = mock<AutomaticUserConfirmationService>();

// For these tests, use the active-user implementation (feature flag disabled)
configService.getFeatureFlag$.mockImplementation(() => of(true));
configService.getFeatureFlag$.mockReturnValue(of(true));

activeAccount = new BehaviorSubject<ObservedValueOf<AccountService["activeAccount$"]>>(null);
accountService.activeAccount$ = activeAccount.asObservable();
Expand Down
5 changes: 3 additions & 2 deletions libs/common/src/platform/services/migration-runner.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ describe("MigrationRunner", () => {
it("should wait until stateVersion is current before completing", async () => {
let stateVersion: number | null = null;

storage.get.mockImplementation((key) => {
storage.get.mockImplementation(<T>(key: string): Promise<T> => {
if (key === "stateVersion") {
return Promise.resolve(stateVersion);
return Promise.resolve(stateVersion) as Promise<T>;
}
return Promise.resolve(null) as Promise<T>;
});

let promiseCompleted = false;
Expand Down
2 changes: 1 addition & 1 deletion libs/common/src/tools/rx.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* include structuredClone in test environment.
* @jest-environment ../../../../shared/test.environment.ts
* @jest-environment ../../libs/shared/test.environment.ts
*/
// @ts-strict-ignore this file explicitly tests what happens when types are ignored
import { of, firstValueFrom, Subject, tap, EmptyError, BehaviorSubject } from "rxjs";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* include structuredClone in test environment.
* @jest-environment ../../../../shared/test.environment.ts
* @jest-environment ../../libs/shared/test.environment.ts
*/
import { mock } from "jest-mock-extended";
import { of, firstValueFrom } from "rxjs";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,7 @@ describe("PasswordRandomizer", () => {
// given. In the password generator, the array is generated from the
// options. Thus, returning a fixed set of results effectively overrides
// the randomizer's arguments.
randomizer.shuffle.mockImplementation(() => {
const results = [Ascii.Full.Uppercase, Ascii.Full.Digit];
return Promise.resolve(results);
});
randomizer.shuffle.mockResolvedValue([Ascii.Full.Uppercase, Ascii.Full.Digit]);

const result = await password.randomAscii({
all: 0,
Expand Down
Loading
Loading