mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
[ACS-10518]: Search input keyboard navigation accessibility fixes (#11270)
* [ACS-10518]: add permissions panel clear button updates * [ACS-10518]: adds content-node-selector panel clear button updates * [ACS-10518]: adds no-pointer class * [ACS-10518]: adds no-pointer * [ACS-10518]: minor fixes * [ACS-10518]: fixes padding * [ACS-10518]: unit tests refactor * [ACS-10518]: minor fixes
This commit is contained in:
+38
-19
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core';
|
||||||
import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
|
import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { Node, NodeEntry, NodePaging, RequestScope, ResultSetPaging, SiteEntry, SitePaging, SitePagingList } from '@alfresco/js-api';
|
import { Node, NodeEntry, NodePaging, RequestScope, ResultSetPaging, SiteEntry, SitePaging, SitePagingList } from '@alfresco/js-api';
|
||||||
@@ -30,6 +30,7 @@ import { SearchQueryBuilderService } from '../../search';
|
|||||||
import { mockSearchRequest } from '../../mock/search-query.mock';
|
import { mockSearchRequest } from '../../mock/search-query.mock';
|
||||||
import { SitesService } from '../../common/services/sites.service';
|
import { SitesService } from '../../common/services/sites.service';
|
||||||
import { NodesApiService } from '../../common/services/nodes-api.service';
|
import { NodesApiService } from '../../common/services/nodes-api.service';
|
||||||
|
import { UnitTestingUtils } from '../../../../../core/src/lib/testing/unit-testing-utils';
|
||||||
|
|
||||||
const fakeResultSetPaging: ResultSetPaging = {
|
const fakeResultSetPaging: ResultSetPaging = {
|
||||||
list: {
|
list: {
|
||||||
@@ -60,15 +61,18 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
|||||||
const fakeNodeEntry = new Node({ id: 'fakeId' });
|
const fakeNodeEntry = new Node({ id: 'fakeId' });
|
||||||
const nodeEntryEvent = new NodeEntryEvent(fakeNodeEntry);
|
const nodeEntryEvent = new NodeEntryEvent(fakeNodeEntry);
|
||||||
let searchQueryBuilderService: SearchQueryBuilderService;
|
let searchQueryBuilderService: SearchQueryBuilderService;
|
||||||
|
let testingUtils: UnitTestingUtils;
|
||||||
|
|
||||||
const typeToSearchBox = (searchTerm = 'string-to-search') => {
|
const typeToSearchBox = (searchTerm = 'string-to-search'): void => {
|
||||||
const searchInput = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-input"]'));
|
const searchInput = testingUtils.getByCSS('[data-automation-id="content-node-selector-search-input"]');
|
||||||
searchInput.nativeElement.value = searchTerm;
|
searchInput.nativeElement.value = searchTerm;
|
||||||
component.searchInput.setValue(searchTerm);
|
component.searchInput.setValue(searchTerm);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
};
|
};
|
||||||
|
|
||||||
const triggerSearchResults = (searchResults: ResultSetPaging) => {
|
const getSearchIcon = (type: string): DebugElement => testingUtils.getByCSS(`[data-automation-id="content-node-selector-search-${type}"]`);
|
||||||
|
|
||||||
|
const triggerSearchResults = (searchResults: ResultSetPaging): void => {
|
||||||
const service = fixture.debugElement.injector.get(SearchQueryBuilderService);
|
const service = fixture.debugElement.injector.get(SearchQueryBuilderService);
|
||||||
service.executed.next(searchResults);
|
service.executed.next(searchResults);
|
||||||
};
|
};
|
||||||
@@ -92,6 +96,8 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
|||||||
searchQueryBuilderService = fixture.debugElement.injector.get(SearchQueryBuilderService);
|
searchQueryBuilderService = fixture.debugElement.injector.get(SearchQueryBuilderService);
|
||||||
searchQueryBuilderService.resetToDefaults();
|
searchQueryBuilderService.resetToDefaults();
|
||||||
|
|
||||||
|
testingUtils = new UnitTestingUtils(fixture.debugElement);
|
||||||
|
|
||||||
spyOn(nodeService, 'getNode').and.returnValue(
|
spyOn(nodeService, 'getNode').and.returnValue(
|
||||||
of(
|
of(
|
||||||
new Node({
|
new Node({
|
||||||
@@ -196,7 +202,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
|||||||
spyOn(component, 'clearSearch');
|
spyOn(component, 'clearSearch');
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const clearIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-clear"]'));
|
const clearIcon = getSearchIcon('clear');
|
||||||
clearIcon.nativeElement.click();
|
clearIcon.nativeElement.click();
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -357,8 +363,8 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
tick(debounceSearch);
|
tick(debounceSearch);
|
||||||
|
|
||||||
const searchIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-icon"]'));
|
const searchIcon = getSearchIcon('icon');
|
||||||
const clearIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-clear"]'));
|
const clearIcon = getSearchIcon('clear');
|
||||||
|
|
||||||
expect(searchIcon).not.toBeNull();
|
expect(searchIcon).not.toBeNull();
|
||||||
expect(clearIcon).toBeNull();
|
expect(clearIcon).toBeNull();
|
||||||
@@ -371,13 +377,26 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
|||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const searchIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-icon"]'));
|
const searchIcon = getSearchIcon('icon');
|
||||||
const clearIcon = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-clear"]'));
|
const clearIcon = getSearchIcon('clear');
|
||||||
|
|
||||||
expect(searchIcon).toBeNull();
|
expect(searchIcon).toBeNull();
|
||||||
expect(clearIcon).not.toBeNull();
|
expect(clearIcon).not.toBeNull();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should call clear method on the X (clear) button click', fakeAsync(() => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
typeToSearchBox('123');
|
||||||
|
tick(debounceSearch);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
spyOn(component, 'clear');
|
||||||
|
const clearButton = getSearchIcon('clear');
|
||||||
|
clearButton.nativeElement.click();
|
||||||
|
expect(component.clear).toHaveBeenCalled();
|
||||||
|
}));
|
||||||
|
|
||||||
it('should clear the search field, nodes and chosenNode when clicking on the X (clear) icon', async () => {
|
it('should clear the search field, nodes and chosenNode when clicking on the X (clear) icon', async () => {
|
||||||
component.chosenNode = [entry];
|
component.chosenNode = [entry];
|
||||||
|
|
||||||
@@ -553,7 +572,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should show the current folder content instead of search results if search was not performed', async () => {
|
it('should show the current folder content instead of search results if search was not performed', async () => {
|
||||||
const documentList = fixture.debugElement.query(By.directive(DocumentListComponent));
|
const documentList = testingUtils.getByDirective(DocumentListComponent);
|
||||||
expect(documentList).not.toBeNull();
|
expect(documentList).not.toBeNull();
|
||||||
expect(documentList.componentInstance.currentFolderId).toBe('cat-girl-nuku-nuku');
|
expect(documentList.componentInstance.currentFolderId).toBe('cat-girl-nuku-nuku');
|
||||||
});
|
});
|
||||||
@@ -565,7 +584,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
|||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const documentList = fixture.debugElement.query(By.directive(DocumentListComponent));
|
const documentList = testingUtils.getByDirective(DocumentListComponent);
|
||||||
expect(documentList).not.toBeNull();
|
expect(documentList).not.toBeNull();
|
||||||
expect(
|
expect(
|
||||||
documentList.componentInstance.rowFilter({
|
documentList.componentInstance.rowFilter({
|
||||||
@@ -593,7 +612,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
|||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const documentList = fixture.debugElement.query(By.directive(DocumentListComponent));
|
const documentList = testingUtils.getByDirective(DocumentListComponent);
|
||||||
expect(documentList).not.toBeNull();
|
expect(documentList).not.toBeNull();
|
||||||
expect(documentList.componentInstance.rowFilter).toBeTruthy();
|
expect(documentList.componentInstance.rowFilter).toBeTruthy();
|
||||||
|
|
||||||
@@ -607,7 +626,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
|||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const documentList = fixture.debugElement.query(By.directive(DocumentListComponent));
|
const documentList = testingUtils.getByDirective(DocumentListComponent);
|
||||||
expect(documentList).not.toBeNull();
|
expect(documentList).not.toBeNull();
|
||||||
expect(documentList.componentInstance.imageResolver).toBe(resolver);
|
expect(documentList.componentInstance.imageResolver).toBe(resolver);
|
||||||
});
|
});
|
||||||
@@ -619,7 +638,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
|||||||
triggerSearchResults(fakeResultSetPaging);
|
triggerSearchResults(fakeResultSetPaging);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const documentList = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-document-list"]'));
|
const documentList = testingUtils.getByCSS('[data-automation-id="content-node-selector-document-list"]');
|
||||||
expect(documentList).not.toBeNull();
|
expect(documentList).not.toBeNull();
|
||||||
expect(component.hasValidQuery).toEqual(true);
|
expect(component.hasValidQuery).toEqual(true);
|
||||||
expect(documentList.componentInstance.currentFolderId).toBeNull();
|
expect(documentList.componentInstance.currentFolderId).toBeNull();
|
||||||
@@ -664,12 +683,12 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
fixture.whenStable().then(() => {
|
||||||
const clearButton = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-search-clear"]'));
|
const clearButton = getSearchIcon('clear');
|
||||||
expect(clearButton).not.toBeNull();
|
expect(clearButton).not.toBeNull();
|
||||||
clearButton.triggerEventHandler('click', {});
|
clearButton.triggerEventHandler('click', {});
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const documentList = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-document-list"]'));
|
const documentList = testingUtils.getByCSS('[data-automation-id="content-node-selector-document-list"]');
|
||||||
expect(documentList).not.toBeNull();
|
expect(documentList).not.toBeNull();
|
||||||
expect(documentList.componentInstance.currentFolderId).toBe('cat-girl-nuku-nuku');
|
expect(documentList.componentInstance.currentFolderId).toBe('cat-girl-nuku-nuku');
|
||||||
done();
|
done();
|
||||||
@@ -696,13 +715,13 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
|||||||
component.siteChanged({ entry: { guid: 'Kame-Sennin Muten Roshi' } } as SiteEntry);
|
component.siteChanged({ entry: { guid: 'Kame-Sennin Muten Roshi' } } as SiteEntry);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
let documentList = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-document-list"]'));
|
let documentList = testingUtils.getByCSS('[data-automation-id="content-node-selector-document-list"]');
|
||||||
expect(documentList.componentInstance.currentFolderId).toBe('Kame-Sennin Muten Roshi');
|
expect(documentList.componentInstance.currentFolderId).toBe('Kame-Sennin Muten Roshi');
|
||||||
|
|
||||||
component.siteChanged({ entry: { guid: undefined } } as SiteEntry);
|
component.siteChanged({ entry: { guid: undefined } } as SiteEntry);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
documentList = fixture.debugElement.query(By.css('[data-automation-id="content-node-selector-document-list"]'));
|
documentList = testingUtils.getByCSS('[data-automation-id="content-node-selector-document-list"]');
|
||||||
expect(documentList.componentInstance.currentFolderId).toBe('cat-girl-nuku-nuku');
|
expect(documentList.componentInstance.currentFolderId).toBe('cat-girl-nuku-nuku');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
@@ -711,7 +730,7 @@ describe('ContentNodeSelectorPanelComponent', () => {
|
|||||||
describe('Pagination "Load more" button', () => {
|
describe('Pagination "Load more" button', () => {
|
||||||
it('should NOT be shown by default', () => {
|
it('should NOT be shown by default', () => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const pagination = fixture.debugElement.query(By.css('[data-automation-id="adf-infinite-pagination-button"]'));
|
const pagination = testingUtils.getByCSS('[data-automation-id="adf-infinite-pagination-button"]');
|
||||||
expect(pagination).toBeNull();
|
expect(pagination).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+16
-8
@@ -13,18 +13,26 @@
|
|||||||
adf-auto-focus
|
adf-auto-focus
|
||||||
data-automation-id="content-node-selector-search-input">
|
data-automation-id="content-node-selector-search-input">
|
||||||
|
|
||||||
<mat-icon *ngIf="searchTerm.length > 0"
|
<button
|
||||||
matSuffix (click)="clear()"
|
matSuffix
|
||||||
class="adf-content-node-selector-content-input-icon"
|
mat-icon-button
|
||||||
data-automation-id="content-node-selector-search-clear">clear
|
*ngIf="searchTerm.length > 0"
|
||||||
</mat-icon>
|
data-automation-id="content-node-selector-search-clear"
|
||||||
|
class="adf-content-node-selector-search-clear-button"
|
||||||
|
(click)="clear()"
|
||||||
|
[attr.aria-label]="'COMMON.CLEAR' | translate"
|
||||||
|
[attr.title]="'COMMON.CLEAR' | translate"
|
||||||
|
>
|
||||||
|
<mat-icon class="adf-content-node-selector-content-input-icon">clear</mat-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
<mat-icon *ngIf="searchTerm.length === 0"
|
<mat-icon
|
||||||
|
*ngIf="searchTerm.length === 0"
|
||||||
matSuffix
|
matSuffix
|
||||||
class="adf-content-node-selector-content-input-icon"
|
class="adf-content-node-selector-content-input-icon"
|
||||||
data-automation-id="content-node-selector-search-icon">search
|
data-automation-id="content-node-selector-search-icon"
|
||||||
|
>search
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
|
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<adf-sites-dropdown
|
<adf-sites-dropdown
|
||||||
*ngIf="showDropdownSiteList"
|
*ngIf="showDropdownSiteList"
|
||||||
|
|||||||
+15
-2
@@ -75,18 +75,31 @@ h2.adf-search-results-label {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
|
|
||||||
.adf-content-node-selector-content-input-icon {
|
.adf-content-node-selector-content-input-icon:is(mat-icon) {
|
||||||
color: var(--adf-theme-foreground-icon-color-054);
|
color: var(--adf-theme-foreground-icon-color-054);
|
||||||
cursor: pointer;
|
|
||||||
padding: 0 0 8px;
|
padding: 0 0 8px;
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-content-node-selector-search-clear-button {
|
||||||
|
padding: 0;
|
||||||
|
width: 20px;
|
||||||
|
height: 28px;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline-offset: -1.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adf-content-node-selector-content-input-icon:is(mat-icon) {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--adf-theme-foreground-base-color);
|
color: var(--adf-theme-foreground-base-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#{ms.$mat-form-field-subscript-wrapper} {
|
#{ms.$mat-form-field-subscript-wrapper} {
|
||||||
display: none;
|
display: none;
|
||||||
|
|||||||
+2
-1
@@ -19,7 +19,8 @@
|
|||||||
class="adf-permission-search-input-clear-button"
|
class="adf-permission-search-input-clear-button"
|
||||||
(click)="clearSearch()"
|
(click)="clearSearch()"
|
||||||
[attr.aria-label]="'COMMON.CLEAR' | translate"
|
[attr.aria-label]="'COMMON.CLEAR' | translate"
|
||||||
[attr.title]="'COMMON.CLEAR' | translate">
|
[attr.title]="'COMMON.CLEAR' | translate"
|
||||||
|
>
|
||||||
<mat-icon class="adf-permission-search-icon">clear</mat-icon>
|
<mat-icon class="adf-permission-search-icon">clear</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|||||||
+8
-5
@@ -80,11 +80,6 @@ $search-result-height: calc(100% - 60px);
|
|||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: var(--adf-theme-foreground-base-color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-permission-search-input-clear-button {
|
.adf-permission-search-input-clear-button {
|
||||||
@@ -92,6 +87,14 @@ $search-result-height: calc(100% - 60px);
|
|||||||
width: 20px;
|
width: 20px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
margin-right: 1.5px;
|
margin-right: 1.5px;
|
||||||
|
|
||||||
|
.adf-permission-search-icon:is(mat-icon) {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--adf-theme-foreground-base-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user