mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
add back events for browser refresh extension (#11085)
- something went sideways in a merge
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
bitSuffix
|
||||
bitPasswordInputToggle
|
||||
data-testid="visibility-for-card-number"
|
||||
(toggledChange)="logCardEvent($event, EventType.Cipher_ClientToggledCardNumberVisible)"
|
||||
></button>
|
||||
</bit-form-field>
|
||||
|
||||
@@ -60,6 +61,7 @@
|
||||
bitSuffix
|
||||
bitPasswordInputToggle
|
||||
data-testid="visibility-for-card-code"
|
||||
(toggledChange)="logCardEvent($event, EventType.Cipher_ClientToggledCardCodeVisible)"
|
||||
></button>
|
||||
</bit-form-field>
|
||||
</bit-card>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { ReactiveFormsModule } from "@angular/forms";
|
||||
import { By } from "@angular/platform-browser";
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { CardView } from "@bitwarden/common/vault/models/view/card.view";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
@@ -27,6 +28,7 @@ describe("CardDetailsSectionComponent", () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [CardDetailsSectionComponent, CommonModule, ReactiveFormsModule],
|
||||
providers: [
|
||||
{ provide: EventCollectionService, useValue: mock<EventCollectionService>() },
|
||||
{ provide: CipherFormContainer, useValue: cipherFormProvider },
|
||||
{ provide: I18nService, useValue: { t: (key: string) => key } },
|
||||
],
|
||||
|
||||
@@ -4,6 +4,8 @@ import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { FormBuilder, ReactiveFormsModule } from "@angular/forms";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { CardView } from "@bitwarden/common/vault/models/view/card.view";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
@@ -91,10 +93,13 @@ export class CardDetailsSectionComponent implements OnInit {
|
||||
{ name: "12 - " + this.i18nService.t("december"), value: "12" },
|
||||
];
|
||||
|
||||
EventType = EventType;
|
||||
|
||||
constructor(
|
||||
private cipherFormContainer: CipherFormContainer,
|
||||
private formBuilder: FormBuilder,
|
||||
private i18nService: I18nService,
|
||||
private eventCollectionService: EventCollectionService,
|
||||
) {
|
||||
this.cipherFormContainer.registerChildForm("cardDetails", this.cardDetailsForm);
|
||||
|
||||
@@ -149,6 +154,21 @@ export class CardDetailsSectionComponent implements OnInit {
|
||||
return this.i18nService.t("cardDetails");
|
||||
}
|
||||
|
||||
async logCardEvent(hiddenFieldVisible: boolean, event: EventType) {
|
||||
const { mode, originalCipher } = this.cipherFormContainer.config;
|
||||
|
||||
const isEdit = ["edit", "partial-edit"].includes(mode);
|
||||
|
||||
if (hiddenFieldVisible && isEdit) {
|
||||
await this.eventCollectionService.collect(
|
||||
event,
|
||||
originalCipher.id,
|
||||
false,
|
||||
originalCipher.organizationId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** Set form initial form values from the current cipher */
|
||||
private setInitialValues() {
|
||||
const { cardholderName, number, brand, expMonth, expYear, code } = this.originalCipherView.card;
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
bitPasswordInputToggle
|
||||
data-testid="visibility-for-custom-hidden-field"
|
||||
[disabled]="!canViewPasswords(i)"
|
||||
(toggledChange)="logHiddenEvent($event)"
|
||||
></button>
|
||||
</bit-form-field>
|
||||
|
||||
|
||||
@@ -4,7 +4,9 @@ import { CdkDragDrop } from "@angular/cdk/drag-drop";
|
||||
import { DebugElement } from "@angular/core";
|
||||
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
import { By } from "@angular/platform-browser";
|
||||
import { mock } from "jest-mock-extended";
|
||||
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import {
|
||||
CardLinkedId,
|
||||
@@ -50,6 +52,7 @@ describe("CustomFieldsComponent", () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [CustomFieldsComponent],
|
||||
providers: [
|
||||
{ provide: EventCollectionService, useValue: mock<EventCollectionService>() },
|
||||
{
|
||||
provide: I18nService,
|
||||
useValue: { t: (...keys: string[]) => keys.filter(Boolean).join(" ") },
|
||||
|
||||
@@ -19,6 +19,8 @@ import { FormArray, FormBuilder, FormsModule, ReactiveFormsModule } from "@angul
|
||||
import { Subject, zip } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { CipherType, FieldType, LinkedIdType } from "@bitwarden/common/vault/enums";
|
||||
import { CardView } from "@bitwarden/common/vault/models/view/card.view";
|
||||
@@ -118,6 +120,7 @@ export class CustomFieldsComponent implements OnInit, AfterViewInit {
|
||||
private formBuilder: FormBuilder,
|
||||
private i18nService: I18nService,
|
||||
private liveAnnouncer: LiveAnnouncer,
|
||||
private eventCollectionService: EventCollectionService,
|
||||
) {
|
||||
this.destroyed$ = inject(DestroyRef);
|
||||
this.cipherFormContainer.registerChildForm("customFields", this.customFieldsForm);
|
||||
@@ -301,6 +304,21 @@ export class CustomFieldsComponent implements OnInit, AfterViewInit {
|
||||
}
|
||||
}
|
||||
|
||||
async logHiddenEvent(hiddenFieldVisible: boolean) {
|
||||
const { mode, originalCipher } = this.cipherFormContainer.config;
|
||||
|
||||
const isEdit = ["edit", "partial-edit"].includes(mode);
|
||||
|
||||
if (hiddenFieldVisible && isEdit) {
|
||||
await this.eventCollectionService.collect(
|
||||
EventType.Cipher_ClientToggledHiddenFieldVisible,
|
||||
originalCipher.id,
|
||||
false,
|
||||
originalCipher.organizationId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the linked field options for the current cipher type
|
||||
*
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
*ngIf="viewHiddenFields"
|
||||
data-testid="toggle-password-visibility"
|
||||
bitPasswordInputToggle
|
||||
(toggledChange)="logVisibleEvent($event, EventType.Cipher_ClientToggledPasswordVisible)"
|
||||
></button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -113,6 +114,7 @@
|
||||
*ngIf="viewHiddenFields"
|
||||
data-testid="toggle-totp-visibility"
|
||||
bitPasswordInputToggle
|
||||
(toggledChange)="logVisibleEvent($event, EventType.Cipher_ClientToggledTOTPSeedVisible)"
|
||||
></button>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
import { DatePipe } from "@angular/common";
|
||||
import { Component } from "@angular/core";
|
||||
import { ComponentFixture, fakeAsync, TestBed, tick } from "@angular/core/testing";
|
||||
import { By } from "@angular/platform-browser";
|
||||
import { mock, MockProxy } from "jest-mock-extended";
|
||||
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { Fido2CredentialView } from "@bitwarden/common/vault/models/view/fido2-credential.view";
|
||||
import { LoginView } from "@bitwarden/common/vault/models/view/login.view";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
import { BitPasswordInputToggleDirective } from "@bitwarden/components/src/form-field/password-input-toggle.directive";
|
||||
|
||||
import { CipherFormGenerationService } from "../../abstractions/cipher-form-generation.service";
|
||||
import { TotpCaptureService } from "../../abstractions/totp-capture.service";
|
||||
@@ -34,6 +39,7 @@ describe("LoginDetailsSectionComponent", () => {
|
||||
let toastService: MockProxy<ToastService>;
|
||||
let totpCaptureService: MockProxy<TotpCaptureService>;
|
||||
let i18nService: MockProxy<I18nService>;
|
||||
const collect = jest.fn().mockResolvedValue(null);
|
||||
|
||||
beforeEach(async () => {
|
||||
cipherFormContainer = mock<CipherFormContainer>();
|
||||
@@ -43,6 +49,7 @@ describe("LoginDetailsSectionComponent", () => {
|
||||
toastService = mock<ToastService>();
|
||||
totpCaptureService = mock<TotpCaptureService>();
|
||||
i18nService = mock<I18nService>();
|
||||
collect.mockClear();
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [LoginDetailsSectionComponent],
|
||||
@@ -53,6 +60,7 @@ describe("LoginDetailsSectionComponent", () => {
|
||||
{ provide: ToastService, useValue: toastService },
|
||||
{ provide: TotpCaptureService, useValue: totpCaptureService },
|
||||
{ provide: I18nService, useValue: i18nService },
|
||||
{ provide: EventCollectionService, useValue: { collect } },
|
||||
],
|
||||
})
|
||||
.overrideComponent(LoginDetailsSectionComponent, {
|
||||
@@ -255,6 +263,32 @@ describe("LoginDetailsSectionComponent", () => {
|
||||
expect(getTogglePasswordVisibilityBtn()).toBeNull();
|
||||
});
|
||||
|
||||
it("logs password viewed event when toggledChange is true", async () => {
|
||||
cipherFormContainer.config.mode = "edit";
|
||||
cipherFormContainer.config.originalCipher = {
|
||||
id: "111-222-333",
|
||||
organizationId: "333-444-555",
|
||||
} as Cipher;
|
||||
jest.spyOn(component, "viewHiddenFields", "get").mockReturnValue(true);
|
||||
fixture.detectChanges();
|
||||
|
||||
const passwordToggle = fixture.debugElement.query(
|
||||
By.directive(BitPasswordInputToggleDirective),
|
||||
);
|
||||
await passwordToggle.triggerEventHandler("toggledChange", true);
|
||||
|
||||
expect(collect).toHaveBeenCalledWith(
|
||||
EventType.Cipher_ClientToggledPasswordVisible,
|
||||
"111-222-333",
|
||||
false,
|
||||
"333-444-555",
|
||||
);
|
||||
|
||||
await passwordToggle.triggerEventHandler("toggledChange", false);
|
||||
|
||||
expect(collect).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
describe("password generation", () => {
|
||||
it("should show generate password button when editable", () => {
|
||||
expect(getGeneratePasswordBtn()).not.toBeNull();
|
||||
|
||||
@@ -6,6 +6,8 @@ import { map } from "rxjs";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { Fido2CredentialView } from "@bitwarden/common/vault/models/view/fido2-credential.view";
|
||||
import { LoginView } from "@bitwarden/common/vault/models/view/login.view";
|
||||
@@ -48,6 +50,7 @@ import { AutofillOptionsComponent } from "../autofill-options/autofill-options.c
|
||||
],
|
||||
})
|
||||
export class LoginDetailsSectionComponent implements OnInit {
|
||||
EventType = EventType;
|
||||
loginDetailsForm = this.formBuilder.group({
|
||||
username: [""],
|
||||
password: [""],
|
||||
@@ -106,6 +109,7 @@ export class LoginDetailsSectionComponent implements OnInit {
|
||||
private generationService: CipherFormGenerationService,
|
||||
private auditService: AuditService,
|
||||
private toastService: ToastService,
|
||||
private eventCollectionService: EventCollectionService,
|
||||
@Optional() private totpCaptureService?: TotpCaptureService,
|
||||
) {
|
||||
this.cipherFormContainer.registerChildForm("loginDetails", this.loginDetailsForm);
|
||||
@@ -163,6 +167,24 @@ export class LoginDetailsSectionComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
/** Logs the givin event when in edit mode */
|
||||
logVisibleEvent = async (passwordVisible: boolean, event: EventType) => {
|
||||
const { mode, originalCipher } = this.cipherFormContainer.config;
|
||||
|
||||
const isEdit = ["edit", "partial-edit"].includes(mode);
|
||||
|
||||
if (!passwordVisible || !isEdit || !originalCipher) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.eventCollectionService.collect(
|
||||
event,
|
||||
originalCipher.id,
|
||||
false,
|
||||
originalCipher.organizationId,
|
||||
);
|
||||
};
|
||||
|
||||
captureTotp = async () => {
|
||||
if (!this.canCaptureTotp) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user