Skip to content

Commit 31aa9a0

Browse files
committed
Merge branch 'typescript-context'
2 parents 4e93ed9 + bc9990a commit 31aa9a0

File tree

8 files changed

+70
-24
lines changed

8 files changed

+70
-24
lines changed

docs/state-management.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,18 @@ When("I increment the variable by {int}", function(number) {
6565
Then("the variable should contain {int}", function(number) {
6666
expect(this.variable).to.equal(number);
6767
});
68-
````
68+
```
69+
70+
## TypeScript
71+
72+
If you're using TypeScript, you can get optimum type safety and completion based on your custom world, by setting the type of `this` in your step functions:
73+
74+
```ts
75+
interface CustomWorld extends Mocha.Context {
76+
eat: (count: number) => void;
77+
}
78+
79+
When("I eat {int} cucumbers", function (this: CustomWorld, count: number) {
80+
this.eat(count);
81+
});
82+
```

lib/diagnostics/diagnose.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ export interface UnmatchedStep {
4545

4646
export interface AmbiguousStep {
4747
step: DiagnosticStep;
48-
definitions: IStepDefinition<unknown[]>[];
48+
definitions: IStepDefinition<unknown[], Mocha.Context>[];
4949
}
5050

5151
export interface DiagnosticResult {
5252
definitionsUsage: {
53-
definition: IStepDefinition<unknown[]>;
53+
definition: IStepDefinition<unknown[], Mocha.Context>;
5454
steps: DiagnosticStep[];
5555
}[];
5656
unmatchedSteps: UnmatchedStep[];
@@ -72,16 +72,18 @@ export function comparePosition(a: Position, b: Position) {
7272
}
7373

7474
export function compareStepDefinition(
75-
a: IStepDefinition<unknown[]>,
76-
b: IStepDefinition<unknown[]>
75+
a: IStepDefinition<unknown[], Mocha.Context>,
76+
b: IStepDefinition<unknown[], Mocha.Context>
7777
) {
7878
return (
7979
expressionToString(a.expression) === expressionToString(b.expression) &&
8080
comparePosition(position(a), position(b))
8181
);
8282
}
8383

84-
export function position(definition: IStepDefinition<unknown[]>): Position {
84+
export function position(
85+
definition: IStepDefinition<unknown[], Mocha.Context>
86+
): Position {
8587
return assertAndReturn(definition.position, "Expected to find a position");
8688
}
8789

lib/diagnostics/index.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,18 @@ export function comparePosition(a: Position, b: Position) {
5555
}
5656

5757
export function compareStepDefinition(
58-
a: IStepDefinition<unknown[]>,
59-
b: IStepDefinition<unknown[]>
58+
a: IStepDefinition<unknown[], Mocha.Context>,
59+
b: IStepDefinition<unknown[], Mocha.Context>
6060
) {
6161
return (
6262
expressionToString(a.expression) === expressionToString(b.expression) &&
6363
comparePosition(position(a), position(b))
6464
);
6565
}
6666

67-
export function position(definition: IStepDefinition<unknown[]>): Position {
67+
export function position(
68+
definition: IStepDefinition<unknown[], Mocha.Context>
69+
): Position {
6870
return assertAndReturn(definition.position, "Expected to find a position");
6971
}
7072

lib/index.test-d.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,27 @@ After({ tags: "foo" }, function () {
109109
expectType<Mocha.Context>(this);
110110
});
111111

112+
interface CustomWorld extends Mocha.Context {
113+
pageDriver: {
114+
navigateTo(url: string): void;
115+
};
116+
}
117+
118+
Given(/foo/, function (this: CustomWorld, url: string) {
119+
expectType<CustomWorld>(this);
120+
this.pageDriver.navigateTo(url);
121+
});
122+
123+
When(/foo/, function (this: CustomWorld, url: string) {
124+
expectType<CustomWorld>(this);
125+
this.pageDriver.navigateTo(url);
126+
});
127+
128+
Then(/foo/, function (this: CustomWorld, url: string) {
129+
expectType<CustomWorld>(this);
130+
this.pageDriver.navigateTo(url);
131+
});
132+
112133
expectType<messages.GherkinDocument>(window.testState.gherkinDocument);
113134
expectType<messages.Pickle[]>(window.testState.pickles);
114135
expectType<messages.Pickle>(window.testState.pickle);

lib/index.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ export function doesFeatureMatch(expression: string): boolean {
5454
throw createUnimplemented();
5555
}
5656

57-
export function defineStep<T extends unknown[]>(
57+
export function defineStep<T extends unknown[], C extends Mocha.Context>(
5858
// eslint-disable-next-line @typescript-eslint/no-unused-vars
5959
description: string | RegExp,
6060
// eslint-disable-next-line @typescript-eslint/no-unused-vars
61-
implementation: IStepDefinitionBody<T>
61+
implementation: IStepDefinitionBody<T, C>
6262
) {
6363
throw createUnimplemented();
6464
}
@@ -77,7 +77,9 @@ export function Step(
7777
}
7878

7979
// eslint-disable-next-line @typescript-eslint/no-unused-vars
80-
export function defineParameterType<T>(options: IParameterTypeDefinition<T>) {
80+
export function defineParameterType<T, C extends Mocha.Context>(
81+
options: IParameterTypeDefinition<T, C>
82+
) {
8183
throw createUnimplemented();
8284
}
8385

lib/methods.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ import {
1919
IStepDefinitionBody,
2020
} from "./types";
2121

22-
function defineStep<T extends unknown[]>(
22+
function defineStep<T extends unknown[], C extends Mocha.Context>(
2323
description: string | RegExp,
24-
implementation: IStepDefinitionBody<T>
24+
implementation: IStepDefinitionBody<T, C>
2525
) {
2626
getRegistry().defineStep(description, implementation);
2727
}
@@ -34,7 +34,9 @@ function runStepDefininition(
3434
getRegistry().runStepDefininition(world, text, argument);
3535
}
3636

37-
function defineParameterType<T>(options: IParameterTypeDefinition<T>) {
37+
function defineParameterType<T, C extends Mocha.Context>(
38+
options: IParameterTypeDefinition<T, C>
39+
) {
3840
getRegistry().defineParameterType(options);
3941
}
4042

lib/registry.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ import {
2424

2525
import { maybeRetrievePositionFromSourceMap, Position } from "./source-map";
2626

27-
export interface IStepDefinition<T extends unknown[]> {
27+
export interface IStepDefinition<T extends unknown[], C extends Mocha.Context> {
2828
expression: Expression;
29-
implementation: IStepDefinitionBody<T>;
29+
implementation: IStepDefinitionBody<T, C>;
3030
position?: Position;
3131
}
3232

@@ -70,7 +70,7 @@ export class Registry {
7070
position?: Position;
7171
}[] = [];
7272

73-
public stepDefinitions: IStepDefinition<unknown[]>[] = [];
73+
public stepDefinitions: IStepDefinition<unknown[], Mocha.Context>[] = [];
7474

7575
public beforeHooks: IHook[] = [];
7676

@@ -123,11 +123,11 @@ export class Registry {
123123
});
124124
}
125125

126-
public defineParameterType<T>({
126+
public defineParameterType<T, C extends Mocha.Context>({
127127
name,
128128
regexp,
129129
transformer,
130-
}: IParameterTypeDefinition<T>) {
130+
}: IParameterTypeDefinition<T, C>) {
131131
this.parameterTypeRegistry.defineParameterType(
132132
new ParameterType(name, regexp, null, transformer, true, false)
133133
);

lib/types.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
export interface IParameterTypeDefinition<T> {
1+
export interface IParameterTypeDefinition<T, C extends Mocha.Context> {
22
name: string;
33
regexp: RegExp;
4-
transformer: (this: Mocha.Context, ...match: string[]) => T;
4+
transformer: (this: C, ...match: string[]) => T;
55
}
66

77
export interface IHookBody {
88
(this: Mocha.Context): void;
99
}
1010

11-
export interface IStepDefinitionBody<T extends unknown[]> {
12-
(this: Mocha.Context, ...args: T): void;
11+
export interface IStepDefinitionBody<
12+
T extends unknown[],
13+
C extends Mocha.Context
14+
> {
15+
(this: C, ...args: T): void;
1316
}
1417

1518
export type YieldType<T extends Generator> = T extends Generator<infer R>

0 commit comments

Comments
 (0)