/// <reference types="chai" />
import * as chai from 'chai';
import { Handle } from '@dojo/core/interfaces';
import Task from '@dojo/core/async/Task';
import Suite from '../Suite';
import Test from '../Test';
import ErrorFormatter, { ErrorFormatOptions } from '../common/ErrorFormatter';
import { BenchmarkConfig, Config, PluginDescriptor, ReporterDescriptor } from '../common/config';
import Reporter from '../reporters/Reporter';
import { ObjectInterface } from '../interfaces/object';
import { TddInterface } from '../interfaces/tdd';
import { BddInterface } from '../interfaces/bdd';
import { BenchmarkInterface } from '../interfaces/benchmark';
import { RuntimeEnvironment } from '../types';
export interface Executor {
    readonly config: Config;
    readonly suites: Suite[];
    addSuite(factory: (parentSuite: Suite) => void): void;
    configure(options: {
        [key: string]: any;
    }): void;
    emit<T extends NoDataEvents>(eventName: T): Task<void>;
    emit<T extends keyof Events>(eventName: T, data: Events[T]): Task<void>;
    formatError(error: Error, options?: ErrorFormatOptions): string;
    log(...args: any[]): Task<void>;
    on<T extends keyof Events>(eventName: T, listener: Listener<Events[T]>): Handle;
    on(listener: Listener<{
        name: string;
        data?: any;
    }>): Handle;
}
export default abstract class BaseExecutor<E extends Events, C extends Config, P extends Plugins> implements Executor {
    protected _config: C;
    protected _rootSuite: Suite;
    protected _events: InternEvent<E>[];
    protected _errorFormatter: ErrorFormatter | undefined;
    protected _hasSuiteErrors: boolean;
    protected _hasTestErrors: boolean;
    protected _hasEmittedErrors: boolean;
    protected _loader: Loader;
    protected _loaderOptions: any;
    protected _loaderInit: Promise<Loader> | undefined;
    protected _loadingPlugins: {
        name: string;
        init: Task<void>;
    }[];
    protected _loadingPluginOptions: any | undefined;
    protected _listeners: {
        [event: string]: Listener<any>[];
    };
    protected _plugins: {
        [name: string]: any;
    };
    protected _reporters: Reporter[];
    protected _runTask: Task<void> | undefined;
    protected _reportersInitialized: boolean;
    constructor(options?: {
        [key in keyof C]?: any;
    });
    readonly abstract environment: RuntimeEnvironment;
    readonly config: C;
    readonly suites: Suite[];
    formatError(error: Error, options?: ErrorFormatOptions): string;
    abstract loadScript(script: string | string[]): Task<void>;
    addSuite(factory: (parentSuite: Suite) => void): void;
    configure(options: {
        [key in keyof C]?: any;
    }): void;
    emit<T extends NoDataEvents>(eventName: T): Task<void>;
    emit<T extends keyof E>(eventName: T, data: E[T]): Task<void>;
    getInterface(name: 'object'): ObjectInterface;
    getInterface(name: 'tdd'): TddInterface;
    getInterface(name: 'bdd'): BddInterface;
    getInterface(name: 'benchmark'): BenchmarkInterface;
    getPlugin<Y extends keyof P>(type: Y, name: string): P[Y];
    getPlugin(name: 'chai'): typeof chai;
    getPlugin(name: 'interface.object'): ObjectInterface;
    getPlugin(name: 'interface.tdd'): TddInterface;
    getPlugin(name: 'interface.bdd'): BddInterface;
    getPlugin(name: 'interface.benchmark'): BenchmarkInterface;
    getPlugin<T>(name: string): T;
    log(...args: any[]): Task<void>;
    on<T extends keyof E>(eventName: T, listener: Listener<E[T]>): Handle;
    on(listener: Listener<{
        name: string;
        data?: any;
    }>): Handle;
    registerInterface(name: string, iface: any): void;
    registerLoader(init: LoaderInit): void;
    registerPlugin<T extends keyof P>(type: T, name: string, init: PluginInitializer<P[T]>): void;
    registerPlugin(name: string, init: PluginInitializer): void;
    registerReporter(name: string, init: ReporterInitializer): void;
    run(): Task<void>;
    protected _afterRun(): Task<void>;
    protected _assignPlugin(name: string, plugin: any): void;
    protected _beforeRun(): Task<boolean>;
    protected _initReporters(): Task<void>;
    protected _drainEventQueue(): Task<void>;
    protected _emitCoverage(source?: string): Task<void> | undefined;
    protected _loadLoader(): Promise<void>;
    protected _loadPluginsWithLoader(): Task<void>;
    protected _loadPlugins(): Task<void>;
    protected _loadScripts(scripts: PluginDescriptor[], loader: (script: string) => Promise<void>): Task<void>;
    protected _loadSuites(): Task<void>;
    protected _processOption(key: keyof C, value: any): void;
    protected _resolveConfig(): Task<void>;
    protected _runTests(): Task<void>;
}
export { BenchmarkConfig, Config, PluginDescriptor, ReporterDescriptor };
export interface InternEvent<E extends Events> {
    eventName: keyof E;
    data?: any;
}
export { Handle };
export interface Listener<T> {
    (arg: T): void | Promise<void>;
}
export interface CoverageMessage {
    sessionId?: string;
    source?: string;
    coverage: any;
}
export interface DeprecationMessage {
    original: string;
    replacement?: string;
    message?: string;
}
export interface ExecutorEvent {
    name: keyof Events;
    data: any;
}
export interface Events {
    '*': ExecutorEvent;
    afterRun: void;
    beforeRun: void;
    coverage: CoverageMessage;
    deprecated: DeprecationMessage;
    error: Error;
    log: string;
    runEnd: void;
    runStart: void;
    suiteAdd: Suite;
    suiteEnd: Suite;
    suiteStart: Suite;
    testAdd: Test;
    testEnd: Test;
    testStart: Test;
    warning: string;
}
export declare type NoDataEvents = 'runStart' | 'runEnd' | 'beforeRun' | 'afterRun';
export interface Plugins {
    reporter: ReporterInitializer;
}
export interface Loader {
    (modules: string[]): Promise<void>;
}
export interface LoaderInit {
    (options: {
        [key: string]: any;
    }): Promise<Loader> | Loader;
}
export interface PluginInitializer<T extends any = any> {
    (options?: {
        [key: string]: any;
    }): Task<T> | T;
}
export interface ReporterInitializer {
    (options?: any): Reporter;
}
