packages/__tests__/src/setup-shared.ts
import { IDisposable } from '@aurelia/kernel';
import { BrowserPlatform } from '@aurelia/platform-browser';
import { ConnectableSwitcher } from '@aurelia/runtime';
import { setPlatform, assert, ensureTaskQueuesEmpty, onFixtureCreated, IFixture } from '@aurelia/testing';
interface ExtendedSuite extends Mocha.Suite {
$duration?: number;
}
function getRootSuite(suite: ExtendedSuite): ExtendedSuite {
while (!suite.parent.root) {
suite = suite.parent;
}
return suite;
}
export function $setup(platform: BrowserPlatform): void {
setPlatform(platform);
BrowserPlatform.set(globalThis, platform);
if (typeof window !== 'undefined') window.addEventListener('error', e => console.log(e));
const globalStart = platform.performanceNow();
let firstTestStart = 0;
let currentRootSuite: ExtendedSuite = (void 0)!;
let currentSuite: ExtendedSuite = (void 0)!;
let start: number;
let fixtures: IFixture<unknown>[] = [];
let fixtureHookHandler: IDisposable | undefined = void 0;
// eslint-disable-next-line
beforeEach(function() {
(globalThis as any)['__DEV__'] = typeof process !== 'undefined' ? !!process.env.__DEV__ : false;
start = platform.performanceNow();
if (firstTestStart === 0) {
firstTestStart = start;
console.log(`Test initialization took ${Math.round(firstTestStart - globalStart)}ms`);
}
const totalElapsed = start - firstTestStart;
const ts = new Date(totalElapsed).toISOString().slice(14, -1);
const title = this.currentTest!.fullTitle();
if (title.length > 1000) {
console.log(`[${ts}] Super long title! "${title.slice(0, 1000)}...(+${title.length - 1000})"`);
}
const nextSuite = this.currentTest!.parent as ExtendedSuite;
if (currentSuite !== nextSuite) {
if (currentSuite !== void 0) {
const duration = currentSuite.$duration;
const total = currentSuite.total();
const perTest = duration / total;
if (perTest > 20) {
console.log(`[${ts}] slow: ${String(total).padStart(5, ' ')} tests after ${String(Math.round(duration)).padStart(5, ' ')}ms (${String(Math.round(perTest)).padStart(3, ' ')}ms/test): "${currentSuite.fullTitle()}"`);
}
}
currentSuite = nextSuite;
}
const nextRootSuite = getRootSuite(nextSuite);
if (currentRootSuite !== nextRootSuite) {
console.log(`[${ts}] > ${String(nextRootSuite.total()).padStart(5, ' ')} tests in "${nextRootSuite.fullTitle()}"`);
currentRootSuite = nextRootSuite;
}
fixtureHookHandler = onFixtureCreated(fixture => {
fixtures.push(fixture);
});
});
// eslint-disable-next-line
afterEach(function() {
fixtureHookHandler?.dispose();
fixtureHookHandler = void 0;
const promises: (void | Promise<void>)[] = [];
for (const fixture of fixtures) {
if (!fixture.torn) {
promises.push(fixture.tearDown());
}
}
const cleanup = () => {
const elapsed = platform.performanceNow() - start;
let suite = currentSuite;
do {
suite.$duration = (suite.$duration ?? 0) + elapsed;
suite = suite.parent;
} while (suite);
try {
const shouldThrow = this.test?.isFailed();
if (shouldThrow) {
try {
assert.areTaskQueuesEmpty();
} catch (ex) {
console.log(`Failed test ${this.test?.title} with task queue not empted. Cleaning up.`);
console.log(ex);
ensureTaskQueuesEmpty();
}
} else {
assert.areTaskQueuesEmpty();
}
} catch (ex) {
ensureTaskQueuesEmpty();
assertNoWatcher(false);
}
assertNoWatcher(true);
};
fixtures = [];
if (promises.some(p => p instanceof Promise)) {
return Promise.all(promises).then(cleanup);
}
cleanup();
});
const assertNoWatcher = (shouldThrow: boolean) => {
let hasWatcher = false;
let currentWatcher = ConnectableSwitcher.current;
while (currentWatcher != null) {
hasWatcher = true;
ConnectableSwitcher.exit(currentWatcher);
currentWatcher = ConnectableSwitcher.current;
}
if (hasWatcher) {
if (shouldThrow) {
throw new Error('There is still some watcher not removed.');
} else {
console.error('There is still some watcher not removed.');
}
}
};
}