diff --git a/lib/govuk_schemas/random.rb b/lib/govuk_schemas/random.rb index 19dd6b7..e78480c 100644 --- a/lib/govuk_schemas/random.rb +++ b/lib/govuk_schemas/random.rb @@ -1,5 +1,3 @@ -require "securerandom" - module GovukSchemas # @private module Random @@ -27,7 +25,7 @@ def uri end def base_path - "/" + rand(1..5).times.map { SecureRandom.uuid }.join("/") + "/" + rand(1..5).times.map { uuid }.join("/") end def govuk_subdomain_url @@ -48,19 +46,29 @@ def bool end def anchor - "##{SecureRandom.hex}" + "##{hex}" end def random_identifier(separator:) Utils.parameterize(WORDS.sample(rand(1..10)).join("-")).gsub("-", separator) end + def uuid + # matches uuid regex e.g. e058aad7-ce86-5181-8801-4ddcb3c8f27c + # /^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/ + "#{hex(8)}-#{hex(4)}-1#{hex(3)}-a#{hex(3)}-#{hex(12)}" + end + + def hex(length = 10) + length.times.map { bool ? random_letter : random_number }.join("") + end + def string_for_regex(pattern) case pattern.to_s when "^(placeholder|placeholder_.+)$" ["placeholder", "placeholder_#{WORDS.sample}"].sample when "^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$" - SecureRandom.uuid + uuid when "^/(([a-zA-Z0-9._~!$&'()*+,;=:@-]|%[0-9a-fA-F]{2})+(/([a-zA-Z0-9._~!$&'()*+,;=:@-]|%[0-9a-fA-F]{2})*)*)?$" base_path when "^[1-9][0-9]{3}[-/](0[1-9]|1[0-2])[-/](0[1-9]|[12][0-9]|3[0-1])$" @@ -80,7 +88,7 @@ def string_for_regex(pattern) when "^https://([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[A-Za-z0-9])?\\.)*gov\\.uk(/(([a-zA-Z0-9._~!$&'()*+,;=:@-]|%[0-9a-fA-F]{2})+(/([a-zA-Z0-9._~!$&'()*+,;=:@-]|%[0-9a-fA-F]{2})*)*)?(\\?([a-zA-Z0-9._~!$&'()*+,;=:@-]|%[0-9a-fA-F]{2})*)?(#([a-zA-Z0-9._~!$&'()*+,;=:@-]|%[0-9a-fA-F]{2})*)?)?$" govuk_subdomain_url when '[a-z0-9\-_]' - "#{SecureRandom.hex}-#{SecureRandom.hex}" + "#{hex}-#{hex}" else raise <<-DOC Don't know how to generate random string for pattern #{pattern.inspect} @@ -96,6 +104,18 @@ def string_for_regex(pattern) DOC end end + + private + + def random_letter + letters = ("a".."f").to_a + letters[rand(0..letters.count - 1)] + end + + def random_number + numbers = ("0".."9").to_a + numbers[rand(0..numbers.count - 1)] + end end end end diff --git a/lib/govuk_schemas/random_example.rb b/lib/govuk_schemas/random_example.rb index ef9f283..3846ecf 100644 --- a/lib/govuk_schemas/random_example.rb +++ b/lib/govuk_schemas/random_example.rb @@ -24,6 +24,11 @@ class RandomExample # schema = GovukSchemas::Schema.find(frontend_schema: "detailed_guide") # GovukSchemas::RandomExample.new(schema: schema).payload # + # If you need a 'consistent' random response, you can set the seed using + # (for example) `srand(777)` and know that the payload will always be the + # same. Note that timestamps in the payload will continue to reflect the + # current time. + # # @param [Hash] schema A JSON schema. # @return [GovukSchemas::RandomExample] def initialize(schema:) diff --git a/spec/lib/random_example_spec.rb b/spec/lib/random_example_spec.rb index 080e8ce..afb031d 100644 --- a/spec/lib/random_example_spec.rb +++ b/spec/lib/random_example_spec.rb @@ -25,6 +25,16 @@ end end + it "returns the same output if a seed is detected" do + schema = GovukSchemas::Schema.random_schema(schema_type: "frontend") + srand(777) # these srand calls would be in the upstream application + first_payload = GovukSchemas::RandomExample.new(schema: schema).payload + srand(777) + second_payload = GovukSchemas::RandomExample.new(schema: schema).payload + + expect(first_payload).to eql(second_payload) + end + it "can customise the payload" do schema = GovukSchemas::Schema.random_schema(schema_type: "frontend")