From c6fa6e8a872e7e7ecd9d0c9b0511c72d22ee4f12 Mon Sep 17 00:00:00 2001 From: Blackbaud-PatrickOFriel Date: Fri, 21 Apr 2017 10:58:15 -0400 Subject: [PATCH 1/3] Make sortFields work properly without an array --- .../list/fixtures/list.component.fixture.html | 1 + .../list/fixtures/list.component.fixture.ts | 2 + src/modules/list/list.component.spec.ts | 137 ++++++++++++------ src/modules/list/list.component.ts | 13 +- 4 files changed, 107 insertions(+), 46 deletions(-) diff --git a/src/modules/list/fixtures/list.component.fixture.html b/src/modules/list/fixtures/list.component.fixture.html index 0d4306e25..9d7049075 100644 --- a/src/modules/list/fixtures/list.component.fixture.html +++ b/src/modules/list/fixtures/list.component.fixture.html @@ -1,6 +1,7 @@ diff --git a/src/modules/list/fixtures/list.component.fixture.ts b/src/modules/list/fixtures/list.component.fixture.ts index 69281e30e..5cb50550b 100644 --- a/src/modules/list/fixtures/list.component.fixture.ts +++ b/src/modules/list/fixtures/list.component.fixture.ts @@ -14,6 +14,8 @@ export class ListTestComponent { @ViewChild('toolbar') public toolbar: SkyListToolbarComponent; + public sortFields: any; + constructor(@Inject('items') public items: any) { } diff --git a/src/modules/list/list.component.spec.ts b/src/modules/list/list.component.spec.ts index cc82079cf..2c923ad17 100644 --- a/src/modules/list/list.component.spec.ts +++ b/src/modules/list/list.component.spec.ts @@ -104,13 +104,17 @@ describe('List Component', () => { nativeElement = fixture.nativeElement as HTMLElement; element = fixture.debugElement as DebugElement; component = fixture.componentInstance; + + })); + + function initializeList() { fixture.detectChanges(); // always skip the first update to ListState, when state is ready // run detectChanges once more then begin tests state.skip(1).take(1).subscribe(() => fixture.detectChanges()); fixture.detectChanges(); - })); + } function applySearch(value: string) { component.toolbar.searchComponent.applySearchText(value); @@ -118,55 +122,64 @@ describe('List Component', () => { return fixture.whenStable(); } - it('should load data', () => { - expect(element.queryAll(By.css('tr.sky-grid-row')).length).toBe(7); - }); - - it('should load new data', () => { - expect(element.queryAll(By.css('tr.sky-grid-row')).length).toBe(7); - fixture.detectChanges(); - bs.next([ - { id: '1', column1: '1', column2: 'Large', - column3: 2, column4: moment().add(15, 'minute') }, - { id: '2', column1: '22', column2: 'Small', - column3: 3, column4: moment().add(60, 'minute') }, - { id: '3', column1: '33', column2: 'Medium', - column3: 4, column4: moment().add(45, 'minute') } - ]); - fixture.detectChanges(); - expect(element.queryAll(By.css('tr.sky-grid-row')).length).toBe(3); - }); + describe('basic actions', () => { + beforeEach(async(() => { + initializeList(); + })); - it('should update displayed items when data is updated', () => { - let newItems = [ - { id: '11', column1: '11', column2: 'Coffee', - column3: 11, column4: moment().add(11, 'minute') }, - { id: '12', column1: '12', column2: 'Tea', - column3: 12, column4: moment().add(12, 'minute') } - ]; + it('should load data', () => { - bs.next(newItems); - fixture.detectChanges(); + expect(element.queryAll(By.css('tr.sky-grid-row')).length).toBe(7); + }); - expect(element.queryAll(By.css('tr.sky-grid-row')).length).toBe(2); - }); + it('should load new data', () => { + expect(element.queryAll(By.css('tr.sky-grid-row')).length).toBe(7); + fixture.detectChanges(); + bs.next([ + { id: '1', column1: '1', column2: 'Large', + column3: 2, column4: moment().add(15, 'minute') }, + { id: '2', column1: '22', column2: 'Small', + column3: 3, column4: moment().add(60, 'minute') }, + { id: '3', column1: '33', column2: 'Medium', + column3: 4, column4: moment().add(45, 'minute') } + ]); + fixture.detectChanges(); + expect(element.queryAll(By.css('tr.sky-grid-row')).length).toBe(3); + }); - it('should search based on input text', async(() => { - fixture.detectChanges(); - applySearch('banana').then(() => { + it('should update displayed items when data is updated', () => { + let newItems = [ + { id: '11', column1: '11', column2: 'Coffee', + column3: 11, column4: moment().add(11, 'minute') }, + { id: '12', column1: '12', column2: 'Tea', + column3: 12, column4: moment().add(12, 'minute') } + ]; + bs.next(newItems); fixture.detectChanges(); + expect(element.queryAll(By.css('tr.sky-grid-row')).length).toBe(2); + }); + it('should search based on input text', async(() => { + fixture.detectChanges(); applySearch('banana').then(() => { + fixture.detectChanges(); expect(element.queryAll(By.css('tr.sky-grid-row')).length).toBe(2); + + applySearch('banana').then(() => { + fixture.detectChanges(); + expect(element.queryAll(By.css('tr.sky-grid-row')).length).toBe(2); + }); }); - }); - })); + })); + }); describe('sorting', () => { - it('should sort', () => { + it('should sort', fakeAsync(() => { + initializeList(); + tick(); expect(element.queryAll(By.css('tr.sky-grid-row')).length).toBe(7); dispatcher.next(new ListSortSetFieldSelectorsAction([ { @@ -202,9 +215,11 @@ describe('List Component', () => { expect(element.query( By.css('sky-grid-cell[sky-cmp-id=".column3"]') ).nativeElement.textContent.trim()).toBe('21'); - }); + })); - it('should sort based on column using cached search', async(() => { + it('should sort based on column using cached search', fakeAsync(() => { + initializeList(); + tick(); applySearch('banana') .then(() => { fixture.detectChanges(); @@ -227,10 +242,40 @@ describe('List Component', () => { }); })); + it('should set initial sort with non-array', fakeAsync(() => { + component.sortFields = { + fieldSelector: 'column3', + descending: true + }; + + initializeList(); + tick(); + + expect(element.query( + By.css('sky-grid-cell[sky-cmp-id=".column3"]') + ).nativeElement.textContent.trim()).toBe('21'); + })); + + it('should set initial sort with array', fakeAsync(() => { + component.sortFields = [{ + fieldSelector: 'column3', + descending: true + }]; + + initializeList(); + tick(); + + expect(element.query( + By.css('sky-grid-cell[sky-cmp-id=".column3"]') + ).nativeElement.textContent.trim()).toBe('21'); + })); + }); describe('refreshDisplayedItems', () => { - it('should refresh items', async(() => { + it('should refresh items', fakeAsync(() => { + initializeList(); + tick(); component.list.refreshDisplayedItems(); fixture.detectChanges(); expect(element.queryAll(By.css('tr.sky-grid-row')).length).toBe(7); @@ -238,17 +283,21 @@ describe('List Component', () => { }); describe('itemCount', () => { - it('should return item count', () => { + it('should return item count', fakeAsync(() => { + initializeList(); + tick(); component.list.itemCount.take(1).subscribe(u => { state.take(1).subscribe((s) => { expect(u).toBe(s.items.count); }); }); - }); + })); }); describe('lastUpdate', () => { - it('should return last updated date', async(() => { + it('should return last updated date', fakeAsync(() => { + initializeList(); + tick(); component.list.lastUpdate.take(1).subscribe(u => { state.take(1).subscribe((s) => { expect(moment(u).isSame(s.items.lastUpdate)).toBeTruthy(); @@ -256,7 +305,9 @@ describe('List Component', () => { }); })); - it('should return undefined if not defined', async(() => { + it('should return undefined if not defined', fakeAsync(() => { + initializeList(); + tick(); state.map((s) => s.items.lastUpdate = undefined).take(1).subscribe(); component.list.lastUpdate.take(1).subscribe((u) => { expect(u).toBeUndefined(); diff --git a/src/modules/list/list.component.ts b/src/modules/list/list.component.ts index 47ac2cb9e..e2f4b1076 100644 --- a/src/modules/list/list.component.ts +++ b/src/modules/list/list.component.ts @@ -144,9 +144,16 @@ export class SkyListComponent implements AfterContentInit, OnChanges { } // set sort fields - getValue(this.sortFields, (sortFields: ListSortFieldSelectorModel[]) => - this.dispatcher.next(new ListSortSetFieldSelectorsAction(sortFields || [])) - ); + getValue(this.sortFields, + (sortFields: ListSortFieldSelectorModel[] | ListSortFieldSelectorModel) => { + let sortArray: any; + if (!Array.isArray(sortFields) && sortFields) { + sortArray = [sortFields]; + } else { + sortArray = sortFields; + } + this.dispatcher.next(new ListSortSetFieldSelectorsAction(sortArray || [])); + }); this.displayedItems.subscribe(result => { this.dispatcher.next(new ListItemsSetLoadingAction()); From 7660a332b14159ad9deac5d4db4c61c7fc987b71 Mon Sep 17 00:00:00 2001 From: Blackbaud-PatrickOFriel Date: Fri, 21 Apr 2017 11:36:52 -0400 Subject: [PATCH 2/3] Update in memory data provider to show more than 10 entries without paging --- .../list-data-in-memory.provider.ts | 20 +++++++++++++------ src/modules/list/list-data-request.model.ts | 4 ++-- src/modules/list/state/paging/paging.model.ts | 18 ++++++++--------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/modules/list-data-provider-in-memory/list-data-in-memory.provider.ts b/src/modules/list-data-provider-in-memory/list-data-in-memory.provider.ts index af92b112c..8e3e5f252 100644 --- a/src/modules/list-data-provider-in-memory/list-data-in-memory.provider.ts +++ b/src/modules/list-data-provider-in-memory/list-data-in-memory.provider.ts @@ -48,12 +48,20 @@ export class SkyListInMemoryDataProvider extends ListDataProvider { public get(request: ListDataRequestModel): Observable { return this.filteredItems(request).map((result: Array) => { - let itemStart = (request.pageNumber - 1) * request.pageSize; - let pagedResult = result.slice(itemStart, itemStart + request.pageSize); - return new ListDataResponseModel({ - count: result.length, - items: pagedResult - }); + if (request.pageNumber && request.pageSize) { + let itemStart = (request.pageNumber - 1) * request.pageSize; + let pagedResult = result.slice(itemStart, itemStart + request.pageSize); + return new ListDataResponseModel({ + count: result.length, + items: pagedResult + }); + } else { + return new ListDataResponseModel({ + count: result.length, + items: result + }) + } + }); } diff --git a/src/modules/list/list-data-request.model.ts b/src/modules/list/list-data-request.model.ts index e1922ee72..74824ceb5 100644 --- a/src/modules/list/list-data-request.model.ts +++ b/src/modules/list/list-data-request.model.ts @@ -4,8 +4,8 @@ import { ListSortModel } from './state/sort/sort.model'; export class ListDataRequestModel { public filters: ListFilterModel[]; - public pageSize: number = 10; - public pageNumber: number = 1; + public pageSize: number; + public pageNumber: number; public search: ListSearchModel; public sort: ListSortModel; diff --git a/src/modules/list/state/paging/paging.model.ts b/src/modules/list/state/paging/paging.model.ts index 4ee9146a0..c6194953d 100644 --- a/src/modules/list/state/paging/paging.model.ts +++ b/src/modules/list/state/paging/paging.model.ts @@ -1,17 +1,15 @@ export class ListPagingModel { - public itemsPerPage: number = 10; - public maxDisplayedPages: number = 5; - public pageCount: number = 0; - public pageNumber: number = 1; - public displayedPages: number[] = []; + public itemsPerPage: number; + public maxDisplayedPages: number; + public pageCount: number; + public pageNumber: number; constructor(data?: any) { if (data !== undefined) { - this.itemsPerPage = data.itemsPerPage; - this.maxDisplayedPages = data.maxDisplayedPages; - this.pageCount = data.pageCount; - this.pageNumber = data.pageNumber; - this.displayedPages = data.displayedPages; + this.itemsPerPage = data.itemsPerPage || 10; + this.maxDisplayedPages = data.maxDisplayedPages || 5; + this.pageCount = data.pageCount || 0; + this.pageNumber = data.pageNumber || 1; } } } From 7eb2eded29d05cac05a3f0a4a8ba0695073b1c7d Mon Sep 17 00:00:00 2001 From: Blackbaud-PatrickOFriel Date: Fri, 21 Apr 2017 11:53:11 -0400 Subject: [PATCH 3/3] tests for undefined paging --- .../list-data-in-memory.provider.spec.ts | 27 +++++++++++++++++++ .../list-data-in-memory.provider.ts | 2 +- src/modules/list/list.component.spec.ts | 11 ++++++-- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/modules/list-data-provider-in-memory/list-data-in-memory.provider.spec.ts b/src/modules/list-data-provider-in-memory/list-data-in-memory.provider.spec.ts index e607c3678..ffc0733b3 100644 --- a/src/modules/list-data-provider-in-memory/list-data-in-memory.provider.spec.ts +++ b/src/modules/list-data-provider-in-memory/list-data-in-memory.provider.spec.ts @@ -89,6 +89,33 @@ describe('in memory data provider', () => { tick(); })); + it('should handle more than 10 data entries when paging is undefined', fakeAsync(() => { + + let provider = new SkyListInMemoryDataProvider(Observable.of([ + { id: '1', column1: 101, column2: 'Apple', column3: 'Anne eats apples' }, + { id: '2', column1: 202, column2: 'Banana', column3: 'Ben eats bananas' }, + { id: '3', column1: 303, column2: 'Pear', column3: 'Patty eats pears' }, + { id: '4', column1: 404, column2: 'Grape', column3: 'George eats grapes' }, + { id: '5', column1: 505, column2: 'Banana', column3: 'Becky eats bananas' }, + { id: '6', column1: 606, column2: 'Lemon', column3: 'Larry eats lemons' }, + { id: '7', column1: 707, column2: 'Strawberry', column3: 'Sally eats strawberries' }, + { id: '8', column1: 404, column2: 'Grape', column3: 'George eats grapes' }, + { id: '9', column1: 505, column2: 'Banana', column3: 'Becky eats bananas' }, + { id: '10', column1: 606, column2: 'Lemon', column3: 'Larry eats lemons' }, + { id: '11', column1: 707, column2: 'Strawberry', column3: 'Sally eats strawberries' } + ])); + let request = new ListDataRequestModel({}); + + tick(); + + provider.get(request).take(1).subscribe((result) => { + expect(result.items.length).toBe(11); + expect(result.count).toBe(11); + }); + tick(); + + })); + describe('sorting', () => { it('should handle an ascending sort', fakeAsync(() => { let provider = new SkyListInMemoryDataProvider(items); diff --git a/src/modules/list-data-provider-in-memory/list-data-in-memory.provider.ts b/src/modules/list-data-provider-in-memory/list-data-in-memory.provider.ts index 8e3e5f252..9f12abe72 100644 --- a/src/modules/list-data-provider-in-memory/list-data-in-memory.provider.ts +++ b/src/modules/list-data-provider-in-memory/list-data-in-memory.provider.ts @@ -59,7 +59,7 @@ export class SkyListInMemoryDataProvider extends ListDataProvider { return new ListDataResponseModel({ count: result.length, items: result - }) + }); } }); diff --git a/src/modules/list/list.component.spec.ts b/src/modules/list/list.component.spec.ts index 2c923ad17..875348f42 100644 --- a/src/modules/list/list.component.spec.ts +++ b/src/modules/list/list.component.spec.ts @@ -37,7 +37,8 @@ import { ListSortFieldSelectorModel, ListSortLabelModel, ListFilterModel, - ListItemModel + ListItemModel, + ListPagingModel } from './state'; import { SkyListInMemoryDataProvider } from '../list-data-provider-in-memory'; @@ -1030,8 +1031,14 @@ describe('List Component', () => { describe('models and actions', () => { it('should handle undefined data for request model', () => { let model = new ListDataRequestModel(); + expect(model.pageNumber).toBeUndefined(); + expect(model.pageSize).toBeUndefined(); + }); + + it('should handle missing data for paging model', () => { + let model = new ListPagingModel({}); expect(model.pageNumber).toBe(1); - expect(model.pageSize).toBe(10); + expect(model.itemsPerPage).toBe(10); }); it('should handle undefined data for response model', () => {