hurl icon indicating copy to clipboard operation
hurl copied to clipboard

Clarification of valid isDate values

Open humphd opened this issue 1 year ago • 6 comments

What is the current bug behavior?

error: Assert failure
  --> ds/src/test/integration/rag.hurl:21:0
   |
21 | jsonpath "$.created" isDate
   |   actual:   string <2024-02-11T14:35:47.592Z>
   |   expected: date
   |

Steps to reproduce

Using isDate with a string in the form "2024-02-11T14:35:47.592Z" fails the isDate assertion, which surprises me.

What is the expected correct behavior?

I feel like this should pass, or the docs need to properly reflect the expected format.

humphd avatar Feb 11 '24 14:02 humphd

Yes the doc is not clear enough (a never ending story)!

I've not tested the snippet but the way to test it is:

  • "$.created" : is a string
  • convert the string to a date using toDate filter: "$.created" toDate "%Y-%m-%dT%H:%M:%S%.f%:z". We're levering the chrono Rust crate format specification so, in that case, the filter can also be transformed to "$.created" toDate "%+"
  • now we have a date type so "$.created" toDate "%+" isDate should be OK

We've preferred that users explicitly transform string to date using a format to accommodate each possible use case. Can you test it ? If it's OK, I will label the issue with "documentation" and we'll make the doc clearer.

jcamiel avatar Feb 11 '24 15:02 jcamiel

There is also the format filter that transform a date to string. It can be used to exctract component of date, or test equality:

GET https://example.org
HTTP 200
[Asserts]
certificate "Subject" == "CN=example.org"
certificate "Issuer" == "C=US, O=Let's Encrypt, CN=R3"
certificate "Expire-Date" daysAfterNow > 15
certificate "Expire-Date" format "%Y-%m%d" == "2024-05-12"
certificate "Serial-Number" matches "[0-9af]+"

in that particular case certificate "Expire-Date"returns a date type so there is no need to use toDate.

jcamiel avatar Feb 11 '24 15:02 jcamiel

Doing jsonpath "$.created" toDate "%+" isDate worked, thank you for that--I wouldn't have figured this out! I agree, a docs fix might be good to let people know this is possible.

humphd avatar Feb 11 '24 16:02 humphd

The isDate predicate is not really useful, as it will suceed with an input Date value. We can add the isIsoDate predicate that will check that the input string is a valid YYYY-MM-DDTHH:mm:ss.sssZ Date. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString

jsonpath "$.created" isIsoDate

fabricereix avatar Feb 14 '24 09:02 fabricereix

Much better! Enhancement issue created => #2427

jcamiel avatar Feb 14 '24 09:02 jcamiel

I was reviewing a first PR on this topic and it raises some questions.

  1. has our isIsoDate check the same semantic as https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString? In the MDN, the format used is the date string format from ECMAScript.

The format can be:

  • YYYY-MM-DDTHH:mm:ss.sssZ (the format we usually found in JSON etc...)
  • date only forms: YYYY, YYYY-MM, YYYY-MM-DD
  • date-time forms: all date only forms with the following combination: THH:mm, THH:mm:ss, THH:mm:ss.sss

The date-time forms can have an optional timezone format (YYYYTHH:mmZ)

I think we must limit to the "full" format YYYY-MM-DDTHH:mm:ss.sssZ. For instance, for Hurl "2011-01-01" is not an ISO date, while it's a valid date using ECMAScript date string format.

  1. The name of the predicate isIsoDate vs isRfc3339Date?

Given the first point, I'm not really sure about the isIsoDate name. In chrono Rust crate, there is a method DateTime::parse_from_rfc3339 and maybe it will be more "correct" if we call our predicate isRfc3339Date

Extract from the chrono Rust crates:

Why isn’t this named parse_from_iso8601? That’s because ISO 8601 allows representing values in a wide range of formats, only some of which represent actual date-and-time instances (rather than periods, ranges, dates, or times). Some valid ISO 8601 values are also simultaneously valid RFC 3339 values, but not all RFC 3339 values are valid ISO 8601 values (or the other way around)

Any ideas on the 2 points?

jcamiel avatar Feb 20 '24 15:02 jcamiel

Hi @humphd we have implement the isIsoDate predicate in #2565: it takes a string as input an check the RFC3339 format : 'YYYY-MM-DDTHH:mm:ss.sssZ'

So now this assert should be OK (and certainly what's more obvious):

GET https://api.foo.com
HTTP 200
[Asserts]
jsonpath "$.created" isIsoDate

Just need to update the documentation. Maybe we'll deprecate isDate as it doesn't provide much value...

Thanks for the good feedbacks, as usual 😄 !

jcamiel avatar Mar 21 '24 19:03 jcamiel

Amazing! Thanks for fixing this so quickly, I think it's a good addition.

humphd avatar Mar 22 '24 14:03 humphd