@tapjs/core
Version:
pluggable core of node-tap
511 lines • 14.1 kB
TypeScript
/**
* The base class that is extended by all TAP-generating classes
*
* @module
*/
import { Domain } from 'async-hook-domain';
import { AsyncResource } from 'async_hooks';
import { Minipass } from 'minipass';
import { FinalResults, Parser, TapError } from 'tap-parser';
import { Deferred } from 'trivial-deferred';
import { Counts } from './counts.js';
import type { Extra, TestBase } from './index.js';
import { Lists } from './lists.js';
/**
* Events emitted by the Base class
*/
export interface TapBaseEvents extends Minipass.Events<string> {
/**
* emitted when a timeout occurs
*/
timeout: [threw?: Extra];
/**
* emitted when the test bails out
*/
bailout: [reason?: string];
/**
* emitted when the test is complete
*/
complete: [results: FinalResults];
}
/**
* Wrapper for the async-hook-domain that catches errors thrown during
* test operation.
*
* @see {@link https://npmjs.com/async-hook-domain}
*/
export declare class TapWrap extends AsyncResource {
test: Base;
onDestroy?: () => void;
constructor(test: Base);
emitDestroy(): this;
}
/**
* A number indicating an amount of milliseconds
*/
export type MILLISECONDS = number;
/**
* Options that may be passed to any TAP-generating class
*/
export interface BaseOpts extends Extra {
/**
* Bail out on the first failure
*/
bail?: boolean;
/**
* Treat any unknown non-TAP data as an error
* May be set at run-time by the TAP stream using `pragma +strict`
*/
strict?: boolean;
/**
* Do not emit the `TAP version 14` line.
*/
omitVersion?: boolean;
/**
* Do not elide empty lines and other unnecessary whitespace
*/
preserveWhitespace?: boolean;
/**
* Skip this test entirely, emitting a `# SKIP` directive
*/
skip?: boolean | string;
/**
* Mark this test as to be done later, emitting a `# TODO` directive
*/
todo?: boolean | string;
/**
* Amount of time in milliseconds before this test times out
*/
timeout?: MILLISECONDS;
/**
* track passes in the results lists, default false
*/
passes?: boolean;
/**
* treat todo tests as failures, default false
*/
failTodo?: boolean;
/**
* treat skip tests as failures, default false
*/
failSkip?: boolean;
/**
* treat only:true tests as failures, default false
*/
failOnly?: boolean;
/**
* The amount of time that this test took to complete.
*
* Typically, this is not set explicitly, but inferred from the actual
* time spent. However in some cases, it may be reported by the
* top-level `# time=...` comment in a TAP subprocess stream.
*/
time?: number;
/**
* The TAP data from a buffered test.
*
* @internal
*
* @group Internal Machinery
*/
tapChildBuffer?: string;
/**
* The stack where this test was initiated
*/
stack?: string;
/**
* Parent test of this test
*/
parent?: Base | TestBase;
/**
* The name of this test
*/
name?: string;
/**
* Numeric identifier attached to child tests. Most of the time, this is
* set based on the `TAP_CHILD_ID` environment variable.
*/
childId?: number;
/**
* Any arbitrary data that is provided to this test object. Often, this
* is set in a `t.before()` or `t.beforeEach()` method. Scalar values
* are inherited by child tests. Object values are extended in child
* tests using `Object.create()`.
*
* If not set in the options, this is initialized to a null-prototyped
* object, so that usage like `t.context.foo = 'bar'` will work as expected.
*
* This is initialized and set on the Test object in the `runMain` method,
* *not* at construction time. If set explicitly on the Test object in a
* `before` hook, then any context specified on options or inherited from
* the parent test will be ignored.
*/
context?: any;
/**
* Number of spaces that this test is indented.
*
* @internal
*
* @group Internal Machinery
*/
indent?: string;
/**
* True to output LOTS AND LOTS of noisy debugging information.
* Set at the top level by the `TAP_DEBUG` environment variable.
*/
debug?: boolean;
/**
* Parser to use for this TAP stream.
*
* @internal
*
* @group Internal Machinery
*/
parser?: Parser;
/**
* True if this test should be buffered, and only processed once
* complete.
*
* Defaults to true when `t.jobs` is set to a value greater than 1.
*
* If set false in that case, then the test will NOT be run in parallel,
* so this provides a way to control the parallelism within a test suite.
*/
buffered?: boolean;
/**
* Setting silent:true in a subtest option makes it completely excluded
* from test output, UNLESS it fails.
*
* This was used historically for a few things which are now implemented
* with a more sophisticated promise management system, but can be handy in
* some rare situations.
*/
silent?: boolean;
}
export declare class Base<Events extends TapBaseEvents = TapBaseEvents> extends Minipass<string, string, Events> {
#private;
/**
* Set upon test completion when a child test is ready to be processed by its
* parent.
*/
readyToProcess: boolean;
/**
* Options provided to this test
*/
options: BaseOpts;
/**
* number of spaces to indent the TAP stream
*/
indent: string;
/**
* TapWrap AsyncResource that limits the async-hook-domain
*
* @group Internal Machinery
*/
hook: TapWrap;
/**
* the async-hook-domain that catches throws and Promise rejections
*
* @group Internal Machinery
*/
hookDomain: Domain;
/**
* The timer that fires when the test times out
*
* @group Internal Machinery
*/
timer?: NodeJS.Timeout;
/**
* Set to true when the test times out, so its failure status can be
* determined later.
*/
timedOut: boolean;
/**
* The tap parser attached to this TAP stream
*
* @group Internal Machinery
*/
parser: Parser;
/**
* Method that writes to stderr when `debug: true` is set in the options,
* or no-ops otherwise
*/
debug: (...args: any[]) => void;
/**
* The count of all assertions that this stream emitted
*
* @group Test Reflection
*/
counts: Counts;
/**
* Lists of todo, skip, and failure test points. If `passes: true` is
* set in the options, then passing test points will also be tracked.
*
* @group Test Reflection
*/
lists: Lists;
/**
* the name of this test
*
* @group Test Reflection
*/
name: string;
/**
* Set on completion. The results of the test run.
*
* @group Test Reflection
*/
results?: FinalResults;
/**
* Parent test of this TAP stream
*
* @group Internal Machinery
*/
parent?: Base | TestBase;
/**
* Nesting level, for serialization to node test runner
*
* Note that this is zero for parent-less tests, and *also* zero
* for the first level of children.
*/
nestingLevel: number;
/**
* Bail out on the first failed test point
*/
bail: boolean;
/**
* Treat non-TAP data as an error.
* May be set with `pragma +strict` in the TAP stream, or unset with
* `pragma: -strict`.
*/
strict: boolean;
/**
* Do not emit the `TAP version 14` line at the start
*/
omitVersion: boolean;
/**
* Do not elide extraneous whitespace and empty lines.
*/
preserveWhitespace: boolean;
/**
* Unrecoverable TAP protocol errors in the stream
*
* @group Test Reflection
*/
errors: TapError[];
/**
* Numeric identifier for this test
*/
childId: number;
get context(): any;
set context(c: any);
/**
* the TAP stream data for buffered tests
*
* @internal
*
* @group Internal Machinery
*/
output: string;
/**
* True if this test should be buffered and only processed on completion
*
* @internal
*
* @group Internal Machinery
*/
buffered: boolean;
/**
* True if this test emitted a bailout
*
* @group Test Reflection
*/
bailedOut: string | boolean;
/**
* high resolution bigint time when this test started
*
* @group Internal Machinery
*/
start: bigint;
/**
* Amount of time in milliseconds that this test took to complete.
*
* @group Test Reflection
*/
time: MILLISECONDS;
/**
* High resolution time in ns that this test took to complete.
*
* @group Test Reflection
*/
hrtime: bigint;
/**
* True if this test should be buffered and only emit data if it fails
*/
silent: boolean;
/**
* A `Deferred` promise wrapper that is resolved when this test completes.
*
* @group Internal Machinery
*/
deferred?: Deferred<FinalResults>;
constructor(options?: BaseOpts);
/**
* Set the amount of time in milliseconds before this test is considered
* a timeout. The time is counted from right now, so for example, repeatedly
* calling `t.setTimeout(100)` can keep it going indefinitely, as long as
* you call it more often than every 100ms.
*
* Calling `setTimeout(0)` will remove the timer and allow the test to run
* indefinitely.
*
* @group Test Lifecycle Management
*/
setTimeout(n: MILLISECONDS): void;
/**
* Called when a timeout occurs. Only exposed because it has to be called
* and/or extended by other classes, which all have their own sorts of
* timeout behavior specific to the type of thing they represent.
*
* @internal
*
* @group Internal Machinery
*/
timeout(options?: {
expired?: string;
message?: string;
}): void;
/**
* Run the `main` test function. Called by
* {@link @tapjs/core!test-base.TestBase} when starting a subtest.
* Initializes the TapWrap hook
*
* @internal
*
* @group Internal Machinery
*/
runMain(cb: () => void): void;
/**
* Returns true if this test has begun
*
* @group Test Reflection
*/
get started(): boolean;
/**
* True if the test has printed *some* output of any kind
*
* @group Test Reflection
*/
get printedOutput(): boolean;
/**
* Boolean indicating whether the underlying stream can be written to,
* or if it has been ended.
*/
get streamWritable(): boolean;
/**
* The main test function. For this Base class, this is a no-op. Subclasses
* implement this in their specific ways.
*
* @internal
*
* @group Internal Machinery
*/
main(cb: () => void): void;
/**
* Stream write method.
*
* For buffered tests, this collects the output in the
* {@link @tapjs/core!base.Base#output}
* field. Sets {@link @tapjs/core!base.Base#printedOutput} to `true` when
* called.
*
* Note: you *probably* never need to call this. Instead, use the various
* assertion methods and other parts of the API.
*
* @internal
*
* @group Internal Machinery
*/
write(c: string): boolean;
/**
* Method called when the parser encounters a bail out
*
* Extended by {@link @tapjs/core!test-base.TestBase}
*/
onbail(reason?: string): void;
/**
* Method called when the parser completes and emits its final results
*
* Extended by {@link @tapjs/core!worker.Worker} and
* {@link @tapjs/core!tap.TAP} classes
*
* @internal
*
* @group Internal Machinery
*/
oncomplete(results: FinalResults): void;
/**
* extension point for plugins that want to be notified when the test
* is about to end, whether explicitly or implicitly.
*
* If the function returns a Promise, it will be awaited before ending
* the TAP stream.
*
* @internal
*
* @group Internal Machinery
*/
onbeforeend(): Promise<void> | void;
/**
* extension point for plugins that want to be notified when the test
* is completely done, and terminating its parser.
*
* @internal
*
* @group Internal Machinery
*/
onEOF(): Promise<void> | void;
/**
* extension point for TestBase to know when a child tests is done being
* processed and it's safe to move on to the next one.
*
* @internal
*
* @group Internal Machinery
*/
ondone(): void;
/**
* EventEmitter emit method, but closes the
* {@link @tapjs/core!base.Base#hook} and
* {@link @tapjs/core!base.Base#hookDomain} when emitting `'end'`.
*
* @internal
*
* @group Internal Machinery
*/
emit<Event extends keyof Events>(ev: Event, ...data: Events[Event]): boolean;
/**
* Mark the test as ended. In this base class, this is a no-op, but
* in {@link @tapjs/core!test-base.TestBase}, it also triggers the other
* end-of-test operations.
*/
end(): this;
/**
* Method called when an unrecoverable error is encountered in a test.
*
* Typically, in tests you would not call this, you'd just actually throw
* an error.
*
* @internal
*
* @group Internal Machinery
*/
threw(er: any, extra?: Extra, proxy?: boolean, ended?: boolean): Extra | void | undefined;
/**
* returns true if the test has not as yet encountered any failures
*
* @group Test Reflection
*/
passing(): boolean;
}
//# sourceMappingURL=base.d.ts.map