1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-12 06:13:38 +00:00

Migrate remaining components to standalone in libs/components (#15053)

Migrates the remaining non standalone components from libs/components. Also resolved some linting ignores and applying strict typescript.
This commit is contained in:
Oscar Hinton
2025-06-05 09:52:53 +02:00
committed by GitHub
parent 7386a4fa9e
commit e8e2181252
12 changed files with 57 additions and 109 deletions

View File

@@ -85,11 +85,11 @@ import { IconComponent } from "./vault/components/icon.component";
TextDragDirective, TextDragDirective,
CopyClickDirective, CopyClickDirective,
A11yTitleDirective, A11yTitleDirective,
AutofocusDirective,
], ],
declarations: [ declarations: [
A11yInvalidDirective, A11yInvalidDirective,
ApiActionDirective, ApiActionDirective,
AutofocusDirective,
BoxRowDirective, BoxRowDirective,
DeprecatedCalloutComponent, DeprecatedCalloutComponent,
CopyTextDirective, CopyTextDirective,

View File

@@ -1,7 +1,5 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Component, DebugElement } from "@angular/core"; import { Component, DebugElement } from "@angular/core";
import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; import { ComponentFixture, TestBed } from "@angular/core/testing";
import { By } from "@angular/platform-browser"; import { By } from "@angular/platform-browser";
import { ButtonModule } from "./index"; import { ButtonModule } from "./index";
@@ -13,21 +11,18 @@ describe("Button", () => {
let disabledButtonDebugElement: DebugElement; let disabledButtonDebugElement: DebugElement;
let linkDebugElement: DebugElement; let linkDebugElement: DebugElement;
beforeEach(waitForAsync(() => { beforeEach(async () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ButtonModule], imports: [TestApp],
declarations: [TestApp],
}); });
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. await TestBed.compileComponents();
// eslint-disable-next-line @typescript-eslint/no-floating-promises
TestBed.compileComponents();
fixture = TestBed.createComponent(TestApp); fixture = TestBed.createComponent(TestApp);
testAppComponent = fixture.debugElement.componentInstance; testAppComponent = fixture.debugElement.componentInstance;
buttonDebugElement = fixture.debugElement.query(By.css("button")); buttonDebugElement = fixture.debugElement.query(By.css("button"));
disabledButtonDebugElement = fixture.debugElement.query(By.css("button#disabled")); disabledButtonDebugElement = fixture.debugElement.query(By.css("button#disabled"));
linkDebugElement = fixture.debugElement.query(By.css("a")); linkDebugElement = fixture.debugElement.query(By.css("a"));
})); });
it("should not be disabled when loading and disabled are false", () => { it("should not be disabled when loading and disabled are false", () => {
testAppComponent.loading = false; testAppComponent.loading = false;
@@ -85,11 +80,11 @@ describe("Button", () => {
<button id="disabled" type="button" bitButton disabled>Button</button> <button id="disabled" type="button" bitButton disabled>Button</button>
`, `,
standalone: false, imports: [ButtonModule],
}) })
class TestApp { class TestApp {
buttonType: string; buttonType?: string;
block: boolean; block?: boolean;
disabled: boolean; disabled?: boolean;
loading: boolean; loading?: boolean;
} }

View File

@@ -1,18 +1,15 @@
import { DIALOG_DATA, DialogModule, DialogRef } from "@angular/cdk/dialog"; import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog";
import { Component, Inject } from "@angular/core"; import { Component, Inject } from "@angular/core";
import { provideAnimations } from "@angular/platform-browser/animations";
import { Meta, StoryObj, moduleMetadata } from "@storybook/angular"; import { Meta, StoryObj, moduleMetadata } from "@storybook/angular";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { ButtonModule } from "../button"; import { ButtonModule } from "../button";
import { IconButtonModule } from "../icon-button";
import { SharedModule } from "../shared";
import { I18nMockService } from "../utils/i18n-mock.service"; import { I18nMockService } from "../utils/i18n-mock.service";
import { DialogComponent } from "./dialog/dialog.component"; import { DialogModule } from "./dialog.module";
import { DialogService } from "./dialog.service"; import { DialogService } from "./dialog.service";
import { DialogCloseDirective } from "./directives/dialog-close.directive";
import { DialogTitleContainerDirective } from "./directives/dialog-title-container.directive";
interface Animal { interface Animal {
animal: string; animal: string;
@@ -20,7 +17,7 @@ interface Animal {
@Component({ @Component({
template: `<button bitButton type="button" (click)="openDialog()">Open Dialog</button>`, template: `<button bitButton type="button" (click)="openDialog()">Open Dialog</button>`,
standalone: false, imports: [ButtonModule],
}) })
class StoryDialogComponent { class StoryDialogComponent {
constructor(public dialogService: DialogService) {} constructor(public dialogService: DialogService) {}
@@ -50,7 +47,7 @@ class StoryDialogComponent {
</ng-container> </ng-container>
</bit-dialog> </bit-dialog>
`, `,
standalone: false, imports: [DialogModule, ButtonModule],
}) })
class StoryDialogContentComponent { class StoryDialogContentComponent {
constructor( constructor(
@@ -68,17 +65,8 @@ export default {
component: StoryDialogComponent, component: StoryDialogComponent,
decorators: [ decorators: [
moduleMetadata({ moduleMetadata({
declarations: [StoryDialogContentComponent],
imports: [
SharedModule,
ButtonModule,
DialogModule,
IconButtonModule,
DialogCloseDirective,
DialogComponent,
DialogTitleContainerDirective,
],
providers: [ providers: [
provideAnimations(),
DialogService, DialogService,
{ {
provide: I18nService, provide: I18nService,

View File

@@ -1,6 +1,6 @@
import { Component } from "@angular/core"; import { Component } from "@angular/core";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; import { provideAnimations } from "@angular/platform-browser/animations";
import { Meta, StoryObj, applicationConfig, moduleMetadata } from "@storybook/angular"; import { Meta, StoryObj, applicationConfig } from "@storybook/angular";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -31,7 +31,7 @@ import { DialogModule } from "../../dialog.module";
</bit-callout> </bit-callout>
} }
`, `,
standalone: false, imports: [ButtonModule, CalloutModule, DialogModule],
}) })
class StoryDialogComponent { class StoryDialogComponent {
protected dialogs: { title: string; dialogs: SimpleDialogOptions[] }[] = [ protected dialogs: { title: string; dialogs: SimpleDialogOptions[] }[] = [
@@ -147,11 +147,9 @@ export default {
title: "Component Library/Dialogs/Service/SimpleConfigurable", title: "Component Library/Dialogs/Service/SimpleConfigurable",
component: StoryDialogComponent, component: StoryDialogComponent,
decorators: [ decorators: [
moduleMetadata({
imports: [ButtonModule, BrowserAnimationsModule, DialogModule, CalloutModule],
}),
applicationConfig({ applicationConfig({
providers: [ providers: [
provideAnimations(),
{ {
provide: I18nService, provide: I18nService,
useFactory: () => { useFactory: () => {

View File

@@ -1,13 +1,11 @@
import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog"; import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
import { Component, Inject } from "@angular/core"; import { Component, Inject } from "@angular/core";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; import { provideAnimations } from "@angular/platform-browser/animations";
import { Meta, StoryObj, moduleMetadata } from "@storybook/angular"; import { Meta, StoryObj, moduleMetadata } from "@storybook/angular";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { ButtonModule } from "../../button"; import { ButtonModule } from "../../button";
import { IconButtonModule } from "../../icon-button";
import { SharedModule } from "../../shared/shared.module";
import { I18nMockService } from "../../utils/i18n-mock.service"; import { I18nMockService } from "../../utils/i18n-mock.service";
import { DialogModule } from "../dialog.module"; import { DialogModule } from "../dialog.module";
import { DialogService } from "../dialog.service"; import { DialogService } from "../dialog.service";
@@ -18,7 +16,7 @@ interface Animal {
@Component({ @Component({
template: `<button type="button" bitButton (click)="openDialog()">Open Simple Dialog</button>`, template: `<button type="button" bitButton (click)="openDialog()">Open Simple Dialog</button>`,
standalone: false, imports: [ButtonModule],
}) })
class StoryDialogComponent { class StoryDialogComponent {
constructor(public dialogService: DialogService) {} constructor(public dialogService: DialogService) {}
@@ -49,7 +47,7 @@ class StoryDialogComponent {
</ng-container> </ng-container>
</bit-simple-dialog> </bit-simple-dialog>
`, `,
standalone: false, imports: [ButtonModule, DialogModule],
}) })
class StoryDialogContentComponent { class StoryDialogContentComponent {
constructor( constructor(
@@ -67,15 +65,8 @@ export default {
component: StoryDialogComponent, component: StoryDialogComponent,
decorators: [ decorators: [
moduleMetadata({ moduleMetadata({
declarations: [StoryDialogContentComponent],
imports: [
SharedModule,
IconButtonModule,
ButtonModule,
BrowserAnimationsModule,
DialogModule,
],
providers: [ providers: [
provideAnimations(),
DialogService, DialogService,
{ {
provide: I18nService, provide: I18nService,

View File

@@ -6,7 +6,6 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
import { IconButtonModule } from "../icon-button"; import { IconButtonModule } from "../icon-button";
import { BitIconButtonComponent } from "../icon-button/icon-button.component"; import { BitIconButtonComponent } from "../icon-button/icon-button.component";
import { InputModule } from "../input/input.module";
import { I18nMockService } from "../utils/i18n-mock.service"; import { I18nMockService } from "../utils/i18n-mock.service";
import { BitFormFieldControl } from "./form-field-control"; import { BitFormFieldControl } from "./form-field-control";
@@ -25,7 +24,7 @@ import { BitPasswordInputToggleDirective } from "./password-input-toggle.directi
</bit-form-field> </bit-form-field>
</form> </form>
`, `,
standalone: false, imports: [FormFieldModule, IconButtonModule],
}) })
class TestFormFieldComponent {} class TestFormFieldComponent {}
@@ -37,8 +36,7 @@ describe("PasswordInputToggle", () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [FormFieldModule, IconButtonModule, InputModule], imports: [TestFormFieldComponent],
declarations: [TestFormFieldComponent],
providers: [ providers: [
{ {
provide: I18nService, provide: I18nService,

View File

@@ -19,7 +19,6 @@ import { FocusableElement } from "../shared/focusable-element";
*/ */
@Directive({ @Directive({
selector: "[appAutofocus], [bitAutofocus]", selector: "[appAutofocus], [bitAutofocus]",
standalone: false,
}) })
export class AutofocusDirective implements AfterContentChecked { export class AutofocusDirective implements AfterContentChecked {
@Input() set appAutofocus(condition: boolean | string) { @Input() set appAutofocus(condition: boolean | string) {

View File

@@ -1,5 +1,5 @@
import { Component } from "@angular/core"; import { Component } from "@angular/core";
import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; import { ComponentFixture, TestBed } from "@angular/core/testing";
import { By } from "@angular/platform-browser"; import { By } from "@angular/platform-browser";
import { MenuTriggerForDirective } from "./menu-trigger-for.directive"; import { MenuTriggerForDirective } from "./menu-trigger-for.directive";
@@ -16,19 +16,16 @@ describe("Menu", () => {
// The overlay is created outside the root debugElement, so we need to query its parent // The overlay is created outside the root debugElement, so we need to query its parent
const getBitMenuPanel = () => document.querySelector(".bit-menu-panel"); const getBitMenuPanel = () => document.querySelector(".bit-menu-panel");
beforeEach(waitForAsync(() => { beforeEach(async () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [MenuModule], imports: [TestApp],
declarations: [TestApp],
}); });
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. await TestBed.compileComponents();
// eslint-disable-next-line @typescript-eslint/no-floating-promises
TestBed.compileComponents();
fixture = TestBed.createComponent(TestApp); fixture = TestBed.createComponent(TestApp);
fixture.detectChanges(); fixture.detectChanges();
})); });
it("should open when the trigger is clicked", async () => { it("should open when the trigger is clicked", async () => {
const buttonDebugElement = fixture.debugElement.query(By.directive(MenuTriggerForDirective)); const buttonDebugElement = fixture.debugElement.query(By.directive(MenuTriggerForDirective));
@@ -73,6 +70,6 @@ describe("Menu", () => {
<a id="item2" bitMenuItem>Item 2</a> <a id="item2" bitMenuItem>Item 2</a>
</bit-menu> </bit-menu>
`, `,
standalone: false, imports: [MenuModule],
}) })
class TestApp {} class TestApp {}

View File

@@ -1,7 +1,5 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Component } from "@angular/core"; import { Component } from "@angular/core";
import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; import { ComponentFixture, TestBed } from "@angular/core/testing";
import { By } from "@angular/platform-browser"; import { By } from "@angular/platform-browser";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -17,26 +15,23 @@ describe("RadioButton", () => {
let testAppComponent: TestApp; let testAppComponent: TestApp;
let radioButton: HTMLInputElement; let radioButton: HTMLInputElement;
beforeEach(waitForAsync(() => { beforeEach(async () => {
mockGroupComponent = new MockedButtonGroupComponent(); mockGroupComponent = new MockedButtonGroupComponent();
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [RadioButtonModule], imports: [TestApp],
declarations: [TestApp],
providers: [ providers: [
{ provide: RadioGroupComponent, useValue: mockGroupComponent }, { provide: RadioGroupComponent, useValue: mockGroupComponent },
{ provide: I18nService, useValue: new I18nMockService({}) }, { provide: I18nService, useValue: new I18nMockService({}) },
], ],
}); });
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. await TestBed.compileComponents();
// eslint-disable-next-line @typescript-eslint/no-floating-promises
TestBed.compileComponents();
fixture = TestBed.createComponent(TestApp); fixture = TestBed.createComponent(TestApp);
fixture.detectChanges(); fixture.detectChanges();
testAppComponent = fixture.debugElement.componentInstance; testAppComponent = fixture.debugElement.componentInstance;
radioButton = fixture.debugElement.query(By.css("input[type=radio]")).nativeElement; radioButton = fixture.debugElement.query(By.css("input[type=radio]")).nativeElement;
})); });
it("should emit value when clicking on radio button", () => { it("should emit value when clicking on radio button", () => {
testAppComponent.value = "value"; testAppComponent.value = "value";
@@ -77,7 +72,7 @@ class MockedButtonGroupComponent implements Partial<RadioGroupComponent> {
@Component({ @Component({
selector: "test-app", selector: "test-app",
template: `<bit-radio-button [value]="value"><bit-label>Element</bit-label></bit-radio-button>`, template: `<bit-radio-button [value]="value"><bit-label>Element</bit-label></bit-radio-button>`,
standalone: false, imports: [RadioButtonModule],
}) })
class TestApp { class TestApp {
value?: string; value?: string;

View File

@@ -1,5 +1,5 @@
import { Component } from "@angular/core"; import { Component } from "@angular/core";
import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; import { ComponentFixture, TestBed } from "@angular/core/testing";
import { FormsModule } from "@angular/forms"; import { FormsModule } from "@angular/forms";
import { By } from "@angular/platform-browser"; import { By } from "@angular/platform-browser";
@@ -16,16 +16,13 @@ describe("RadioGroupComponent", () => {
let buttonElements: RadioButtonComponent[]; let buttonElements: RadioButtonComponent[];
let radioButtons: HTMLInputElement[]; let radioButtons: HTMLInputElement[];
beforeEach(waitForAsync(() => { beforeEach(async () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [FormsModule, RadioButtonModule], imports: [TestApp],
declarations: [TestApp],
providers: [{ provide: I18nService, useValue: new I18nMockService({}) }], providers: [{ provide: I18nService, useValue: new I18nMockService({}) }],
}); });
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. await TestBed.compileComponents();
// eslint-disable-next-line @typescript-eslint/no-floating-promises
TestBed.compileComponents();
fixture = TestBed.createComponent(TestApp); fixture = TestBed.createComponent(TestApp);
fixture.detectChanges(); fixture.detectChanges();
testAppComponent = fixture.debugElement.componentInstance; testAppComponent = fixture.debugElement.componentInstance;
@@ -37,7 +34,7 @@ describe("RadioGroupComponent", () => {
.map((e) => e.nativeElement); .map((e) => e.nativeElement);
fixture.detectChanges(); fixture.detectChanges();
})); });
it("should select second element when setting selected to second", async () => { it("should select second element when setting selected to second", async () => {
testAppComponent.selected = "second"; testAppComponent.selected = "second";
@@ -75,7 +72,7 @@ describe("RadioGroupComponent", () => {
<bit-radio-button value="third">Third</bit-radio-button> <bit-radio-button value="third">Third</bit-radio-button>
</bit-radio-group> </bit-radio-group>
`, `,
standalone: false, imports: [FormsModule, RadioButtonModule],
}) })
class TestApp { class TestApp {
selected?: string; selected?: string;

View File

@@ -1,7 +1,5 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Component } from "@angular/core"; import { Component } from "@angular/core";
import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; import { ComponentFixture, TestBed } from "@angular/core/testing";
import { By } from "@angular/platform-browser"; import { By } from "@angular/platform-browser";
import { ToggleGroupModule } from "./toggle-group.module"; import { ToggleGroupModule } from "./toggle-group.module";
@@ -13,15 +11,12 @@ describe("Button", () => {
let buttonElements: ToggleComponent<unknown>[]; let buttonElements: ToggleComponent<unknown>[];
let radioButtons: HTMLInputElement[]; let radioButtons: HTMLInputElement[];
beforeEach(waitForAsync(() => { beforeEach(async () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ToggleGroupModule], imports: [TestApp],
declarations: [TestApp],
}); });
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. await TestBed.compileComponents();
// eslint-disable-next-line @typescript-eslint/no-floating-promises
TestBed.compileComponents();
fixture = TestBed.createComponent(TestApp); fixture = TestBed.createComponent(TestApp);
testAppComponent = fixture.debugElement.componentInstance; testAppComponent = fixture.debugElement.componentInstance;
buttonElements = fixture.debugElement buttonElements = fixture.debugElement
@@ -32,7 +27,7 @@ describe("Button", () => {
.map((e) => e.nativeElement); .map((e) => e.nativeElement);
fixture.detectChanges(); fixture.detectChanges();
})); });
it("should select second element when setting selected to second", () => { it("should select second element when setting selected to second", () => {
testAppComponent.selected = "second"; testAppComponent.selected = "second";
@@ -67,7 +62,7 @@ describe("Button", () => {
<bit-toggle value="third">Third</bit-toggle> <bit-toggle value="third">Third</bit-toggle>
</bit-toggle-group> </bit-toggle-group>
`, `,
standalone: false, imports: [ToggleGroupModule],
}) })
class TestApp { class TestApp {
selected?: string; selected?: string;

View File

@@ -1,7 +1,5 @@
// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Component } from "@angular/core"; import { Component } from "@angular/core";
import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; import { ComponentFixture, TestBed } from "@angular/core/testing";
import { By } from "@angular/platform-browser"; import { By } from "@angular/platform-browser";
import { ToggleGroupComponent } from "./toggle-group.component"; import { ToggleGroupComponent } from "./toggle-group.component";
@@ -13,22 +11,19 @@ describe("Button", () => {
let testAppComponent: TestApp; let testAppComponent: TestApp;
let radioButton: HTMLInputElement; let radioButton: HTMLInputElement;
beforeEach(waitForAsync(() => { beforeEach(async () => {
mockGroupComponent = new MockedButtonGroupComponent(); mockGroupComponent = new MockedButtonGroupComponent();
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ToggleGroupModule], imports: [TestApp],
declarations: [TestApp],
providers: [{ provide: ToggleGroupComponent, useValue: mockGroupComponent }], providers: [{ provide: ToggleGroupComponent, useValue: mockGroupComponent }],
}); });
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling. await TestBed.compileComponents();
// eslint-disable-next-line @typescript-eslint/no-floating-promises
TestBed.compileComponents();
fixture = TestBed.createComponent(TestApp); fixture = TestBed.createComponent(TestApp);
testAppComponent = fixture.debugElement.componentInstance; testAppComponent = fixture.debugElement.componentInstance;
radioButton = fixture.debugElement.query(By.css("input[type=radio]")).nativeElement; radioButton = fixture.debugElement.query(By.css("input[type=radio]")).nativeElement;
})); });
it("should emit value when clicking on radio button", () => { it("should emit value when clicking on radio button", () => {
testAppComponent.value = "value"; testAppComponent.value = "value";
@@ -69,7 +64,7 @@ class MockedButtonGroupComponent implements Partial<ToggleGroupComponent> {
@Component({ @Component({
selector: "test-app", selector: "test-app",
template: ` <bit-toggle [value]="value">Element</bit-toggle>`, template: ` <bit-toggle [value]="value">Element</bit-toggle>`,
standalone: false, imports: [ToggleGroupModule],
}) })
class TestApp { class TestApp {
value?: string; value?: string;