Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugin support #2078

Closed
davidjgoss opened this issue Jul 1, 2022 · 6 comments
Closed

plugin support #2078

davidjgoss opened this issue Jul 1, 2022 · 6 comments
Assignees
Labels
⚡ enhancement Request for new functionality

Comments

@davidjgoss
Copy link
Contributor

davidjgoss commented Jul 1, 2022

🤔 What's the problem you're trying to solve?

If you want to augment the core functionality of Cucumber - for something that's not a formatter - you have two choices:

  1. Push it into the core (i.e. what has been done for publishing to the reports service)
  2. Wrap Cucumber, influencing its inputs and acting on its outputs (i.e. what has been started for TCP-based ordering)

Neither of these options are great for the average user with a good idea, and both of these specific use cases would be better served by an official plugin mechanism so you can hook into Cucumber's test run lifecycle, change things, and react to things.

✨ What's your proposed solution?

TBA!

At a basic level we need two things:

A way to write a plugin

The bare minimum might be something like:

export default {
  async init() {}
  onMessage(envelope) {}
}

We'll also likely need:

  • A way to provide configuration for/to the plugin
  • A way for the plugin to output to stderr (e.g. the publish banner)
  • "Lifecycle hooks" so plugins can provide a function which can influence core logic - so for the TCP case something like async inferOrder(pickles: Pickle[]): Promise<Pickle[]>

A way to reference a plugin

Something like:

npx cucumber-js --plugin @cucumber/publish

I think a good start would be to create some plumbing for plugins internally, and reimplement the publish functionality in terms of that. I'm happy to give that a go.

@davidjgoss davidjgoss added the ⚡ enhancement Request for new functionality label Jul 1, 2022
@davidjgoss davidjgoss self-assigned this Jul 1, 2022
@davidjgoss
Copy link
Contributor Author

cc @aslakhellesoy @mattwynne

@aurelien-reeves
Copy link
Contributor

I like the idea, and I agree with your analysis and choices 👌

@mattwynne
Copy link
Member

mattwynne commented Jul 12, 2022

I think an approach where we try to identify and refactor existing/internal code towards using an API boundary that we could stabilise and make public sounds great. Happy to pair with you on this @davidjgoss if you want to bounce some ideas around.

Not necessarily solving the same problem but worth adding for context:

When @tooky and I re-wrote the guts of cucumber-ruby, we ended up with a "plugin" mechanism based on the chain-of-responsibility design pattern. Express's request handlers are another example of the same pattern. Each plugin (or "filter" as we called them) receives the stream of test cases (like a pickle, but with extra info about how to invoke it) and is given a receiver (the next filter in the chain) to whom it should pass on whichever test cases it chooses. It can filter out test cases by choosing not to pass them on, and it can also enrich or otherwise mutate test cases before passing them on.

A lot of code fell into place when we adopted this model, allowing us to assemble most of Cucumber's behavour from lots of small pieces, e.g:

I'm not sure if you already have something like this inside cucumber-js, but it might be worth thinking about as part of this. I'm pretty sure it would provide what the TCP extension needs, for example.

@mattwynne
Copy link
Member

https://github.com/cucumber/cucumber-electron is another piece worth considering in all this, currently implemented as a wrapper but we agreed (in theory) that it should really be part of this codebase.

@mattwynne
Copy link
Member

mattwynne commented Jul 13, 2022

@charlierudolph
Copy link
Member

Formatters could also be a special form of a plugin. Maybe have someway for the plugin to declare its a formatter and thus to get passed a function to log (which will be either a file stream or stdout)

In general, like the idea. Very curious what exactly will be the scope of what get supported

@cucumber cucumber locked and limited conversation to collaborators Jul 23, 2022
@davidjgoss davidjgoss converted this issue into discussion #2091 Jul 23, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
⚡ enhancement Request for new functionality
Projects
None yet
Development

No branches or pull requests

4 participants