govuk_schemas 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.md +21 -0
- data/README.md +55 -0
- data/Rakefile +13 -0
- data/bin/console +14 -0
- data/govuk_schemas.gemspec +32 -0
- data/jenkins-schema.sh +6 -0
- data/jenkins.sh +74 -0
- data/lib/govuk_schemas.rb +10 -0
- data/lib/govuk_schemas/random.rb +70 -0
- data/lib/govuk_schemas/random_example.rb +98 -0
- data/lib/govuk_schemas/random_item_generator.rb +116 -0
- data/lib/govuk_schemas/schema.rb +21 -0
- data/lib/govuk_schemas/version.rb +3 -0
- metadata +160 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 86ab8f1354a414976519683f3009987795b77cb9
|
4
|
+
data.tar.gz: e5caf947e5b0739b46da534969301d406aefb336
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 03cc33af634da41b35d1c27802601d0e06f1d4b51baae435653f94a51bc235f1edd16ca5b70d95d315186dee69ae09bdc9b54eec7ab0ada1fb819953644bb26f
|
7
|
+
data.tar.gz: bfe60c024bb8b1ab2b564f67d01e3921b894e37d99cc4e2a754f42201a107d931e80578b5b470be91d29b1e15b24acaa436b6bf2676f2bcf18372e325c73c9a5
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3.1
|
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Crown Copyright (Government Digital Service)
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# GOV.UK Schemas
|
2
|
+
|
3
|
+
Gem to work with the [GOV.UK Content Schemas](https://github.com/alphagov/govuk-content-schemas).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
The gem is currently unreleased:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem "govuk_schemas", github: "alphagov/govuk_schemas"
|
11
|
+
```
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
### Generating random content
|
16
|
+
|
17
|
+
|
18
|
+
Generate a valid content item for the [frontend schema for detailed guides](...).
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
irb(main):001:0> GovukSchemas::RandomExample.for_frontend("detailed_guide").payload
|
22
|
+
=> {"base_path"=>"/e42dd28e9ed96dc17626ac8b1b7b8511", "title"=>"dolor est...", "publishing_app"=>"elit"...}
|
23
|
+
```
|
24
|
+
|
25
|
+
### Using it to guarantee valid data
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
irb(main):001:0> random = GovukSchemas::RandomExample.for_frontend("detailed_guide")
|
29
|
+
irb(main):002:0> random.merge_and_validate(base_path: "/foo")
|
30
|
+
=> {"base_path"=>"/foo", "title"=>"dolor est...", "publishing_app"=>"elit"...}
|
31
|
+
```
|
32
|
+
|
33
|
+
Which will fail if the data you provide would generate an invalid content item.
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
irb(main):001:0> random = GovukSchemas::RandomExample.for_frontend("detailed_guide")
|
37
|
+
irb(main):002:0> random.merge_and_validate(base_path: nil)
|
38
|
+
=> ERROR
|
39
|
+
```
|
40
|
+
|
41
|
+
## Running the test suite
|
42
|
+
|
43
|
+
Make sure you have `govuk-content-schemas` cloned in a sibling directory:
|
44
|
+
|
45
|
+
```
|
46
|
+
bundle exec rake
|
47
|
+
```
|
48
|
+
|
49
|
+
## Releasing the gem
|
50
|
+
|
51
|
+
This gem is currently not on Rubygems. Use it directly from GitHub.
|
52
|
+
|
53
|
+
## License
|
54
|
+
|
55
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
require "gem_publisher"
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
task default: [:spec]
|
8
|
+
|
9
|
+
desc "Publish gem to RubyGems"
|
10
|
+
task :publish_gem do |_t|
|
11
|
+
published_gem = GemPublisher.publish_if_updated("govuk_schemas.gemspec", :rubygems)
|
12
|
+
puts "Published #{published_gem}" if published_gem
|
13
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "govuk_schemas"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'govuk_schemas/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "govuk_schemas"
|
8
|
+
spec.version = GovukSchemas::VERSION
|
9
|
+
spec.authors = ["GOV.UK Dev"]
|
10
|
+
spec.email = ["govuk-dev@digital.cabinet-office.gov.uk"]
|
11
|
+
|
12
|
+
spec.summary = "Gem to generate test data based on GOV.UK content schemas"
|
13
|
+
spec.description = "Gem to generate test data based on GOV.UK content schemas"
|
14
|
+
spec.homepage = "https://github.com/alphagov/govuk_schemas_gem"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency "json-schema"
|
23
|
+
spec.add_dependency "activesupport"
|
24
|
+
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.4"
|
27
|
+
spec.add_development_dependency "gem_publisher", "~> 1.5.0"
|
28
|
+
spec.add_development_dependency "pry-byebug"
|
29
|
+
spec.add_development_dependency "govuk-lint", "~> 1.2.1"
|
30
|
+
|
31
|
+
spec.required_ruby_version = ">= 2.3.1"
|
32
|
+
end
|
data/jenkins-schema.sh
ADDED
data/jenkins.sh
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
REPO_NAME=${REPO_NAME:-"alphagov/govuk_schemas_gem"}
|
6
|
+
CONTEXT_MESSAGE=${CONTEXT_MESSAGE:-"default"}
|
7
|
+
GH_STATUS_GIT_COMMIT=${SCHEMA_GIT_COMMIT:-${GIT_COMMIT}}
|
8
|
+
|
9
|
+
function github_status {
|
10
|
+
REPO_NAME="$1"
|
11
|
+
STATUS="$2"
|
12
|
+
MESSAGE="$3"
|
13
|
+
gh-status "$REPO_NAME" "$GH_STATUS_GIT_COMMIT" "$STATUS" -d "Build #${BUILD_NUMBER} ${MESSAGE}" -u "$BUILD_URL" -c "$CONTEXT_MESSAGE" >/dev/null
|
14
|
+
}
|
15
|
+
|
16
|
+
function error_handler {
|
17
|
+
trap - ERR # disable error trap to avoid recursion
|
18
|
+
local parent_lineno="$1"
|
19
|
+
local message="$2"
|
20
|
+
local code="${3:-1}"
|
21
|
+
if [[ -n "$message" ]] ; then
|
22
|
+
echo "Error on or near line ${parent_lineno}: ${message}; exiting with status ${code}"
|
23
|
+
else
|
24
|
+
echo "Error on or near line ${parent_lineno}; exiting with status ${code}"
|
25
|
+
fi
|
26
|
+
github_status "$REPO_NAME" error "errored on Jenkins"
|
27
|
+
exit "${code}"
|
28
|
+
}
|
29
|
+
|
30
|
+
trap 'error_handler ${LINENO}' ERR
|
31
|
+
github_status "$REPO_NAME" pending "is running on Jenkins"
|
32
|
+
|
33
|
+
# Cleanup anything left from previous test runs
|
34
|
+
git clean -fdx
|
35
|
+
|
36
|
+
# Try to merge master into the current branch, and abort if it doesn't exit
|
37
|
+
# cleanly (ie there are conflicts). This will be a noop if the current branch
|
38
|
+
# is master.
|
39
|
+
git merge --no-commit origin/master || git merge --abort
|
40
|
+
|
41
|
+
echo "Running ruby linter"
|
42
|
+
bundle install --path "${HOME}/bundles/${JOB_NAME}"
|
43
|
+
bundle exec govuk-lint-ruby \
|
44
|
+
--format html --out rubocop-${GIT_COMMIT}.html \
|
45
|
+
--format clang
|
46
|
+
|
47
|
+
# Clone govuk-content-schemas depedency for contract tests
|
48
|
+
rm -rf /tmp/govuk-content-schemas
|
49
|
+
git clone git@github.com:alphagov/govuk-content-schemas.git /tmp/govuk-content-schemas
|
50
|
+
(
|
51
|
+
cd /tmp/govuk-content-schemas
|
52
|
+
git checkout ${SCHEMA_GIT_COMMIT:-"master"}
|
53
|
+
)
|
54
|
+
export GOVUK_CONTENT_SCHEMAS_PATH=/tmp/govuk-content-schemas
|
55
|
+
|
56
|
+
# Bundle and run tests against multiple ruby versions
|
57
|
+
for version in 2.3.1; do
|
58
|
+
rm -f Gemfile.lock
|
59
|
+
export RBENV_VERSION=$version
|
60
|
+
echo "Running tests under ruby $version"
|
61
|
+
bundle install --path "${HOME}/bundles/${JOB_NAME}"
|
62
|
+
if ! bundle exec rake ${TEST_TASK:-"default"}; then
|
63
|
+
github_status "$REPO_NAME" failure "failed on Jenkins"
|
64
|
+
exit 1
|
65
|
+
fi
|
66
|
+
done
|
67
|
+
unset RBENV_VERSION
|
68
|
+
|
69
|
+
if [[ -n "$PUBLISH_GEM" ]]; then
|
70
|
+
bundle install --path "${HOME}/bundles/${JOB_NAME}"
|
71
|
+
bundle exec rake publish_gem --trace
|
72
|
+
fi
|
73
|
+
|
74
|
+
github_status "$REPO_NAME" success "succeeded on Jenkins"
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require "govuk_schemas/version"
|
2
|
+
require "govuk_schemas/schema"
|
3
|
+
require "govuk_schemas/random_example"
|
4
|
+
|
5
|
+
module GovukSchemas
|
6
|
+
CONTENT_SCHEMA_DIR = ENV["GOVUK_CONTENT_SCHEMAS_PATH"] || "../govuk-content-schemas"
|
7
|
+
|
8
|
+
class InvalidContentGenerated < Exception
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "active_support/core_ext/string"
|
2
|
+
|
3
|
+
module GovukSchemas
|
4
|
+
module Random
|
5
|
+
class << self
|
6
|
+
WORDS = %w[Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut suscipit at mauris non bibendum. Ut ac massa est. Aenean tempor imperdiet leo vel interdum. Nam sagittis cursus sem ultricies scelerisque. Quisque porttitor risus vel risus finibus, eu sollicitudin nisl aliquet. Sed sed lectus ac dolor molestie interdum. Nam molestie pellentesque purus ac vestibulum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Suspendisse non tempor eros. Mauris eu orci hendrerit, volutpat lorem in, tristique libero. Duis a nibh nibh.].freeze
|
7
|
+
|
8
|
+
def string_for_type(type)
|
9
|
+
if type == 'date-time'
|
10
|
+
time
|
11
|
+
elsif type == 'uri'
|
12
|
+
uri
|
13
|
+
else
|
14
|
+
raise "Unknown attribute type `#{type}`"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def time
|
19
|
+
seconds_ago = rand(10_000_000) - 5_000_000
|
20
|
+
(Time.now + seconds_ago).iso8601
|
21
|
+
end
|
22
|
+
|
23
|
+
# TODO: make this more random with query string, optional anchor.
|
24
|
+
def uri
|
25
|
+
"http://example.com#{base_path}#{anchor}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def base_path
|
29
|
+
"/" + rand(1..5).times.map { SecureRandom.uuid }.join('/')
|
30
|
+
end
|
31
|
+
|
32
|
+
def string(minimum_chars = nil, maximum_chars = nil)
|
33
|
+
minimum_chars = minimum_chars || 0
|
34
|
+
maximum_chars = maximum_chars || 100
|
35
|
+
WORDS.sample(rand(minimum_chars..maximum_chars)).join(' ')
|
36
|
+
end
|
37
|
+
|
38
|
+
def bool
|
39
|
+
rand(2) == 1
|
40
|
+
end
|
41
|
+
|
42
|
+
def anchor
|
43
|
+
"##{SecureRandom.hex}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def string_for_regex(pattern)
|
47
|
+
case pattern.to_s
|
48
|
+
when '^(placeholder|placeholder_.+)$'
|
49
|
+
['placeholder', "placeholder_#{WORDS.sample}"].sample
|
50
|
+
when '^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$'
|
51
|
+
SecureRandom.uuid
|
52
|
+
when "^/(([a-zA-Z0-9._~!$&'()*+,;=:@-]|%[0-9a-fA-F]{2})+(/([a-zA-Z0-9._~!$&'()*+,;=:@-]|%[0-9a-fA-F]{2})*)*)?$"
|
53
|
+
base_path
|
54
|
+
when "^[1-9][0-9]{3}[-/](0[1-9]|1[0-2])[-/](0[1-9]|[12][0-9]|3[0-1])$"
|
55
|
+
Date.today.iso8601
|
56
|
+
when "^[1-9][0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[0-1])$"
|
57
|
+
Date.today.iso8601
|
58
|
+
when "^#.+$"
|
59
|
+
anchor
|
60
|
+
when "^/(([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})*)?$"
|
61
|
+
base_path
|
62
|
+
when '[a-z0-9\-_]'
|
63
|
+
"#{SecureRandom.hex}-#{SecureRandom.hex}"
|
64
|
+
else
|
65
|
+
raise "Regex pattern not found: #{pattern.inspect}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require "govuk_schemas/random"
|
2
|
+
require "govuk_schemas/random_item_generator"
|
3
|
+
require "active_support/core_ext/hash"
|
4
|
+
require "json-schema"
|
5
|
+
require "json"
|
6
|
+
|
7
|
+
module GovukSchemas
|
8
|
+
class RandomExample
|
9
|
+
# TODO: add docs
|
10
|
+
def initialize(schema:)
|
11
|
+
@schema = schema
|
12
|
+
@random_generator = RandomItemGenerator.new(schema: schema)
|
13
|
+
end
|
14
|
+
|
15
|
+
# TODO: add docs
|
16
|
+
def self.for_schema(schema_name, schema_type:)
|
17
|
+
schema = GovukSchemas::Schema.find(schema_name, schema_type: schema_type)
|
18
|
+
GovukSchemas::RandomExample.new(schema: schema)
|
19
|
+
end
|
20
|
+
|
21
|
+
# TODO: add docs
|
22
|
+
def payload
|
23
|
+
item = @random_generator.payload
|
24
|
+
errors = validation_errors_for(item)
|
25
|
+
|
26
|
+
if errors.any?
|
27
|
+
raise InvalidContentGenerated, error_message(item, errors)
|
28
|
+
end
|
29
|
+
|
30
|
+
item
|
31
|
+
end
|
32
|
+
|
33
|
+
# TODO: add docs
|
34
|
+
def merge_and_validate(hash)
|
35
|
+
item = payload.merge(hash.stringify_keys)
|
36
|
+
errors = validation_errors_for(item)
|
37
|
+
|
38
|
+
if errors.any?
|
39
|
+
raise InvalidContentGenerated, error_message_custom(item, errors)
|
40
|
+
end
|
41
|
+
|
42
|
+
item
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def validation_errors_for(item)
|
48
|
+
JSON::Validator.fully_validate(@schema, item, errors_as_objects: true)
|
49
|
+
end
|
50
|
+
|
51
|
+
def error_message(item, errors)
|
52
|
+
<<err
|
53
|
+
An invalid content item was generated by `RandomExample`. This probably
|
54
|
+
means that either you've merged the content item with invalid values, or there's
|
55
|
+
a bug in the generator that causes it to output invalid values. Below you'll find
|
56
|
+
the generated payload, the validation errors and the schema that was used.
|
57
|
+
Together these should be sufficient to debug the issue.
|
58
|
+
|
59
|
+
Errors:
|
60
|
+
--------------------------
|
61
|
+
|
62
|
+
#{JSON.pretty_generate(errors)}
|
63
|
+
|
64
|
+
Generated payload:
|
65
|
+
--------------------------
|
66
|
+
|
67
|
+
#{JSON.pretty_generate([item])}
|
68
|
+
|
69
|
+
Schema:
|
70
|
+
--------------------------
|
71
|
+
|
72
|
+
#{JSON.pretty_generate(@schema)}
|
73
|
+
err
|
74
|
+
end
|
75
|
+
|
76
|
+
def error_message_custom(item, errors)
|
77
|
+
<<err
|
78
|
+
An invalid content item was generated by `RandomExample`. This probably
|
79
|
+
means you've merged the content item with invalid values.
|
80
|
+
|
81
|
+
Errors:
|
82
|
+
--------------------------
|
83
|
+
|
84
|
+
#{JSON.pretty_generate(errors)}
|
85
|
+
|
86
|
+
Generated payload:
|
87
|
+
--------------------------
|
88
|
+
|
89
|
+
#{JSON.pretty_generate([item])}
|
90
|
+
|
91
|
+
Schema:
|
92
|
+
--------------------------
|
93
|
+
|
94
|
+
#{JSON.pretty_generate(@schema)}
|
95
|
+
err
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require "govuk_schemas/random"
|
2
|
+
|
3
|
+
module GovukSchemas
|
4
|
+
# The RandomItemGenerator takes a JSON schema and outputs a random hash that
|
5
|
+
# is valid against said schema.
|
6
|
+
#
|
7
|
+
# The "randomness" here is quote relative, it's particularly tailored to the
|
8
|
+
# GOV.UK content schemas. For example, strings are limited to a couple of
|
9
|
+
# hundred characters to keep the resulting items small.
|
10
|
+
class RandomItemGenerator
|
11
|
+
def initialize(schema:)
|
12
|
+
@schema = schema
|
13
|
+
end
|
14
|
+
|
15
|
+
def payload
|
16
|
+
generate_value(@schema)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def generate_value(props)
|
22
|
+
# JSON schemas can have "pointers". We use this to extract defintions and
|
23
|
+
# reduce duplication. To make the schema easily parsable we inline the
|
24
|
+
# reference here.
|
25
|
+
if props['$ref']
|
26
|
+
props.merge!(lookup_json_pointer(props['$ref']))
|
27
|
+
end
|
28
|
+
|
29
|
+
# Attributes with `enum` specified often omit the `type` from
|
30
|
+
# their definition. It's most likely a string.
|
31
|
+
type = props['type'] || "string"
|
32
|
+
|
33
|
+
# Except when it has properties, because it's defintely an object then.
|
34
|
+
if props['properties']
|
35
|
+
type = "object"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Make sure that we choose a type when there are more than one specified.
|
39
|
+
type = Array(type).sample
|
40
|
+
|
41
|
+
if props['anyOf']
|
42
|
+
# TODO: this should generate values for 1 or more values, instead of just one
|
43
|
+
generate_value(props['anyOf'].sample)
|
44
|
+
elsif props['oneOf']
|
45
|
+
generate_value(props['oneOf'].sample)
|
46
|
+
elsif props['allOf']
|
47
|
+
props['allOf'].each_with_object({}) do |subschema, hash|
|
48
|
+
val = generate_value(subschema)
|
49
|
+
hash.merge(val)
|
50
|
+
end
|
51
|
+
elsif props['enum']
|
52
|
+
props['enum'].sample
|
53
|
+
elsif type == "null"
|
54
|
+
nil
|
55
|
+
elsif type == "object"
|
56
|
+
generate_random_object(props)
|
57
|
+
elsif type == "array"
|
58
|
+
generate_random_array(props)
|
59
|
+
elsif type == "boolean"
|
60
|
+
Random.bool
|
61
|
+
elsif type == "integer"
|
62
|
+
min = props['minimum'] || 0
|
63
|
+
max = props['maximum'] || 10
|
64
|
+
rand(min..max)
|
65
|
+
elsif type == "string"
|
66
|
+
generate_random_string(props)
|
67
|
+
else
|
68
|
+
raise "Unknown attribute type: #{props}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def generate_random_object(subschema)
|
73
|
+
document = {}
|
74
|
+
|
75
|
+
(subschema['properties'] || {}).each do |attribute_name, attribute_properties|
|
76
|
+
# TODO: When the schema contains `subschema['minProperties']` we always
|
77
|
+
# populate all of the keys in the hash. This isn't quite random, but I
|
78
|
+
# haven't found a nice way yet to ensure there's at least n elements in
|
79
|
+
# the hash.
|
80
|
+
if subschema['required'].to_a.include?(attribute_name) || subschema['minProperties'] || Random.bool
|
81
|
+
document[attribute_name] = generate_value(attribute_properties)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
document
|
86
|
+
end
|
87
|
+
|
88
|
+
def generate_random_array(props)
|
89
|
+
min = props['minItems'] || 0
|
90
|
+
max = props['maxItems'] || 10
|
91
|
+
num_items = rand(min..max)
|
92
|
+
|
93
|
+
num_items.times.map do
|
94
|
+
# sometimes arrays don't have `items` specified, not sure if this is a bug
|
95
|
+
generate_value(props['items'] || {})
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def generate_random_string(props)
|
100
|
+
if props["format"]
|
101
|
+
Random.string_for_type(props['format'])
|
102
|
+
elsif props["pattern"]
|
103
|
+
Random.string_for_regex(props['pattern'])
|
104
|
+
else
|
105
|
+
Random.string(props['minLength'], props['maxLength'])
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Look up a "pointer" like "#/definitions/title" in the schema.
|
110
|
+
def lookup_json_pointer(ref)
|
111
|
+
elements = ref.split('/')
|
112
|
+
elements.shift
|
113
|
+
@schema.dig(*elements)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module GovukSchemas
|
2
|
+
class Schema
|
3
|
+
# Find a schema by name
|
4
|
+
#
|
5
|
+
# @param schema_name [String] Name of the schema/format
|
6
|
+
# @param schema_type [String] The type: frontend, backend or links
|
7
|
+
def self.find(schema_name, schema_type:)
|
8
|
+
schema_type = "publisher_v2" if schema_type == "publisher"
|
9
|
+
file_path = "#{GovukSchemas::CONTENT_SCHEMA_DIR}/dist/formats/#{schema_name}/#{schema_type}/schema.json"
|
10
|
+
JSON.parse(File.read(file_path))
|
11
|
+
end
|
12
|
+
|
13
|
+
# Return all schemas in a hash, keyed by schema name
|
14
|
+
def self.all
|
15
|
+
Dir.glob("#{GovukSchemas::CONTENT_SCHEMA_DIR}/dist/**/*.json").reduce({}) do |hash, file_path|
|
16
|
+
hash[file_path] = JSON.parse(File.read(file_path))
|
17
|
+
hash
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: govuk_schemas
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- GOV.UK Dev
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json-schema
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.4'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.4'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: gem_publisher
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.5.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.5.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry-byebug
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: govuk-lint
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.2.1
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.2.1
|
111
|
+
description: Gem to generate test data based on GOV.UK content schemas
|
112
|
+
email:
|
113
|
+
- govuk-dev@digital.cabinet-office.gov.uk
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- ".rspec"
|
120
|
+
- ".rubocop.yml"
|
121
|
+
- ".ruby-version"
|
122
|
+
- Gemfile
|
123
|
+
- LICENSE.md
|
124
|
+
- README.md
|
125
|
+
- Rakefile
|
126
|
+
- bin/console
|
127
|
+
- govuk_schemas.gemspec
|
128
|
+
- jenkins-schema.sh
|
129
|
+
- jenkins.sh
|
130
|
+
- lib/govuk_schemas.rb
|
131
|
+
- lib/govuk_schemas/random.rb
|
132
|
+
- lib/govuk_schemas/random_example.rb
|
133
|
+
- lib/govuk_schemas/random_item_generator.rb
|
134
|
+
- lib/govuk_schemas/schema.rb
|
135
|
+
- lib/govuk_schemas/version.rb
|
136
|
+
homepage: https://github.com/alphagov/govuk_schemas_gem
|
137
|
+
licenses:
|
138
|
+
- MIT
|
139
|
+
metadata: {}
|
140
|
+
post_install_message:
|
141
|
+
rdoc_options: []
|
142
|
+
require_paths:
|
143
|
+
- lib
|
144
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: 2.3.1
|
149
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
requirements: []
|
155
|
+
rubyforge_project:
|
156
|
+
rubygems_version: 2.5.1
|
157
|
+
signing_key:
|
158
|
+
specification_version: 4
|
159
|
+
summary: Gem to generate test data based on GOV.UK content schemas
|
160
|
+
test_files: []
|