|  | 
|  | 1 | +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; | 
|  | 2 | +import { AfterViewInit, Component, TemplateRef, viewChild } from '@angular/core'; | 
| 1 | 3 | import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; | 
| 2 | 4 | 
 | 
| 3 |  | -import { TableColumnInternal } from '../../types/internal.types'; | 
|  | 5 | +import { | 
|  | 6 | +  InnerSortEvent, | 
|  | 7 | +  SortableTableColumnInternal, | 
|  | 8 | +  TableColumnInternal | 
|  | 9 | +} from '../../types/internal.types'; | 
|  | 10 | +import { toInternalColumn } from '../../utils/column-helper'; | 
| 4 | 11 | import { DataTableHeaderCellComponent } from './header-cell.component'; | 
|  | 12 | +import { HeaderCellHarness } from './testing/header-cell.harnes'; | 
| 5 | 13 | 
 | 
| 6 | 14 | describe('DataTableHeaderCellComponent', () => { | 
| 7 | 15 |   let fixture: ComponentFixture<DataTableHeaderCellComponent>; | 
| 8 | 16 |   let component: DataTableHeaderCellComponent; | 
|  | 17 | +  let harness: HeaderCellHarness; | 
| 9 | 18 | 
 | 
| 10 |  | -  beforeEach(waitForAsync(() => { | 
|  | 19 | +  beforeEach(waitForAsync(async () => { | 
| 11 | 20 |     fixture = TestBed.createComponent(DataTableHeaderCellComponent); | 
| 12 | 21 |     component = fixture.componentInstance; | 
| 13 |  | -  })); | 
| 14 |  | - | 
| 15 |  | -  it('should emit new width on resize', () => { | 
| 16 | 22 |     fixture.componentRef.setInput('column', { | 
| 17 | 23 |       name: 'test', | 
| 18 |  | -      resizeable: true | 
|  | 24 | +      prop: 'test', | 
|  | 25 | +      resizeable: true, | 
|  | 26 | +      sortable: true | 
|  | 27 | +    }); | 
|  | 28 | +    fixture.componentRef.setInput('sortType', 'single'); | 
|  | 29 | +    fixture.componentRef.setInput('headerHeight', 50); | 
|  | 30 | +    fixture.componentRef.setInput('ariaHeaderCheckboxMessage', 'Select all rows'); | 
|  | 31 | +    fixture.componentInstance.sort.subscribe(sort => { | 
|  | 32 | +      fixture.componentRef.setInput('sorts', [ | 
|  | 33 | +        { | 
|  | 34 | +          prop: sort.column.name, | 
|  | 35 | +          dir: sort.newValue | 
|  | 36 | +        } | 
|  | 37 | +      ]); | 
| 19 | 38 |     }); | 
|  | 39 | +    harness = await TestbedHarnessEnvironment.harnessForFixture(fixture, HeaderCellHarness); | 
|  | 40 | +  })); | 
|  | 41 | + | 
|  | 42 | +  it('should emit new width on resize', async () => { | 
| 20 | 43 |     spyOn(component.resizing, 'emit'); | 
| 21 |  | -    fixture.detectChanges(); | 
| 22 |  | -    const initialWidth = fixture.nativeElement.clientWidth; | 
| 23 |  | -    const event = new MouseEvent('mousedown'); | 
| 24 |  | -    fixture.nativeElement.querySelector('.resize-handle').dispatchEvent(event); | 
| 25 |  | -    const mouseMoveEvent = new MouseEvent('mousemove', { screenX: 100 }); | 
| 26 |  | -    document.dispatchEvent(mouseMoveEvent); | 
| 27 |  | -    const mouseUpEvent = new MouseEvent('mouseup'); | 
| 28 |  | -    document.dispatchEvent(mouseUpEvent); | 
|  | 44 | +    const initialWidth = await harness.cellWidth(); | 
|  | 45 | +    await harness.resizeCell(); | 
| 29 | 46 |     const newWidth = 100 + initialWidth; | 
| 30 | 47 |     expect(component.resizing.emit).toHaveBeenCalledWith({ | 
| 31 | 48 |       width: newWidth, | 
| 32 |  | -      column: { name: 'test', resizeable: true } as TableColumnInternal<any> | 
|  | 49 | +      column: { | 
|  | 50 | +        name: 'test', | 
|  | 51 | +        prop: 'test', | 
|  | 52 | +        resizeable: true, | 
|  | 53 | +        sortable: true | 
|  | 54 | +      } as TableColumnInternal<any> | 
| 33 | 55 |     }); | 
| 34 | 56 |   }); | 
| 35 | 57 | 
 | 
| 36 |  | -  it('should emit sort event', () => { | 
| 37 |  | -    fixture.componentRef.setInput('column', { | 
| 38 |  | -      prop: 'test', | 
| 39 |  | -      sortable: true | 
| 40 |  | -    }); | 
|  | 58 | +  it('should emit sort event', async () => { | 
| 41 | 59 |     spyOn(component.sort, 'emit'); | 
| 42 |  | -    fixture.detectChanges(); | 
| 43 |  | -    const event = new MouseEvent('click'); | 
| 44 |  | -    fixture.nativeElement.querySelector('.datatable-header-cell-label').dispatchEvent(event); | 
|  | 60 | +    await harness.applySort(); | 
| 45 | 61 |     expect(component.sort.emit).toHaveBeenCalled(); | 
| 46 | 62 |   }); | 
| 47 | 63 | 
 | 
| 48 |  | -  it('should not render resize handle when showResizeHandle is false (last column)', () => { | 
| 49 |  | -    fixture.componentRef.setInput('column', { | 
| 50 |  | -      name: 'test', | 
| 51 |  | -      resizeable: true | 
| 52 |  | -    }); | 
|  | 64 | +  it('should not render resize handle when showResizeHandle is false (last column)', async () => { | 
| 53 | 65 |     fixture.componentRef.setInput('showResizeHandle', false); | 
| 54 |  | -    fixture.detectChanges(); | 
| 55 |  | -    const resizeHandle = fixture.nativeElement.querySelector('.resize-handle'); | 
| 56 |  | -    expect(resizeHandle).toBeNull(); | 
|  | 66 | +    expect(await harness.hasResizeHandle()).toBe(false); | 
| 57 | 67 |   }); | 
| 58 | 68 | 
 | 
| 59 |  | -  it('should render resize handle when showResizeHandle is true', () => { | 
|  | 69 | +  it('should render resize handle when showResizeHandle is true', async () => { | 
|  | 70 | +    fixture.componentRef.setInput('showResizeHandle', true); | 
|  | 71 | +    expect(await harness.hasResizeHandle()).toBe(true); | 
|  | 72 | +  }); | 
|  | 73 | + | 
|  | 74 | +  it('should emit select when checkbox is clicked', async () => { | 
| 60 | 75 |     fixture.componentRef.setInput('column', { | 
| 61 | 76 |       name: 'test', | 
| 62 |  | -      resizeable: true | 
|  | 77 | +      headerCheckboxable: true | 
| 63 | 78 |     }); | 
| 64 |  | -    fixture.componentRef.setInput('showResizeHandle', true); | 
|  | 79 | +    spyOn(component.select, 'emit'); | 
|  | 80 | +    await harness.selectAllRows(); | 
|  | 81 | +    expect(component.select.emit).toHaveBeenCalled(); | 
|  | 82 | +  }); | 
|  | 83 | + | 
|  | 84 | +  it('should toggle sort direction on sort button click', async () => { | 
|  | 85 | +    await harness.applySort(); | 
|  | 86 | +    expect(await harness.getSortDirection()).toBe('asc'); | 
|  | 87 | +    await harness.applySort(); | 
|  | 88 | +    expect(await harness.getSortDirection()).toBe('desc'); | 
|  | 89 | +  }); | 
|  | 90 | + | 
|  | 91 | +  it('should sort on enter key press', async () => { | 
|  | 92 | +    spyOn(component.sort, 'emit'); | 
|  | 93 | +    await harness.applySort(true); | 
|  | 94 | +    expect(component.sort.emit).toHaveBeenCalled(); | 
|  | 95 | +  }); | 
|  | 96 | +}); | 
|  | 97 | + | 
|  | 98 | +@Component({ | 
|  | 99 | +  imports: [DataTableHeaderCellComponent], | 
|  | 100 | +  template: `<datatable-header-cell | 
|  | 101 | +      sortType="single" | 
|  | 102 | +      headerHeight="50" | 
|  | 103 | +      [column]="column" | 
|  | 104 | +      (sort)="sort($event)" | 
|  | 105 | +    /> | 
|  | 106 | +    <ng-template #headerCellTemplate let-sort="sortFn" let-column="column"> | 
|  | 107 | +      <span class="custom-header">Custom Header for {{ column.name }}</span> | 
|  | 108 | +      <button class="custom-sort-button" type="button" (click)="sort($event)" | 
|  | 109 | +        >Custom sort button</button | 
|  | 110 | +      > | 
|  | 111 | +    </ng-template> ` | 
|  | 112 | +}) | 
|  | 113 | +class TestHeaderCellComponent implements AfterViewInit { | 
|  | 114 | +  column: TableColumnInternal<any> = toInternalColumn([ | 
|  | 115 | +    { | 
|  | 116 | +      name: 'test', | 
|  | 117 | +      sortable: true | 
|  | 118 | +    } | 
|  | 119 | +  ])[0]; | 
|  | 120 | + | 
|  | 121 | +  readonly headerCellTemplate = viewChild('headerCellTemplate', { read: TemplateRef<any> }); | 
|  | 122 | + | 
|  | 123 | +  sort(event: InnerSortEvent) {} | 
|  | 124 | + | 
|  | 125 | +  ngAfterViewInit() { | 
|  | 126 | +    this.column = { ...this.column, headerTemplate: this.headerCellTemplate() }; | 
|  | 127 | +  } | 
|  | 128 | +} | 
|  | 129 | + | 
|  | 130 | +describe('DataTableHeaderCellComponent with template', () => { | 
|  | 131 | +  let fixture: ComponentFixture<TestHeaderCellComponent>; | 
|  | 132 | +  let harness: HeaderCellHarness; | 
|  | 133 | + | 
|  | 134 | +  beforeEach(waitForAsync(async () => { | 
|  | 135 | +    fixture = TestBed.createComponent(TestHeaderCellComponent); | 
|  | 136 | +    harness = await TestbedHarnessEnvironment.harnessForFixture(fixture, HeaderCellHarness); | 
|  | 137 | +  })); | 
|  | 138 | + | 
|  | 139 | +  it('should render custom header template', async () => { | 
| 65 | 140 |     fixture.detectChanges(); | 
| 66 |  | -    const resizeHandle = fixture.nativeElement.querySelector('.resize-handle'); | 
| 67 |  | -    expect(resizeHandle).not.toBeNull(); | 
|  | 141 | +    expect(await harness.getHeaderCellText()).toContain('Custom Header for test'); | 
|  | 142 | +  }); | 
|  | 143 | + | 
|  | 144 | +  it('should call sort function on custom button click', async () => { | 
|  | 145 | +    spyOn(fixture.componentInstance, 'sort'); | 
|  | 146 | +    await harness.clickCustomSortButton(); | 
|  | 147 | +    expect(fixture.componentInstance.sort).toHaveBeenCalledWith({ | 
|  | 148 | +      column: fixture.componentInstance.column as SortableTableColumnInternal<any>, | 
|  | 149 | +      prevValue: undefined, | 
|  | 150 | +      newValue: 'asc' | 
|  | 151 | +    }); | 
| 68 | 152 |   }); | 
| 69 | 153 | }); | 
0 commit comments