diff --git a/lib/core/src/lib/datatable/components/datatable/datatable.component.html b/lib/core/src/lib/datatable/components/datatable/datatable.component.html index 5fdbce2a4b..83066fc6b6 100644 --- a/lib/core/src/lib/datatable/components/datatable/datatable.component.html +++ b/lib/core/src/lib/datatable/components/datatable/datatable.component.html @@ -166,7 +166,6 @@ (select)="onEnterKeyPressed(row, $event)" (keyup)="onRowKeyUp(row, $event)" (keydown)="onRowEnterKeyDown(row, $event)" - (click)="onRowClick(row, $event)" [adf-upload]="rowAllowsDrop(row)" [adf-upload-data]="row" [ngStyle]="rowStyle" @@ -210,7 +209,7 @@ [attr.data-automation-id]="getAutomationValue(row)" [attr.aria-selected]="row.isSelected ? true : false" [attr.aria-label]="col.title ? (col.title | translate) : null" - (click)="storeActiveRow(row)" + (click)="onRowClick(row, $event)" (keydown.enter)="onEnterKeyPressed(row, $any($event))" [adf-context-menu]="getContextMenuActions(row, col)" [adf-context-menu-enabled]="contextMenu" diff --git a/lib/core/src/lib/datatable/components/datatable/datatable.component.spec.ts b/lib/core/src/lib/datatable/components/datatable/datatable.component.spec.ts index 46c8f9a2e3..4869c90d00 100644 --- a/lib/core/src/lib/datatable/components/datatable/datatable.component.spec.ts +++ b/lib/core/src/lib/datatable/components/datatable/datatable.component.spec.ts @@ -32,8 +32,6 @@ import { TranslateModule } from '@ngx-translate/core'; import { domSanitizerMock } from '../../../mock/dom-sanitizer-mock'; import { matIconRegistryMock } from '../../../mock/mat-icon-registry-mock'; import { CdkDragDrop } from '@angular/cdk/drag-drop'; -import { take } from 'rxjs/operators'; -import { By } from '@angular/platform-browser'; @Component({selector: 'adf-custom-column-template-component', template: ` @@ -85,67 +83,6 @@ describe('DataTable', () => { let dataTable: DataTableComponent; let element: any; - const testNotShownHeader = (data: ObjectDataTableAdapter) => { - dataTable.ngOnChanges({ - data: new SimpleChange(null, data, false) - }); - - dataTable.showHeader = ShowHeaderMode.Data; - fixture.detectChanges(); - expect(element.querySelector('.adf-datatable-header')).toBeNull(); - - dataTable.showHeader = ShowHeaderMode.Always; - fixture.detectChanges(); - expect(element.querySelector('.adf-datatable-header')).toBeNull(); - - dataTable.showHeader = ShowHeaderMode.Never; - fixture.detectChanges(); - expect(element.querySelector('.adf-datatable-header')).toBeNull(); - }; - - const testIfRowIsSelected = (data: any[], done?: DoneFn) => { - dataTable.selectionMode = 'single'; - dataTable.data = new ObjectDataTableAdapter(data, [new ObjectDataColumn({ key: 'name' })]); - const rows = dataTable.data.getRows(); - - dataTable.ngOnChanges({}); - if (done) { - fixture.detectChanges(); - - dataTable.rowClick.subscribe(() => { - expect(rows[0].isSelected).toBeFalsy(); - expect(rows[1].isSelected).toBeTruthy(); - done(); - }); - } - return rows; - }; - - const testDoubleClickCount = (tickTime = 490, rowClickNumber = 1) => { - let doubleClickCount = 0; - - const row = {} as DataRow; - dataTable.data = new ObjectDataTableAdapter([], []); - dataTable.ngOnChanges({}); - fixture.detectChanges(); - - dataTable.rowDblClick.subscribe(() => { - doubleClickCount += 1; - }); - - dataTable.onRowClick(row, new MouseEvent('click')); - setTimeout(() => { - for (let i = 0; i < rowClickNumber; i++) { - dataTable.onRowClick(row, new MouseEvent('click')); - } - }, 240); - - tick(tickTime); - - - expect(doubleClickCount).toBe(1); - }; - setupTestBed({ imports: [ TranslateModule.forRoot(), @@ -318,13 +255,41 @@ describe('DataTable', () => { dataTable.loading = false; dataTable.noPermission = true; - testNotShownHeader(emptyData); + dataTable.ngOnChanges({ + data: new SimpleChange(null, emptyData, false) + }); + + dataTable.showHeader = ShowHeaderMode.Data; + fixture.detectChanges(); + expect(element.querySelector('.adf-datatable-header')).toBeNull(); + + dataTable.showHeader = ShowHeaderMode.Always; + fixture.detectChanges(); + expect(element.querySelector('.adf-datatable-header')).toBeNull(); + + dataTable.showHeader = ShowHeaderMode.Never; + fixture.detectChanges(); + expect(element.querySelector('.adf-datatable-header')).toBeNull(); }); it('should never show the header if loading is true', () => { dataTable.loading = true; - testNotShownHeader(emptyData); + dataTable.ngOnChanges({ + data: new SimpleChange(null, emptyData, false) + }); + + dataTable.showHeader = ShowHeaderMode.Data; + fixture.detectChanges(); + expect(element.querySelector('.adf-datatable-header')).toBeNull(); + + dataTable.showHeader = ShowHeaderMode.Always; + fixture.detectChanges(); + expect(element.querySelector('.adf-datatable-header')).toBeNull(); + + dataTable.showHeader = ShowHeaderMode.Never; + fixture.detectChanges(); + expect(element.querySelector('.adf-datatable-header')).toBeNull(); }); }); @@ -511,28 +476,65 @@ describe('DataTable', () => { }); it('should select only one row with [single] selection mode', (done) => { - const rows = testIfRowIsSelected([ - { name: '1', isSelected: true }, - { name: '2' } - ], done); + dataTable.selectionMode = 'single'; + dataTable.data = new ObjectDataTableAdapter( + [ + { name: '1', isSelected: true }, + { name: '2' } + ], + [new ObjectDataColumn({ key: 'name' })] + ); + const rows = dataTable.data.getRows(); + + dataTable.ngOnChanges({}); + fixture.detectChanges(); + + dataTable.rowClick.subscribe(() => { + expect(rows[0].isSelected).toBeFalsy(); + expect(rows[1].isSelected).toBeTruthy(); + done(); + }); + dataTable.onRowClick(rows[1], new MouseEvent('click')); }); it('should select only one row with [single] selection mode and key modifier', (done) => { - const rows = testIfRowIsSelected([ - { name: '1', isSelected: true }, - { name: '2' } - ], done); + dataTable.selectionMode = 'single'; + dataTable.data = new ObjectDataTableAdapter( + [ + { name: '1', isSelected: true }, + { name: '2' } + ], + [new ObjectDataColumn({ key: 'name' })] + ); + const rows = dataTable.data.getRows(); + + dataTable.ngOnChanges({}); + fixture.detectChanges(); + + dataTable.rowClick.subscribe(() => { + expect(rows[0].isSelected).toBeFalsy(); + expect(rows[1].isSelected).toBeTruthy(); + done(); + }); + dataTable.onRowClick(rows[1], new MouseEvent('click', { metaKey: true })); }); it('should select only one row with [single] selection mode pressing enter key', () => { - const rows = testIfRowIsSelected([ - { name: '1' }, - { name: '2' } - ]); + dataTable.selectionMode = 'single'; + dataTable.data = new ObjectDataTableAdapter( + [ + { name: '1' }, + { name: '2' } + ], + [new ObjectDataColumn({ key: 'name' })] + ); + const rows = dataTable.data.getRows(); + + dataTable.ngOnChanges({}); dataTable.onEnterKeyPressed(rows[0], null); expect(rows[0].isSelected).toBeTruthy(); expect(rows[1].isSelected).toBeFalsy(); @@ -583,7 +585,7 @@ describe('DataTable', () => { expect(rows[1].isSelected).toBeFalsy(); done(); }); - dataTable.onRowClick(rows[0], new MouseEvent('click')); + dataTable.onRowClick(rows[0], null); }); it('should unselect the row with [multiple] selection mode and modifier key', (done) => { @@ -604,8 +606,7 @@ describe('DataTable', () => { dataTable.onRowClick(rows[0], { metaKey: true, - preventDefault: () => {}, - composedPath: () => [] + preventDefault: () => {} } as any); }); @@ -750,15 +751,55 @@ describe('DataTable', () => { dataTable.ngOnChanges({}); fixture.detectChanges(); - dataTable.onRowClick(row, new MouseEvent('click')); + dataTable.onRowClick(row, null); }); it('should emit double click if there are two single click in 250ms', fakeAsync(() => { - testDoubleClickCount(); + let doubleClickCount = 0; + + const row = {} as DataRow; + dataTable.data = new ObjectDataTableAdapter([], []); + dataTable.ngOnChanges({}); + fixture.detectChanges(); + + dataTable.rowDblClick.subscribe(() => { + doubleClickCount += 1; + }); + + dataTable.onRowClick(row, null); + setTimeout(() => { + dataTable.onRowClick(row, null); + } + , 240); + + tick(490); + + + expect(doubleClickCount).toBe(1); })); it('should emit double click if there are more than two single click in 250ms', fakeAsync(() => { - testDoubleClickCount(740, 2); + let doubleClickCount = 0; + const row = {} as DataRow; + dataTable.data = new ObjectDataTableAdapter([], []); + dataTable.ngOnChanges({}); + fixture.detectChanges(); + + dataTable.rowDblClick.subscribe(() => { + doubleClickCount += 1; + }); + + dataTable.onRowClick(row, null); + setTimeout(() => { + + dataTable.onRowClick(row, null); + dataTable.onRowClick(row, null); + } + , 240); + + tick(740); + + expect(doubleClickCount).toBe(1); })); it('should emit single click if there are two single click in more than 250ms', fakeAsync(() => { @@ -773,10 +814,10 @@ describe('DataTable', () => { clickCount += 1; }); - dataTable.onRowClick(row, new MouseEvent('click')); + dataTable.onRowClick(row, null); setTimeout(() => { - dataTable.onRowClick(row, new MouseEvent('click')); + dataTable.onRowClick(row, null); } , 260); @@ -796,7 +837,7 @@ describe('DataTable', () => { dataTable.ngOnChanges({}); fixture.detectChanges(); - dataTable.onRowClick(row, new MouseEvent('click')); + dataTable.onRowClick(row, null); }); it('should emit row-dblclick dom event', (done) => { @@ -809,13 +850,12 @@ describe('DataTable', () => { }); dataTable.ngOnChanges({}); fixture.detectChanges(); - dataTable.onRowClick(row, new MouseEvent('click')); - dataTable.onRowClick(row, new MouseEvent('click')); + dataTable.onRowClick(row, null); + dataTable.onRowClick(row, null); }); it('should prevent default behaviour on row click event', () => { - const e = new MouseEvent('click'); - spyOn(e, 'preventDefault'); + const e = jasmine.createSpyObj('event', ['preventDefault']); dataTable.ngAfterContentInit(); dataTable.onRowClick(null, e); expect(e.preventDefault).toHaveBeenCalled(); @@ -1333,45 +1373,6 @@ describe('DataTable', () => { expect(dataTable.selectedRowId).toEqual('2345'); expect(row.isContextMenuSource).toBeTrue(); }); - - it('should select the row, regardless of where the user clicks in the row.', async () => { - dataTable.selectionMode = 'single'; - const dataRows = [{ id: 0 }, { id: 1 }]; - dataTable.data = new ObjectDataTableAdapter( - dataRows, - [new ObjectDataColumn({ key: 'id' })] - ); - dataTable.ngOnChanges({ - rows: new SimpleChange(null, dataRows, false) - }); - fixture.detectChanges(); - - const rows = dataTable.data.getRows(); - expect(rows[0].isSelected).toBeFalsy(); - expect(rows[1].isSelected).toBeFalsy(); - - dataTable.resetSelection(); - const rowClickPromise = dataTable.rowClick.pipe(take(1)).toPromise(); - const rowElement = fixture.debugElement.query(By.css(`[data-automation-id="datatable-row-0"]`)).nativeElement as HTMLElement; - rowElement.dispatchEvent(new MouseEvent('click')); - fixture.detectChanges(); - await rowClickPromise; - - const rows2 = dataTable.data.getRows(); - expect(rows2[0].isSelected).toBeTruthy(); - expect(rows2[1].isSelected).toBeFalsy(); - - dataTable.resetSelection(); - const cellClickPromise = dataTable.rowClick.pipe(take(1)).toPromise(); - const cellElement = fixture.debugElement.query(By.css(`[data-automation-id="datatable-row-1"] > div`)).nativeElement as HTMLElement; - cellElement.dispatchEvent(new MouseEvent('click', { bubbles: true })); - fixture.detectChanges(); - await cellClickPromise; - - const rows3 = dataTable.data.getRows(); - expect(rows3[0].isSelected).toBeFalsy(); - expect(rows3[1].isSelected).toBeTruthy(); - }); }); describe('Accesibility', () => { @@ -1463,99 +1464,128 @@ describe('Accesibility', () => { }); }); - describe('Focus row', () => { - let event: KeyboardEvent; - let dataRows: {name: string}[]; + it('should focus next row on ArrowDown event', () => { + const event = new KeyboardEvent('keyup', { + code: 'ArrowDown', + key: 'ArrowDown', + keyCode: 40 + } as KeyboardEventInit ); - beforeEach(() => { - event = new KeyboardEvent('keyup', { - code: 'ArrowUp', - key: 'ArrowUp', - keyCode: 38 - } as KeyboardEventInit); - dataRows = [{name: 'test1'}, {name: 'test2'}]; - dataTable.data = new ObjectDataTableAdapter([], - [new ObjectDataColumn({key: 'name'})] - ); + const dataRows = + [ { name: 'test1'}, { name: 'test2' } ]; + + dataTable.data = new ObjectDataTableAdapter([], + [new ObjectDataColumn({ key: 'name' })] + ); + + dataTable.ngOnChanges({ + rows: new SimpleChange(null, dataRows, false) }); - it('should focus next row on ArrowDown event', () => { - event = new KeyboardEvent('keyup', { - code: 'ArrowDown', - key: 'ArrowDown', - keyCode: 40 - } as KeyboardEventInit); + fixture.detectChanges(); + dataTable.ngAfterViewInit(); - dataTable.ngOnChanges({ - rows: new SimpleChange(null, dataRows, false) - }); + const rowElement = document.querySelectorAll('.adf-datatable-body .adf-datatable-row')[0]; + const rowCellElement = rowElement.querySelector('.adf-datatable-cell'); - fixture.detectChanges(); - dataTable.ngAfterViewInit(); + rowCellElement.dispatchEvent(new MouseEvent('click')); + fixture.debugElement.nativeElement.dispatchEvent(event); - const rowElement = document.querySelectorAll('.adf-datatable-body .adf-datatable-row')[0]; - const rowCellElement = rowElement.querySelector('.adf-datatable-cell'); + expect(document.activeElement.getAttribute('data-automation-id')).toBe('datatable-row-1'); + }); - rowCellElement.dispatchEvent(new MouseEvent('click', {bubbles: true})); - fixture.debugElement.nativeElement.dispatchEvent(event); + it('should focus previous row on ArrowUp event', () => { + const event = new KeyboardEvent('keyup', { + code: 'ArrowUp', + key: 'ArrowUp', + keyCode: 38 + } as KeyboardEventInit ); - expect(document.activeElement.getAttribute('data-automation-id')).toBe('datatable-row-1'); + const dataRows = + [ { name: 'test1'}, { name: 'test2' } ]; + + dataTable.data = new ObjectDataTableAdapter([], + [new ObjectDataColumn({ key: 'name' })] + ); + + dataTable.ngOnChanges({ + rows: new SimpleChange(null, dataRows, false) }); - it('should focus previous row on ArrowUp event', () => { - dataTable.ngOnChanges({ - rows: new SimpleChange(null, dataRows, false) - }); + fixture.detectChanges(); + dataTable.ngAfterViewInit(); - fixture.detectChanges(); - dataTable.ngAfterViewInit(); + const rowElement = document.querySelectorAll('.adf-datatable-body .adf-datatable-row')[1]; + const rowCellElement = rowElement.querySelector('.adf-datatable-cell'); - const rowElement = document.querySelectorAll('.adf-datatable-body .adf-datatable-row')[1]; - const rowCellElement = rowElement.querySelector('.adf-datatable-cell'); + rowCellElement.dispatchEvent(new MouseEvent('click')); + fixture.debugElement.nativeElement.dispatchEvent(event); - rowCellElement.dispatchEvent(new MouseEvent('click', {bubbles: true})); - fixture.debugElement.nativeElement.dispatchEvent(event); + expect(document.activeElement.getAttribute('data-automation-id')).toBe('datatable-row-0'); + }); - expect(document.activeElement.getAttribute('data-automation-id')).toBe('datatable-row-0'); + it('should select header row when `showHeader` is `Always`', () => { + const event = new KeyboardEvent('keyup', { + code: 'ArrowUp', + key: 'ArrowUp', + keyCode: 38 + } as KeyboardEventInit ); + + const dataRows = + [ { name: 'test1'}, { name: 'test2' } ]; + + dataTable.data = new ObjectDataTableAdapter([], + [new ObjectDataColumn({ key: 'name' })] + ); + + dataTable.showHeader = ShowHeaderMode.Always; + + dataTable.ngOnChanges({ + rows: new SimpleChange(null, dataRows, false) }); - it('should select header row when `showHeader` is `Always`', () => { - dataTable.showHeader = ShowHeaderMode.Always; + fixture.detectChanges(); + dataTable.ngAfterViewInit(); - dataTable.ngOnChanges({ - rows: new SimpleChange(null, dataRows, false) - }); + const rowElement = document.querySelector('.adf-datatable-row[data-automation-id="datatable-row-0"]'); + const rowCellElement = rowElement.querySelector('.adf-datatable-cell'); - fixture.detectChanges(); - dataTable.ngAfterViewInit(); + rowCellElement.dispatchEvent(new MouseEvent('click')); + fixture.debugElement.nativeElement.dispatchEvent(event); - const rowElement = document.querySelector('.adf-datatable-row[data-automation-id="datatable-row-0"]'); - const rowCellElement = rowElement.querySelector('.adf-datatable-cell'); + expect(document.activeElement.getAttribute('data-automation-id')).toBe('datatable-row-header'); + }); - rowCellElement.dispatchEvent(new MouseEvent('click', {bubbles: true})); - fixture.debugElement.nativeElement.dispatchEvent(event); + it('should not select header row when `showHeader` is `Never`', () => { + const event = new KeyboardEvent('keyup', { + code: 'ArrowUp', + key: 'ArrowUp', + keyCode: 38 + } as KeyboardEventInit ); - expect(document.activeElement.getAttribute('data-automation-id')).toBe('datatable-row-header'); + const dataRows = + [ { name: 'test1'}, { name: 'test2' } ]; + + dataTable.data = new ObjectDataTableAdapter([], + [new ObjectDataColumn({ key: 'name' })] + ); + + dataTable.showHeader = ShowHeaderMode.Never; + + dataTable.ngOnChanges({ + rows: new SimpleChange(null, dataRows, false) }); - it('should not select header row when `showHeader` is `Never`', () => { - dataTable.showHeader = ShowHeaderMode.Never; + fixture.detectChanges(); + dataTable.ngAfterViewInit(); - dataTable.ngOnChanges({ - rows: new SimpleChange(null, dataRows, false) - }); + const rowElement = document.querySelector('.adf-datatable-row[data-automation-id="datatable-row-0"]'); + const rowCellElement = rowElement.querySelector('.adf-datatable-cell'); - fixture.detectChanges(); - dataTable.ngAfterViewInit(); + rowCellElement.dispatchEvent(new MouseEvent('click')); + fixture.debugElement.nativeElement.dispatchEvent(event); - const rowElement = document.querySelector('.adf-datatable-row[data-automation-id="datatable-row-0"]'); - const rowCellElement = rowElement.querySelector('.adf-datatable-cell'); - - rowCellElement.dispatchEvent(new MouseEvent('click')); - fixture.debugElement.nativeElement.dispatchEvent(event); - - expect(document.activeElement.getAttribute('data-automation-id')).toBe('datatable-row-1'); - }); + expect(document.activeElement.getAttribute('data-automation-id')).toBe('datatable-row-1'); }); it('should remove cell focus when [focus] is set to false', () => { @@ -1803,21 +1833,6 @@ describe('Column Resizing', () => { let data: { id: number; name: string }[] = []; let dataTableSchema: DataColumn[] = []; - - const testClassesAfterResizing = (headerColumnsSelector = '.adf-datatable-cell-header', excludedClass = 'adf-datatable__cursor--pointer') => { - dataTable.isResizingEnabled = true; - fixture.detectChanges(); - - const resizeHandle: HTMLElement = fixture.debugElement.nativeElement.querySelector('.adf-datatable__resize-handle'); - resizeHandle.dispatchEvent(new MouseEvent('mousedown')); - fixture.detectChanges(); - - const headerColumns = fixture.debugElement.nativeElement.querySelectorAll(headerColumnsSelector); - - expect(dataTable.isResizing).toBeTrue(); - headerColumns.forEach((header: HTMLElement) => expect(header.classList).not.toContain(excludedClass)); - }; - setupTestBed({ imports: [ TranslateModule.forRoot(), @@ -1875,11 +1890,35 @@ describe('Column Resizing', () => { }); it('should NOT have the cursor pointer class in the header upon resizing starts', () => { - testClassesAfterResizing(); + dataTable.isResizingEnabled = true; + fixture.detectChanges(); + + const resizeHandle: HTMLElement = fixture.debugElement.nativeElement.querySelector('.adf-datatable__resize-handle'); + resizeHandle.dispatchEvent(new MouseEvent('mousedown')); + fixture.detectChanges(); + + const headerColumns = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header'); + + expect(dataTable.isResizing).toBeTrue(); + headerColumns.forEach((header: HTMLElement) => { + expect(header.classList).not.toContain('adf-datatable__cursor--pointer'); + }); }); it('should NOT have the [adf-datatable-cell-header-content--hovered] class in the header upon resizing starts', () => { - testClassesAfterResizing('.adf-datatable-cell-header-content', 'adf-datatable-cell-header-content--hovered'); + dataTable.isResizingEnabled = true; + fixture.detectChanges(); + + const resizeHandle: HTMLElement = fixture.debugElement.nativeElement.querySelector('.adf-datatable__resize-handle'); + resizeHandle.dispatchEvent(new MouseEvent('mousedown')); + fixture.detectChanges(); + + const headerColumns = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header-content'); + + expect(dataTable.isResizing).toBeTrue(); + headerColumns.forEach((header: HTMLElement) => { + expect(header.classList).not.toContain('adf-datatable-cell-header-content--hovered'); + }); }); it('should NOT display drag icon upon resizing starts', () => { diff --git a/lib/core/src/lib/datatable/components/datatable/datatable.component.ts b/lib/core/src/lib/datatable/components/datatable/datatable.component.ts index 9989b7495e..5406049d45 100644 --- a/lib/core/src/lib/datatable/components/datatable/datatable.component.ts +++ b/lib/core/src/lib/datatable/components/datatable/datatable.component.ts @@ -501,24 +501,16 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges, } onRowClick(row: DataRow, mouseEvent: MouseEvent) { - if (!mouseEvent.composedPath().some( - (element: HTMLElement) => element.id?.startsWith('action_menu_right_') || element.classList?.contains('adf-checkbox-sr-only')) - ) { - if (mouseEvent) { - mouseEvent.preventDefault(); - } - - if (row) { - const dataRowEvent = new DataRowEvent(row, mouseEvent, this); - this.clickObserver.next(dataRowEvent); - } + if (mouseEvent) { + mouseEvent.preventDefault(); } - } - storeActiveRow(row: DataRow) { if (row) { const rowIndex = this.data.getRows().indexOf(row) + (this.isHeaderListVisible() ? 1 : 0); this.keyManager.setActiveItem(rowIndex); + + const dataRowEvent = new DataRowEvent(row, mouseEvent, this); + this.clickObserver.next(dataRowEvent); } } diff --git a/lib/process-services/src/lib/task-list/components/task-list.component.spec.ts b/lib/process-services/src/lib/task-list/components/task-list.component.spec.ts index 75c1a76bdb..2e1c2e5a38 100644 --- a/lib/process-services/src/lib/task-list/components/task-list.component.spec.ts +++ b/lib/process-services/src/lib/task-list/components/task-list.component.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, SimpleChange, ViewChild, OnInit, Output, EventEmitter, SimpleChanges } from '@angular/core'; +import { Component, SimpleChange, ViewChild, OnInit, Output, EventEmitter } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { AppConfigService, setupTestBed, DataRowEvent, ObjectDataRow, DataCellEvent, ObjectDataColumn } from '@alfresco/adf-core'; @@ -39,67 +39,6 @@ describe('TaskListComponent', () => { let appConfig: AppConfigService; let taskListService: TaskListService; - const testMostRecentCall = (changes: SimpleChanges) => { - component.ngAfterContentInit(); - component.ngOnChanges(changes); - fixture.detectChanges(); - - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200, - contentType: 'application/json', - responseText: JSON.stringify(fakeGlobalTask) - }); - }; - - const testSubscribeForFilteredTaskList = (done: DoneFn) => { - component.success.subscribe((res) => { - expect(res).toBeDefined(); - expect(component.rows).toBeDefined(); - expect(component.isListEmpty()).not.toBeTruthy(); - expect(component.rows.length).toEqual(2); - expect(component.rows[0]['name']).toEqual('nameFake1'); - expect(component.rows[0]['processDefinitionId']).toEqual('myprocess:1:4'); - done(); - }); - }; - - const testRowSelection = async (selectionMode?: string) => { - spyOn(taskListService, 'findTasksByState').and.returnValues(of(fakeGlobalTask)); - const state = new SimpleChange(null, 'open', true); - component.multiselect = true; - if (selectionMode) { - component.selectionMode = selectionMode; - } - component.ngOnChanges({ sort: state }); - fixture.detectChanges(); - await fixture.whenStable(); - - const selectTask1 = fixture.nativeElement.querySelector('[data-automation-id="datatable-row-0"] .mat-checkbox-inner-container'); - const selectTask2 = fixture.nativeElement.querySelector('[data-automation-id="datatable-row-1"] .mat-checkbox-inner-container'); - selectTask1.dispatchEvent(new MouseEvent('click', { bubbles: true })); - selectTask1.dispatchEvent(new MouseEvent('click', { bubbles: true })); - selectTask2.dispatchEvent(new MouseEvent('click', { bubbles: true })); - - fixture.detectChanges(); - await fixture.whenStable(); - - let selectRow1 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-0"]'); - let selectRow2 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-1"]'); - expect(selectRow1).toBeDefined(); - expect(selectRow2).toBeDefined(); - expect(component.selectedInstances.length).toBe(2); - selectTask2.dispatchEvent(new MouseEvent('click', { bubbles: true })); - - fixture.detectChanges(); - await fixture.whenStable(); - - expect(component.selectedInstances.length).toBe(1); - selectRow1 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-0"]'); - selectRow2 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-1"]'); - expect(selectRow1).toBeDefined(); - expect(selectRow2).toBeNull(); - }; - setupTestBed({ imports: [ TranslateModule.forRoot(), @@ -218,7 +157,15 @@ describe('TaskListComponent', () => { expect(component.rows[0]['processDefinitionCategory']).toEqual('http://www.activiti.org/processdef'); done(); }); - testMostRecentCall({ state, processDefinitionKey, assignment }); + component.ngAfterContentInit(); + component.ngOnChanges({ state, processDefinitionKey, assignment }); + fixture.detectChanges(); + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: 'application/json', + responseText: JSON.stringify(fakeGlobalTask) + }); }); it('should return the filtered task list by processDefinitionKey', (done) => { @@ -235,7 +182,16 @@ describe('TaskListComponent', () => { expect(component.rows[0]['name']).toEqual('nameFake1'); done(); }); - testMostRecentCall({ state, processDefinitionKey, assignment }); + + component.ngAfterContentInit(); + component.ngOnChanges({ state, processDefinitionKey, assignment }); + fixture.detectChanges(); + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: 'application/json', + responseText: JSON.stringify(fakeGlobalTask) + }); }); it('should return the filtered task list by processInstanceId', (done) => { @@ -252,7 +208,16 @@ describe('TaskListComponent', () => { expect(component.rows[0]['processInstanceId']).toEqual(2511); done(); }); - testMostRecentCall({ state, processInstanceId, assignment }); + + component.ngAfterContentInit(); + component.ngOnChanges({ state, processInstanceId, assignment }); + fixture.detectChanges(); + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: 'application/json', + responseText: JSON.stringify(fakeGlobalTask) + }); }); it('should return the filtered task list by processDefinitionId', (done) => { @@ -260,15 +225,47 @@ describe('TaskListComponent', () => { const processDefinitionId = new SimpleChange(null, 'fakeprocessDefinitionId', true); const assignment = new SimpleChange(null, 'fake-assignee', true); - testSubscribeForFilteredTaskList(done); - testMostRecentCall({ state, processDefinitionId, assignment }); + component.success.subscribe((res) => { + expect(res).toBeDefined(); + expect(component.rows).toBeDefined(); + expect(component.isListEmpty()).not.toBeTruthy(); + expect(component.rows.length).toEqual(2); + expect(component.rows[0]['name']).toEqual('nameFake1'); + expect(component.rows[0]['processDefinitionId']).toEqual('myprocess:1:4'); + done(); + }); + + component.ngAfterContentInit(); + component.ngOnChanges({ state, processDefinitionId, assignment }); + fixture.detectChanges(); + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: 'application/json', + responseText: JSON.stringify(fakeGlobalTask) + }); }); it('should return the filtered task list by created date', (done) => { const state = new SimpleChange(null, 'open', true); const afterDate = new SimpleChange(null, '28-02-2017', true); - testSubscribeForFilteredTaskList(done); - testMostRecentCall({ state, afterDate }); + component.success.subscribe((res) => { + expect(res).toBeDefined(); + expect(component.rows).toBeDefined(); + expect(component.isListEmpty()).not.toBeTruthy(); + expect(component.rows.length).toEqual(2); + expect(component.rows[0]['name']).toEqual('nameFake1'); + expect(component.rows[0]['processDefinitionId']).toEqual('myprocess:1:4'); + done(); + }); + component.ngAfterContentInit(); + component.ngOnChanges({ state, afterDate }); + fixture.detectChanges(); + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: 'application/json', + responseText: JSON.stringify(fakeGlobalTask) + }); }); it('should return the filtered task list for all state', (done) => { @@ -288,7 +285,16 @@ describe('TaskListComponent', () => { expect(component.rows[1]['endDate']).toBeUndefined(); done(); }); - testMostRecentCall({ state, processInstanceId }); + + component.ngAfterContentInit(); + component.ngOnChanges({ state, processInstanceId }); + fixture.detectChanges(); + + jasmine.Ajax.requests.mostRecent().respondWith({ + status: 200, + contentType: 'application/json', + responseText: JSON.stringify(fakeGlobalTask) + }); }); it('should return a currentId null when the taskList is empty', () => { @@ -602,16 +608,83 @@ describe('TaskListComponent', () => { }); it('should be able to unselect a selected tasks using the checkbox', async () => { - await testRowSelection(); + spyOn(taskListService, 'findTasksByState').and.returnValues(of(fakeGlobalTask)); + const state = new SimpleChange(null, 'open', true); + component.multiselect = true; + + component.ngOnChanges({ sort: state }); + + fixture.detectChanges(); + await fixture.whenStable(); + + const selectTask1 = fixture.nativeElement.querySelector('[data-automation-id="datatable-row-0"] .mat-checkbox-inner-container'); + const selectTask2 = fixture.nativeElement.querySelector('[data-automation-id="datatable-row-1"] .mat-checkbox-inner-container'); + selectTask1.click(); + selectTask1.click(); + selectTask2.click(); + + fixture.detectChanges(); + await fixture.whenStable(); + + let selectRow1 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-0"]'); + let selectRow2 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-1"]'); + expect(selectRow1).toBeDefined(); + expect(selectRow2).toBeDefined(); + expect(component.selectedInstances.length).toBe(2); + + selectTask2.click(); + + fixture.detectChanges(); + await fixture.whenStable(); + + expect(component.selectedInstances.length).toBe(1); + selectRow1 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-0"]'); + selectRow2 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-1"]'); + expect(selectRow1).toBeDefined(); + expect(selectRow2).toBeNull(); }); it('should not be able to select different row when selection mode is set to NONE and multiselection is enabled', async () => { - await testRowSelection('none'); + spyOn(taskListService, 'findTasksByState').and.returnValues(of(fakeGlobalTask)); + const state = new SimpleChange(null, 'open', true); + component.multiselect = true; + component.selectionMode = 'none'; + + component.ngOnChanges({ sort: state }); + + fixture.detectChanges(); + await fixture.whenStable(); + + const selectTask1 = fixture.nativeElement.querySelector('[data-automation-id="datatable-row-0"] .mat-checkbox-inner-container'); + const selectTask2 = fixture.nativeElement.querySelector('[data-automation-id="datatable-row-1"] .mat-checkbox-inner-container'); + selectTask1.click(); + selectTask1.click(); + selectTask2.click(); + + fixture.detectChanges(); + await fixture.whenStable(); + + let selectRow1 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-0"]'); + let selectRow2 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-1"]'); + expect(selectRow1).toBeDefined(); + expect(selectRow2).toBeDefined(); + expect(component.selectedInstances.length).toBe(2); + + selectTask2.click(); + fixture.detectChanges(); + await fixture.whenStable(); + + expect(component.selectedInstances.length).toBe(1); + selectRow1 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-0"]'); + selectRow2 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-1"]'); + expect(selectRow1).toBeDefined(); + expect(selectRow2).toBeNull(); + const selectTask2Row = fixture.nativeElement.querySelector('[data-automation-id="text_No name"]'); selectTask2Row.click(); - const selectRow1 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-0"]'); - const selectRow2 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-1"]'); + selectRow1 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-0"]'); + selectRow2 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-1"]'); expect(selectRow1).toBeDefined(); expect(selectRow2).toBeNull(); }); @@ -627,13 +700,25 @@ describe('TaskListComponent', () => { const selectTask1 = fixture.nativeElement.querySelector('[data-automation-id="datatable-row-0"] .mat-checkbox-inner-container'); const selectTask2 = fixture.nativeElement.querySelector('[data-automation-id="datatable-row-1"] .mat-checkbox-inner-container'); - selectTask1.dispatchEvent(new MouseEvent('click', { bubbles: true })); - selectTask1.dispatchEvent(new MouseEvent('click', { bubbles: true })); - selectTask2.dispatchEvent(new MouseEvent('click', { bubbles: true })); + selectTask1.click(); + selectTask1.click(); + selectTask2.click(); fixture.detectChanges(); await fixture.whenStable(); expect(component.selectedInstances.length).toBe(2); + + // const selectTask2Row = fixture.nativeElement.querySelector('[data-automation-id="text_No name"]'); + // selectTask2Row.click(); + + // fixture.detectChanges(); + // await fixture.whenStable(); + + // expect(component.selectedInstances.length).toBe(1); + // const selectRow1 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-0"]'); + // const selectRow2 = fixture.nativeElement.querySelector('[class*="adf-is-selected"][data-automation-id="datatable-row-1"]'); + // expect(selectRow1).toBeNull(); + // expect(selectRow2).toBeDefined(); }); it('should change selected row after clicking on different row', async () => {