Skip to content
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

Expression for an argument list #179

Open
mmiikkkkaa opened this issue Oct 28, 2022 · 4 comments
Open

Expression for an argument list #179

mmiikkkkaa opened this issue Oct 28, 2022 · 4 comments

Comments

@mmiikkkkaa
Copy link

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

In some cases it might be helpful to have a way of declaring several instances of one type as an expression, e.g.
Given the customer selects product(s) {product}+
which could match something like:

Given the customer selects product bike
Given the customer selects products bike, car
Given the customer selects products bike, car, skateboard

and for a better flow maybe also with a filler:

Given the customer selects products bike and car
Given the customer selects products bike, car or skateboard

What already works is something like this:

  val separators = arrayOf(",", ";", "and", "or")

  @ParameterType("^(?:(?:,|;|and|or)?\s?\w+)+$")
  fun products(product: String): List<Product> {
    return product.split(*separators)
      .map { it.trim() }
      .map { Product(it) }
  }

This has the disadvantage, that the regex (if specific things still should be checked) might get complex, since it also has to include all separators and the possibility of them being there or not. Also, the complete string (incl. separators) is highlighted in the feature files. Hence, having that as a feature of cucumber expressions would be nice, since it might make the used regex easier. And might also help with the highlighting in the feature files, since the separators could be displayed in another color.

✨ What's your proposed solution?

I could imagine two different ways. For both ways the definition of the parameter type might be kind of the same like it is now (define how the transformation is done for one single element), but it could define separators:

  @ParameterType(regex = "\\w+", separators=[",", ";", "and", "or"])
  fun product(product: String): List<Product> {
    return Product(it)
  }

Option one: a special notation for marking an expression as "vararg", e.g. {name}+

If the + is provided, the method signature must contain a collection type:

 @Given("the customer selects product(s) {product}+")
  fun givenCustomerSelectsProduct(product: List<Product>) { \* ... *\ }

Option two: no special expression syntax - instead it depends on the method signature if it is a single value or a collection of values is provided.

So both would be possible:

 @Given("the customer selects product(s) {product}")
  fun givenCustomerSelectsProduct(product: Product) { \* ... *\ }

and

 @Given("the customer selects product(s) {product}")
  fun givenCustomerSelectsProduct(product: List<Product>) { \* ... *\ }
@mpkorstanje mpkorstanje self-assigned this Oct 31, 2022
@mpkorstanje
Copy link
Contributor

It's on the agenda for consideration.

I'm curious how your example is supposed to work though. Currently @ParameterType("^(?:(?:,|;|and|or)?\s?\w+)+$") shouldn't work because the ^ and $ would match the start and end of line.

@mpkorstanje
Copy link
Contributor

mpkorstanje commented Oct 31, 2022

And the biggest obstacle is going to be getting the CSV parsing/language parsing done right. Imagine a separator that is also part of a product name:

Given the products Dumbo the Flying Elephant, "Spike and Suzy" and Lord of the Rings

Not to mention the Oxford comma, so now we combine two different separators with no products in between:

Given the products Dumbo the Flying Elephant, "Spike and Suzy", and Lord of the Rings 

And I have no idea how this works in other languages that aren't English. So it might not be possible to come up with a good solution.

@mmiikkkkaa
Copy link
Author

I'm curious how your example is supposed to work though. Currently @ParameterType("^(?:(?:,|;|and|or)?\s?\w+)+$") shouldn't work because the ^ and $ would match the start and end of line.

I tried it without ^ and $, I guess it was kind of an automatism of myself, to add it in my description here. So Please ignore it. 😅

Regarding the other concerns: they are of course tricky, but if it is up to the user to provide possible separators (so no default separators, but explicitly provided ones) and the test data, it might (at least in a first step) simply be the users responsibility to chose both wisely.

If only "," and ";" are provided as separators, neither the language nor the test data itself should be a problem. Also possible would be ignoring separators within quotes, like in your example. The Oxford comma might remain as a problem, as long as it is not also provided as a separator, like

@ParameterType(regex = "\\w+", separators=[",", ";", "and", "or", ", and", ", or"])
  fun product(product: String): List<Product> {
    return Product(it)
  }

@mattwynne
Copy link
Member

I'm curious why you want to put this list on a single line, rather than using a single-column DataTable beneath the step?

@mpkorstanje mpkorstanje removed their assignment May 13, 2023
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

No branches or pull requests

3 participants