# Fused check-chains: extract → coerce type → transform → validate → save,
# all in one declarative `extract:` step (Gatling-style). Chains live happily
# next to the classic `type:`-tagged extractors — mix them freely.
#
# Each `chain:` is the variable name to save. Pick exactly one source
# (jmespath / jsonpath / regex / header / css / xpath / left+right boundary),
# then optionally `as:` a type, run a `transform:` pipeline, `check:` the value
# and fall back to a `default:`.
name: check-chains
description: JMESPath extraction and fused extract/coerce/transform/validate/save chains

defaults:
  http:
    base_url: https://shop.example.com

scenarios:
  catalog:
    executor: constant-vus
    vus: 3
    duration: 30s
    flow:
      - request:
          name: list inventory
          url: /inventory
          extract:
            # JMESPath filter + projection: cheapest item's name, uppercased.
            - chain: cheapest_name
              jmespath: "items | sort_by(@, &price)[0].name"
              as: string
              transform: [trim, uppercase]
              check:
                not_empty: true
                matches: "^[A-Z]+$"

            # JMESPath again, this time keeping the native numeric type, then
            # validating the price falls in a sane range before we save it.
            - chain: cheapest_price
              jmespath: "min(items[].price)"
              as: int
              check: { min: 1, max: 1000 }

            # A classic extractor in the same step — back-compat is preserved.
            - { type: jsonpath, name: item_count, expression: "$.count" }

      - request:
          name: fetch cheapest
          # Both the chain var and the classic var interpolate the same way.
          url: "/items/${cheapest_name}?max=${cheapest_price}&seen=${item_count}"
          checks:
            - { type: status, equals: 200 }

      - request:
          name: place order
          method: POST
          url: /orders
          body:
            json: { item: "${cheapest_name}" }
          extract:
            # Chain over the order response: normalise status to lowercase and
            # assert it is one of the states we expect, saving it for routing.
            - chain: order_status
              jsonpath: "$.status"
              transform: [lowercase]
              check:
                one_of: [pending, paid, shipped, delivered]
                # If the value is unexpected, fail the request but keep going.
                on_failure: continue
              default: pending

      - request:
          name: poll order status
          url: "/orders/status?state=${order_status}"
          checks:
            - { type: status, equals: 200 }

thresholds:
  http_req_failed: ["rate<0.01"]
  checks: ["rate>0.99"]
