racejar 1.0.2 → 1.1.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 +15 -0
- package/README.md +3 -3
- package/example/hello-herman.test.ts +3 -3
- package/example-playwright/playwright-homepage.test.ts +35 -0
- package/package.json +7 -1
- package/src/compile-feature.ts +22 -17
- package/src/playwright/index.ts +1 -0
- package/src/playwright/playwright-gherkin-driver.ts +64 -0
- package/src/step-definitions.ts +15 -18
- package/vitest.workspace.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.1.0](https://github.com/portabletext/editor/compare/racejar-v1.0.3...racejar-v1.1.0) (2024-12-02)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **`compileFeature`:** allow passing context to each `step` ([05d6a23](https://github.com/portabletext/editor/commit/05d6a233d18eada7a46ff52520155f22d58f6ae4))
|
|
9
|
+
* add initial version of `racejar/playwright` ([2cac384](https://github.com/portabletext/editor/commit/2cac3846db0f01a157c00d55b0b7ba802278fe0a))
|
|
10
|
+
|
|
11
|
+
## [1.0.3](https://github.com/portabletext/editor/compare/racejar-v1.0.2...racejar-v1.0.3) (2024-12-01)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* fix type error when defining inline steps without using generics ([d371044](https://github.com/portabletext/editor/commit/d371044dae46e87188bfc52cbadd8708748bb0ce))
|
|
17
|
+
|
|
3
18
|
## [1.0.2](https://github.com/portabletext/editor/compare/racejar-v1.0.1...racejar-v1.0.2) (2024-11-29)
|
|
4
19
|
|
|
5
20
|
|
package/README.md
CHANGED
|
@@ -130,13 +130,13 @@ Feature({
|
|
|
130
130
|
When greeting the person
|
|
131
131
|
Then the greeting is "Hello, Herman!"`,
|
|
132
132
|
stepDefinitions: [
|
|
133
|
-
Given
|
|
133
|
+
Given('the person {string}', (context: Context, person: string) => {
|
|
134
134
|
context.person = person
|
|
135
135
|
}),
|
|
136
|
-
When
|
|
136
|
+
When('greeting the person', (context: Context) => {
|
|
137
137
|
context.greeting = greet(context.person)
|
|
138
138
|
}),
|
|
139
|
-
Then
|
|
139
|
+
Then('the greeting is {string}', (context: Context, greeting: string) => {
|
|
140
140
|
expect(context.greeting).toBe(greeting)
|
|
141
141
|
}),
|
|
142
142
|
],
|
|
@@ -19,13 +19,13 @@ Feature({
|
|
|
19
19
|
When greeting the person
|
|
20
20
|
Then the greeting is "Hello, Herman!"`,
|
|
21
21
|
stepDefinitions: [
|
|
22
|
-
Given
|
|
22
|
+
Given('the person {string}', (context: Context, person: string) => {
|
|
23
23
|
context.person = person
|
|
24
24
|
}),
|
|
25
|
-
When
|
|
25
|
+
When('greeting the person', (context: Context) => {
|
|
26
26
|
context.greeting = greet(context.person)
|
|
27
27
|
}),
|
|
28
|
-
Then
|
|
28
|
+
Then('the greeting is {string}', (context: Context, greeting: string) => {
|
|
29
29
|
expect(context.greeting).toBe(greeting)
|
|
30
30
|
}),
|
|
31
31
|
],
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {expect} from '@playwright/test'
|
|
2
|
+
import {Feature, type PlaywrightContext} from '../src/playwright'
|
|
3
|
+
import {Given, Then, When} from '../src/step-definitions'
|
|
4
|
+
|
|
5
|
+
type Context = PlaywrightContext
|
|
6
|
+
|
|
7
|
+
Feature({
|
|
8
|
+
featureText: `
|
|
9
|
+
Feature: Playwright Homepage
|
|
10
|
+
Scenario: Navigating to Get Started
|
|
11
|
+
Given the homepage
|
|
12
|
+
When clicking the "Get started" link
|
|
13
|
+
Then the heading is "Installation"`,
|
|
14
|
+
stepDefinitions: [
|
|
15
|
+
Given('the homepage', async (context: Context) => {
|
|
16
|
+
await context.playwright.page.goto('https://playwright.dev/')
|
|
17
|
+
}),
|
|
18
|
+
When(
|
|
19
|
+
'clicking the {string} link',
|
|
20
|
+
async (context: Context, linkName: string) => {
|
|
21
|
+
await context.playwright.page
|
|
22
|
+
.getByRole('link', {name: linkName})
|
|
23
|
+
.click()
|
|
24
|
+
},
|
|
25
|
+
),
|
|
26
|
+
Then(
|
|
27
|
+
'the heading is {string}',
|
|
28
|
+
async (context: Context, heading: string) => {
|
|
29
|
+
await expect(
|
|
30
|
+
context.playwright.page.getByRole('heading', {name: heading}),
|
|
31
|
+
).toBeVisible()
|
|
32
|
+
},
|
|
33
|
+
),
|
|
34
|
+
],
|
|
35
|
+
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "racejar",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A testing framework agnostic Gherkin driver",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cucumber",
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"default": "./src/jest/index.ts",
|
|
31
31
|
"types": "./src/jest/index.ts"
|
|
32
32
|
},
|
|
33
|
+
"./playwright": {
|
|
34
|
+
"default": "./src/playwright/index.ts",
|
|
35
|
+
"types": "./src/playwright/index.ts"
|
|
36
|
+
},
|
|
33
37
|
"./vitest": {
|
|
34
38
|
"default": "./src/vitest/index.ts",
|
|
35
39
|
"types": "./src/vitest/index.ts"
|
|
@@ -40,12 +44,14 @@
|
|
|
40
44
|
"@cucumber/gherkin": "^30.0.4",
|
|
41
45
|
"@cucumber/messages": "^27.0.2",
|
|
42
46
|
"@jest/globals": "^29.7.0",
|
|
47
|
+
"@playwright/test": "^1.49.0",
|
|
43
48
|
"@sanity/pkg-utils": "^6.11.13",
|
|
44
49
|
"typescript": "5.7.2",
|
|
45
50
|
"vitest": "^2.1.5"
|
|
46
51
|
},
|
|
47
52
|
"peerDependencies": {
|
|
48
53
|
"@jest/globals": "^29.7.0",
|
|
54
|
+
"@playwright/test": "^1.49.0",
|
|
49
55
|
"vitest": "^2.1.5"
|
|
50
56
|
},
|
|
51
57
|
"scripts": {
|
package/src/compile-feature.ts
CHANGED
|
@@ -5,28 +5,29 @@ 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 {
|
|
9
|
-
StepDefinition,
|
|
10
|
-
StepDefinitionCallbackParameters,
|
|
11
|
-
} from './step-definitions'
|
|
8
|
+
import type {StepDefinition} from './step-definitions'
|
|
12
9
|
|
|
13
10
|
/**
|
|
14
11
|
* @public
|
|
15
12
|
*/
|
|
16
|
-
export type CompiledFeature =
|
|
17
|
-
|
|
18
|
-
tag?: 'only' | 'skip'
|
|
19
|
-
scenarios: Array<{
|
|
13
|
+
export type CompiledFeature<TStepContext extends Record<string, any> = object> =
|
|
14
|
+
{
|
|
20
15
|
name: string
|
|
21
16
|
tag?: 'only' | 'skip'
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
scenarios: Array<{
|
|
18
|
+
name: string
|
|
19
|
+
tag?: 'only' | 'skip'
|
|
20
|
+
steps: Array<(stepContext?: TStepContext) => Promise<void> | void>
|
|
21
|
+
}>
|
|
22
|
+
}
|
|
25
23
|
|
|
26
24
|
/**
|
|
27
25
|
* @public
|
|
28
26
|
*/
|
|
29
|
-
export function compileFeature<
|
|
27
|
+
export function compileFeature<
|
|
28
|
+
TContext extends Record<string, any> = object,
|
|
29
|
+
TStepContext extends Record<string, any> = object,
|
|
30
|
+
>({
|
|
30
31
|
featureText,
|
|
31
32
|
stepDefinitions,
|
|
32
33
|
parameterTypes,
|
|
@@ -34,7 +35,7 @@ export function compileFeature<TContext extends Record<string, any> = object>({
|
|
|
34
35
|
featureText: string
|
|
35
36
|
stepDefinitions: Array<StepDefinition<TContext, any, any, any>>
|
|
36
37
|
parameterTypes?: Array<ParameterType<unknown>>
|
|
37
|
-
}): CompiledFeature {
|
|
38
|
+
}): CompiledFeature<TStepContext> {
|
|
38
39
|
const uuidFn = Messages.IdGenerator.uuid()
|
|
39
40
|
const builder = new Gherkin.AstBuilder(uuidFn)
|
|
40
41
|
const matcher = new Gherkin.GherkinClassicTokenMatcher()
|
|
@@ -116,11 +117,15 @@ export function compileFeature<TContext extends Record<string, any> = object>({
|
|
|
116
117
|
throw new Error(`Multiple implementations found for step: ${step.text}`)
|
|
117
118
|
}
|
|
118
119
|
|
|
119
|
-
const args = matchingStep.args.map((arg) =>
|
|
120
|
-
arg.getValue(matchingStep),
|
|
121
|
-
) as StepDefinitionCallbackParameters<any, any, any>
|
|
120
|
+
const args = matchingStep.args.map((arg) => arg.getValue(matchingStep))
|
|
122
121
|
|
|
123
|
-
return (
|
|
122
|
+
return (stepContext: TStepContext | undefined) =>
|
|
123
|
+
matchingStep.callback(
|
|
124
|
+
Object.assign(context, stepContext),
|
|
125
|
+
args[0],
|
|
126
|
+
args[1],
|
|
127
|
+
args[2],
|
|
128
|
+
)
|
|
124
129
|
})
|
|
125
130
|
|
|
126
131
|
return {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './playwright-gherkin-driver'
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type {ParameterType} from '@cucumber/cucumber-expressions'
|
|
2
|
+
import {test, type BrowserContext, type Page} from '@playwright/test'
|
|
3
|
+
import {compileFeature} from '../compile-feature'
|
|
4
|
+
import type {StepDefinition} from '../step-definitions'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export type PlaywrightContext = {
|
|
10
|
+
playwright: {
|
|
11
|
+
page: Page
|
|
12
|
+
context: BrowserContext
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
export function Feature<
|
|
20
|
+
TContext extends PlaywrightContext = PlaywrightContext,
|
|
21
|
+
>({
|
|
22
|
+
featureText,
|
|
23
|
+
stepDefinitions,
|
|
24
|
+
parameterTypes,
|
|
25
|
+
}: {
|
|
26
|
+
featureText: string
|
|
27
|
+
stepDefinitions: Array<StepDefinition<TContext, any, any, any>>
|
|
28
|
+
parameterTypes?: Array<ParameterType<unknown>>
|
|
29
|
+
}) {
|
|
30
|
+
const feature = compileFeature({
|
|
31
|
+
featureText,
|
|
32
|
+
stepDefinitions,
|
|
33
|
+
parameterTypes,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const describeFn =
|
|
37
|
+
feature.tag === 'only'
|
|
38
|
+
? test.describe.only
|
|
39
|
+
: feature.tag === 'skip'
|
|
40
|
+
? test.describe.skip
|
|
41
|
+
: test.describe
|
|
42
|
+
|
|
43
|
+
describeFn(feature.name, async () => {
|
|
44
|
+
for (const scenario of feature.scenarios) {
|
|
45
|
+
const testFn =
|
|
46
|
+
scenario.tag === 'only'
|
|
47
|
+
? test.only
|
|
48
|
+
: scenario.tag === 'skip'
|
|
49
|
+
? test.skip
|
|
50
|
+
: test
|
|
51
|
+
|
|
52
|
+
testFn(scenario.name, async ({page, context}) => {
|
|
53
|
+
for (const step of scenario.steps) {
|
|
54
|
+
await step({
|
|
55
|
+
playwright: {
|
|
56
|
+
page,
|
|
57
|
+
context,
|
|
58
|
+
},
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
}
|
package/src/step-definitions.ts
CHANGED
|
@@ -1,30 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @public
|
|
3
3
|
*/
|
|
4
|
-
export type
|
|
4
|
+
export type StepDefinitionCallback<
|
|
5
|
+
TContext extends Record<string, any> = object,
|
|
5
6
|
TParamA = undefined,
|
|
6
7
|
TParamB = undefined,
|
|
7
8
|
TParamC = undefined,
|
|
8
9
|
> = TParamA extends undefined
|
|
9
|
-
?
|
|
10
|
+
? (context: TContext) => Promise<void> | void
|
|
10
11
|
: TParamB extends undefined
|
|
11
|
-
?
|
|
12
|
+
? (context: TContext, paramA: TParamA) => Promise<void> | void
|
|
12
13
|
: TParamC extends undefined
|
|
13
|
-
?
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
> = (
|
|
25
|
-
context: TContext,
|
|
26
|
-
...args: StepDefinitionCallbackParameters<TParamA, TParamB, TParamC>
|
|
27
|
-
) => Promise<void> | void
|
|
14
|
+
? (
|
|
15
|
+
context: TContext,
|
|
16
|
+
paramA: TParamA,
|
|
17
|
+
paramB: TParamB,
|
|
18
|
+
) => Promise<void> | void
|
|
19
|
+
: (
|
|
20
|
+
context: TContext,
|
|
21
|
+
paramA: TParamA,
|
|
22
|
+
paramB: TParamB,
|
|
23
|
+
paramC: TParamC,
|
|
24
|
+
) => Promise<void> | void
|
|
28
25
|
|
|
29
26
|
/**
|
|
30
27
|
* @public
|
package/vitest.workspace.ts
CHANGED