mirror of
https://github.com/bitwarden/browser
synced 2026-02-10 05:30:01 +00:00
Merge branch 'main' into dirt/pm-21287/ngrx-poc
This commit is contained in:
@@ -7,7 +7,6 @@ const sharedConfig = require("../../libs/shared/jest.config.angular");
|
||||
/** @type {import('jest').Config} */
|
||||
module.exports = {
|
||||
...sharedConfig,
|
||||
preset: "jest-preset-angular",
|
||||
setupFilesAfterEnv: ["<rootDir>/test.setup.ts"],
|
||||
moduleNameMapper: pathsToModuleNameMapper(
|
||||
{ "@bitwarden/common/spec": ["../../libs/common/spec"], ...(compilerOptions?.paths ?? {}) },
|
||||
|
||||
@@ -5,7 +5,6 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli
|
||||
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
@@ -35,7 +34,6 @@ describe("AutoSubmitLoginBackground", () => {
|
||||
let scriptInjectorService: MockProxy<ScriptInjectorService>;
|
||||
let authStatus$: BehaviorSubject<AuthenticationStatus>;
|
||||
let authService: MockProxy<AuthService>;
|
||||
let configService: MockProxy<ConfigService>;
|
||||
let platformUtilsService: MockProxy<PlatformUtilsService>;
|
||||
let policyDetails: MockProxy<Policy>;
|
||||
let automaticAppLogInPolicy$: BehaviorSubject<Policy[]>;
|
||||
@@ -56,9 +54,6 @@ describe("AutoSubmitLoginBackground", () => {
|
||||
authStatus$ = new BehaviorSubject(AuthenticationStatus.Unlocked);
|
||||
authService = mock<AuthService>();
|
||||
authService.activeAccountStatus$ = authStatus$;
|
||||
configService = mock<ConfigService>({
|
||||
getFeatureFlag: jest.fn().mockResolvedValue(true),
|
||||
});
|
||||
platformUtilsService = mock<PlatformUtilsService>();
|
||||
policyDetails = mock<Policy>({
|
||||
enabled: true,
|
||||
@@ -78,7 +73,6 @@ describe("AutoSubmitLoginBackground", () => {
|
||||
autofillService,
|
||||
scriptInjectorService,
|
||||
authService,
|
||||
configService,
|
||||
platformUtilsService,
|
||||
policyService,
|
||||
accountService,
|
||||
@@ -89,7 +83,7 @@ describe("AutoSubmitLoginBackground", () => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe("when the AutoSubmitLoginBackground feature is disabled", () => {
|
||||
describe("when conditions prevent auto-submit policy activation", () => {
|
||||
it("destroys all event listeners when the AutomaticAppLogIn policy is not enabled", async () => {
|
||||
automaticAppLogInPolicy$.next([mock<Policy>({ ...policyDetails, enabled: false })]);
|
||||
|
||||
@@ -115,7 +109,7 @@ describe("AutoSubmitLoginBackground", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the AutoSubmitLoginBackground feature is enabled", () => {
|
||||
describe("when the AutomaticAppLogIn policy is valid and active", () => {
|
||||
let webRequestDetails: chrome.webRequest.WebRequestBodyDetails;
|
||||
|
||||
describe("starting the auto-submit login workflow", () => {
|
||||
@@ -268,7 +262,6 @@ describe("AutoSubmitLoginBackground", () => {
|
||||
autofillService,
|
||||
scriptInjectorService,
|
||||
authService,
|
||||
configService,
|
||||
platformUtilsService,
|
||||
policyService,
|
||||
accountService,
|
||||
|
||||
@@ -10,8 +10,6 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
|
||||
@@ -42,7 +40,6 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr
|
||||
private autofillService: AutofillService,
|
||||
private scriptInjectorService: ScriptInjectorService,
|
||||
private authService: AuthService,
|
||||
private configService: ConfigService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private policyService: PolicyService,
|
||||
private accountService: AccountService,
|
||||
@@ -51,25 +48,19 @@ export class AutoSubmitLoginBackground implements AutoSubmitLoginBackgroundAbstr
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the auto-submit login policy. Will return early if
|
||||
* the feature flag is not set. If the policy is not enabled, it
|
||||
* Initializes the auto-submit login policy. If the policy is not enabled, it
|
||||
* will trigger a removal of any established listeners.
|
||||
*/
|
||||
async init() {
|
||||
const featureFlagEnabled = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.IdpAutoSubmitLogin,
|
||||
);
|
||||
if (featureFlagEnabled) {
|
||||
this.accountService.activeAccount$
|
||||
.pipe(
|
||||
getUserId,
|
||||
switchMap((userId) =>
|
||||
this.policyService.policiesByType$(PolicyType.AutomaticAppLogIn, userId),
|
||||
),
|
||||
getFirstPolicy,
|
||||
)
|
||||
.subscribe(this.handleAutoSubmitLoginPolicySubscription.bind(this));
|
||||
}
|
||||
this.accountService.activeAccount$
|
||||
.pipe(
|
||||
getUserId,
|
||||
switchMap((userId) =>
|
||||
this.policyService.policiesByType$(PolicyType.AutomaticAppLogIn, userId),
|
||||
),
|
||||
getFirstPolicy,
|
||||
)
|
||||
.subscribe(this.handleAutoSubmitLoginPolicySubscription.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,6 @@ import { BehaviorSubject } from "rxjs";
|
||||
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { Fido2ActiveRequestManager } from "@bitwarden/common/platform/abstractions/fido2/fido2-active-request-manager.abstraction";
|
||||
import {
|
||||
AssertCredentialParams,
|
||||
@@ -60,7 +59,6 @@ describe("Fido2Background", () => {
|
||||
let fido2ClientService!: MockProxy<Fido2ClientService<BrowserFido2ParentWindowReference>>;
|
||||
let vaultSettingsService!: MockProxy<VaultSettingsService>;
|
||||
let scriptInjectorServiceMock!: MockProxy<BrowserScriptInjectorService>;
|
||||
let configServiceMock!: MockProxy<ConfigService>;
|
||||
let enablePasskeysMock$!: BehaviorSubject<boolean>;
|
||||
let activeAccountStatusMock$: BehaviorSubject<AuthenticationStatus>;
|
||||
let authServiceMock!: MockProxy<AuthService>;
|
||||
@@ -80,7 +78,6 @@ describe("Fido2Background", () => {
|
||||
abortController = mock<AbortController>();
|
||||
registeredContentScripsMock = mock<browser.contentScripts.RegisteredContentScript>();
|
||||
scriptInjectorServiceMock = mock<BrowserScriptInjectorService>();
|
||||
configServiceMock = mock<ConfigService>();
|
||||
|
||||
enablePasskeysMock$ = new BehaviorSubject(true);
|
||||
vaultSettingsService.enablePasskeys$ = enablePasskeysMock$;
|
||||
@@ -95,7 +92,6 @@ describe("Fido2Background", () => {
|
||||
fido2ClientService,
|
||||
vaultSettingsService,
|
||||
scriptInjectorServiceMock,
|
||||
configServiceMock,
|
||||
authServiceMock,
|
||||
);
|
||||
fido2Background["abortManager"] = abortManagerMock;
|
||||
@@ -186,7 +182,7 @@ describe("Fido2Background", () => {
|
||||
expect(scriptInjectorServiceMock.inject).toHaveBeenCalledWith({
|
||||
tabId: tabMock.id,
|
||||
injectDetails: sharedScriptInjectionDetails,
|
||||
mv2Details: { file: Fido2ContentScript.PageScriptAppend },
|
||||
mv2Details: { file: Fido2ContentScript.PageScriptDelayAppend },
|
||||
mv3Details: { file: Fido2ContentScript.PageScript, world: "MAIN" },
|
||||
});
|
||||
expect(scriptInjectorServiceMock.inject).toHaveBeenCalledWith({
|
||||
@@ -202,22 +198,6 @@ describe("Fido2Background", () => {
|
||||
enablePasskeysMock$.next(true);
|
||||
await flushPromises();
|
||||
|
||||
expect(BrowserApi.registerContentScriptsMv2).toHaveBeenCalledWith({
|
||||
js: [
|
||||
{ file: Fido2ContentScript.PageScriptAppend },
|
||||
{ file: Fido2ContentScript.ContentScript },
|
||||
],
|
||||
...sharedRegistrationOptions,
|
||||
});
|
||||
});
|
||||
|
||||
it("registers the page-script-delay-append-mv2.js content script when the DelayFido2PageScriptInitWithinMv2 feature flag is enabled", async () => {
|
||||
configServiceMock.getFeatureFlag.mockResolvedValue(true);
|
||||
isManifestVersionSpy.mockImplementation((manifestVersion) => manifestVersion === 2);
|
||||
|
||||
enablePasskeysMock$.next(true);
|
||||
await flushPromises();
|
||||
|
||||
expect(BrowserApi.registerContentScriptsMv2).toHaveBeenCalledWith({
|
||||
js: [
|
||||
{ file: Fido2ContentScript.PageScriptDelayAppend },
|
||||
|
||||
@@ -5,8 +5,6 @@ import { pairwise } from "rxjs/operators";
|
||||
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { Fido2ActiveRequestManager } from "@bitwarden/common/platform/abstractions/fido2/fido2-active-request-manager.abstraction";
|
||||
import {
|
||||
AssertCredentialParams,
|
||||
@@ -60,7 +58,6 @@ export class Fido2Background implements Fido2BackgroundInterface {
|
||||
private fido2ClientService: Fido2ClientService<BrowserFido2ParentWindowReference>,
|
||||
private vaultSettingsService: VaultSettingsService,
|
||||
private scriptInjectorService: ScriptInjectorService,
|
||||
private configService: ConfigService,
|
||||
private authService: AuthService,
|
||||
) {}
|
||||
|
||||
@@ -403,14 +400,6 @@ export class Fido2Background implements Fido2BackgroundInterface {
|
||||
* delayed append script if the associated feature flag is enabled.
|
||||
*/
|
||||
private async getFido2PageScriptAppendFileName() {
|
||||
const shouldDelayInit = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.DelayFido2PageScriptInitWithinMv2,
|
||||
);
|
||||
|
||||
if (shouldDelayInit) {
|
||||
return Fido2ContentScript.PageScriptDelayAppend;
|
||||
}
|
||||
|
||||
return Fido2ContentScript.PageScriptAppend;
|
||||
return Fido2ContentScript.PageScriptDelayAppend;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ describe("FIDO2 page-script for manifest v2", () => {
|
||||
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
require("./fido2-page-script-append.mv2");
|
||||
require("./fido2-page-script-delay-append.mv2.ts");
|
||||
|
||||
expect(window.document.createElement).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -37,7 +37,7 @@ describe("FIDO2 page-script for manifest v2", () => {
|
||||
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
require("./fido2-page-script-append.mv2");
|
||||
require("./fido2-page-script-delay-append.mv2.ts");
|
||||
|
||||
expect(window.document.createElement).toHaveBeenCalledWith("script");
|
||||
expect(chrome.runtime.getURL).toHaveBeenCalledWith(Fido2ContentScript.PageScript);
|
||||
@@ -54,7 +54,7 @@ describe("FIDO2 page-script for manifest v2", () => {
|
||||
|
||||
// FIXME: Remove when updating file. Eslint update
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
require("./fido2-page-script-append.mv2");
|
||||
require("./fido2-page-script-delay-append.mv2.ts");
|
||||
|
||||
expect(window.document.createElement).toHaveBeenCalledWith("script");
|
||||
expect(chrome.runtime.getURL).toHaveBeenCalledWith(Fido2ContentScript.PageScript);
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* This script handles injection of the FIDO2 override page script into the document.
|
||||
* This is required for manifest v2, but will be removed when we migrate fully to manifest v3.
|
||||
*/
|
||||
(function (globalContext) {
|
||||
if (globalContext.document.contentType !== "text/html") {
|
||||
return;
|
||||
}
|
||||
|
||||
const script = globalContext.document.createElement("script");
|
||||
script.src = chrome.runtime.getURL("content/fido2-page-script.js");
|
||||
script.async = false;
|
||||
|
||||
const scriptInsertionPoint =
|
||||
globalContext.document.head || globalContext.document.documentElement;
|
||||
scriptInsertionPoint.prepend(script);
|
||||
})(globalThis);
|
||||
@@ -1,6 +1,5 @@
|
||||
export const Fido2ContentScript = {
|
||||
PageScript: "content/fido2-page-script.js",
|
||||
PageScriptAppend: "content/fido2-page-script-append-mv2.js",
|
||||
PageScriptDelayAppend: "content/fido2-page-script-delay-append-mv2.js",
|
||||
ContentScript: "content/fido2-content-script.js",
|
||||
} as const;
|
||||
|
||||
@@ -1156,7 +1156,6 @@ export default class MainBackground {
|
||||
this.fido2ClientService,
|
||||
this.vaultSettingsService,
|
||||
this.scriptInjectorService,
|
||||
this.configService,
|
||||
this.authService,
|
||||
);
|
||||
|
||||
@@ -1239,7 +1238,6 @@ export default class MainBackground {
|
||||
this.autofillService,
|
||||
this.scriptInjectorService,
|
||||
this.authService,
|
||||
this.configService,
|
||||
this.platformUtilsService,
|
||||
this.policyService,
|
||||
this.accountService,
|
||||
|
||||
@@ -10,7 +10,6 @@ import BrowserPopupUtils from "../browser-popup-utils";
|
||||
@Component({
|
||||
selector: "app-pop-out",
|
||||
templateUrl: "pop-out.component.html",
|
||||
standalone: true,
|
||||
imports: [CommonModule, JslibModule, IconButtonModule],
|
||||
})
|
||||
export class PopOutComponent implements OnInit {
|
||||
|
||||
@@ -11,7 +11,6 @@ import { enableAccountSwitching } from "../flags";
|
||||
@Component({
|
||||
selector: "app-header",
|
||||
templateUrl: "header.component.html",
|
||||
standalone: true,
|
||||
imports: [CommonModule, CurrentAccountComponent],
|
||||
})
|
||||
export class HeaderComponent {
|
||||
|
||||
@@ -9,7 +9,6 @@ import { PopupRouterCacheService } from "../view-cache/popup-router-cache.servic
|
||||
/** Navigate the browser popup to the previous page when the component is clicked. */
|
||||
@Directive({
|
||||
selector: "[popupBackAction]",
|
||||
standalone: true,
|
||||
})
|
||||
export class PopupBackBrowserDirective extends BitActionDirective {
|
||||
constructor(
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Component } from "@angular/core";
|
||||
@Component({
|
||||
selector: "popup-footer",
|
||||
templateUrl: "popup-footer.component.html",
|
||||
standalone: true,
|
||||
imports: [],
|
||||
})
|
||||
export class PopupFooterComponent {}
|
||||
|
||||
@@ -19,7 +19,6 @@ import { PopupPageComponent } from "./popup-page.component";
|
||||
@Component({
|
||||
selector: "popup-header",
|
||||
templateUrl: "popup-header.component.html",
|
||||
standalone: true,
|
||||
imports: [TypographyModule, CommonModule, IconButtonModule, JslibModule, AsyncActionsModule],
|
||||
})
|
||||
export class PopupHeaderComponent {
|
||||
|
||||
@@ -36,7 +36,6 @@ import { PopupTabNavigationComponent } from "./popup-tab-navigation.component";
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
`,
|
||||
standalone: true,
|
||||
})
|
||||
class ExtensionContainerComponent {}
|
||||
|
||||
@@ -71,7 +70,6 @@ class ExtensionContainerComponent {}
|
||||
</bit-item-group>
|
||||
</bit-section>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [CommonModule, ItemModule, BadgeModule, IconButtonModule, SectionComponent],
|
||||
})
|
||||
class VaultComponent {
|
||||
@@ -86,7 +84,6 @@ class VaultComponent {
|
||||
Add
|
||||
</button>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [ButtonModule],
|
||||
})
|
||||
class MockAddButtonComponent {}
|
||||
@@ -102,7 +99,6 @@ class MockAddButtonComponent {}
|
||||
aria-label="Pop out"
|
||||
></button>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [IconButtonModule],
|
||||
})
|
||||
class MockPopoutButtonComponent {}
|
||||
@@ -114,7 +110,6 @@ class MockPopoutButtonComponent {}
|
||||
<bit-avatar text="Ash Ketchum" size="small"></bit-avatar>
|
||||
</button>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [AvatarModule],
|
||||
})
|
||||
class MockCurrentAccountComponent {}
|
||||
@@ -122,7 +117,6 @@ class MockCurrentAccountComponent {}
|
||||
@Component({
|
||||
selector: "mock-search",
|
||||
template: ` <bit-search placeholder="Search"> </bit-search> `,
|
||||
standalone: true,
|
||||
imports: [SearchModule],
|
||||
})
|
||||
class MockSearchComponent {}
|
||||
@@ -134,7 +128,6 @@ class MockSearchComponent {}
|
||||
This is an important note about these ciphers
|
||||
</bit-banner>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [BannerModule],
|
||||
})
|
||||
class MockBannerComponent {}
|
||||
@@ -154,7 +147,6 @@ class MockBannerComponent {}
|
||||
<vault-placeholder></vault-placeholder>
|
||||
</popup-page>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [
|
||||
PopupPageComponent,
|
||||
PopupHeaderComponent,
|
||||
@@ -180,7 +172,6 @@ class MockVaultPageComponent {}
|
||||
<vault-placeholder></vault-placeholder>
|
||||
</popup-page>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [
|
||||
PopupPageComponent,
|
||||
PopupHeaderComponent,
|
||||
@@ -205,7 +196,6 @@ class MockVaultPagePoppedComponent {}
|
||||
<div class="tw-text-main">Generator content here</div>
|
||||
</popup-page>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [
|
||||
PopupPageComponent,
|
||||
PopupHeaderComponent,
|
||||
@@ -230,7 +220,6 @@ class MockGeneratorPageComponent {}
|
||||
<div class="tw-text-main">Send content here</div>
|
||||
</popup-page>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [
|
||||
PopupPageComponent,
|
||||
PopupHeaderComponent,
|
||||
@@ -255,7 +244,6 @@ class MockSendPageComponent {}
|
||||
<div class="tw-text-main">Settings content here</div>
|
||||
</popup-page>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [
|
||||
PopupPageComponent,
|
||||
PopupHeaderComponent,
|
||||
@@ -283,7 +271,6 @@ class MockSettingsPageComponent {}
|
||||
</popup-footer>
|
||||
</popup-page>
|
||||
`,
|
||||
standalone: true,
|
||||
imports: [
|
||||
PopupPageComponent,
|
||||
PopupHeaderComponent,
|
||||
|
||||
@@ -6,7 +6,6 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
@Component({
|
||||
selector: "popup-page",
|
||||
templateUrl: "popup-page.component.html",
|
||||
standalone: true,
|
||||
host: {
|
||||
class: "tw-h-full tw-flex tw-flex-col tw-overflow-y-hidden",
|
||||
},
|
||||
|
||||
@@ -17,7 +17,6 @@ export type NavButton = {
|
||||
@Component({
|
||||
selector: "popup-tab-navigation",
|
||||
templateUrl: "popup-tab-navigation.component.html",
|
||||
standalone: true,
|
||||
imports: [CommonModule, LinkModule, RouterModule, JslibModule, IconModule],
|
||||
host: {
|
||||
class: "tw-block tw-h-full tw-w-full tw-flex tw-flex-col",
|
||||
|
||||
@@ -17,7 +17,6 @@ export type DesktopSyncVerificationDialogParams = {
|
||||
|
||||
@Component({
|
||||
templateUrl: "desktop-sync-verification-dialog.component.html",
|
||||
standalone: true,
|
||||
imports: [JslibModule, ButtonModule, DialogModule],
|
||||
})
|
||||
export class DesktopSyncVerificationDialogComponent implements OnDestroy, OnInit {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { WritableSignal, signal } from "@angular/core";
|
||||
import { TestBed, discardPeriodicTasks, fakeAsync, tick } from "@angular/core/testing";
|
||||
import { TestBed } from "@angular/core/testing";
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { BehaviorSubject, firstValueFrom, timeout } from "rxjs";
|
||||
|
||||
@@ -483,22 +483,15 @@ describe("VaultPopupItemsService", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should update searchText$ when applyFilter is called", fakeAsync(() => {
|
||||
let latestValue: string | null;
|
||||
it("should update searchText$ when applyFilter is called", (done) => {
|
||||
service.searchText$.subscribe((val) => {
|
||||
latestValue = val;
|
||||
expect(val).toEqual("test search");
|
||||
expect(viewCacheService.mockSignal()).toEqual("test search");
|
||||
done();
|
||||
});
|
||||
tick();
|
||||
expect(latestValue!).toEqual("");
|
||||
|
||||
service.applyFilter("test search");
|
||||
tick();
|
||||
expect(latestValue!).toEqual("test search");
|
||||
|
||||
expect(viewCacheService.mockSignal()).toEqual("test search");
|
||||
|
||||
discardPeriodicTasks();
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
// A function to generate a list of ciphers of different types
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"files": ["./test.setup.ts"],
|
||||
"compilerOptions": {
|
||||
"isolatedModules": true,
|
||||
"emitDecoratorMetadata": false,
|
||||
"esModuleInterop": true
|
||||
}
|
||||
},
|
||||
"files": ["./test.setup.ts"]
|
||||
}
|
||||
|
||||
@@ -324,8 +324,6 @@ if (manifestVersion == 2) {
|
||||
// Manifest V2 background pages can be run through the regular build pipeline.
|
||||
// Since it's a standard webpage.
|
||||
mainConfig.entry.background = "./src/platform/background.ts";
|
||||
mainConfig.entry["content/fido2-page-script-append-mv2"] =
|
||||
"./src/autofill/fido2/content/fido2-page-script-append.mv2.ts";
|
||||
mainConfig.entry["content/fido2-page-script-delay-append-mv2"] =
|
||||
"./src/autofill/fido2/content/fido2-page-script-delay-append.mv2.ts";
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ const sharedConfig = require("../../libs/shared/jest.config.angular");
|
||||
/** @type {import('jest').Config} */
|
||||
module.exports = {
|
||||
...sharedConfig,
|
||||
preset: "jest-preset-angular",
|
||||
setupFilesAfterEnv: ["<rootDir>/test.setup.ts"],
|
||||
moduleNameMapper: pathsToModuleNameMapper(
|
||||
{ "@bitwarden/common/spec": ["../../libs/common/spec"], ...(compilerOptions?.paths ?? {}) },
|
||||
|
||||
@@ -9,7 +9,6 @@ export type BrowserSyncVerificationDialogParams = {
|
||||
|
||||
@Component({
|
||||
templateUrl: "browser-sync-verification-dialog.component.html",
|
||||
standalone: true,
|
||||
imports: [JslibModule, ButtonModule, DialogModule],
|
||||
})
|
||||
export class BrowserSyncVerificationDialogComponent {
|
||||
|
||||
@@ -13,7 +13,6 @@ import { FormFieldModule } from "@bitwarden/components";
|
||||
*/
|
||||
@Component({
|
||||
selector: "app-user-verification",
|
||||
standalone: true,
|
||||
imports: [CommonModule, JslibModule, ReactiveFormsModule, FormFieldModule, FormsModule],
|
||||
templateUrl: "user-verification.component.html",
|
||||
providers: [
|
||||
|
||||
@@ -9,7 +9,6 @@ export type VerifyNativeMessagingDialogData = {
|
||||
|
||||
@Component({
|
||||
templateUrl: "verify-native-messaging-dialog.component.html",
|
||||
standalone: true,
|
||||
imports: [JslibModule, ButtonModule, DialogModule],
|
||||
})
|
||||
export class VerifyNativeMessagingDialogComponent {
|
||||
|
||||
@@ -7,7 +7,6 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
@Component({
|
||||
selector: "app-nav",
|
||||
templateUrl: "nav.component.html",
|
||||
standalone: true,
|
||||
imports: [CommonModule, RouterLink, RouterLinkActive],
|
||||
})
|
||||
export class NavComponent {
|
||||
|
||||
@@ -24,7 +24,6 @@ export interface ApproveSshRequestParams {
|
||||
@Component({
|
||||
selector: "app-approve-ssh-request",
|
||||
templateUrl: "approve-ssh-request.html",
|
||||
standalone: true,
|
||||
imports: [
|
||||
DialogModule,
|
||||
CommonModule,
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"isolatedModules": true,
|
||||
"emitDecoratorMetadata": false
|
||||
},
|
||||
"files": ["./test.setup.ts"]
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ const sharedConfig = require("../../libs/shared/jest.config.angular");
|
||||
/** @type {import('jest').Config} */
|
||||
module.exports = {
|
||||
...sharedConfig,
|
||||
preset: "jest-preset-angular",
|
||||
setupFilesAfterEnv: ["<rootDir>/test.setup.ts"],
|
||||
moduleNameMapper: {
|
||||
// Replace ESM SDK with Node compatible SDK
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bitwarden/web-vault",
|
||||
"version": "2025.5.1",
|
||||
"version": "2025.6.0",
|
||||
"scripts": {
|
||||
"build:oss": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" webpack",
|
||||
"build:bit": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" webpack -c ../../bitwarden_license/bit-web/webpack.config.js",
|
||||
|
||||
@@ -11,7 +11,9 @@ import { DialogService, SimpleDialogOptions } from "@bitwarden/components";
|
||||
|
||||
import { OrganizationWarningsService } from "./organization-warnings.service";
|
||||
|
||||
describe("OrganizationWarningsService", () => {
|
||||
// Skipped since Angular complains about `TypeError: Cannot read properties of undefined (reading 'ngModule')`
|
||||
// which is typically a sign of circular dependencies. The problem seems to be originating from `ChangePlanDialogComponent`.
|
||||
describe.skip("OrganizationWarningsService", () => {
|
||||
let dialogService: MockProxy<DialogService>;
|
||||
let i18nService: MockProxy<I18nService>;
|
||||
let organizationApiService: MockProxy<OrganizationApiServiceAbstraction>;
|
||||
|
||||
@@ -10,7 +10,6 @@ import { SharedModule } from "../shared";
|
||||
type SizeTypes = "xlarge" | "large" | "default" | "small" | "xsmall";
|
||||
@Component({
|
||||
selector: "dynamic-avatar",
|
||||
standalone: true,
|
||||
imports: [SharedModule],
|
||||
template: `<span [title]="title">
|
||||
<bit-avatar
|
||||
|
||||
@@ -15,7 +15,6 @@ import { SharedModule } from "../../shared";
|
||||
@Component({
|
||||
selector: "environment-selector",
|
||||
templateUrl: "environment-selector.component.html",
|
||||
standalone: true,
|
||||
imports: [SharedModule],
|
||||
})
|
||||
export class EnvironmentSelectorComponent implements OnInit {
|
||||
|
||||
@@ -19,6 +19,7 @@ import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { ContainerService } from "@bitwarden/common/platform/services/container.service";
|
||||
import { UserAutoUnlockKeyService } from "@bitwarden/common/platform/services/user-auto-unlock-key.service";
|
||||
import { EventUploadService } from "@bitwarden/common/services/event/event-upload.service";
|
||||
import { TaskService } from "@bitwarden/common/vault/tasks";
|
||||
import { KeyService as KeyServiceAbstraction } from "@bitwarden/key-management";
|
||||
|
||||
import { VersionService } from "../platform/version.service";
|
||||
@@ -43,6 +44,7 @@ export class InitService {
|
||||
private sdkLoadService: SdkLoadService,
|
||||
private configService: ConfigService,
|
||||
private bulkEncryptService: BulkEncryptService,
|
||||
private taskService: TaskService,
|
||||
@Inject(DOCUMENT) private document: Document,
|
||||
) {}
|
||||
|
||||
@@ -75,6 +77,7 @@ export class InitService {
|
||||
this.themingService.applyThemeChangesTo(this.document);
|
||||
this.versionService.applyVersionToWindow();
|
||||
void this.ipcService.init();
|
||||
this.taskService.listenForTaskNotifications();
|
||||
|
||||
const containerService = new ContainerService(this.keyService, this.encryptService);
|
||||
containerService.attachToGlobal(this.win);
|
||||
|
||||
@@ -10,7 +10,6 @@ import { SharedModule } from "../shared";
|
||||
@Component({
|
||||
selector: "app-frontend-layout",
|
||||
templateUrl: "frontend-layout.component.html",
|
||||
standalone: true,
|
||||
imports: [SharedModule, EnvironmentSelectorComponent],
|
||||
})
|
||||
export class FrontendLayoutComponent implements OnInit, OnDestroy {
|
||||
|
||||
@@ -49,13 +49,13 @@ class MockStateService {
|
||||
@Component({
|
||||
selector: "product-switcher",
|
||||
template: `<button type="button" bitIconButton="bwi-filter"></button>`,
|
||||
standalone: false,
|
||||
})
|
||||
class MockProductSwitcher {}
|
||||
|
||||
@Component({
|
||||
selector: "dynamic-avatar",
|
||||
template: `<bit-avatar [text]="name$ | async"></bit-avatar>`,
|
||||
standalone: true,
|
||||
imports: [CommonModule, AvatarModule],
|
||||
})
|
||||
class MockDynamicAvatar implements Partial<DynamicAvatarComponent> {
|
||||
|
||||
@@ -17,7 +17,6 @@ import { TrialFlowService } from "./../../billing/services/trial-flow.service";
|
||||
@Component({
|
||||
selector: "org-switcher",
|
||||
templateUrl: "org-switcher.component.html",
|
||||
standalone: true,
|
||||
imports: [CommonModule, JslibModule, NavigationModule],
|
||||
})
|
||||
export class OrgSwitcherComponent {
|
||||
|
||||
@@ -12,7 +12,6 @@ import { NavigationModule } from "@bitwarden/components";
|
||||
*ngIf="isDev"
|
||||
(click)="toggleWidth()"
|
||||
></bit-nav-item>`,
|
||||
standalone: true,
|
||||
imports: [CommonModule, NavigationModule],
|
||||
})
|
||||
export class ToggleWidthComponent {
|
||||
|
||||
@@ -19,7 +19,6 @@ import { WebLayoutModule } from "./web-layout.module";
|
||||
@Component({
|
||||
selector: "app-user-layout",
|
||||
templateUrl: "user-layout.component.html",
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule,
|
||||
|
||||
@@ -8,7 +8,6 @@ import { ProductSwitcherModule } from "./product-switcher/product-switcher.modul
|
||||
@Component({
|
||||
selector: "app-layout",
|
||||
templateUrl: "web-layout.component.html",
|
||||
standalone: true,
|
||||
imports: [CommonModule, LayoutComponent, ProductSwitcherModule],
|
||||
})
|
||||
export class WebLayoutComponent {
|
||||
|
||||
@@ -9,7 +9,6 @@ import { ToggleWidthComponent } from "./toggle-width.component";
|
||||
@Component({
|
||||
selector: "app-side-nav",
|
||||
templateUrl: "web-side-nav.component.html",
|
||||
standalone: true,
|
||||
imports: [CommonModule, NavigationModule, ProductSwitcherModule, ToggleWidthComponent],
|
||||
})
|
||||
export class WebSideNavComponent {
|
||||
|
||||
@@ -8,6 +8,9 @@ import { AccessComponent } from "./tools/send/send-access/access.component";
|
||||
import { OrganizationBadgeModule } from "./vault/individual-vault/organization-badge/organization-badge.module";
|
||||
import { VaultFilterModule } from "./vault/individual-vault/vault-filter/vault-filter.module";
|
||||
|
||||
// Register the locales for the application
|
||||
import "./shared/locales";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
SharedModule,
|
||||
|
||||
@@ -15,7 +15,6 @@ import { SharedModule } from "../shared";
|
||||
@Component({
|
||||
selector: "app-domain-rules",
|
||||
templateUrl: "domain-rules.component.html",
|
||||
standalone: true,
|
||||
imports: [SharedModule, HeaderModule],
|
||||
})
|
||||
export class DomainRulesComponent implements OnInit {
|
||||
|
||||
@@ -41,7 +41,6 @@ import { SharedModule } from "../shared";
|
||||
@Component({
|
||||
selector: "app-preferences",
|
||||
templateUrl: "preferences.component.html",
|
||||
standalone: true,
|
||||
imports: [SharedModule, HeaderModule, VaultTimeoutInputComponent],
|
||||
})
|
||||
export class PreferencesComponent implements OnInit, OnDestroy {
|
||||
|
||||
@@ -9,7 +9,6 @@ import { SharedModule } from "../../shared.module";
|
||||
@Component({
|
||||
selector: "app-account-fingerprint",
|
||||
templateUrl: "account-fingerprint.component.html",
|
||||
standalone: true,
|
||||
imports: [SharedModule],
|
||||
})
|
||||
export class AccountFingerprintComponent implements OnInit {
|
||||
|
||||
@@ -32,9 +32,6 @@ import {
|
||||
TypographyModule,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
// Register the locales for the application
|
||||
import "./locales";
|
||||
|
||||
/**
|
||||
* This NgModule should contain the most basic shared directives, pipes, and components. They
|
||||
* should be widely used by other modules to be considered for adding to this module. If in doubt
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"isolatedModules": true,
|
||||
"emitDecoratorMetadata": false
|
||||
},
|
||||
"files": ["./test.setup.ts"]
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ const sharedConfig = require("../../libs/shared/jest.config.angular");
|
||||
/** @type {import('jest').Config} */
|
||||
module.exports = {
|
||||
...sharedConfig,
|
||||
preset: "jest-preset-angular",
|
||||
setupFilesAfterEnv: ["../../apps/web/test.setup.ts"],
|
||||
moduleNameMapper: pathsToModuleNameMapper(
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { AppComponent as BaseAppComponent } from "@bitwarden/web-vault/app/app.component";
|
||||
|
||||
import { ActivateAutofillPolicy } from "./admin-console/policies/activate-autofill.component";
|
||||
@@ -25,13 +24,8 @@ export class AppComponent extends BaseAppComponent implements OnInit {
|
||||
new ActivateAutofillPolicy(),
|
||||
]);
|
||||
|
||||
this.configService.getFeatureFlag(FeatureFlag.IdpAutoSubmitLogin).then((enabled) => {
|
||||
if (
|
||||
enabled &&
|
||||
!this.policyListService.getPolicies().some((p) => p instanceof AutomaticAppLoginPolicy)
|
||||
) {
|
||||
this.policyListService.addPolicies([new AutomaticAppLoginPolicy()]);
|
||||
}
|
||||
});
|
||||
if (!this.policyListService.getPolicies().some((p) => p instanceof AutomaticAppLoginPolicy)) {
|
||||
this.policyListService.addPolicies([new AutomaticAppLoginPolicy()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
type="button"
|
||||
[buttonType]="'primary'"
|
||||
bitButton
|
||||
*ngIf="isCriticalAppsFeatureEnabled"
|
||||
[disabled]="!selectedUrls.size"
|
||||
[loading]="markingAsCritical"
|
||||
(click)="markAppsAsCritical()"
|
||||
@@ -74,7 +73,6 @@
|
||||
[showRowCheckBox]="true"
|
||||
[showRowMenuForCriticalApps]="false"
|
||||
[selectedUrls]="selectedUrls"
|
||||
[isCriticalAppsFeatureEnabled]="isCriticalAppsFeatureEnabled"
|
||||
[isDrawerIsOpenForThisRecord]="isDrawerOpenForTableRow"
|
||||
[checkboxChange]="onCheckboxChange"
|
||||
[showAppAtRiskMembers]="showAppAtRiskMembers"
|
||||
|
||||
@@ -21,7 +21,6 @@ import {
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { FeatureFlag } 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 { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
@@ -74,13 +73,8 @@ export class AllApplicationsComponent implements OnInit {
|
||||
|
||||
destroyRef = inject(DestroyRef);
|
||||
isLoading$: Observable<boolean> = of(false);
|
||||
isCriticalAppsFeatureEnabled = false;
|
||||
|
||||
async ngOnInit() {
|
||||
this.isCriticalAppsFeatureEnabled = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.CriticalApps,
|
||||
);
|
||||
|
||||
const organizationId = this.activatedRoute.snapshot.paramMap.get("organizationId") ?? "";
|
||||
const userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<ng-container>
|
||||
<bit-table-scroll [dataSource]="dataSource" [rowSize]="53">
|
||||
<ng-container header>
|
||||
<th *ngIf="isCriticalAppsFeatureEnabled"></th>
|
||||
<th></th>
|
||||
<th bitCell></th>
|
||||
<th bitSortable="applicationName" bitCell>{{ "application" | i18n }}</th>
|
||||
<th bitSortable="atRiskPasswordCount" bitCell>{{ "atRiskPasswords" | i18n }}</th>
|
||||
@@ -12,7 +12,7 @@
|
||||
<ng-template bitRowDef let-row>
|
||||
<td
|
||||
bitCell
|
||||
*ngIf="isCriticalAppsFeatureEnabled && showRowCheckBox"
|
||||
*ngIf="showRowCheckBox"
|
||||
[ngClass]="{ 'tw-bg-primary-100': isDrawerIsOpenForThisRecord(row.applicationName) }"
|
||||
>
|
||||
<input
|
||||
|
||||
@@ -18,7 +18,6 @@ export class AppTableRowScrollableComponent {
|
||||
@Input() showRowMenuForCriticalApps: boolean = false;
|
||||
@Input() showRowCheckBox: boolean = false;
|
||||
@Input() selectedUrls: Set<string> = new Set<string>();
|
||||
@Input() isCriticalAppsFeatureEnabled: boolean = false;
|
||||
@Input() isDrawerIsOpenForThisRecord!: (applicationName: string) => boolean;
|
||||
@Input() showAppAtRiskMembers!: (applicationName: string) => void;
|
||||
@Input() unmarkAsCriticalApp!: (applicationName: string) => void;
|
||||
|
||||
@@ -82,7 +82,6 @@
|
||||
[dataSource]="dataSource"
|
||||
[showRowCheckBox]="false"
|
||||
[showRowMenuForCriticalApps]="true"
|
||||
[isCriticalAppsFeatureEnabled]="true"
|
||||
[isDrawerIsOpenForThisRecord]="isDrawerOpenForTableRow"
|
||||
[showAppAtRiskMembers]="showAppAtRiskMembers"
|
||||
[unmarkAsCriticalApp]="unmarkAsCriticalApp"
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<bit-tab label="{{ 'allApplicationsWithCount' | i18n: appsCount }}">
|
||||
<tools-all-applications></tools-all-applications>
|
||||
</bit-tab>
|
||||
<bit-tab *ngIf="isCriticalAppsFeatureEnabled">
|
||||
<bit-tab>
|
||||
<ng-template bitTabLabel>
|
||||
<i class="bwi bwi-star"></i>
|
||||
{{ "criticalApplicationsWithCount" | i18n: (criticalApps$ | async)?.length ?? 0 }}
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
DrawerType,
|
||||
PasswordHealthReportApplicationsResponse,
|
||||
} from "@bitwarden/bit-common/dirt/reports/risk-insights/models/password-health";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { devFlagEnabled } from "@bitwarden/common/platform/misc/flags";
|
||||
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||
@@ -70,7 +69,6 @@ export class RiskInsightsComponent implements OnInit {
|
||||
|
||||
dataLastUpdated: Date = new Date();
|
||||
|
||||
isCriticalAppsFeatureEnabled: boolean = false;
|
||||
criticalApps$: Observable<PasswordHealthReportApplicationsResponse[]> = new Observable();
|
||||
showDebugTabs: boolean = false;
|
||||
|
||||
@@ -100,10 +98,6 @@ export class RiskInsightsComponent implements OnInit {
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.isCriticalAppsFeatureEnabled = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.CriticalApps,
|
||||
);
|
||||
|
||||
this.showDebugTabs = devFlagEnabled("showRiskInsightsDebug");
|
||||
|
||||
this.route.paramMap
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"isolatedModules": true,
|
||||
"emitDecoratorMetadata": false
|
||||
},
|
||||
"files": ["../../apps/web/test.setup.ts"]
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ export default tseslint.config(
|
||||
"@angular-eslint/no-output-on-prefix": 0,
|
||||
"@angular-eslint/no-output-rename": 0,
|
||||
"@angular-eslint/no-outputs-metadata-property": 0,
|
||||
"@angular-eslint/prefer-standalone": 0,
|
||||
"@angular-eslint/use-lifecycle-interface": "error",
|
||||
"@angular-eslint/use-pipe-transform-interface": 0,
|
||||
"@bitwarden/platform/required-using": "error",
|
||||
|
||||
@@ -8,7 +8,6 @@ const sharedConfig = require("../../libs/shared/jest.config.angular");
|
||||
module.exports = {
|
||||
...sharedConfig,
|
||||
displayName: "libs/admin-console tests",
|
||||
preset: "jest-preset-angular",
|
||||
setupFilesAfterEnv: ["<rootDir>/test.setup.ts"],
|
||||
moduleNameMapper: pathsToModuleNameMapper(
|
||||
// lets us use @bitwarden/common/spec in tests
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"isolatedModules": true,
|
||||
"emitDecoratorMetadata": false
|
||||
},
|
||||
"files": ["./test.setup.ts"]
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ const sharedConfig = require("../../libs/shared/jest.config.angular");
|
||||
module.exports = {
|
||||
...sharedConfig,
|
||||
displayName: "libs/angular tests",
|
||||
preset: "jest-preset-angular",
|
||||
setupFilesAfterEnv: ["<rootDir>/test.setup.ts"],
|
||||
moduleNameMapper: pathsToModuleNameMapper(
|
||||
// lets us use @bitwarden/common/spec in tests
|
||||
|
||||
@@ -13,7 +13,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
|
||||
import { activeAuthGuard } from "./active-auth.guard";
|
||||
|
||||
@Component({ template: "" })
|
||||
@Component({ template: "", standalone: false })
|
||||
class EmptyComponent {}
|
||||
|
||||
describe("activeAuthGuard", () => {
|
||||
|
||||
@@ -27,6 +27,7 @@ const testStringFeatureValue = "test-value";
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
standalone: false,
|
||||
})
|
||||
class TestComponent {
|
||||
testBooleanFeature = testBooleanFeature;
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Directive, HostListener, Input } from "@angular/core";
|
||||
|
||||
@Directive({
|
||||
selector: "[appTextDrag]",
|
||||
standalone: true,
|
||||
host: {
|
||||
draggable: "true",
|
||||
class: "tw-cursor-move",
|
||||
|
||||
@@ -2,7 +2,6 @@ import { Pipe, PipeTransform } from "@angular/core";
|
||||
|
||||
@Pipe({
|
||||
name: "pluralize",
|
||||
standalone: true,
|
||||
})
|
||||
export class PluralizePipe implements PipeTransform {
|
||||
transform(count: number, singular: string, plural: string): string {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { I18nMockService, ToastService } from "@bitwarden/components/src";
|
||||
|
||||
import { canAccessFeature } from "./feature-flag.guard";
|
||||
|
||||
@Component({ template: "" })
|
||||
@Component({ template: "", standalone: false })
|
||||
export class EmptyComponent {}
|
||||
|
||||
describe("canAccessFeature", () => {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"isolatedModules": true,
|
||||
"emitDecoratorMetadata": false
|
||||
},
|
||||
"files": ["./test.setup.ts"]
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ const sharedConfig = require("../../libs/shared/jest.config.angular");
|
||||
module.exports = {
|
||||
...sharedConfig,
|
||||
displayName: "libs/auth tests",
|
||||
preset: "jest-preset-angular",
|
||||
setupFilesAfterEnv: ["<rootDir>/test.setup.ts"],
|
||||
moduleNameMapper: pathsToModuleNameMapper(
|
||||
// lets us use @bitwarden/common/spec in tests
|
||||
|
||||
@@ -44,7 +44,7 @@ import { TwoFactorAuthComponentCacheService } from "./two-factor-auth-component-
|
||||
import { TwoFactorAuthComponentService } from "./two-factor-auth-component.service";
|
||||
import { TwoFactorAuthComponent } from "./two-factor-auth.component";
|
||||
|
||||
@Component({})
|
||||
@Component({ standalone: false })
|
||||
class TestTwoFactorComponent extends TwoFactorAuthComponent {}
|
||||
|
||||
describe("TwoFactorAuthComponent", () => {
|
||||
|
||||
@@ -11,7 +11,7 @@ import { LoginStrategyServiceAbstraction } from "../../common";
|
||||
|
||||
import { TwoFactorAuthGuard } from "./two-factor-auth.guard";
|
||||
|
||||
@Component({ template: "" })
|
||||
@Component({ template: "", standalone: true })
|
||||
export class EmptyComponent {}
|
||||
|
||||
describe("TwoFactorAuthGuard", () => {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"isolatedModules": true,
|
||||
"emitDecoratorMetadata": false
|
||||
},
|
||||
"files": ["./test.setup.ts"]
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ const sharedConfig = require("../../libs/shared/jest.config.angular");
|
||||
module.exports = {
|
||||
...sharedConfig,
|
||||
displayName: "libs/billing tests",
|
||||
preset: "jest-preset-angular",
|
||||
setupFilesAfterEnv: ["<rootDir>/test.setup.ts"],
|
||||
moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, {
|
||||
prefix: "<rootDir>/",
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"isolatedModules": true,
|
||||
"emitDecoratorMetadata": false
|
||||
},
|
||||
"files": ["./test.setup.ts"]
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ export abstract class ApiService {
|
||||
deleteManyCiphersAdmin: (request: CipherBulkDeleteRequest) => Promise<any>;
|
||||
putMoveCiphers: (request: CipherBulkMoveRequest) => Promise<any>;
|
||||
putShareCipher: (id: string, request: CipherShareRequest) => Promise<CipherResponse>;
|
||||
putShareCiphers: (request: CipherBulkShareRequest) => Promise<any>;
|
||||
putShareCiphers: (request: CipherBulkShareRequest) => Promise<CipherResponse[]>;
|
||||
putCipherCollections: (
|
||||
id: string,
|
||||
request: CipherCollectionsRequest,
|
||||
|
||||
@@ -21,9 +21,7 @@ export enum FeatureFlag {
|
||||
|
||||
/* Autofill */
|
||||
BlockBrowserInjectionsByDomain = "block-browser-injections-by-domain",
|
||||
DelayFido2PageScriptInitWithinMv2 = "delay-fido2-page-script-init-within-mv2",
|
||||
EnableNewCardCombinedExpiryAutofill = "enable-new-card-combined-expiry-autofill",
|
||||
IdpAutoSubmitLogin = "idp-auto-submit-login",
|
||||
NotificationRefresh = "notification-refresh",
|
||||
UseTreeWalkerApiForPageDetailsCollection = "use-tree-walker-api-for-page-details-collection",
|
||||
MacOsNativeCredentialSync = "macos-native-credential-sync",
|
||||
@@ -37,7 +35,6 @@ export enum FeatureFlag {
|
||||
UseOrganizationWarningsService = "use-organization-warnings-service",
|
||||
|
||||
/* Data Insights and Reporting */
|
||||
CriticalApps = "pm-14466-risk-insights-critical-application",
|
||||
EnableRiskInsightsNotifications = "enable-risk-insights-notifications",
|
||||
|
||||
/* Key Management */
|
||||
@@ -87,15 +84,12 @@ export const DefaultFeatureFlagValue = {
|
||||
|
||||
/* Autofill */
|
||||
[FeatureFlag.BlockBrowserInjectionsByDomain]: FALSE,
|
||||
[FeatureFlag.DelayFido2PageScriptInitWithinMv2]: FALSE,
|
||||
[FeatureFlag.EnableNewCardCombinedExpiryAutofill]: FALSE,
|
||||
[FeatureFlag.IdpAutoSubmitLogin]: FALSE,
|
||||
[FeatureFlag.NotificationRefresh]: FALSE,
|
||||
[FeatureFlag.UseTreeWalkerApiForPageDetailsCollection]: FALSE,
|
||||
[FeatureFlag.MacOsNativeCredentialSync]: FALSE,
|
||||
|
||||
/* Data Insights and Reporting */
|
||||
[FeatureFlag.CriticalApps]: FALSE,
|
||||
[FeatureFlag.EnableRiskInsightsNotifications]: FALSE,
|
||||
|
||||
/* Tools */
|
||||
|
||||
@@ -532,8 +532,8 @@ export class ApiService implements ApiServiceAbstraction {
|
||||
return new CipherResponse(r);
|
||||
}
|
||||
|
||||
putShareCiphers(request: CipherBulkShareRequest): Promise<any> {
|
||||
return this.send("PUT", "/ciphers/share", request, true, false);
|
||||
async putShareCiphers(request: CipherBulkShareRequest): Promise<CipherResponse[]> {
|
||||
return await this.send("PUT", "/ciphers/share", request, true, true);
|
||||
}
|
||||
|
||||
async putCipherCollections(
|
||||
|
||||
@@ -836,7 +836,7 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
organizationId: string,
|
||||
collectionIds: string[],
|
||||
userId: UserId,
|
||||
): Promise<any> {
|
||||
) {
|
||||
const promises: Promise<any>[] = [];
|
||||
const encCiphers: Cipher[] = [];
|
||||
for (const cipher of ciphers) {
|
||||
@@ -851,7 +851,16 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
await Promise.all(promises);
|
||||
const request = new CipherBulkShareRequest(encCiphers, collectionIds, userId);
|
||||
try {
|
||||
await this.apiService.putShareCiphers(request);
|
||||
const response = await this.apiService.putShareCiphers(request);
|
||||
const responseMap = new Map(response.map((c) => [c.id, c]));
|
||||
|
||||
encCiphers.forEach((cipher) => {
|
||||
const matchingCipher = responseMap.get(cipher.id);
|
||||
if (matchingCipher) {
|
||||
cipher.revisionDate = new Date(matchingCipher.revisionDate);
|
||||
}
|
||||
});
|
||||
await this.upsert(encCiphers.map((c) => c.toCipherData()));
|
||||
} catch (e) {
|
||||
for (const cipher of ciphers) {
|
||||
cipher.organizationId = null;
|
||||
@@ -859,7 +868,6 @@ export class CipherService implements CipherServiceAbstraction {
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
await this.upsert(encCiphers.map((c) => c.toCipherData()));
|
||||
}
|
||||
|
||||
saveAttachmentWithServer(
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"isolatedModules": true,
|
||||
"emitDecoratorMetadata": false
|
||||
},
|
||||
"files": ["./test.setup.ts"]
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ const sharedConfig = require("../../libs/shared/jest.config.angular");
|
||||
module.exports = {
|
||||
...sharedConfig,
|
||||
displayName: "libs/components tests",
|
||||
preset: "jest-preset-angular",
|
||||
setupFilesAfterEnv: ["<rootDir>/test.setup.ts"],
|
||||
moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, {
|
||||
prefix: "<rootDir>/",
|
||||
|
||||
@@ -6,7 +6,6 @@ import { FocusableElement } from "../shared/focusable-element";
|
||||
|
||||
@Directive({
|
||||
selector: "bitA11yCell",
|
||||
standalone: true,
|
||||
providers: [{ provide: FocusableElement, useExisting: A11yCellDirective }],
|
||||
})
|
||||
export class A11yCellDirective implements FocusableElement {
|
||||
|
||||
@@ -15,7 +15,6 @@ import { A11yRowDirective } from "./a11y-row.directive";
|
||||
|
||||
@Directive({
|
||||
selector: "bitA11yGrid",
|
||||
standalone: true,
|
||||
})
|
||||
export class A11yGridDirective implements AfterViewInit {
|
||||
@HostBinding("attr.role")
|
||||
|
||||
@@ -13,7 +13,6 @@ import { A11yCellDirective } from "./a11y-cell.directive";
|
||||
|
||||
@Directive({
|
||||
selector: "bitA11yRow",
|
||||
standalone: true,
|
||||
})
|
||||
export class A11yRowDirective implements AfterViewInit {
|
||||
@HostBinding("attr.role")
|
||||
|
||||
@@ -4,7 +4,6 @@ import { Directive, ElementRef, Input, OnInit, Renderer2 } from "@angular/core";
|
||||
|
||||
@Directive({
|
||||
selector: "[appA11yTitle]",
|
||||
standalone: true,
|
||||
})
|
||||
export class A11yTitleDirective implements OnInit {
|
||||
@Input() set appA11yTitle(title: string) {
|
||||
|
||||
@@ -15,7 +15,6 @@ import { FunctionReturningAwaitable, functionToObservable } from "../utils/funct
|
||||
*/
|
||||
@Directive({
|
||||
selector: "[bitAction]",
|
||||
standalone: true,
|
||||
})
|
||||
export class BitActionDirective implements OnDestroy {
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
@@ -14,7 +14,6 @@ import { FunctionReturningAwaitable, functionToObservable } from "../utils/funct
|
||||
*/
|
||||
@Directive({
|
||||
selector: "[formGroup][bitSubmit]",
|
||||
standalone: true,
|
||||
})
|
||||
export class BitSubmitDirective implements OnInit, OnDestroy {
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
@@ -25,7 +25,6 @@ import { BitSubmitDirective } from "./bit-submit.directive";
|
||||
*/
|
||||
@Directive({
|
||||
selector: "button[bitFormButton]",
|
||||
standalone: true,
|
||||
})
|
||||
export class BitFormButtonDirective implements OnDestroy {
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
@@ -30,11 +30,11 @@ const template = `
|
||||
<button type="button" bitSuffix bitIconButton="bwi-refresh" bitFormButton [bitAction]="refresh"></button>
|
||||
</bit-form-field>
|
||||
|
||||
<button class="tw-mr-2" type="submit" buttonType="primary" bitButton bitFormButton>Submit</button>
|
||||
<button class="tw-mr-2" type="button" buttonType="secondary" bitButton bitFormButton>Cancel</button>
|
||||
<button class="tw-mr-2" type="button" buttonType="danger" bitButton bitFormButton [bitAction]="delete">Delete</button>
|
||||
<button class="tw-mr-2" type="button" buttonType="secondary" bitButton bitFormButton [disabled]="true">Disabled</button>
|
||||
<button class="tw-mr-2" type="button" buttonType="secondary" bitIconButton="bwi-star" bitFormButton [bitAction]="delete">Delete</button>
|
||||
<button class="tw-me-2" type="submit" buttonType="primary" bitButton bitFormButton>Submit</button>
|
||||
<button class="tw-me-2" type="button" buttonType="secondary" bitButton bitFormButton>Cancel</button>
|
||||
<button class="tw-me-2" type="button" buttonType="danger" bitButton bitFormButton [bitAction]="delete">Delete</button>
|
||||
<button class="tw-me-2" type="button" buttonType="secondary" bitButton bitFormButton [disabled]="true">Disabled</button>
|
||||
<button class="tw-me-2" type="button" buttonType="secondary" bitIconButton="bwi-star" bitFormButton [bitAction]="delete">Delete</button>
|
||||
</form>`;
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -12,7 +12,7 @@ import { IconButtonModule } from "../icon-button";
|
||||
import { BitActionDirective } from "./bit-action.directive";
|
||||
|
||||
const template = /*html*/ `
|
||||
<button bitButton buttonType="primary" [bitAction]="action" class="tw-mr-2">
|
||||
<button bitButton buttonType="primary" [bitAction]="action" class="tw-me-2">
|
||||
Perform action {{ statusEmoji }}
|
||||
</button>
|
||||
<button bitIconButton="bwi-trash" buttonType="danger" [bitAction]="action"></button>`;
|
||||
|
||||
@@ -27,7 +27,6 @@ const SizeClasses: Record<SizeTypes, string[]> = {
|
||||
template: `@if (src) {
|
||||
<img [src]="src" title="{{ title || text }}" [ngClass]="classList" />
|
||||
}`,
|
||||
standalone: true,
|
||||
imports: [NgClass],
|
||||
})
|
||||
export class AvatarComponent implements OnChanges {
|
||||
|
||||
@@ -10,7 +10,6 @@ import { BadgeModule, BadgeVariant } from "../badge";
|
||||
@Component({
|
||||
selector: "bit-badge-list",
|
||||
templateUrl: "badge-list.component.html",
|
||||
standalone: true,
|
||||
imports: [BadgeModule, I18nPipe],
|
||||
})
|
||||
export class BadgeListComponent implements OnChanges {
|
||||
|
||||
@@ -51,16 +51,15 @@ const hoverStyles: Record<BadgeVariant, string[]> = {
|
||||
* The Badge directive can be used on a `<span>` (non clickable events), or an `<a>` or `<button>` tag
|
||||
|
||||
* > `NOTE:` The Focus and Hover states only apply to badges used for interactive events.
|
||||
*
|
||||
*
|
||||
* > `NOTE:` The `disabled` state only applies to buttons.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Component({
|
||||
selector: "span[bitBadge], a[bitBadge], button[bitBadge]",
|
||||
providers: [{ provide: FocusableElement, useExisting: BadgeComponent }],
|
||||
imports: [CommonModule],
|
||||
templateUrl: "badge.component.html",
|
||||
standalone: true,
|
||||
})
|
||||
export class BadgeComponent implements FocusableElement {
|
||||
@HostBinding("class") get classList() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div
|
||||
class="tw-flex tw-items-center tw-gap-2 tw-p-2 tw-pl-4 tw-text-main tw-border-transparent tw-bg-clip-padding tw-border-solid tw-border-b tw-border-0"
|
||||
class="tw-flex tw-items-center tw-gap-2 tw-p-2 tw-ps-4 tw-text-main tw-border-transparent tw-bg-clip-padding tw-border-solid tw-border-b tw-border-0"
|
||||
[ngClass]="bannerClass"
|
||||
[attr.role]="useAlertRole ? 'status' : null"
|
||||
[attr.aria-live]="useAlertRole ? 'polite' : null"
|
||||
|
||||
@@ -28,7 +28,6 @@ const defaultIcon: Record<BannerType, string> = {
|
||||
@Component({
|
||||
selector: "bit-banner",
|
||||
templateUrl: "./banner.component.html",
|
||||
standalone: true,
|
||||
imports: [CommonModule, IconButtonModule, I18nPipe],
|
||||
})
|
||||
export class BannerComponent implements OnInit {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<ng-template>
|
||||
@if (icon) {
|
||||
<i class="bwi {{ icon }} !tw-mr-2" aria-hidden="true"></i>
|
||||
<i class="bwi {{ icon }} !tw-me-2" aria-hidden="true"></i>
|
||||
}
|
||||
<ng-content></ng-content>
|
||||
</ng-template>
|
||||
|
||||
@@ -7,7 +7,6 @@ import { QueryParamsHandling } from "@angular/router";
|
||||
@Component({
|
||||
selector: "bit-breadcrumb",
|
||||
templateUrl: "./breadcrumb.component.html",
|
||||
standalone: true,
|
||||
})
|
||||
export class BreadcrumbComponent {
|
||||
@Input()
|
||||
|
||||
@@ -16,7 +16,6 @@ import { BreadcrumbComponent } from "./breadcrumb.component";
|
||||
@Component({
|
||||
selector: "bit-breadcrumbs",
|
||||
templateUrl: "./breadcrumbs.component.html",
|
||||
standalone: true,
|
||||
imports: [CommonModule, LinkModule, RouterModule, IconButtonModule, MenuModule],
|
||||
})
|
||||
export class BreadcrumbsComponent {
|
||||
|
||||
@@ -85,6 +85,7 @@ describe("Button", () => {
|
||||
|
||||
<button id="disabled" type="button" bitButton disabled>Button</button>
|
||||
`,
|
||||
standalone: false,
|
||||
})
|
||||
class TestApp {
|
||||
buttonType: string;
|
||||
|
||||
@@ -52,7 +52,6 @@ const buttonStyles: Record<ButtonType, string[]> = {
|
||||
selector: "button[bitButton], a[bitButton]",
|
||||
templateUrl: "button.component.html",
|
||||
providers: [{ provide: ButtonLikeAbstraction, useExisting: ButtonComponent }],
|
||||
standalone: true,
|
||||
imports: [NgClass],
|
||||
host: {
|
||||
"[attr.disabled]": "disabledAttr()",
|
||||
|
||||
@@ -88,13 +88,13 @@ export const DisabledWithAttribute: Story = {
|
||||
props: args,
|
||||
template: `
|
||||
@if (disabled) {
|
||||
<button bitButton disabled [loading]="loading" [block]="block" buttonType="primary" class="tw-mr-2">Primary</button>
|
||||
<button bitButton disabled [loading]="loading" [block]="block" buttonType="secondary" class="tw-mr-2">Secondary</button>
|
||||
<button bitButton disabled [loading]="loading" [block]="block" buttonType="danger" class="tw-mr-2">Danger</button>
|
||||
<button bitButton disabled [loading]="loading" [block]="block" buttonType="primary" class="tw-me-2">Primary</button>
|
||||
<button bitButton disabled [loading]="loading" [block]="block" buttonType="secondary" class="tw-me-2">Secondary</button>
|
||||
<button bitButton disabled [loading]="loading" [block]="block" buttonType="danger" class="tw-me-2">Danger</button>
|
||||
} @else {
|
||||
<button bitButton [loading]="loading" [block]="block" buttonType="primary" class="tw-mr-2">Primary</button>
|
||||
<button bitButton [loading]="loading" [block]="block" buttonType="secondary" class="tw-mr-2">Secondary</button>
|
||||
<button bitButton [loading]="loading" [block]="block" buttonType="danger" class="tw-mr-2">Danger</button>
|
||||
<button bitButton [loading]="loading" [block]="block" buttonType="primary" class="tw-me-2">Primary</button>
|
||||
<button bitButton [loading]="loading" [block]="block" buttonType="secondary" class="tw-me-2">Secondary</button>
|
||||
<button bitButton [loading]="loading" [block]="block" buttonType="danger" class="tw-me-2">Danger</button>
|
||||
}
|
||||
`,
|
||||
}),
|
||||
@@ -110,10 +110,10 @@ export const Block: Story = {
|
||||
template: `
|
||||
<span class="tw-flex">
|
||||
<button bitButton [buttonType]="buttonType" [block]="block">[block]="true" Button</button>
|
||||
<a bitButton [buttonType]="buttonType" [block]="block" href="#" class="tw-ml-2">[block]="true" Link</a>
|
||||
<a bitButton [buttonType]="buttonType" [block]="block" href="#" class="tw-ms-2">[block]="true" Link</a>
|
||||
|
||||
<button bitButton [buttonType]="buttonType" block class="tw-ml-2">block Button</button>
|
||||
<a bitButton [buttonType]="buttonType" block href="#" class="tw-ml-2">block Link</a>
|
||||
<button bitButton [buttonType]="buttonType" block class="tw-ms-2">block Button</button>
|
||||
<a bitButton [buttonType]="buttonType" block href="#" class="tw-ms-2">block Link</a>
|
||||
</span>
|
||||
`,
|
||||
}),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<aside
|
||||
class="tw-mb-4 tw-box-border tw-rounded-lg tw-border tw-border-l-4 tw-border-solid tw-bg-background tw-pl-3 tw-pr-2 tw-py-2 tw-leading-5 tw-text-main"
|
||||
class="tw-mb-4 tw-box-border tw-rounded-lg tw-border tw-border-l-4 tw-border-solid tw-bg-background tw-ps-3 tw-pe-2 tw-py-2 tw-leading-5 tw-text-main"
|
||||
[ngClass]="calloutClass"
|
||||
[attr.aria-labelledby]="titleId"
|
||||
>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user