# Flow control: repeat, while, if/else and weighted random branches —
# the control flow from Gatling (repeat/during/doIf/randomSwitch) and the
# weighted-task model from Locust, in declarative YAML.
name: flow-control
description: loops, conditionals and weighted branching in a single flow

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

js:
  script: |
    // Conditions below are evaluated in the VU's JS runtime.

scenarios:
  realistic_user:
    executor: ramping-vus
    start_vus: 0
    stages: [ { duration: 30s, target: 20 }, { duration: 2m, target: 20 } ]
    flow:
      # Browse a random number of product pages (1–5).
      - js: "session.vars.pages = 1 + Math.floor(Math.random() * 5)"
      - js: "session.vars.seen = 0"
      - while:
          condition: "Number(session.vars.seen) < Number(session.vars.pages)"
          max_iterations: 10
          steps:
            - request: { name: product, url: "/products/${js: 1 + Math.floor(Math.random()*100)}" }
            - think_time: { type: uniform, min: 1s, max: 3s }
            - js: "session.vars.seen = Number(session.vars.seen) + 1"

      # Weighted behaviour split (Locust @task weights / Gatling randomSwitch):
      # 70% just browse, 25% add to cart, 5% check out.
      - random:
          strategy: weighted
          choices:
            - weight: 70
              name: browse_only
              steps:
                - request: { name: search, url: "/search?q=widget" }
            - weight: 25
              name: add_to_cart
              steps:
                - request:
                    name: add to cart
                    method: POST
                    url: /cart
                    body: { json: { sku: "W-1" } }
                    checks: [ { type: status, equals: 201 } ]
            - weight: 5
              name: checkout
              steps:
                - request: { name: checkout, method: POST, url: /checkout }

      # Retry-ish: hit a flaky endpoint up to 3 times, stop once it succeeds.
      - repeat:
          times: 3
          counter: attempt
          steps:
            - if:
                condition: "session.vars.ok !== 'true'"
                then:
                  - request:
                      name: flaky
                      url: /api/sometimes-503
                      extract:
                        - { type: header, name: status_class, header: X-Status, default: "5xx" }
                      checks:
                        - { type: status, one_of: [200, 201] }
                  - js: "session.vars.ok = (session.vars.response && JSON.parse(session.vars.response||'{}')) ? 'true' : session.vars.ok"

thresholds:
  http_req_failed: [ "rate<0.1" ]
  checks: [ "rate>0.8" ]
