Wait for element to be bound before karma test is executed?


#1

Hi all! I recently upgraded Aurelia dependencies in my project, and I’ve noticed random issues in my Karma screen and component tests that didn’t exist previously. Often, my tests pass completely fine, but there are other times where it seems that the test doesn’t finish bootstrapping the data to the DOM before the test is executed, so I will randomly get failures looking for bound values or even an “a. Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.” error at times. It’s inconsistent, and not specific to one test.

Has anyone else encountered this? It seems to be when there are a good number of tests run together, and happens more often in our Continuous Integration server than when running locally. A quick example of how I’m setting up bindings:

Test snippet

describe('Testing the component', () => {
	
	let dataRows = [
		{
			propertyOne: 'a',
			propertyTwo: 'b'
		},
		{
			propertyOne: 'c',
			propertyTwo: 'd'
		}
	];
	
	let expected = [
		{
			propertyOne: 'a',
			propertyTwo: 'b'
		},
		{
			propertyOne: 'c',
			propertyTwo: 'd'
		}
	];
	
	beforeEach(() => {
		component = StageComponent
			.withResources('component/my-component')
			.inView('<my-component data-array.bind="testDataArray"></my-component>')
			.boundTo({
				testDataArray: dataRows
			});
	});
	
	afterEach(() => {
		component.dispose();
	});
	
	it('should display the correct result count', done => {
		component.create(bootstrap).then(() => {
		  const resultCount = document.getElementById('result-count');
		  expect(resultCount.innerText).toEqual('Displaying 2 Results');
		  done();
		  return null;
		}).catch(error => {
		  fail("An error has occurred: " + error.toString());
		});
	});
	// etc.
});

Example Component JS

@customElement('my-component')
@inject(Element, ComponentSession)
export class MyComponent {
	@bindable dataArray;
	
	constructor(element, componentSession) {
		this.element = element;
		this.session = componentSession;
	}
	
	attached() {
		// attaches array of data to a table element, updates a string that says 
		// "Displaying x Results" with a row count from the table, and some other
		// setup
		
		this.resultCount = this.dataArray.length;
	
		// etc.
	}
	// other helper methods below...
}

Example component HTML

<template>
	<table>
		<!-- A table using repeat.for to build the table rows from an array ...-->
	</table>
	<p>
		<strong id="result-count">Displaying ${resultCount} Results</strong>
	</p>
</template>

Example error for this test
Expected 'Displaying Results' to equal 'Displaying 2 Results'.

These are definitely very simplified snippets and I use more than one binding in my component, but I’m wondering if anything jumps out to someone based on the way we tend to set up these tests.

I’ve noticed that if I make each individual test wait 5 milliseconds after bootstrapping the components before execution, the tests seem to never fail, so something odd seems to be happening with waiting asynchronously


#2

Could you try delete node_modules folder and package-lock.json file and then do a clean npm install and re-run those tests to see if the issue persists? I’m not sure why it suddenly start working in a weird way like that so I guess probably it has something to do with duplicated dependencies.


#4

Yeah that’s the weird thing because it happens the most when running in our continuous integration build server, so it is doing a fresh build every time; node_modules aren’t checked in with it. I can only reproduce it locally if I copy/paste my 27 tests repeatedly until they reach over 400 tests.

These are my aurelia dependencies:

    "aurelia-bootstrapper": "2.3.1",
    "aurelia-event-aggregator": "1.0.1",
    "aurelia-fetch-client": "1.7.0",
    "aurelia-framework": "1.3.0",
    "aurelia-history-browser": "1.2.0",
    "aurelia-loader-webpack": "2.2.1",
    "aurelia-loader": "1.0.0",
    "aurelia-logging-console": "1.0.0",
    "aurelia-logging": "1.5.0",
    "aurelia-pal-browser": "1.8.0",
    "aurelia-polyfills": "1.3.0",
    "aurelia-route-recognizer": "1.3.1",
    "aurelia-router": "1.6.3",
    "aurelia-templating": "1.10.1",
    "aurelia-templating-binding": "1.5.2",
    "aurelia-templating-resources": "1.7.1",
    "aurelia-templating-router": "1.3.3",
    "aurelia-metadata": "1.0.4",
    "aurelia-validation": "1.3.2",

With the following aurelia devDependencies:

"aurelia-loader-nodejs": "1.0.1",
"aurelia-pal-nodejs": "1.2.0",
"aurelia-protractor-plugin": "1.0.6",
"aurelia-testing": "1.0.0",
"aurelia-webpack-plugin": "2.0.0-rc.5",

Also using Webpack 3.12.0

Is it possible that I’m being too specific by calling out each of these aurelia dependencies and some should have already come included with others?


#5

It probably has something to do with some code in one of your tests, from what described. At least it feels so to me. If so, I think I can only help if we can have some code to check.