Skip to content

Commit

Permalink
Type experimental macros
Browse files Browse the repository at this point in the history
  • Loading branch information
novemberborn committed Apr 4, 2020
1 parent de59e75 commit e33b3a2
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
40 changes: 40 additions & 0 deletions experimental.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,35 @@ import {ExecutionContext, ImplementationResult, MetaInterface} from '.';
export type Implementation<Context = unknown> = (t: ExecutionContext<Context>) => ImplementationResult;
export type ImplementationWithArgs<Args extends any[], Context = unknown> = (t: ExecutionContext<Context>, ...args: Args) => ImplementationResult;

export type Macro<Args extends any[] = [], Context = unknown> = {
exec (t: ExecutionContext<Context>, ...args: Args): ImplementationResult;
title? (providedTitle?: string, ...args: Args): string;
};

export interface MacroInterface<InheritedContext = unknown> {
<Args extends any[] = [], Context = InheritedContext> (implementation: ImplementationWithArgs<Args, Context>): Macro<Args, Context>;
<Args extends any[] = [], Context = InheritedContext> (macro: Macro<Args, Context>): Macro<Args, Context>;
}

export interface TestInterface<Context = unknown> {
/** Declare a concurrent test. */
(title: string, implementation: Implementation<Context>): void;

/** Declare a concurrent test. */
<Args extends any[]> (title: string, implementation: ImplementationWithArgs<Args, Context>, ...args: Args): void;

/** Declare a concurrent test. */
(title: string, macro: Macro<[], Context>): void;

/** Declare a concurrent test. */
<Args extends any[]> (title: string, macro: Macro<Args, Context>, ...args: Args): void;

/** Declare a concurrent test. */
(macro: Macro<[], Context>): void;

/** Declare a concurrent test. */
<Args extends any[]> (macro: Macro<Args, Context>, ...args: Args): void;

/** Declare a hook that is run once, after all tests have passed. */
after: AfterInterface<Context>;

Expand All @@ -58,6 +80,9 @@ export interface TestInterface<Context = unknown> {
/** Declare a hook that is run before each test. */
beforeEach: BeforeInterface<Context>;

/** Create a macro you can reuse in multiple tests. */
macro: MacroInterface<Context>;

/** Declare a test that is expected to fail. */
failing: FailingInterface<Context>;

Expand Down Expand Up @@ -161,6 +186,18 @@ export interface SerialInterface<Context = unknown> {
/** Declare a serial test. */
<Args extends any[]> (title: string, implementation: ImplementationWithArgs<Args, Context>, ...args: Args): void;

/** Declare a serial test. */
(title: string, macro: Macro<[], Context>): void;

/** Declare a serial test. */
<Args extends any[]> (title: string, macro: Macro<Args, Context>, ...args: Args): void;

/** Declare a serial test. */
(macro: Macro<[], Context>): void;

/** Declare a serial test. */
<Args extends any[]> (macro: Macro<Args, Context>, ...args: Args): void;

/** Declare a serial hook that is run once, after all tests have passed. */
after: AfterInterface<Context>;

Expand All @@ -173,6 +210,9 @@ export interface SerialInterface<Context = unknown> {
/** Declare a serial hook that is run before each test. */
beforeEach: BeforeInterface<Context>;

/** Create a macro you can reuse in multiple tests. */
macro: MacroInterface<Context>;

/** Declare a serial test that is expected to fail. */
failing: FailingInterface<Context>;

Expand Down
80 changes: 80 additions & 0 deletions test-d/experimental-macro.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import {expectError} from 'tsd';
import test, {TestInterface} from '../experimental';

{
const macro = test.macro(t => t.pass());
test(macro);
test('title', macro);
test.serial(macro);
test.serial('title', macro);
expectError(test(macro, 'foo'));
expectError(test('title', macro, 'foo'));
expectError(test.serial(macro, 'foo'));
expectError(test.serial('title', macro, 'foo'));
}

{
const macro = test.serial.macro(t => t.pass());
test(macro);
test.serial(macro);
}

{
const macro = test.macro<[string]>((t, string) => t.is(string, 'foo'));
test(macro, 'foo');
test('title', macro, 'foo');
test.serial(macro, 'foo');
test.serial('title', macro, 'foo');
expectError(test(macro));
expectError(test('title', macro));
expectError(test.serial(macro));
expectError(test.serial('title', macro));
}

{
const macro = test.macro<[string]>({
exec: (t, string) => t.is(string, 'foo')
});
test(macro, 'foo');
test('title', macro, 'foo');
test.serial(macro, 'foo');
test.serial('title', macro, 'foo');
expectError(test.serial(macro));
expectError(test.serial('title', macro));
}

{
const macro = test.macro<[string]>({
exec: (t, string) => t.is(string, 'foo'),
title: (prefix, string) => `${prefix ?? 'title'} ${string}`
});
test(macro, 'foo');
test('title', macro, 'foo');
test.serial(macro, 'foo');
test.serial('title', macro, 'foo');
expectError(test(macro));
expectError(test('title', macro));
expectError(test.serial(macro));
expectError(test.serial('title', macro));
}

test.serial.macro<[], { str: string }>(t => t.is(t.context.str, 'foo'));
test.serial.macro<[string], { str: string }>((t, string) => t.is(t.context.str, string));
(test as TestInterface<{ str: string }>).macro(t => t.is(t.context.str, 'foo'));
(test as TestInterface<{ str: string }>).macro<[string]>((t, string) => t.is(t.context.str, string));

{
const macro = test.macro<[], { foo: string }>(t => t.is(t.context.foo, 'foo'));
// ;(test as TestInterface<{foo: string, bar: string}>)(macro)
expectError((test as TestInterface<{bar: string}>)(macro));
}

{
const macro = test.macro(t => t.pass());
expectError(test.before(macro));
expectError(test.beforeEach(macro));
expectError(test.after(macro));
expectError(test.after.always(macro));
expectError(test.afterEach(macro));
expectError(test.afterEach.always(macro));
}

0 comments on commit e33b3a2

Please sign in to comment.