ACS-8106: (a11y) Replace Material Tooltip with standard tooltip (#9894) (#9907)

Co-authored-by: Denys Vuika <denys.vuika@gmail.com>
This commit is contained in:
Pablo Martinez
2024-07-09 15:22:20 +02:00
committed by GitHub
parent 0d77ebb836
commit 41965a4561
96 changed files with 254 additions and 561 deletions

View File

@@ -10,7 +10,7 @@
<adf-toolbar class="adf-cloud-form-toolbar" *ngIf="displayMode === 'fullScreen' && findDisplayConfiguration('fullScreen')?.options?.displayToolbar">
<div class="adf-cloud-form__form-title">
<span class="adf-cloud-form__display-name" [matTooltip]="form.taskName">
<span class="adf-cloud-form__display-name" [title]="form.taskName">
{{form.taskName}}
<ng-container *ngIf="!form.taskName">
{{'FORM.FORM_RENDERER.NAMELESS_TASK' | translate}}
@@ -23,7 +23,7 @@
data-automation-id="adf-toolbar-right-back"
[attr.aria-label]="'ADF_VIEWER.ACTIONS.CLOSE' | translate"
[attr.data-automation-id]="'adf-cloud-form-close-button'"
[matTooltip]="'ADF_VIEWER.ACTIONS.CLOSE' | translate"
[title]="'ADF_VIEWER.ACTIONS.CLOSE' | translate"
mat-icon-button
title="{{ 'ADF_VIEWER.ACTIONS.CLOSE' | translate }}"
(click)="switchToDisplayMode()">
@@ -48,12 +48,12 @@
<mat-icon>fullscreen</mat-icon>
</button>
</div>
<div *ngIf="showRefreshButton" class="adf-cloud-form-reload-button" [matTooltip]="'ADF_VIEWER.ACTIONS.FULLSCREEN' | translate">
<div *ngIf="showRefreshButton" class="adf-cloud-form-reload-button" [title]="'ADF_VIEWER.ACTIONS.FULLSCREEN' | translate">
<button mat-icon-button (click)="onRefreshClicked()" [attr.aria-label]="'ADF_VIEWER.ACTIONS.FULLSCREEN' | translate">
<mat-icon>refresh</mat-icon>
</button>
</div>
<span *ngIf="isTitleEnabled()" class="adf-cloud-form-title" [matTooltip]="form.taskName">
<span *ngIf="isTitleEnabled()" class="adf-cloud-form-title" [title]="form.taskName">
{{form.taskName}}
<ng-container *ngIf="!form.taskName">
{{'FORM.FORM_RENDERER.NAMELESS_TASK' | translate}}

View File

@@ -12,9 +12,7 @@
class="adf-attach-widget__menu-upload__button"
color="primary"
[id]="field.id"
[matTooltip]="field.tooltip"
matTooltipPosition="above"
matTooltipShowDelay="1000">
[title]="field.tooltip">
{{ 'FORM.FIELD.ATTACH' | translate }}
<mat-icon class="adf-attach-widget__menu-upload__button__icon">{{getWidgetIcon()}}</mat-icon>
</button>

View File

@@ -71,9 +71,6 @@ import {
import { By } from '@angular/platform-browser';
import { of, throwError } from 'rxjs';
import { FormCloudModule } from '../../../form-cloud.module';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
const mockNodeToBeVersioned: any = {
isFile: true,
@@ -125,7 +122,6 @@ describe('AttachFileCloudWidgetComponent', () => {
let localizedDataPipe: LocalizedDatePipe;
let newVersionUploaderService: NewVersionUploaderService;
let notificationService: NotificationService;
let loader: HarnessLoader;
const createUploadWidgetField = (
form: FormModel,
@@ -169,7 +165,6 @@ describe('AttachFileCloudWidgetComponent', () => {
contentNodeSelectorPanelService = TestBed.inject(ContentNodeSelectorPanelService);
openUploadFileDialogSpy = spyOn(contentCloudNodeSelectorService, 'openUploadFileDialog').and.returnValue(of([fakeNode]));
localizedDataPipe = new LocalizedDatePipe();
loader = TestbedHarnessEnvironment.loader(fixture);
});
afterEach(() => {
@@ -926,37 +921,4 @@ describe('AttachFileCloudWidgetComponent', () => {
expect(spyOnShowError).toHaveBeenCalledWith(mockError.value);
});
});
describe('when tooltip is set', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
type: FormFieldTypes.UPLOAD,
tooltip: 'my custom tooltip'
});
fixture.detectChanges();
});
it('should show tooltip', async () => {
const attachButton = fixture.nativeElement.querySelector('button');
attachButton.dispatchEvent(new Event('mouseenter'));
const tooltipElement = await loader.getHarness(MatTooltipHarness);
expect(await tooltipElement.isOpen()).toBeTrue();
expect(await tooltipElement.getTooltipText()).toBe('my custom tooltip');
});
it('should hide tooltip', async () => {
const attachButton = fixture.nativeElement.querySelector('.adf-attach-widget__menu-upload__button');
attachButton.dispatchEvent(new Event('mouseenter'));
fixture.detectChanges();
attachButton.dispatchEvent(new Event('mouseleave'));
fixture.detectChanges();
const tooltipElement = await loader.getHarness(MatTooltipHarness);
expect(await tooltipElement.isOpen()).toBeFalse();
});
});
});

