mirror of
https://github.com/bitwarden/browser
synced 2025-12-12 14:23:32 +00:00
* remove todo * Retrieve cache cipher for add-edit form * user prefilled cipher for add-edit form * add listener for clearing view cache * clear local cache when clearing global state * track initial value of cache for down stream logic that should only occur on non-cached values * add feature flag for edit form persistence * add tests for cipher form cache service * fix optional initialValues * add services to cipher form storybook * fix strict types * rename variables to be platform agnostic * use deconstructed collectionIds variable to avoid them be overwritten * use the originalCipherView for initial values * add comment about signal equality * prevent events from being emitted when adding uris to the existing form - This stops other values from being overwrote in the initialization process * add check for cached cipher when adding initial uris
128 lines
4.2 KiB
TypeScript
128 lines
4.2 KiB
TypeScript
import { Component } from "@angular/core";
|
|
import { ComponentFixture, TestBed } from "@angular/core/testing";
|
|
import { mock, MockProxy } from "jest-mock-extended";
|
|
import { BehaviorSubject } from "rxjs";
|
|
|
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
import { CipherRepromptType } from "@bitwarden/common/vault/enums";
|
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
|
|
|
import { PasswordRepromptService } from "../../../services/password-reprompt.service";
|
|
import { CipherFormContainer } from "../../cipher-form-container";
|
|
import { CustomFieldsComponent } from "../custom-fields/custom-fields.component";
|
|
|
|
import { AdditionalOptionsSectionComponent } from "./additional-options-section.component";
|
|
|
|
@Component({
|
|
standalone: true,
|
|
selector: "vault-custom-fields",
|
|
template: "",
|
|
})
|
|
class MockCustomFieldsComponent {}
|
|
|
|
describe("AdditionalOptionsSectionComponent", () => {
|
|
let component: AdditionalOptionsSectionComponent;
|
|
let fixture: ComponentFixture<AdditionalOptionsSectionComponent>;
|
|
let cipherFormProvider: MockProxy<CipherFormContainer>;
|
|
let passwordRepromptService: MockProxy<PasswordRepromptService>;
|
|
let passwordRepromptEnabled$: BehaviorSubject<boolean>;
|
|
|
|
const getInitialCipherView = jest.fn(() => null);
|
|
|
|
beforeEach(async () => {
|
|
getInitialCipherView.mockClear();
|
|
|
|
cipherFormProvider = mock<CipherFormContainer>({ getInitialCipherView });
|
|
passwordRepromptService = mock<PasswordRepromptService>();
|
|
passwordRepromptEnabled$ = new BehaviorSubject(true);
|
|
passwordRepromptService.enabled$ = passwordRepromptEnabled$;
|
|
|
|
await TestBed.configureTestingModule({
|
|
imports: [AdditionalOptionsSectionComponent],
|
|
providers: [
|
|
{ provide: CipherFormContainer, useValue: cipherFormProvider },
|
|
{ provide: PasswordRepromptService, useValue: passwordRepromptService },
|
|
{ provide: I18nService, useValue: mock<I18nService>() },
|
|
],
|
|
})
|
|
.overrideComponent(AdditionalOptionsSectionComponent, {
|
|
remove: {
|
|
imports: [CustomFieldsComponent],
|
|
},
|
|
add: {
|
|
imports: [MockCustomFieldsComponent],
|
|
},
|
|
})
|
|
.compileComponents();
|
|
|
|
fixture = TestBed.createComponent(AdditionalOptionsSectionComponent);
|
|
component = fixture.componentInstance;
|
|
fixture.detectChanges();
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
it("registers 'additionalOptionsForm' form with CipherFormContainer", () => {
|
|
expect(cipherFormProvider.registerChildForm).toHaveBeenCalledWith(
|
|
"additionalOptions",
|
|
component.additionalOptionsForm,
|
|
);
|
|
});
|
|
|
|
it("patches 'additionalOptionsForm' changes to CipherFormContainer", () => {
|
|
component.additionalOptionsForm.patchValue({
|
|
notes: "new notes",
|
|
reprompt: true,
|
|
});
|
|
|
|
const expectedCipher = new CipherView();
|
|
expectedCipher.notes = "new notes";
|
|
expectedCipher.reprompt = CipherRepromptType.Password;
|
|
|
|
expect(cipherFormProvider.patchCipher).toHaveBeenCalled();
|
|
const patchFn = cipherFormProvider.patchCipher.mock.lastCall[0];
|
|
|
|
const updated = patchFn(new CipherView());
|
|
|
|
expect(updated).toEqual(expectedCipher);
|
|
});
|
|
|
|
it("disables 'additionalOptionsForm' when in partial-edit mode", () => {
|
|
cipherFormProvider.config.mode = "partial-edit";
|
|
|
|
component.ngOnInit();
|
|
|
|
expect(component.additionalOptionsForm.disabled).toBe(true);
|
|
});
|
|
|
|
it("initializes 'additionalOptionsForm' from `getInitialCipherValue`", () => {
|
|
getInitialCipherView.mockReturnValueOnce({
|
|
notes: "original notes",
|
|
reprompt: 1,
|
|
} as CipherView);
|
|
|
|
component.ngOnInit();
|
|
|
|
expect(component.additionalOptionsForm.value).toEqual({
|
|
notes: "original notes",
|
|
reprompt: true,
|
|
});
|
|
});
|
|
|
|
it("hides password reprompt checkbox when disabled", () => {
|
|
passwordRepromptEnabled$.next(true);
|
|
fixture.detectChanges();
|
|
|
|
let checkbox = fixture.nativeElement.querySelector("input[formControlName='reprompt']");
|
|
expect(checkbox).not.toBeNull();
|
|
|
|
passwordRepromptEnabled$.next(false);
|
|
fixture.detectChanges();
|
|
|
|
checkbox = fixture.nativeElement.querySelector("input[formControlName='reprompt']");
|
|
expect(checkbox).toBeNull();
|
|
});
|
|
});
|