Skip to content

Instantly share code, notes, and snippets.

@rfreedman
Created February 12, 2018 17:35
Show Gist options
  • Save rfreedman/b12c9dbfbdd66888dbb1f730bfc29e8c to your computer and use it in GitHub Desktop.
Save rfreedman/b12c9dbfbdd66888dbb1f730bfc29e8c to your computer and use it in GitHub Desktop.
Example of using unroll in an async test for an Angular Component
import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
import {SampleService} from './sample.service';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {ConfigurationService, LoggerService, PUDateTimePipe, PUDateTimePipeModule, PULoggerModule} from '@princeton/pu-csi-angular-core';
import {SampleListComponent} from './sample-list.component';
import {CommonModule} from '@angular/common';
import {BrowserModule} from '@angular/platform-browser';
import {SharedAnimationsModule} from '../shared/animations/shared-animations.module';
import {HttpClient, HttpClientModule} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import {RouterTestingModule} from '@angular/router/testing';
import {MockConfigurationService} from '../../testing/mock-configuration.service';
import * as unroll from 'unroll';
unroll.use(it);
describe('SampleListComponent', () => {
let fixture: ComponentFixture<SampleListComponent>;
let service: SampleService;
let componentElement: any;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
CommonModule,
BrowserModule,
BrowserAnimationsModule,
RouterTestingModule,
SharedAnimationsModule,
PUDateTimePipeModule,
PULoggerModule.forRoot(),
HttpClientModule
],
declarations: [
SampleListComponent
],
providers: [
{provide: ConfigurationService, useClass: MockConfigurationService, deps: [HttpClient, LoggerService]},
SampleService
]
}).compileComponents();
fixture = TestBed.createComponent(SampleListComponent);
service = TestBed.get(SampleService);
componentElement = fixture.debugElement.nativeElement;
}));
it('should render title in a h3 tag', async(() => {
// empty Observable, because we don't care about the data for this test
spyOn(service, 'getAllSamples').and.returnValue(Observable.empty);
expect(componentElement.querySelector('h3').textContent).toContain('Samples');
}));
// You wouldn't actually write this test (because it essentially just tests the framework),
// But this shows that the async test works with respect to the expected sequence of events
it('should have no data before detectChanges, full data after', async(() => {
const data = [{
id: 0,
field2: 'foo2',
field3: 'foo3',
createDate: new Date(),
createUser: 'xxx',
updateDate: new Date(),
updateUser: 'yyy'
},
{
id: 1,
field2: 'xxxx',
field3: 'yyyy',
createDate: new Date(),
createUser: 'zzzzz',
updateDate: new Date(),
updateUser: 'aaaa'
}
];
const tableName = 'sample-table';
const rowSelector = `table[name="${tableName}"] tr`;
const rowCount = () => componentElement.querySelectorAll(rowSelector).length;
spyOn(service, 'getAllSamples').and.returnValue(Observable.of(data)); // mock the service call
expect(rowCount()).toBe(1); // just the header row
fixture.detectChanges(); // kick off ngOnInit and a change detection cycle
expect(rowCount()).toBe(data.length + 1); // header row + data rows
}));
describe('should render samples in a table', () => {
const data = [{
id: 0,
field2: 'foo2',
field3: 'foo3',
createDate: new Date(),
createUser: 'xxx',
updateDate: new Date(),
updateUser: 'yyy'
},
{
id: 1,
field2: 'xxxx',
field3: 'yyyy',
createDate: new Date(),
createUser: 'zzzzz',
updateDate: new Date(),
updateUser: 'aaaa'
}
];
const datePipe = new PUDateTimePipe();
const tableName = 'sample-table';
const cellValue = (row, col, extra) => {
const selector = `table[name="${tableName}"] tr:nth-child(${row}) td:nth-child(${col}) ${extra}`;
return componentElement.querySelector(selector).textContent;
}
unroll(`for table ${tableName} at row #row, column #col`, (done, testArgs) => {
spyOn(service, 'getAllSamples').and.returnValue(Observable.of(data)); // mock the service call
fixture.detectChanges(); // kick off ngOnInit and a change detection cycle
const foundValue = cellValue(testArgs['row'], testArgs['col'], testArgs['extra']);
expect(foundValue).toBe(testArgs['value'].toString(),
`Expected to find value ${testArgs['value']} in row ${testArgs['row']}, col ${testArgs['col']}, but found ${foundValue} instead`);
done();
}, [
['row', 'col', 'extra', 'value'],
[1, 1, 'a', data[0].id.toString()],
[1, 2, '', data[0].field2],
[1, 3, '', data[0].field3],
[1, 4, '', datePipe.transform(data[0].createDate, [])],
[1, 5, '', data[0].createUser],
[1, 6, '', datePipe.transform(data[0].updateDate, [])],
[1, 7, '', data[0].updateUser],
[2, 1, 'a', data[1].id.toString()],
[2, 2, '', data[1].field2],
[2, 3, '', data[1].field3],
[2, 4, '', datePipe.transform(data[1].createDate, [])],
[2, 5, '', data[1].createUser],
[2, 6, '', datePipe.transform(data[1].updateDate, [])],
[2, 7, '', data[1].updateUser]
]);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment