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

Support default values when capturing variables or enable a way to dynamically generate boolean variables #3436

Open
1 task
lambrospetrou opened this issue Nov 23, 2024 · 4 comments
Labels
enhancement New feature or request

Comments

@lambrospetrou
Copy link

lambrospetrou commented Nov 23, 2024

Problem to solve

I am writing a test suite for an API, and I want to use the skip option to conditionally run some requests based on the response of a previous request.

The condition depends on the previous response containing a certain field with a specific value, e.g. $.result.id, or the response containing (or not) certain items.

However, if I use the following, it fails when the ID doesn't exist (e.g. indicates a failure of resource creation):

[Captures]
db_id: jsonpath "$.result.id"

Example error:

32 | db_id: jsonpath "$.result.uuid"
   |        ^^^^^^^^^^^^^^^^^^^^^^^^ The query didn't return any result

I cannot even proceed to the next step, which will conditionally create the resource if it doesn't exist. In other test suites, I might want to delete it if it already exists to get back to a clean state.

I tried using the filter syntax with recursive descent, which gives me back an empty array (e.g. db_id: jsonpath "$.result[?(@.uuid)]..uuid"). But this doesn't work either, since the empty array is not a valid type to be put into the skip option.

Proposal

Allow captures to provide a default value to variables if the specified filter results in a missing value. Or provide an option that will make the captures without valid value resolutions to not fail the script and just leave the variable with its previous value (so that I can preset it to a default).

In the end, what I need is a way to declare a variable with a boolean value that can be passed to skip, based on the response of a previous request.

Additional context and resources

Tasks to complete

  • ...
@lambrospetrou lambrospetrou added the enhancement New feature or request label Nov 23, 2024
@lambrospetrou
Copy link
Author

lambrospetrou commented Nov 24, 2024

Another option instead of allowing defaults in variable capturing is to allow predicates (e.g. db_exsts: jsonpath "$.result[?(@.name == 'some-name')].uuid" count > 1).

For example, storing the result of a predicate into a variable would allow me to set a variable to true/false so that I can use that later in the skip option.

Or, if none of the above options are wanted, the skip option should support query/filters/predicates and not just a raw boolean, otherwise it's not easy to use it flexibly since there is no way to generate a boolean value dynamically with the existing filters. Adding a toBoolean is another way but it will be messy and inflexible.

@lambrospetrou lambrospetrou changed the title Support default values when capturing variables Support default values when capturing variables or enable a way to dynamically generate boolean variables Nov 24, 2024
@jcamiel
Copy link
Collaborator

jcamiel commented Nov 24, 2024

Hi guys,

We had a very clear model with queries, captures and asserts:

  • a capture uses a query to get some data from response
  • an assert tests the result of a query against a predicate.

Now, I think we're going to a model where there are expressions everywhere. You can correct me @fabricereix if I'm mistaken but the model will be:

  • an expression returns a value
  • a capture captures the expression evaluation
  • an assert tests that an expression evaluation is true

We want to express "naturally" this kind of file:

GET https:// foo.com
[Options]
skip: {{ results isEmpty }}

Or

GET https:// foo.com
HTTP 200
[Captures]
foo: jsonpath "$.results" count >= 4

It seems natural so we want to support it. Default values can fit into the expression model, for instance (syntax TBD):

GET https:// foo.com
HTTP 200
[Captures]
foo: jsonpath "$.results" count or 4

We're going to make small steps towards this model, starting with the next version where we're introducing functions. We want to have a clean model and the code that's reflecting that so everything is maintainable and can be augmented.

@fabricereix maybe we can write all this in a spec doc, it's helped a lot for previous features and everybody can improve it if we miss some things/usecases.

@lambrospetrou
Copy link
Author

@jcamiel Love this end game! If we can get this flexibility, Hurl will be top-notch and will be able to model most of the common user journey flows.

Let me know if there is any way I can help, even if just for testing 😅

@fabricereix
Copy link
Collaborator

Yes!! it will be nice to rely only on expressions for everything.
We like our model with query/predicate, but it could even better without them!
Using just expressions to define captures and asserts.
Predicates replaced by filters that return a bool value, but also queries replaced by functions.

This more generic model will unlock many use cases.
Spec doc to gather many examples/use cases seems indeed a good idea.

Another uniformization, we might consider, is choosing only one syntax between the current query syntax or the placeholder one.

[Options]
skip: {{ results isEmpty }}

and

[Captures]
foo: jsonpath "$.results" count >= 4

If both of them have an expression after the ':', we might want to have exactly the same syntax.
I will tend to think that the 2nd one is more hurly.
We could still keep the placeholder {{...}} for template strings (such as the url)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants