Skip to content

Conversation

mpkorstanje
Copy link
Contributor

@mpkorstanje mpkorstanje commented Oct 10, 2025

🤔 What's changed?

Initial implementation of the message based usage formatter

⚡️ What's your motivation?

Extract a usage formatter with a common test set based on cucumber messages.

🏷️ What kind of change is this?

  • ⚡ New feature (non-breaking change which adds new behaviour)

♻️ Anything particular you want feedback on?

Feature wise this implementation tries to strike a balance between the cucumber-js and cucumber-ruby and cucumber-jvm implementations.

Because the rendering is quite different for each implementation, I suspect it might be nessesary to support multiple formats. To make that possible there is a separation between creating the usage report and serializing it. I would expect all implementations to at least test the json serialization. The other formats are optional.

Is that workable?

📋 Checklist:

  • I agree to respect and uphold the Cucumber Community Code of Conduct
  • I've changed the behaviour of the code
    • I have added/updated tests to cover my changes.
  • My change requires a change to the documentation.
    • I have updated the documentation accordingly.
  • Users should know about my change
    • I have added an entry to the "Unreleased" section of the CHANGELOG, linking to this pull request.

@mpkorstanje mpkorstanje force-pushed the initial-implementation branch from 5dbdef0 to 69940b9 Compare October 10, 2025 21:22
@mpkorstanje mpkorstanje marked this pull request as ready for review October 10, 2025 23:06
@davidjgoss
Copy link

This looks great. But the structure is missing a bit of fidelity that would be required to map to cucumber-js usage-json formatter. Here's a sample:

[
  {
    "code": "async function (args, envString) {\n    const renderedArgs = mustache_1.default.render((0, value_checker_1.valueOrDefault)(args, ''), this);\n    const stringArgs = (0, string_argv_1.default)(renderedArgs);\n    const env = this.parseEnvString(envString);\n    return await this.run(this.localExecutablePath, stringArgs, env);\n}",
    "line": 32,
    "pattern": "I run cucumber-js with arguments `{}` and env `{}`",
    "patternType": "CucumberExpression",
    "uri": "features/step_definitions/cli_steps.ts",
    "meanDuration": {
      "seconds": 0,
      "nanos": 894491702
    },
    "matches": [
      {
        "line": 40,
        "text": "I run cucumber-js with arguments `` and env `CUCUMBER_PUBLISH_ENABLED=1`",
        "uri": "features/publish.feature",
        "duration": {
          "seconds": 1,
          "nanos": 869399124
        }
      }
    ]
  }
]

Things of note:

  • code we can live without, it's won't be added to messages anyway
  • uri and line are separate fields - should the standard one use a location object, maybe borrow the shape from messages?
  • patternType is there to distinguish between regexp and cucumber expressions - again maybe we should be using the expression object from messages
  • seconds and nanos for a duration - you see the pattern here

@mpkorstanje
Copy link
Contributor Author

mpkorstanje commented Oct 13, 2025

cucumber-js usage-json formatter.

I didn't know that existsed. I'll reuse messages.

@mpkorstanje
Copy link
Contributor Author

@davidjgoss

  • renamed steps to matches. Though not 100% accurate since this doesn't include ambiguous steps.
  • used location object from messages
  • used source reference from messages
  • used step definition pattern from messages
  • intentionally did not reuse source reference for the steps. Though it is a shame we didn't give Pickles a source reference.

This looks pretty decent to me.

{
  "stepDefinitions": [
    {
      "sourceReference": {
        "uri": "samples/multiple-features/multiple-features.ts",
        "location": {
          "line": 3
        }
      },
      "duration": {
        "sum": {
          "seconds": 0,
          "nanos": 9000000
        },
        "mean": {
          "seconds": 0,
          "nanos": 1000000
        },
        "moe95": {
          "seconds": 0,
          "nanos": 0
        }
      },
      "expression": {
        "source": "an order for {string}",
        "type": "CUCUMBER_EXPRESSION"
      },
      "matches": [
        {
          "text": "an order for \"eggs\"",
          "duration": {
            "seconds": 0,
            "nanos": 1000000
          },
          "uri": "samples/multiple-features/multiple-features-1.feature",
          "location": {
            "line": 3,
            "column": 3
          }
        },
...

@mpkorstanje mpkorstanje merged commit e6a0a84 into main Oct 15, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants