Q14 of 40 · Karate

How do you handle dynamic dates and timestamps in Karate assertions?

KarateMidkaratedatestimestampsassertionsembedded-js

Short answer

Short answer: For format validation, use * match response.createdAt == '#string' or a regex: '#regex \\d{4}-\\d{2}-\\d{2}.*'. For value-relative checks (created today, expires in 30 days), compute the expected date with embedded JavaScript using Java's LocalDate, then assert equality against the computed value.

Detail

Server-generated timestamps can't be hard-coded in test assertions. Karate provides two approaches:

1. Type-only check (most common — don't care about the value):

* match response.createdAt == '#string'     # any string
* match response.createdAt == '#regex \d{4}-\d{2}-\d{2}.*'  # ISO date format
* match response.expiresAt == '#present'   # field exists

2. Value-relative check (care about the date value):

* def today = function() { return java.time.LocalDate.now().toString() }
* match response.createdAt contains today()

* def addDays =
  """
  function(n) {
    return java.time.LocalDate.now().plusDays(n).toString();
  }
  """
* match response.expiresAt contains addDays(30)

3. Extract and compare in JS:

* def created = response.createdAt
* def isRecent = function() {
    var then = new Date(created);
    var now  = new Date();
    return (now - then) < 5000; // within 5 seconds
  }
* assert isRecent()

The key principle: avoid asserting the exact timestamp value unless you genuinely need to verify the server stores the right time. Most tests only need format validation.

// EXAMPLE

timestamp-assertions.feature

Feature: Dynamic date assertions

  Scenario: Created order has timestamps in the last 5 seconds
    * url 'https://api.example.com'
    Given path '/orders'
    And   request { userId: 1, items: [{ sku: 'A1', qty: 1 }] }
    When  method POST
    Then  status 201

    # Format check — is it an ISO 8601 date string?
    * match response.createdAt == '#regex \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.*'

    # Value check — created today?
    * def today = java.time.LocalDate.now().toString()
    * match response.createdAt contains today

    # Expiry check — subscription expires in 30 days?
    * def expectedExpiry = java.time.LocalDate.now().plusDays(30).toString()
    * def order = call read('classpath:helpers/get-order.feature') { id: response.id }
    * match order.expiresOn == expectedExpiry

// WHAT INTERVIEWERS LOOK FOR

Using regex for format validation and Java's LocalDate/LocalDateTime via interop for relative date assertions. The principle of avoiding hard-coded timestamp values in tests is a maturity signal.

// COMMON PITFALL

Hard-coding an exact timestamp like '2025-01-15T10:00:00Z' — this works once, fails every other day. Use format validation or compute the expected value dynamically.