I have problem with a Jest unit test in my Open Source Aurelia-Slickgrid library (a datagrid lib), it’s a flaky test only when starting fresh or using jest --clearCache
(basically no cache it always fails). When I run the 2nd pass, basicaly as soon as I have cache and I’m not clearing the cache, it always pass but I would like to make it work at all time and I need it to always pass with CircleCI that I just implemented). Note that it’s a big Custom Element, it’s a datagrid library. My main goal is to get it passing on CircleCI which always start without cache .
The error I get is
Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.
Here’s a quick look at my flaky unit test (see the full test code here). Also note that I made the same library with Angular (code is ~75% the same between Aurelia & Angular) and the test is not flaky in Angular)
import { StageComponent } from 'aurelia-testing';
import { bootstrap } from 'aurelia-bootstrapper';
import { PLATFORM } from 'aurelia-pal';
describe('Aurelia-Slickgrid Custom Component', () => {
let component;
const view = `<aurelia-slickgrid
grid-id="grid1"
column-definitions.bind="columnDefinitions"
grid-options.bind="gridOptions"
dataset.bind="dataset">
</aurelia-slickgrid>`;
beforeEach(() => {
component = StageComponent
.withResources([
PLATFORM.moduleName('./aurelia-slickgrid'),
PLATFORM.moduleName('./slick-pagination'),
PLATFORM.moduleName('./value-converters/asgNumber')
])
.inView(view)
.boundTo({ gridId: 'grid1', columnDefinitions: [], dataset: [], gridOptions: {}, aureliaGridReady });
component.bootstrap((aurelia, callback) => {
aurelia.use.standardConfiguration();
// aurelia.container.registerInstance(SlickgridConfig, new SlickgridConfig());
});
});
// this passes fine
it('should make sure Aurelia-Slickgrid is defined', () => {
expect(component).toBeTruthy();
expect(component.constructor).toBeDefined();
});
// this always FAIL with empty cache but works fine on 2nd run after cache is filled
it('should create a grid and expect multiple Event Aggregator being called', async () => {
await component.create(bootstrap);
expect(eventAggregator.publish).toHaveBeenCalledTimes(3);
expect(eventAggregator.publish).toHaveBeenNthCalledWith(1, 'onBeforeGridCreate', true);
expect(eventAggregator.publish).toHaveBeenNthCalledWith(2, 'onGridCreated', expect.any(Object));
expect(eventAggregator.publish).toHaveBeenNthCalledWith(3, 'onDataviewCreated', expect.any(Object));
component.dispose();
expect(eventAggregator.publish).toHaveBeenNthCalledWith(4, 'onBeforeGridDestroy', expect.any(Object));
expect(eventAggregator.publish).toHaveBeenNthCalledWith(5, 'onAfterGridDestroyed', true);
});
});
I also have an index.ts
to load and register certain things but I don’t think it affects the flaky test… or does it?
index.ts
(here is the file on GitHub)
import { PLATFORM } from 'aurelia-pal';
import { AureliaSlickgridCustomElement } from './aurelia-slickgrid';
import { SlickPaginationCustomElement } from './slick-pagination';
import { SlickgridConfig } from './slickgrid-config';
import { Filters } from './filters/index';
// expose all public classes
// aggregators, editors, formatters, services...
export * from './models/index';
export * from './formatters/index';
export * from './grouping-formatters/index';
export * from './sorters/index';
export * from './aggregators/index';
export * from './editors/index';
export * from './filter-conditions/index';
export * from './filters/index';
export * from './services/index';
export function configure(aurelia: any, callback: any) {
aurelia.globalResources(PLATFORM.moduleName('./aurelia-slickgrid'));
aurelia.globalResources(PLATFORM.moduleName('./slick-pagination'));
aurelia.globalResources(PLATFORM.moduleName('./value-converters/asgNumber'));
// must register a transient so the container will get a new instance everytime
aurelia.container.registerTransient(Filters.autoComplete);
aurelia.container.registerTransient(Filters.compoundDate);
aurelia.container.registerTransient(Filters.compoundInput);
aurelia.container.registerTransient(Filters.compoundSlider);
aurelia.container.registerTransient(Filters.input);
aurelia.container.registerTransient(Filters.multipleSelect);
aurelia.container.registerTransient(Filters.singleSelect);
aurelia.container.registerTransient(Filters.select);
aurelia.container.registerTransient(Filters.slider);
const config = new SlickgridConfig();
aurelia.container.registerInstance(SlickgridConfig, config);
if (typeof callback === 'function') {
callback(config);
}
}
export {
AureliaSlickgridCustomElement,
SlickPaginationCustomElement,
SlickgridConfig
};