View File

@@ -20,8 +20,7 @@
</div>
<div *ngIf="(!hasFile || multipleOption) && !field.readOnly">
<button mat-raised-button color="primary" (click)="uploadFiles.click()" [matTooltip]="field.tooltip"
matTooltipPosition="above" matTooltipShowDelay="1000">
<button mat-raised-button color="primary" (click)="uploadFiles.click()" [title]="field.tooltip">
{{ 'FORM.FIELD.UPLOAD' | translate }}<mat-icon>file_upload</mat-icon>
<input #uploadFiles [multiple]="multipleOption" type="file" [id]="field.form.nodeId"
(change)="onFileChanged($event)" />

View File

@@ -15,9 +15,7 @@
[min]="minDate"
[max]="maxDate"
[disabled]="field.readOnly"
[matTooltip]="field.tooltip"
matTooltipPosition="above"
matTooltipShowDelay="1000"
[title]="field.tooltip"
(dateChange)="onDateChanged($event)"
(blur)="markAsTouched()">
<mat-datepicker-toggle matSuffix [for]="datePicker" [disabled]="field.readOnly"></mat-datepicker-toggle>

View File

@@ -21,10 +21,6 @@ import { FormFieldModel, FormModel, FormFieldTypes, DateFieldValidator, MinDateF
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
import { DateAdapter } from '@angular/material/core';
import { isEqual, subDays, addDays } from 'date-fns';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
import { MatInputHarness } from '@angular/material/input/testing';
describe('DateWidgetComponent', () => {
let widget: DateCloudWidgetComponent;
@@ -32,7 +28,6 @@ describe('DateWidgetComponent', () => {
let element: HTMLElement;
let adapter: DateAdapter<Date>;
let form: FormModel;
let loader: HarnessLoader;
beforeEach(() => {
TestBed.configureTestingModule({
@@ -47,7 +42,6 @@ describe('DateWidgetComponent', () => {
widget = fixture.componentInstance;
element = fixture.nativeElement;
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should setup min value for date picker', () => {
@@ -433,34 +427,6 @@ describe('DateWidgetComponent', () => {
});
});
describe('when tooltip is set', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
type: FormFieldTypes.DATE,
tooltip: 'my custom tooltip'
});
fixture.detectChanges();
});
it('should show tooltip', async () => {
const dateCloudInput = await loader.getHarness(MatInputHarness);
await (await dateCloudInput.host()).dispatchEvent('mouseenter');
const tooltipElement = await loader.getHarness(MatTooltipHarness);
expect(await tooltipElement.isOpen()).toBeTruthy();
expect(await tooltipElement.getTooltipText()).toEqual('my custom tooltip');
});
it('should hide tooltip', async () => {
const dateCloudInput = await loader.getHarness(MatInputHarness);
await (await dateCloudInput.host()).dispatchEvent('mouseenter');
await (await dateCloudInput.host()).dispatchEvent('mouseleave');
const tooltipElement = await loader.getHarness(MatTooltipHarness);
expect(await tooltipElement.isOpen()).toBeFalsy();
});
});
describe('when is required', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {

View File

@@ -16,12 +16,10 @@
[disabled]="field.readOnly"
[compareWith]="compareDropdownValues"
(ngModelChange)="selectionChangedForField(field)"
[matTooltip]="field.tooltip"
[title]="field.tooltip"
[required]="isRequired()"
panelClass="adf-select-filter"
(blur)="markAsTouched()"
matTooltipPosition="above"
matTooltipShowDelay="1000"
[multiple]="field.hasMultipleValues">
<adf-select-filter-input *ngIf="showInputFilter" (change)="filter$.next($event)"></adf-select-filter-input>

View File

@@ -37,7 +37,6 @@ import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectHarness } from '@angular/material/select/testing';
import { MatFormFieldHarness } from '@angular/material/form-field/testing';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
describe('DropdownCloudWidgetComponent', () => {
let formService: FormService;
@@ -259,38 +258,6 @@ describe('DropdownCloudWidgetComponent', () => {
});
});
describe('when tooltip is set', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {
type: FormFieldTypes.DROPDOWN,
tooltip: 'my custom tooltip'
});
fixture.detectChanges();
});
it('should show tooltip', async () => {
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
const dropdownInput = await dropdown.host();
dropdownInput.dispatchEvent('mouseenter');
const tooltipElement = await loader.getHarness(MatTooltipHarness);
expect(tooltipElement).toBeTruthy();
expect(await tooltipElement.getTooltipText()).toBe('my custom tooltip');
expect(await tooltipElement.isOpen()).toBeTruthy();
});
it('should hide tooltip', async () => {
const dropdown = await loader.getHarness(MatSelectHarness.with({ selector: '.adf-select' }));
const dropdownInput = await dropdown.host();
await dropdownInput.dispatchEvent('mouseenter');
await dropdownInput.dispatchEvent('mouseleave');
const tooltipElement = await loader.getHarness(MatTooltipHarness);
expect(await tooltipElement.isOpen()).toBeFalsy();
});
});
describe('when is required', () => {
beforeEach(() => {
widget.field = new FormFieldModel(new FormModel({ taskId: '<id>' }), {

View File

@@ -15,9 +15,7 @@
(changedGroups)="onChangedGroup($event)"
[preSelectGroups]="preSelectGroup"
(blur)="markAsTouched()"
[matTooltip]="field.tooltip"
[matTooltipPosition]="'above'"
[matTooltipShowDelay]="1000">
[attr.title]="field.tooltip">
</adf-cloud-group>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired() && isTouched()"

View File

@@ -22,7 +22,6 @@ import { ProcessServiceCloudTestingModule } from '../../../../testing/process-se
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
import { MatChipHarness } from '@angular/material/chips/testing';
import { MatFormFieldHarness } from '@angular/material/form-field/testing';
@@ -74,23 +73,8 @@ describe('GroupCloudWidgetComponent', () => {
await fixture.whenStable();
fixture.detectChanges();
const tooltipElement = await loader.getHarness(MatTooltipHarness);
expect(await tooltipElement.isOpen()).toBeTruthy();
expect(await tooltipElement.getTooltipText()).toEqual('my custom tooltip');
});
it('should hide tooltip', async () => {
const cloudGroupInput = element.querySelector('[data-automation-id="adf-cloud-group-search-input"]');
cloudGroupInput.dispatchEvent(new Event('mouseenter'));
await fixture.whenStable();
fixture.detectChanges();
cloudGroupInput.dispatchEvent(new Event('mouseleave'));
await fixture.whenStable();
fixture.detectChanges();
const tooltipElement = await loader.getHarness(MatTooltipHarness);
expect(await tooltipElement.isOpen()).toBeFalsy();
const tooltip = cloudGroupInput.getAttribute('title');
expect(tooltip).toEqual('my custom tooltip');
});
});
@@ -167,8 +151,8 @@ describe('GroupCloudWidgetComponent', () => {
const formField = await loader.getHarness(MatFormFieldHarness);
expect(await formField.isDisabled()).toBeTrue();
const gtoupChip = await loader.getHarness(MatChipHarness);
expect(await gtoupChip.isDisabled()).toBeTrue();
const groupChip = await loader.getHarness(MatChipHarness);
expect(await groupChip.isDisabled()).toBeTrue();
});
it('should multi chips be disabled', async () => {

View File

@@ -17,9 +17,7 @@
[mode]="mode"
[groupsRestriction]="groupsRestriction"
(blur)="markAsTouched()"
[matTooltip]="field.tooltip"
matTooltipPosition="above"
matTooltipShowDelay="1000">
[attr.title]="field.tooltip">
</adf-cloud-people>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget class="adf-dropdown-required-message" *ngIf="isInvalidFieldRequired() && isTouched()"

View File

@@ -24,7 +24,6 @@ import { IdentityUserService } from '../../../../people/services/identity-user.s
import { mockShepherdsPie, mockYorkshirePudding } from '../../../../people/mock/people-cloud.mock';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
import { MatFormFieldHarness } from '@angular/material/form-field/testing';
import { MatChipHarness } from '@angular/material/chips/testing';
@@ -102,23 +101,8 @@ describe('PeopleCloudWidgetComponent', () => {
await fixture.whenStable();
fixture.detectChanges();
const tooltipElement = await loader.getHarness(MatTooltipHarness);
expect(await tooltipElement.isOpen()).toBeTruthy();
expect(await tooltipElement.getTooltipText()).toEqual('my custom tooltip');
});
it('should hide tooltip', async () => {
const cloudPeopleInput = element.querySelector('adf-cloud-people');
cloudPeopleInput.dispatchEvent(new Event('mouseenter'));
await fixture.whenStable();
fixture.detectChanges();
cloudPeopleInput.dispatchEvent(new Event('mouseleave'));
await fixture.whenStable();
fixture.detectChanges();
const tooltipElement = await loader.getHarness(MatTooltipHarness);
expect(await tooltipElement.isOpen()).toBeFalsy();
const tooltip = cloudPeopleInput.getAttribute('title');
expect(tooltip).toEqual('my custom tooltip');
});
});

View File

@@ -4,9 +4,7 @@
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }}<span class="adf-asterisk" *ngIf="isRequired()">*</span></label>
<mat-radio-group [ngClass]="(field.alignmentType === 'vertical') ? 'adf-radio-group': 'adf-radio-group-horizontal'" class="adf-radio-group" [(ngModel)]="field.value" [disabled]="field.readOnly">
<mat-radio-button
[matTooltip]="field.tooltip"
matTooltipPosition="above"
matTooltipShowDelay="1000"
[title]="field.tooltip"
[id]="field.id + '-' + opt.id"
[name]="field.id"
[value]="opt.id"

View File

@@ -24,7 +24,6 @@ import { of, throwError } from 'rxjs';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatRadioButtonHarness, MatRadioGroupHarness } from '@angular/material/radio/testing';
import { MatTooltipHarness } from '@angular/material/tooltip/testing';
describe('RadioButtonsCloudWidgetComponent', () => {
let fixture: ComponentFixture<RadioButtonsCloudWidgetComponent>;
@@ -219,19 +218,8 @@ describe('RadioButtonsCloudWidgetComponent', () => {
it('should show tooltip', async () => {
const radioButton = await loader.getHarness(MatRadioButtonHarness);
await (await radioButton.host()).hover();
const tooltip = await loader.getHarness(MatTooltipHarness);
expect(await tooltip.getTooltipText()).toBe('my custom tooltip');
});
it('should hide tooltip', async () => {
const radioButton = await loader.getHarness(MatRadioButtonHarness);
const tooltipElement = await loader.getHarness(MatTooltipHarness);
await (await radioButton.host()).hover();
expect(await tooltipElement.isOpen()).toBeTrue();
await (await radioButton.host()).mouseAway();
expect(await tooltipElement.isOpen()).toBeFalse();
const tooltip = await (await radioButton.host()).getAttribute('title');
expect(tooltip).toBe('my custom tooltip');
});
});
});

View File

@@ -8,7 +8,7 @@
[removable]="!(group.readonly)"
[attr.data-automation-id]="'adf-cloud-group-chip-' + group.name"
(removed)="onRemove(group)"
matTooltip="{{ (group.readonly ? 'ADF_CLOUD_GROUPS.MANDATORY' : '') | translate }}">
title="{{ (group.readonly ? 'ADF_CLOUD_GROUPS.MANDATORY' : '') | translate }}">
{{group.name}}
<mat-icon
*ngIf="!(group.readonly || readOnly)"

View File

@@ -37,25 +37,56 @@ import { MatSelectModule } from '@angular/material/select';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatTableModule } from '@angular/material/table';
import { MatTabsModule } from '@angular/material/tabs';
import { MatTooltipModule } from '@angular/material/tooltip';
@NgModule({
providers: [
{ provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: { floatLabel: 'never' } }
],
providers: [{ provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: { floatLabel: 'never' } }],
imports: [
MatAutocompleteModule, MatButtonModule, MatCardModule, MatDialogModule,
MatCheckboxModule, MatDatepickerModule, MatGridListModule, MatIconModule, MatInputModule,
MatListModule, MatOptionModule, MatRadioModule, MatSelectModule, MatSlideToggleModule, MatTableModule,
MatTabsModule, MatProgressSpinnerModule, MatNativeDateModule, MatRippleModule, MatTooltipModule,
MatChipsModule, MatMenuModule, MatExpansionModule
MatAutocompleteModule,
MatButtonModule,
MatCardModule,
MatDialogModule,
MatCheckboxModule,
MatDatepickerModule,
MatGridListModule,
MatIconModule,
MatInputModule,
MatListModule,
MatOptionModule,
MatRadioModule,
MatSelectModule,
MatSlideToggleModule,
MatTableModule,
MatTabsModule,
MatProgressSpinnerModule,
MatNativeDateModule,
MatRippleModule,
MatChipsModule,
MatMenuModule,
MatExpansionModule
],
exports: [
MatAutocompleteModule, MatButtonModule, MatCardModule, MatDialogModule,
MatCheckboxModule, MatDatepickerModule, MatGridListModule, MatIconModule, MatInputModule,
MatListModule, MatOptionModule, MatRadioModule, MatSelectModule, MatSlideToggleModule, MatTableModule,
MatTabsModule, MatProgressSpinnerModule, MatNativeDateModule, MatRippleModule, MatTooltipModule,
MatChipsModule, MatMenuModule, MatExpansionModule
MatAutocompleteModule,
MatButtonModule,
MatCardModule,
MatDialogModule,
MatCheckboxModule,
MatDatepickerModule,
MatGridListModule,
MatIconModule,
MatInputModule,
MatListModule,
MatOptionModule,
MatRadioModule,
MatSelectModule,
MatSlideToggleModule,
MatTableModule,
MatTabsModule,
MatProgressSpinnerModule,
MatNativeDateModule,
MatRippleModule,
MatChipsModule,
MatMenuModule,
MatExpansionModule
]
})
export class MaterialModule {}

View File

@@ -8,7 +8,7 @@
[removable]="!(user.readonly)"
[attr.data-automation-id]="'adf-people-cloud-chip-' + user.username"
(removed)="onRemove(user)"
matTooltip="{{ (user.readonly ? 'ADF_CLOUD_GROUPS.MANDATORY' : '') | translate }}">
title="{{ (user.readonly ? 'ADF_CLOUD_GROUPS.MANDATORY' : '') | translate }}">
{{user | fullName}}
<mat-icon
matChipRemove

View File

@@ -8,7 +8,7 @@
<span *ngIf="showTitle"> {{ 'ADF_CLOUD_EDIT_PROCESS_FILTER.TITLE' | translate}}</span>
<div *ngIf="showFilterActions" class="adf-cloud-edit-process-filter-actions">
<ng-container *ngIf="toggleFilterActions">
<button *ngFor="let filterAction of processFilterActions" mat-icon-button matTooltip="{{ filterAction.tooltip | translate}}" [attr.data-automation-id]="'adf-filter-action-' + filterAction.actionType" [disabled]="isDisabledAction(filterAction)" (click)="executeFilterActions($event, filterAction)">
<button *ngFor="let filterAction of processFilterActions" mat-icon-button title="{{ filterAction.tooltip | translate}}" [attr.data-automation-id]="'adf-filter-action-' + filterAction.actionType" [disabled]="isDisabledAction(filterAction)" (click)="executeFilterActions($event, filterAction)">
<adf-icon [value]="filterAction.icon"></adf-icon>
</button>
</ng-container>

View File

@@ -10,7 +10,7 @@
<ng-container *ngIf="toggleFilterActions">
<button *ngFor="let filterAction of taskFilterActions"
mat-icon-button
matTooltip="{{ filterAction.tooltip | translate}}"
title="{{ filterAction.tooltip | translate}}"
[attr.data-automation-id]="'adf-filter-action-' + filterAction.actionType"
[disabled]="isDisabledAction(filterAction)"
(click)="executeFilterActions(filterAction)">