class GovukSchemas::RandomSchemaGenerator

def generate_value(props)

def generate_value(props)
  # TODO: #/definitions/nested_headers are recursively nested and can cause
  # infinite loops. We need to add something that detects and prevents the
  # loop. In the meantime return a valid value.
  if props["$ref"] == "#/definitions/nested_headers"
    return [{ "text" => "1", "level" => 1, "id" => "ABC" }]
  end
  # JSON schemas can have "pointers". We use this to extract defintions and
  # reduce duplication. To make the schema easily parsable we inline the
  # reference here.
  if props["$ref"]
    props.merge!(lookup_json_pointer(props["$ref"]))
  end
  # Attributes with `enum` specified often omit the `type` from
  # their definition. It's most likely a string.
  type = props["type"] || "string"
  # Except when it has properties, because it's defintely an object then.
  if props["properties"]
    type = "object"
  end
  # Make sure that we choose a type when there are more than one specified.
  type = Array(type).sample(random: @random)
  if props["anyOf"]
    generate_value(props["anyOf"].sample(random: @random))
  elsif props["oneOf"] && type != "object"
    # FIXME: Generating valid data for a `oneOf` schema is quite interesting.
    # According to the JSON Schema spec a `oneOf` schema is only valid if
    # the data is valid against *only one* of the clauses. To do this
    # properly, we'd have to verify that the data generated below doesn't
    # validate against the other schemas in `props['oneOf']`.
    generate_value(props["oneOf"].sample(random: @random))
  elsif props["allOf"]
    props["allOf"].each_with_object({}) do |subschema, hash|
      val = generate_value(subschema)
      hash.merge(val)
    end
  elsif props["enum"]
    props["enum"].sample(random: @random)
  elsif type == "null"
    nil
  elsif type == "object"
    generate_random_object(props)
  elsif type == "array"
    generate_random_array(props)
  elsif type == "boolean"
    @generator.bool
  elsif type == "integer"
    min = props["minimum"] || 0
    max = props["maximum"] || 10
    @random.rand(min..max)
  elsif type == "string"
    generate_random_string(props)
  else
    raise "Unknown attribute type: #{props}"
  end
end