{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://schemas.loadmill.local/loadmill-test-suite.json",
  "title": "LoadmillTestSuite",
  "type": "object",
  "required": ["conf", "flows", "dependencies"],
  "additionalProperties": false,
  "properties": {
    "conf": { "$ref": "#/definitions/TestSuiteConf" },
    "flows": {
      "type": "array",
      "items": { "$ref": "#/definitions/LoadmillTestSuiteFlow" }
    },
    "hooks": { "$ref": "#/definitions/HookFlowConfs" },
    "dependencies": { "$ref": "#/definitions/SuiteDependencies" }
  },
  "definitions": {
    "LoadmillTestSuiteFlow": {
      "type": "object",
      "required": ["order", "conf", "status"],
      "additionalProperties": false,
      "properties": {
        "order": { "type": "integer" },
        "conf": { "$ref": "#/definitions/TestSuiteFlowConf" },
        "status": { "$ref": "#/definitions/FlowStatus" },
        "id": { "type": "string", "format": "uuid" },
        "assignedLabelsIds": {
          "type": "array",
          "items": { "$ref": "#/definitions/FlowLabelId" }
        }
      }
    },

    "FlowStatus": {
      "type": "string",
      "description": "FlowStatus represents the execution status / mode in which this Test Flow is when running a Test Suite. 'Active' will run always, 'Evaluating' will also run but will not fail the Test Suite if failed, 'Draft' will only run in manual run, and 'Disabled' will never run.",
      "enum": ["Disabled", "Draft", "Evaluating", "Active"]
    },

    "FlowLabelId": {
      "type": "object",
      "required": ["id"],
      "additionalProperties": false,
      "properties": {
        "id": { "type": "string", "format": "uuid" }
      }
    },

    "BaseMeta": {
      "type": "object",
      "properties": {
        "description": { "type": "string" }
      }
    },

    "StrictBaseMeta": {
      "type": "object",
      "required": ["description"],
      "properties": {
        "description": { "type": "string" }
      },
      "additionalProperties": false
    },

    "MetaWithDependencies": {
      "type": "object",
      "properties": {
        "description": { "type": "string" },
        "dependencies": {
          "type": "array",
          "items": { "$ref": "#/definitions/TestSuiteFlowDependency" }
        },
        "dependenciesData": {
          "type": "array",
          "items": { "$ref": "#/definitions/LoadmillSharedFlow" }
        }
      }
    },

    "StrictMetaWithDependencies": {
      "type": "object",
      "required": ["description"],
      "properties": {
        "description": { "type": "string" },
        "dependencies": {
          "type": "array",
          "items": { "$ref": "#/definitions/TestSuiteFlowDependency" }
        },
        "dependenciesData": {
          "type": "array",
          "items": { "$ref": "#/definitions/LoadmillSharedFlow" }
        }
      },
      "additionalProperties": false
    },

    "HeaderEntry": {
      "type": "object",
      "minProperties": 1,
      "maxProperties": 1,
      "additionalProperties": { "type": "string" }
    },

    "ParameterEntry": {
      "type": "object",
      "minProperties": 1,
      "maxProperties": 1,
      "additionalProperties": { "$ref": "#/definitions/JSONValue" }
    },

    "JQueryExtraction": {
      "oneOf": [
        { "type": "string" },
        {
          "type": "object",
          "required": ["query"],
          "additionalProperties": false,
          "properties": {
            "query": { "type": "string" },
            "attr": { "type": "string" }
          }
        }
      ]
    },

    "ExtractionValue": {
      "oneOf": [
        { "type": "string" },
        {
          "type": "object",
          "minProperties": 1,
          "additionalProperties": false,
          "properties": {
            "regex": { "type": "string" },
            "header": { "type": "string" },
            "jsonPath": { "type": "string" },
            "edn": { "type": "string" },
            "xPath": { "type": "string" },
            "jQuery": { "$ref": "#/definitions/JQueryExtraction" },
            "ws": { "type": "string" }
          }
        }
      ]
    },

    "Extraction": {
      "type": "object",
      "minProperties": 1,
      "additionalProperties": { "$ref": "#/definitions/ExtractionValue" }
    },

    "Assertion": {
      "type": "object",
      "required": ["check"],
      "additionalProperties": false,
      "properties": {
        "check": { "type": "string" },
        "equals": { "type": "string" },
        "notEquals": { "type": "string" },
        "contains": { "type": "string" },
        "notContains": { "type": "string" },
        "matches": { "type": "string" },
        "JSONSchema": { "type": "string" },
        "JSONContains": { "type": "string" },
        "XMLContains": { "type": "string" },
        "greater": { "type": "string" },
        "lesser": { "type": "string" },
        "falsy": { "type": ["string", "boolean"] },
        "AIVerify": { "type": "string" },
        "disabled": { "type": "boolean" }
      }
    },

    "Assertions": {
      "type": "array",
      "items": { "$ref": "#/definitions/Assertion" }
    },

    "StepMeta": {
      "type": "object",
      "required": ["type"],
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "enum": ["login", "beforeEach", "flow", "afterEach", "flowInFlow", "beforeAll", "afterAll"]
        },
        "location": {
          "type": "object",
          "required": ["order", "index"],
          "additionalProperties": false,
          "properties": {
            "order": { "type": "integer" },
            "index": { "type": "integer" }
          }
        }
      }
    },

    "HookFlowConfs": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "beforeAll": { "$ref": "#/definitions/CustomHookFlowConf" },
        "beforeEach": { "$ref": "#/definitions/CustomHookFlowConf" },
        "afterEach": { "$ref": "#/definitions/CustomHookFlowConf" },
        "afterAll": { "$ref": "#/definitions/CustomHookFlowConf" }
      }
    },

    "CustomHookFlowConf": {
      "allOf": [
        { "$ref": "#/definitions/CommonFlowConf" },
        {
          "type": "object",
          "properties": {
            "meta": { "$ref": "#/definitions/MetaWithDependencies" }
          }
        }
      ]
    },

    "SuiteDependencies": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "hooks": {
          "oneOf": [
            { "$ref": "#/definitions/HooksDependencies" },
            { "$ref": "#/definitions/ExternalHooks" }
          ]
        },
        "login": {
          "type": "object",
          "required": ["id"],
          "additionalProperties": false,
          "properties": {
            "id": { "type": "string", "format": "uuid" }
          }
        },
        "labels": {
          "type": "array",
          "items": { "$ref": "#/definitions/FlowLabel" }
        },
        "flowsData": {
          "type": "array",
          "items": { "$ref": "#/definitions/LoadmillSharedFlow" }
        }
      }
    },
    "ExternalHook": {
      "type": "object",
      "required": ["id", "conf"],
      "additionalProperties": false,
      "properties": {
        "id": { "type": "string", "format": "uuid" },
        "conf": { "$ref": "#/definitions/HookFlowConf" }
      }
    },
    "HookFlowConf": { "$ref": "#/definitions/CommonFlowConf" },
    "ExternalHooks": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "beforeAll": { "$ref": "#/definitions/ExternalHook" },
        "beforeEach": { "$ref": "#/definitions/ExternalHook" },
        "afterEach": { "$ref": "#/definitions/ExternalHook" },
        "afterAll": { "$ref": "#/definitions/ExternalHook" }
      }
    },

    "HooksDependencies": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "beforeAllId": { "type": "string", "format": "uuid" },
        "beforeEachId": { "type": "string", "format": "uuid" },
        "afterEachId": { "type": "string", "format": "uuid" },
        "afterAllId": { "type": "string", "format": "uuid" }
      }
    },

    "FlowLabel": {
      "type": "object",
      "required": ["id", "description", "color"],
      "additionalProperties": false,
      "properties": {
        "id": { "type": "string", "format": "uuid" },
        "description": { "type": "string" },
        "color": { "type": "string" }
      }
    },

    "LoadmillSharedFlow": {
      "type": "object",
      "required": ["id", "description", "conf"],
      "additionalProperties": false,
      "properties": {
        "id": { "type": "string", "format": "uuid" },
        "description": { "type": "string" },
        "conf": { "$ref": "#/definitions/SharedFlowConf" }
      }
    },

    "SharedFlowConf": {
      "allOf": [
        { "$ref": "#/definitions/CommonFlowConf" },
        {
          "type": "object",
          "properties": {
            "meta": { "$ref": "#/definitions/StrictBaseMeta" }
          }
        }
      ]
    },

    "TestSuiteConf": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "meta": { "$ref": "#/definitions/StrictBaseMeta" },
        "auth": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "user": { "type": "string" },
            "password": { "type": "string" }
          }
        },
        "useCookies": { "type": "boolean" },
        "cookiesScope": { "type": "string" },
        "parameters": { "$ref": "#/definitions/Parameters" },
        "loginFlow": {
          "type": "array",
          "items": { "$ref": "#/definitions/Step" }
        },
        "authenticationHeaders": {
          "$ref": "#/definitions/LoadmillHeaders"
        },
        "sharedLoginFlowParameters": {
          "type": "array",
          "items": { "$ref": "#/definitions/ParameterEntry" }
        },
        "sharedLoginFlowDescription": { "type": "string" },
        "parametersScope": { "type": "string" },
        "executionMode": {
          "type": "string",
          "enum": ["Dependent", "Independent"]
        }
      }
    },

    "TestSuiteFlowConf": {
      "allOf": [
        { "$ref": "#/definitions/CommonFlowConf" },
        {
          "type": "object",
          "properties": {
            "meta": { "$ref": "#/definitions/StrictMetaWithDependencies" }
          }
        }
      ]
    },

    "CommonFlowConf": {
      "type": "object",
      "required": ["requests"],
      "additionalProperties": false,
      "properties": {
        "meta": { "$ref": "#/definitions/MetaWithDependencies" },
        "requests": {
          "type": "array",
          "items": { "$ref": "#/definitions/Step" }
        },
        "groups": {
          "type": "array",
          "items": { "$ref": "#/definitions/StepsGroup" }
        },
        "useCookies": { "type": "boolean" },
        "useProxy": { "type": "boolean" },
        "skipLoginFlow": { "type": "boolean" },
        "authenticationHeaders": { "$ref": "#/definitions/LoadmillHeaders" },
        "parameterPools": {
          "type": "array",
          "items": { "type": "string" }
        },
        "parameters": { "$ref": "#/definitions/Parameters" },
        "concurrency": { "type": "integer" },
        "duration": { "type": "integer" },
        "rampUp": { "type": "integer" },
        "iterationDelay": { "type": "integer" },
        "targetedCountries": {
          "type": "array",
          "items": { "type": "string" }
        },
        "alwaysDistributed": { "type": "boolean" },
        "maxFlakyFlowRetries": { "type": "integer" },
        "flakyFlowDelay": { "type": "integer" },
        "sensitiveData": { "type": "boolean" },
        "xmlDecode": { "type": "boolean" },
        "scopeParameters": {
          "type": "array",
          "items": { "$ref": "#/definitions/ParameterEntry" }
        },
        "cookies": {
          "type": "object",
          "additionalProperties": { "type": "string" }
        },
        "afterEachRequests": {
          "type": "array",
          "items": { "$ref": "#/definitions/Step" }
        },
        "afterAllRequests": {
          "type": "array",
          "items": { "$ref": "#/definitions/Step" }
        },
        "serviceDefinitionId": { "type": "string", "format": "uuid" }
      }
    },

    "ArrayRepeat": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "collectionParamName", "assignedParamName"],
      "properties": {
        "id": { "type": "string", "format": "uuid" },
        "type": { "type": "string", "enum": ["ArrayRepeat"] },
        "delay": { "type": "integer" },
        "collectionParamName": { "type": "string" },
        "assignedParamName": { "type": "string" }
      }
    },

    "DynamicRepeat": {
      "oneOf": [{ "$ref": "#/definitions/ArrayRepeat" }]
    },

    "StepsGroup": {
      "type": "object",
      "required": ["id"],
      "additionalProperties": false,
      "properties": {
        "id": { "type": "string", "format": "uuid" },
        "description": { "type": "string" },
        "repeat": { "$ref": "#/definitions/DynamicRepeat" }
      }
    },

    "TestSuiteFlowDependency": {
      "type": "object",
      "required": ["sharedFlowId", "order"],
      "additionalProperties": false,
      "properties": {
        "sharedFlowId": { "type": "string", "format": "uuid" },
        "index": { "type": "integer" },
        "order": { "type": "integer" }
      }
    },

    "Parameters": {
      "type": "array",
      "items": { "$ref": "#/definitions/ParameterEntry" }
    },

    "LoadmillHeaders": {
      "type": "array",
      "items": { "$ref": "#/definitions/HeaderEntry" }
    },

    "Step": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "enum": ["Request", "Code", "ExtractAndAssert", "Wait", "WebSocket", "Playwright"]
        },
        "id": { "type": "string", "format": "uuid" },
        "description": { "type": "string" },
        "disabled": { "type": "boolean" },
        "auth": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "user": { "type": "string" },
            "password": { "type": "string" }
          }
        },
        "method": {
          "type": "string",
          "enum": ["GET", "POST", "PUT", "DELETE", "PATCH"]
        },
        "url": { "type": "string" },
        "headers": { "$ref": "#/definitions/LoadmillHeaders" },
        "postData": {
          "type": "object",
          "required": ["text"],
          "additionalProperties": false,
          "properties": {
            "text": { "type": "string" },
            "mimeType": { "type": "string" },
            "params": {
              "type": "array",
              "items": {
                "type": "object",
                "required": ["name", "value"],
                "additionalProperties": false,
                "properties": {
                  "name": { "type": "string" },
                  "value": { "type": "string" }
                }
              }
            }
          }
        },
        "postFormData": {
          "type": "array",
          "items": {
            "type": "object",
            "required": ["name", "value"],
            "additionalProperties": false,
            "properties": {
              "name": { "type": "string" },
              "value": { "type": "string" },
              "fileName": { "type": "string" },
              "contentType": { "type": "string" }
            }
          }
        },
        "file": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "key": { "type": "string" },
            "name": { "type": "string" },
            "signedUrl": { "type": "string" }
          }
        },
        "graphqlPostData": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "operationName": { "type": "string" },
            "query": { "type": "string" },
            "variables": { "type": "string" }
          }
        },
        "grpc": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "service": { "type": "string" },
            "method": { "type": "string" },
            "message": { "type": "string" }
          }
        },
        "flowId": { "type": "string", "format": "uuid" },
        "groupId": { "type": "string", "format": "uuid" },
        "cachePenetration": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "cacheControl": { "type": "string" },
            "mode": {
              "type": "string",
              "enum": ["none", "default", "always-query", "always-header"]
            }
          }
        },
        "useCookies": { "type": "boolean" },
        "stopBefore": { "type": "string" },
        "skipBefore": {
          "type": "object",
          "additionalProperties": false,
          "required": ["condition"],
          "properties": {
            "condition": { "type": "string" },
            "negate": { "type": "boolean" },
            "goTo": { "type": "string" }
          }
        },
        "expectedStatus": {
          "type": "string",
          "enum": ["SUCCESS", "ERROR", "ANY"]
        },
        "timeout": { "type": "integer" },
        "delay": { "type": ["integer", "string"] },
        "wait": { "type": ["integer", "string"] },
        "extract": {
          "type": "array",
          "items": { "$ref": "#/definitions/Extraction" }
        },
        "assert": { "$ref": "#/definitions/Assertions" },
        "loop": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "assert": { "$ref": "#/definitions/Assertion" },
            "iterations": { "type": "integer" },
            "wait": { "type": ["integer", "string"] }
          }
        },
        "meta": { "$ref": "#/definitions/StepMeta" },
        "noRedirects": { "type": "boolean" },
        "httpVersion": {
          "type": "string",
          "enum": ["HTTP/1.1", "HTTP/2.0"]
        },
        "messagesToRetrieve": {
          "type": "string",
          "enum": ["Last", "Last 10", "Last 50"]
        },
        "maxExtractionsResolutionTime": { "type": "integer" },
        "action": {
          "type": "string",
          "enum": ["Connect", "Send", "Receive"]
        },
        "headedMode": {
          "type": "string",
          "enum": ["--headed", "--debug"]
        },
        "postScript": { "type": "string" }
      }
    },

    "JSONValue": {
      "oneOf": [
        { "type": "string" },
        { "type": "number" },
        { "type": "boolean" },
        { "type": "null" },
        { "type": "array", "items": { "$ref": "#/definitions/JSONValue" } },
        { "type": "object", "additionalProperties": { "$ref": "#/definitions/JSONValue" } }
      ]
    }
  }
}
