Skip to content

Commit

Permalink
Merge pull request #63 from alphagov/allow-unique-arrays
Browse files Browse the repository at this point in the history
Generate unique items for arrays with the "uniqueItems" property
  • Loading branch information
kevindew authored Mar 10, 2021
2 parents 8c2b10b + 0d42167 commit 31b688c
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 4.3.0

* Generate unique items for arrays with the "uniqueItems" property. ([#63](https://github.com/alphagov/govuk_schemas/pull/63))

# 4.2.0

* Add support for generating random HH:MM time strings that match a regex. ([#62](https://github.com/alphagov/govuk_schemas/pull/62))
Expand Down
19 changes: 17 additions & 2 deletions lib/govuk_schemas/random_schema_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,27 @@ def generate_random_object(subschema)
def generate_random_array(props)
min = props["minItems"] || 0
max = props["maxItems"] || 10
unique = props["uniqueItems"] == true
num_items = @random.rand(min..max)
items = []
attempts = 0
max_attempts = num_items * 100

num_items.times.map do
until items.length == num_items
# sometimes arrays don't have `items` specified, not sure if this is a bug
generate_value(props["items"] || {})
new_value = generate_value(props["items"] || {})

if unique && items.include?(new_value)
attempts += 1
raise "Failed to create a unique array item after #{max_attempts} attempts" if attempts >= max_attempts
next
end

attempts = 0
items << new_value
end

items
end

def generate_random_string(props)
Expand Down
2 changes: 1 addition & 1 deletion lib/govuk_schemas/version.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module GovukSchemas
# @private
VERSION = "4.2.0".freeze
VERSION = "4.3.0".freeze
end
39 changes: 39 additions & 0 deletions spec/lib/random_schema_generator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,44 @@
expect(generator.payload["my_enum"]).to eq("a")
expect(generator.payload.keys).to include("my_field")
end

describe "unique arrays" do
it "handles arrays that require unique items" do
schema = {
"type" => "array",
"items" => { "type" => "string" },
"uniqueItems" => true,
"minItems" => 5,
"maxItems" => 5,
}

generator = GovukSchemas::RandomSchemaGenerator.new(schema: schema)

# These stubs are to ensure determinism in the random array value
# generation.
allow(generator).to receive(:generate_value).and_call_original
allow(generator)
.to receive(:generate_value)
.with({ "type" => "string" })
.and_return(*%w[a a b b c c d d e e])

expect(generator.payload).to match_array(%w[a b c d e])
end

it "raises an error for a situation where it can't generate a random array" do
schema = {
"type" => "array",
"items" => { "enum" => %w[a b] },
"uniqueItems" => true,
"minItems" => 3,
"maxItems" => 3,
}

generator = GovukSchemas::RandomSchemaGenerator.new(schema: schema)

expect { generator.payload }
.to raise_error "Failed to create a unique array item after 300 attempts"
end
end
end
end

0 comments on commit 31b688c

Please sign in to comment.