
Karma-mocha has an issue[1]: when unhandled exception is thrown right after a test ends, the mocha doesn't executu other tests, but Karma reports success. With the fix, the exception is rethrown correctly after all tests and Karma fails (as expected). [1] https://github.com/karma-runner/karma-mocha/issues/227 Change-Id: Iae031a01ead3a9004b0c290559f0b070c58a6919
197 lines
5.6 KiB
JavaScript
197 lines
5.6 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright (C) 2020 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
import './common-test-setup.js';
|
|
import '@polymer/test-fixture/test-fixture.js';
|
|
import 'chai/chai.js';
|
|
self.assert = window.chai.assert;
|
|
self.expect = window.chai.expect;
|
|
|
|
// Workaround for https://github.com/karma-runner/karma-mocha/issues/227
|
|
let unhandledError = null;
|
|
|
|
window.addEventListener('error', e => {
|
|
// For uncaught error mochajs doesn't print the full stack trace.
|
|
// We should print it ourselves.
|
|
console.error('Uncaught error:');
|
|
console.error(e.error.stack.toString());
|
|
unhandledError = e;
|
|
});
|
|
|
|
let originalOnBeforeUnload;
|
|
|
|
suiteSetup(() => {
|
|
// This suiteSetup() method is called only once before all tests
|
|
|
|
// Can't use window.addEventListener("beforeunload",...) here,
|
|
// the handler is raised too late.
|
|
originalOnBeforeUnload = window.onbeforeunload;
|
|
window.onbeforeunload = e => {
|
|
// If a test reloads a page, we can't prevent it.
|
|
// However we can print earror and the stack trace with assert.fail
|
|
try {
|
|
throw new Error();
|
|
} catch (e) {
|
|
console.error('Page reloading attempt detected.');
|
|
console.error(e.stack.toString());
|
|
}
|
|
originalOnBeforeUnload(e);
|
|
};
|
|
});
|
|
|
|
suiteTeardown(() => {
|
|
// This suiteTeardown() method is called only once after all tests
|
|
window.onbeforeunload = originalOnBeforeUnload;
|
|
if (unhandledError) {
|
|
throw unhandledError;
|
|
}
|
|
});
|
|
|
|
// Tests can use fake timers (sandbox.useFakeTimers)
|
|
// Keep the original one for use in test utils methods.
|
|
const nativeSetTimeout = window.setTimeout;
|
|
|
|
/**
|
|
* Triggers a flush of any pending events, observations, etc and calls you back
|
|
* after they have been processed if callback is passed; otherwise returns
|
|
* promise.
|
|
*
|
|
* @param {function()} callback
|
|
*/
|
|
function flush(callback) {
|
|
// Ideally, this function would be a call to Polymer.dom.flush, but that
|
|
// doesn't support a callback yet
|
|
// (https://github.com/Polymer/polymer-dev/issues/851)
|
|
window.Polymer.dom.flush();
|
|
if (callback) {
|
|
nativeSetTimeout(callback, 0);
|
|
} else {
|
|
return new Promise(resolve => {
|
|
nativeSetTimeout(resolve, 0);
|
|
});
|
|
}
|
|
}
|
|
|
|
self.flush = flush;
|
|
|
|
class TestFixtureIdProvider {
|
|
static get instance() {
|
|
if (!TestFixtureIdProvider._instance) {
|
|
TestFixtureIdProvider._instance = new TestFixtureIdProvider();
|
|
}
|
|
return TestFixtureIdProvider._instance;
|
|
}
|
|
|
|
constructor() {
|
|
this.fixturesCount = 1;
|
|
}
|
|
|
|
generateNewFixtureId() {
|
|
this.fixturesCount++;
|
|
return `fixture-${this.fixturesCount}`;
|
|
}
|
|
}
|
|
|
|
class TestFixture {
|
|
constructor(fixtureId) {
|
|
this.fixtureId = fixtureId;
|
|
}
|
|
|
|
/**
|
|
* Create an instance of a fixture's template.
|
|
*
|
|
* @param {Object} model - see Data-bound sections at
|
|
* https://www.webcomponents.org/element/@polymer/test-fixture
|
|
* @return {HTMLElement | HTMLElement[]} - if the fixture's template contains
|
|
* a single element, returns the appropriated instantiated element.
|
|
* Otherwise, it return an array of all instantiated elements from the
|
|
* template.
|
|
*/
|
|
instantiate(model) {
|
|
// The window.fixture method is defined in common-test-setup.js
|
|
return window.fixture(this.fixtureId, model);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wraps provided template to a test-fixture tag and adds test-fixture to
|
|
* the document. You can use the html function to create a template.
|
|
*
|
|
* Example:
|
|
* import {html} from '@polymer/polymer/lib/utils/html-tag.js';
|
|
*
|
|
* // Create fixture at the root level of a test file
|
|
* const basicTestFixture = fixtureFromTemplate(html`
|
|
* <gr-cursor-manager cursor-target-class="targeted"></gr-cursor-manager>
|
|
* <ul>
|
|
* <li>A</li>
|
|
* <li>B</li>
|
|
* <li>C</li>
|
|
* <li>D</li>
|
|
* </ul>
|
|
* `);
|
|
* ...
|
|
* // Instantiate fixture when needed:
|
|
*
|
|
* suite('example') {
|
|
* let elements;
|
|
* setup(() => {
|
|
* elements = basicTestFixture.instantiate();
|
|
* });
|
|
* }
|
|
*
|
|
* @param {HTMLTemplateElement} template - a template for a fixture
|
|
* @return {TestFixture} - the instance of TestFixture class
|
|
*/
|
|
function fixtureFromTemplate(template) {
|
|
const fixtureId = TestFixtureIdProvider.instance.generateNewFixtureId();
|
|
const testFixture = document.createElement('test-fixture');
|
|
testFixture.setAttribute('id', fixtureId);
|
|
testFixture.appendChild(template);
|
|
document.body.appendChild(testFixture);
|
|
return new TestFixture(fixtureId);
|
|
}
|
|
|
|
/**
|
|
* Wraps provided tag to a test-fixture/template tags and adds test-fixture
|
|
* to the document.
|
|
*
|
|
* Example:
|
|
*
|
|
* // Create fixture at the root level of a test file
|
|
* const basicTestFixture = fixtureFromElement('gr-diff-view');
|
|
* ...
|
|
* // Instantiate fixture when needed:
|
|
*
|
|
* suite('example') {
|
|
* let element;
|
|
* setup(() => {
|
|
* element = basicTestFixture.instantiate();
|
|
* });
|
|
* }
|
|
*
|
|
* @param {HTMLTemplateElement} template - a template for a fixture
|
|
* @return {TestFixture} - the instance of TestFixture class
|
|
*/
|
|
function fixtureFromElement(tagName) {
|
|
const template = document.createElement('template');
|
|
template.innerHTML = `<${tagName}></${tagName}>`;
|
|
return fixtureFromTemplate(template);
|
|
}
|
|
|
|
window.fixtureFromTemplate = fixtureFromTemplate;
|
|
window.fixtureFromElement = fixtureFromElement;
|