racejar 1.1.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/example/hello-herman.test.ts +12 -7
- package/example/hooks.test.ts +42 -0
- package/package.json +1 -1
- package/src/compile-feature.ts +27 -0
- package/src/hooks.ts +32 -0
- package/src/index.ts +1 -0
- package/src/jest/jest-gherkin-driver.ts +15 -1
- package/src/playwright/playwright-gherkin-driver.ts +37 -12
- package/src/vitest/vitest-gherkin-driver.ts +13 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.2.0](https://github.com/portabletext/editor/compare/racejar-v1.1.3...racejar-v1.2.0) (2025-02-10)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add support for `Before` and `After` hooks ([#784](https://github.com/portabletext/editor/issues/784)) ([0cee059](https://github.com/portabletext/editor/commit/0cee059aff7bb799ed51b608d8068490bc379d12))
|
|
9
|
+
* Add support for Data Tables and Doc Strings ([#783](https://github.com/portabletext/editor/issues/783)) ([2083aab](https://github.com/portabletext/editor/commit/2083aab7637ef5c5f95e25b5b4373b63869dde74))
|
|
10
|
+
|
|
3
11
|
## [1.1.3](https://github.com/portabletext/editor/compare/racejar-v1.1.2...racejar-v1.1.3) (2025-02-05)
|
|
4
12
|
|
|
5
13
|
|
|
@@ -2,11 +2,12 @@ import {expect} from 'vitest'
|
|
|
2
2
|
import {Given, Then, When} from '../src/step-definitions'
|
|
3
3
|
import {Feature} from '../src/vitest'
|
|
4
4
|
|
|
5
|
-
function greet(name: string) {
|
|
6
|
-
return `Hello
|
|
5
|
+
function greet(name: string, greeting: string) {
|
|
6
|
+
return `Hello ${name}, ${greeting}`
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
type Context = {
|
|
10
|
+
greetingPrefix: string
|
|
10
11
|
person: string
|
|
11
12
|
greeting: string
|
|
12
13
|
}
|
|
@@ -16,15 +17,19 @@ Feature({
|
|
|
16
17
|
Feature: Greeting
|
|
17
18
|
Scenario: Greeting a person
|
|
18
19
|
Given the person "Herman"
|
|
19
|
-
When greeting the person
|
|
20
|
-
|
|
20
|
+
When greeting the person with:
|
|
21
|
+
| how are you? |
|
|
22
|
+
Then the greeting is "Hello Herman, how are you?"`,
|
|
21
23
|
stepDefinitions: [
|
|
22
24
|
Given('the person {string}', (context: Context, person: string) => {
|
|
23
25
|
context.person = person
|
|
24
26
|
}),
|
|
25
|
-
When(
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
When(
|
|
28
|
+
'greeting the person with:',
|
|
29
|
+
(context: Context, greeting: string[][]) => {
|
|
30
|
+
context.greeting = greet(context.person, greeting[0][0])
|
|
31
|
+
},
|
|
32
|
+
),
|
|
28
33
|
Then('the greeting is {string}', (context: Context, greeting: string) => {
|
|
29
34
|
expect(context.greeting).toBe(greeting)
|
|
30
35
|
}),
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {expect} from 'vitest'
|
|
2
|
+
import {After, Before} from '../src/hooks'
|
|
3
|
+
import {Given, Then, When} from '../src/step-definitions'
|
|
4
|
+
import {Feature} from '../src/vitest'
|
|
5
|
+
|
|
6
|
+
function greet(prefix: string, name: string) {
|
|
7
|
+
return `${prefix} ${name}`
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type Context = {
|
|
11
|
+
greetingPrefix: string
|
|
12
|
+
person: string
|
|
13
|
+
greeting: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
Feature({
|
|
17
|
+
featureText: `
|
|
18
|
+
Feature: Greeting
|
|
19
|
+
Scenario: Greeting a person
|
|
20
|
+
Given the person "Herman"
|
|
21
|
+
When greeting the person
|
|
22
|
+
Then the greeting is "Hello Herman"`,
|
|
23
|
+
hooks: [
|
|
24
|
+
Before((context: Context) => {
|
|
25
|
+
context.greetingPrefix = 'Hello'
|
|
26
|
+
}),
|
|
27
|
+
After((context: Context) => {
|
|
28
|
+
expect(context.greeting).toBe('Hello Herman')
|
|
29
|
+
}),
|
|
30
|
+
],
|
|
31
|
+
stepDefinitions: [
|
|
32
|
+
Given('the person {string}', (context: Context, person: string) => {
|
|
33
|
+
context.person = person
|
|
34
|
+
}),
|
|
35
|
+
When('greeting the person', (context: Context) => {
|
|
36
|
+
context.greeting = greet(context.greetingPrefix, context.person)
|
|
37
|
+
}),
|
|
38
|
+
Then('the greeting is {string}', (context: Context, greeting: string) => {
|
|
39
|
+
expect(context.greeting).toBe(greeting)
|
|
40
|
+
}),
|
|
41
|
+
],
|
|
42
|
+
})
|
package/package.json
CHANGED
package/src/compile-feature.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
} from '@cucumber/cucumber-expressions'
|
|
6
6
|
import * as Gherkin from '@cucumber/gherkin'
|
|
7
7
|
import * as Messages from '@cucumber/messages'
|
|
8
|
+
import type {Hook} from './hooks'
|
|
8
9
|
import type {StepDefinition} from './step-definitions'
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -18,6 +19,8 @@ export type CompiledFeature<TStepContext extends Record<string, any> = object> =
|
|
|
18
19
|
name: string
|
|
19
20
|
tag?: 'only' | 'skip'
|
|
20
21
|
steps: Array<(stepContext?: TStepContext) => Promise<void> | void>
|
|
22
|
+
beforeHooks: Array<(stepContext?: TStepContext) => Promise<void> | void>
|
|
23
|
+
afterHooks: Array<(stepContext?: TStepContext) => Promise<void> | void>
|
|
21
24
|
}>
|
|
22
25
|
}
|
|
23
26
|
|
|
@@ -29,10 +32,12 @@ export function compileFeature<
|
|
|
29
32
|
TStepContext extends Record<string, any> = object,
|
|
30
33
|
>({
|
|
31
34
|
featureText,
|
|
35
|
+
hooks,
|
|
32
36
|
stepDefinitions,
|
|
33
37
|
parameterTypes,
|
|
34
38
|
}: {
|
|
35
39
|
featureText: string
|
|
40
|
+
hooks?: Array<Hook<TStepContext>>
|
|
36
41
|
stepDefinitions: Array<StepDefinition<TContext, any, any, any>>
|
|
37
42
|
parameterTypes?: Array<ParameterType<unknown>>
|
|
38
43
|
}): CompiledFeature<TStepContext> {
|
|
@@ -118,6 +123,16 @@ export function compileFeature<
|
|
|
118
123
|
}
|
|
119
124
|
|
|
120
125
|
const args = matchingStep.args.map((arg) => arg.getValue(matchingStep))
|
|
126
|
+
if (step.argument?.dataTable) {
|
|
127
|
+
args.push(
|
|
128
|
+
step.argument.dataTable.rows.map((row) =>
|
|
129
|
+
row.cells.map((cell) => cell.value),
|
|
130
|
+
),
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
if (step.argument?.docString) {
|
|
134
|
+
args.push(step.argument.docString.content)
|
|
135
|
+
}
|
|
121
136
|
|
|
122
137
|
return (stepContext: TStepContext | undefined) =>
|
|
123
138
|
matchingStep.callback(
|
|
@@ -138,6 +153,18 @@ export function compileFeature<
|
|
|
138
153
|
? ('only' as const)
|
|
139
154
|
: undefined,
|
|
140
155
|
steps,
|
|
156
|
+
beforeHooks: (hooks ?? [])
|
|
157
|
+
.filter((hook) => hook.type === 'Before')
|
|
158
|
+
.map(
|
|
159
|
+
(hook) => (stepContext: TStepContext | undefined) =>
|
|
160
|
+
hook.callback(Object.assign(context, stepContext)),
|
|
161
|
+
),
|
|
162
|
+
afterHooks: (hooks ?? [])
|
|
163
|
+
.filter((hook) => hook.type === 'After')
|
|
164
|
+
.map(
|
|
165
|
+
(hook) => (stepContext: TStepContext | undefined) =>
|
|
166
|
+
hook.callback(Object.assign(context, stepContext)),
|
|
167
|
+
),
|
|
141
168
|
}
|
|
142
169
|
})
|
|
143
170
|
|
package/src/hooks.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @public
|
|
3
|
+
*/
|
|
4
|
+
export type Hook<TContext extends Record<string, any> = object> = {
|
|
5
|
+
type: 'Before' | 'After'
|
|
6
|
+
callback: HookCallback<TContext>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export type HookCallback<TContext extends Record<string, any> = object> = (
|
|
13
|
+
context: TContext,
|
|
14
|
+
) => Promise<void> | void
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
export function Before<TContext extends Record<string, any> = object>(
|
|
20
|
+
callback: HookCallback<TContext>,
|
|
21
|
+
): Hook<TContext> {
|
|
22
|
+
return {type: 'Before', callback}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export function After<TContext extends Record<string, any> = object>(
|
|
29
|
+
callback: HookCallback<TContext>,
|
|
30
|
+
): Hook<TContext> {
|
|
31
|
+
return {type: 'After', callback}
|
|
32
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {ParameterType} from '@cucumber/cucumber-expressions'
|
|
2
|
-
import {describe, test} from '@jest/globals'
|
|
2
|
+
import {afterEach, beforeEach, describe, test} from '@jest/globals'
|
|
3
3
|
import {compileFeature} from '../compile-feature'
|
|
4
|
+
import type {Hook} from '../hooks'
|
|
4
5
|
import type {StepDefinition} from '../step-definitions'
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -8,15 +9,18 @@ import type {StepDefinition} from '../step-definitions'
|
|
|
8
9
|
*/
|
|
9
10
|
export function Feature<TContext extends Record<string, any> = object>({
|
|
10
11
|
featureText,
|
|
12
|
+
hooks,
|
|
11
13
|
stepDefinitions,
|
|
12
14
|
parameterTypes,
|
|
13
15
|
}: {
|
|
14
16
|
featureText: string
|
|
17
|
+
hooks: Array<Hook<TContext>>
|
|
15
18
|
stepDefinitions: Array<StepDefinition<TContext, any, any, any>>
|
|
16
19
|
parameterTypes?: Array<ParameterType<unknown>>
|
|
17
20
|
}) {
|
|
18
21
|
const feature = compileFeature({
|
|
19
22
|
featureText,
|
|
23
|
+
hooks,
|
|
20
24
|
stepDefinitions,
|
|
21
25
|
parameterTypes,
|
|
22
26
|
})
|
|
@@ -30,6 +34,13 @@ export function Feature<TContext extends Record<string, any> = object>({
|
|
|
30
34
|
|
|
31
35
|
describeFn(feature.name, () => {
|
|
32
36
|
for (const scenario of feature.scenarios) {
|
|
37
|
+
for (const before of scenario.beforeHooks) {
|
|
38
|
+
beforeEach(before)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const after of scenario.afterHooks) {
|
|
42
|
+
afterEach(after)
|
|
43
|
+
}
|
|
33
44
|
const testFn =
|
|
34
45
|
scenario.tag === 'only'
|
|
35
46
|
? test.only
|
|
@@ -38,6 +49,9 @@ export function Feature<TContext extends Record<string, any> = object>({
|
|
|
38
49
|
: test
|
|
39
50
|
|
|
40
51
|
testFn(scenario.name, async () => {
|
|
52
|
+
for (const before of scenario.beforeHooks) {
|
|
53
|
+
await before()
|
|
54
|
+
}
|
|
41
55
|
for (const step of scenario.steps) {
|
|
42
56
|
await step()
|
|
43
57
|
}
|
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
import type {ParameterType} from '@cucumber/cucumber-expressions'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
test,
|
|
4
|
+
type PlaywrightTestArgs,
|
|
5
|
+
type PlaywrightTestOptions,
|
|
6
|
+
type PlaywrightWorkerArgs,
|
|
7
|
+
type PlaywrightWorkerOptions,
|
|
8
|
+
} from '@playwright/test'
|
|
3
9
|
import {compileFeature} from '../compile-feature'
|
|
10
|
+
import type {Hook} from '../hooks'
|
|
4
11
|
import type {StepDefinition} from '../step-definitions'
|
|
5
12
|
|
|
13
|
+
type PlaywrightOptions = PlaywrightTestArgs &
|
|
14
|
+
PlaywrightTestOptions &
|
|
15
|
+
PlaywrightWorkerArgs &
|
|
16
|
+
PlaywrightWorkerOptions
|
|
17
|
+
|
|
6
18
|
/**
|
|
7
19
|
* @public
|
|
8
20
|
*/
|
|
9
|
-
export type PlaywrightContext = {
|
|
10
|
-
playwright:
|
|
11
|
-
page: Page
|
|
12
|
-
context: BrowserContext
|
|
13
|
-
}
|
|
21
|
+
export type PlaywrightContext = Record<'string', any> & {
|
|
22
|
+
playwright: PlaywrightOptions
|
|
14
23
|
}
|
|
15
24
|
|
|
16
25
|
/**
|
|
@@ -20,15 +29,18 @@ export function Feature<
|
|
|
20
29
|
TContext extends PlaywrightContext = PlaywrightContext,
|
|
21
30
|
>({
|
|
22
31
|
featureText,
|
|
32
|
+
hooks,
|
|
23
33
|
stepDefinitions,
|
|
24
34
|
parameterTypes,
|
|
25
35
|
}: {
|
|
26
36
|
featureText: string
|
|
37
|
+
hooks: Array<Hook<TContext>>
|
|
27
38
|
stepDefinitions: Array<StepDefinition<TContext, any, any, any>>
|
|
28
39
|
parameterTypes?: Array<ParameterType<unknown>>
|
|
29
40
|
}) {
|
|
30
41
|
const feature = compileFeature({
|
|
31
42
|
featureText,
|
|
43
|
+
hooks,
|
|
32
44
|
stepDefinitions,
|
|
33
45
|
parameterTypes,
|
|
34
46
|
})
|
|
@@ -42,6 +54,22 @@ export function Feature<
|
|
|
42
54
|
|
|
43
55
|
describeFn(feature.name, () => {
|
|
44
56
|
for (const scenario of feature.scenarios) {
|
|
57
|
+
for (const before of scenario.beforeHooks) {
|
|
58
|
+
test.beforeEach(async (playwrightOptions) => {
|
|
59
|
+
await before({
|
|
60
|
+
playwright: playwrightOptions,
|
|
61
|
+
} as TContext)
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
for (const after of scenario.afterHooks) {
|
|
66
|
+
test.afterEach(async (playwrightOptions) => {
|
|
67
|
+
await after({
|
|
68
|
+
playwright: playwrightOptions,
|
|
69
|
+
} as TContext)
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
|
|
45
73
|
const testFn =
|
|
46
74
|
scenario.tag === 'only'
|
|
47
75
|
? test.only
|
|
@@ -49,14 +77,11 @@ export function Feature<
|
|
|
49
77
|
? test.skip
|
|
50
78
|
: test
|
|
51
79
|
|
|
52
|
-
testFn(scenario.name, async (
|
|
80
|
+
testFn(scenario.name, async (playwrightOptions) => {
|
|
53
81
|
for (const step of scenario.steps) {
|
|
54
82
|
await step({
|
|
55
|
-
playwright:
|
|
56
|
-
|
|
57
|
-
context,
|
|
58
|
-
},
|
|
59
|
-
})
|
|
83
|
+
playwright: playwrightOptions,
|
|
84
|
+
} as TContext)
|
|
60
85
|
}
|
|
61
86
|
})
|
|
62
87
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {ParameterType} from '@cucumber/cucumber-expressions'
|
|
2
|
-
import {describe, test} from 'vitest'
|
|
2
|
+
import {afterEach, beforeEach, describe, test} from 'vitest'
|
|
3
3
|
import {compileFeature} from '../compile-feature'
|
|
4
|
+
import type {Hook} from '../hooks'
|
|
4
5
|
import type {StepDefinition} from '../step-definitions'
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -8,15 +9,18 @@ import type {StepDefinition} from '../step-definitions'
|
|
|
8
9
|
*/
|
|
9
10
|
export function Feature<TContext extends Record<string, any> = object>({
|
|
10
11
|
featureText,
|
|
12
|
+
hooks,
|
|
11
13
|
stepDefinitions,
|
|
12
14
|
parameterTypes,
|
|
13
15
|
}: {
|
|
14
16
|
featureText: string
|
|
17
|
+
hooks?: Array<Hook<TContext>>
|
|
15
18
|
stepDefinitions: Array<StepDefinition<TContext, any, any, any>>
|
|
16
19
|
parameterTypes?: Array<ParameterType<unknown>>
|
|
17
20
|
}) {
|
|
18
21
|
const feature = compileFeature({
|
|
19
22
|
featureText,
|
|
23
|
+
hooks,
|
|
20
24
|
stepDefinitions,
|
|
21
25
|
parameterTypes,
|
|
22
26
|
})
|
|
@@ -30,6 +34,14 @@ export function Feature<TContext extends Record<string, any> = object>({
|
|
|
30
34
|
|
|
31
35
|
describeFn(feature.name, () => {
|
|
32
36
|
for (const scenario of feature.scenarios) {
|
|
37
|
+
for (const before of scenario.beforeHooks) {
|
|
38
|
+
beforeEach(before)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const after of scenario.afterHooks) {
|
|
42
|
+
afterEach(after)
|
|
43
|
+
}
|
|
44
|
+
|
|
33
45
|
const testFn =
|
|
34
46
|
scenario.tag === 'only'
|
|
35
47
|
? test.only
|