Skip to content

Step expressions

Since 3.5.0 vitest-cucumber provides step expressions inspired by cucumber-expression.

Example:

Feature: Background run before scenario tests
Scenario: scenario with expression
    Given I use "Vue" 3.2
    Then  I can't use Vue 2
    And   I use typescript for $2
    And   I can't use React, Angular, Solid

In unit tests, values are passed after test context ctx:

describeFeature(feature, (f) => {
    f.Scenario(`scenario with expression`, (s) => {
        s.Given(`I use {string} {number}`, (ctx: TaskContext, framework: string, version: number) => {
            expect(framework).toEqual(`Vue`)
            expect(version).toEqual(3.2)
        })
        s.Then(`I can't use Vue {number}`, (ctx: TaskContext, version: number) => {
            expect(version).toEqual(2)
        })
        s.And(`I use typescript for {number}`, (ctx: TaskContext, num: number) => {
            expect(num).toEqual(2)
        })
        s.And(`I can't use {list}`, (ctx : TaskContext, list: string[]) => {
            expect(list.length).toEqual(3)
            expect(list).toContain(`Angular`)
            expect(list).toContain(`React`)
            expect(list).toContain(`Solid`)
        })
    })
})

Match string between quotes or double quotes

Given I use "vitest-cucumber"
Given('I use {string}', (ctx : lib : string) => {
    expect(string).toBe('vitest-cucumber')
})

Match number with or without ,

Given I use Vue 3.2 with Astro 4
Given('Given I use Vue {number} with Astro {number}', (ctx : vue: number, astro: number) => {
    expect(vue).toBe(3.2)
    expect(astro).toBe(4)
})

Removed since v4.0.0.

Can be replaced with {number}.

Match text and split it to array with a separator.

Given I love Vue, Astro, Typescript
Given('I love {list}', (ctx : list: string[]) => {
    expect(list).toEqual([
        "Vue", "Astro", "Typescript"
    ])
})

You can use a custom separator like ; : {list:";"}.

Given I read id;name;city in CSV file
And   I see snake_case
Given('I read {list:";"} in CSV file', (ctx : list: string[]) => {
    expect(list).toEqual([
        "id", "name", "city"
    ])
})
And("I see {list:'_'}", (ctx, list : string[]) => {
    expect(list).toEqual([
        "snake", "case"
    ])
})

Match text according supported formats and return a Date.

Given It's 10/25/24
Given("It's {date}", (ctx : d: Date) => {
    expect(d.getMonth()).toEqual(9)
})

Supported formats :

  • MM/DD/YYYY
  • YYYY-MM-DD
  • YYYY-MM-DD
  • MM/DD/YYYY HH:MM:SS

Match any character in step title.

Given I Vue with nanostores
Given('I Vu{char} with n{char}nostores', (ctx : first: string, last: string) => {
    expect(first).toBe('e')
    expect(last).toBe('a')
})

Match text and return number only for integer. Use {number} for float.

Given I use Vue 3
And   I use Storybook 8.2
Given("I use Vue {int}", (ctx : version: number) => {
    expect(version).toBe(3)
})
// And will failed
And("I use Storybook {int}", () => {})

Match word in step title.

Given I Vue with nanostores
Given('I {word} with {word}', (ctx : first: string, last: string) => {
    expect(first).toBe('Vue')
    expect(last).toBe('nanostores')
})

Match anything section in step title.

Given I Vue with nanostores
Given('I Vue {any}', (ctx : result: string) => {
    expect(result).toBe('with nanostores')
})

Since 6.4.0, vitest-cucumber also supports generic steps via Step(...) in defineSteps. A generic step matches any step keyword (Given, When, Then, And, But) when the step details or expression pattern are the same.

See Generic steps for details and an example.

Match any email.

Given I send mail to john@smith.com
Given('I send mail to {email}', (ctx : mail: string) => {
    expect(mail).toBe('john@smith.com')
})

Match text and check if it equals true

Given I can code with one hand is true
And   I can code on paper is false
Given('I can code with one hand is {boolean}', (ctx : result: boolean) => {
    expect(result).toBe(true)
})
And('I can code on {boolean} is {boolean}', (ctx : first: boolean, last: boolean) => {
    expect(first).toBe(false)
    expect(last).toBe(false)
})

Match url and return a string. Protocol like https:// is required.

Given I read doc on http://github.com
And   I launch redis://localhost
Given('I read doc on {url}', (ctx : url: string) => {
    expect(url).toEqual('http://github.com')
})
And('I launch {url}', (ctx : url: string) => {
    expect(url).toBe('redis://localhost')
})

Match currency with built-in symbols and parsecurrency.

Given I have $200 in the bank
And   This item costs $2.5 or 3€
Given('I have {currency} in the bank', (ctx : currency: Currency) => {
    expect(currency).toEqual({
        currency: 'USD',
        raw: '$200',
        value: 200,
    })
})
And("This item costs {currency} or {currency}", (ctx, first: Currency, second: Currency) => {
    expect(first).toEqual({
        currency: 'USD',
        raw: '$2.5',
        value: 2.5,
    })
    expect(last).toEqual({
        currency: 'EUR',
        raw: '3€',
        value: 3,
    })
})

vitest-cucumber provides defineParameterExpression to define your own expression.

Example :

// vitest.setup.ts
type Color = 'red' | 'blue' | 'yellow'

defineParameterExpression({
    name: 'color',
    regexp: /red|blue|yellow/,
    transformer: (s) => s as Color,
})
Given My favorite color is red
Given("My favorite color is {color}", (ctx, color : Color) => {
    expect(color).toBe('red')
})