Skip to the content.

For years i have been using Cucumber with Ruby, but i’ve recently changed job and now i am using Javascript/Typescript.

This is a reference for me on how to use the different data table formats with cucumber-js.



Typescript implementation

Imagine there is a createUser function that takes name, email, city and dob as parameters. I’m just going to console.log() the information so we can understand what’s happening, but in reality this would likely do something more interesting.

function createUser(name: string, email: string, city: string, dob: string) {
  console.log(`Creating ${name} (${email}) who lives in ${city} and was born ${dob}.`);
  // actual implementation not included
}



Option 1. Key-value pairs using .rowsHash()

This is a 2-column table format where the left is the key and the right is the value. I like to write the keys in uppercase for readability, but it’s not necessary.

This scenario will create 1 user.

  Scenario: Key-value pairs using .rowsHash()
    Given the following user exists
      | NAME  | Ganesh Raffaella |
      | EMAIL | gr@example.com   |
      | CITY  | Redlands         |
      | DOB   | 1965-03-30       |

This step can be implemented like this:

Given('the following user exists', function (dataTable) {
  const data = dataTable.rowsHash();
  createUser(data["NAME"], data["EMAIL"], data["CITY"], data["DOB"]);
});

Output:

  Scenario: Key-value pairs using .rowsHash()
    Given the following user exists
      │ NAME  │ Ganesh Raffaella │
      │ EMAIL │ gr@example.com   │
      │ CITY  │ Redlands         │
      │ DOB   │ 1965-03-30       │
Creating Ganesh Raffaella (gr@example.com) who lives in Redlands and was born 1965-03-30.



Option 2. Table with headings using .hashes()

This is a multi-row format where the first row is a heading. The step definition will need to loop through the rows.

This scenario will create 3 users.

  Scenario: Table with headings using .hashes()
    Given the following users exist
      | NAME              | EMAIL          | CITY      | DOB        |
      | Lauriane Mosciski | lm@example.com | Bismarck  | 1954-04-10 |
      | Valentin Schultz  | vs@example.com | Lynchburg | 1950-01-01 |
      | Shea Ziemann      | sz@example.com | Medford   | 1982-06-19 |

This step can be implemented like this:

Given('the following users exist', function (dataTable) {
  const data = dataTable.hashes();
  for (const row of data) {
    createUser(row["NAME"], row["EMAIL"], row["CITY"], row["DOB"]);
  }
});

Output:

  Scenario: Table with headings using .hashes()
    Given the following users exist
      │ NAME              │ EMAIL          │ CITY      │ DOB        │
      │ Lauriane Mosciski │ lm@example.com │ Bismarck  │ 1954-04-10 │
      │ Valentin Schultz  │ vs@example.com │ Lynchburg │ 1950-01-01 │
      │ Shea Ziemann      │ sz@example.com │ Medford   │ 1982-06-19 │
Creating Lauriane Mosciski (lm@example.com) who lives in Bismarck and was born 1954-04-10.
Creating Valentin Schultz (vs@example.com) who lives in Lynchburg and was born 1950-01-01.
Creating Shea Ziemann (sz@example.com) who lives in Medford and was born 1982-06-19.



Option 3. Table without headings using .raw()

You can also use a table without headings and access the raw data with indices. I don’t like this because it seems less clear, but I’m just documenting it as an option in case it’s useful for some reason.

This scenario will create 4 users.

  Scenario: Table without headings using .raw()
    Given the following users exist
      | Elza Kiehn    | ek@example.com | Garden Grove | 1927-10-11 |
      | Delores Kulas | dk@example.com | Euless       | 1948-11-23 |
      | Gerard Marks  | gm@example.com | Carlsbad     | 1942-07-03 |
      | Hilda White   | hw@example.com | Owensboro    | 1933-02-19 |

The step can be implemented like this:

Given('the following users exist', function (dataTable) {
  const data = dataTable.raw();
  for (const row of data) {
    createUser(row[0], row[1], row[2], row[3]);
  }
});

Output:

  Scenario: Table without headings using .raw()
    Given the following users exist
      │ Elza Kiehn    │ ek@example.com │ Garden Grove │ 1927-10-11 │
      │ Delores Kulas │ dk@example.com │ Euless       │ 1948-11-23 │
      │ Gerard Marks  │ gm@example.com │ Carlsbad     │ 1942-07-03 │
      │ Hilda White   │ hw@example.com │ Owensboro    │ 1933-02-19 │
Creating Elza Kiehn (ek@example.com) who lives in Garden Grove and was born 1927-10-11.
Creating Delores Kulas (dk@example.com) who lives in Euless and was born 1948-11-23.
Creating Gerard Marks (gm@example.com) who lives in Carlsbad and was born 1942-07-03.
Creating Hilda White (hw@example.com) who lives in Owensboro and was born 1933-02-19.



Bonus option: Scenario Outline

It’s also possible to use a Scenario Outline which is not a table step at all but sends example values using a table format.

In this example, the whole scenario will run for each row in the examples table.

This will create 2 users.

  Scenario Outline: Create <NAME>
    Given a user called "<NAME>"  with email address "<EMAIL>" who lives in "<CITY>" and was born "<DOB>"

    Examples: 
      | NAME            | EMAIL          | CITY          | DOB        |
      | Vivienne Senger | vs@example.com | Everett       | 1965-11-09 |
      | Mallory Wisoky  | mw@example.com | Boynton Beach | 1927-12-09 |

The step can be implemented like this:

Given('a user called {string}  with email address {string} who lives in {string} and was born {string}', function (name, email, city, dob) {
  createUser(name, email, city, dob);
});

Output:

  Scenario Outline: Create Vivienne Senger
    Given a user called "Vivienne Senger"  with email address "vs@example.com" who lives in "Everett" and was born "1965-11-09"
Creating Vivienne Senger (vs@example.com) who lives in Everett and was born 1965-11-09.

  Scenario Outline: Create Mallory Wisoky
    Given a user called "Mallory Wisoky"  with email address "mw@example.com" who lives in "Boynton Beach" and was born "1927-12-09"
Creating Mallory Wisoky (mw@example.com) who lives in Boynton Beach and was born 1927-12-09.



Any questions? Find me on Mastodon: @aimeerivers@queer.party