json-spec 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.gitmodules +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +960 -0
- data/Rakefile +10 -0
- data/api_documentation.md +611 -0
- data/cachivache/.gitignore +1 -0
- data/cachivache/Gemfile +4 -0
- data/cachivache/README.md +247 -0
- data/cachivache/Rakefile +19 -0
- data/cachivache/Vagrantfile +70 -0
- data/cachivache/cachivache.rb +59 -0
- data/cachivache/lib/let-behaviour.rb +27 -0
- data/cachivache/lib/rake-helper.rb +131 -0
- data/cachivache/lib/sh-file-context.rb +39 -0
- data/cachivache/lib/sh-if-context.rb +31 -0
- data/cachivache/stuff/.gitkeep +0 -0
- data/cachivache/stuff/ruby-json-spec.rb +22 -0
- data/examples/example-1-simple.rb +66 -0
- data/examples/example-2-default-expectations.rb +63 -0
- data/examples/example-3-each-field.rb +104 -0
- data/examples/example-4-to-be-as-defined-in.rb +117 -0
- data/examples/example-5-custom-expectations.rb +153 -0
- data/examples/example-6-custom-messages.rb +36 -0
- data/examples/example-7-full-example.rb +231 -0
- data/examples/fixtures.rb +77 -0
- data/examples/validation-printer.rb +47 -0
- data/json-spec.gemspec +29 -0
- data/lib/cabeza-de-termo/json-spec/errors/error.rb +6 -0
- data/lib/cabeza-de-termo/json-spec/errors/expectation-not-found-error.rb +8 -0
- data/lib/cabeza-de-termo/json-spec/errors/modifier-not-found-error.rb +8 -0
- data/lib/cabeza-de-termo/json-spec/errors/unkown-json-type-error.rb +8 -0
- data/lib/cabeza-de-termo/json-spec/errors/validation-error.rb +8 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/default-expectations/default-expectation-builder.rb +29 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/default-expectations/default-expectations-mapping.rb +54 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/block-expectation-definition.rb +16 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/class-expectation-definition.rb +15 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expectation-definition.rb +19 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expectations-definition-builder.rb +136 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expecting-all-of-expectation-definition.rb +23 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expecting-any-of-expectation-definition.rb +23 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/expecting-expectation-definition.rb +17 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-builders/negating-expectation-definition.rb +16 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/expectation-library-definition-builder.rb +35 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/class-modifier-definition.rb +15 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/composing-modifiers-definition.rb +28 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/modifier-definition.rb +13 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/definition-builders/modifier-builders/modifiers-definition-builder.rb +73 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/expectations-library.rb +150 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/initializers/default-library-initializer.rb +265 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/initializers/library-initializer.rb +9 -0
- data/lib/cabeza-de-termo/json-spec/expectations-library/messages/expectation-messages-mapping.rb +27 -0
- data/lib/cabeza-de-termo/json-spec/expectations/abstract-expectation.rb +39 -0
- data/lib/cabeza-de-termo/json-spec/expectations/all-expectations-composite.rb +33 -0
- data/lib/cabeza-de-termo/json-spec/expectations/any-expectation-composite.rb +33 -0
- data/lib/cabeza-de-termo/json-spec/expectations/block-expectation.rb +28 -0
- data/lib/cabeza-de-termo/json-spec/expectations/expectation.rb +51 -0
- data/lib/cabeza-de-termo/json-spec/expectations/is-email-expectation.rb +16 -0
- data/lib/cabeza-de-termo/json-spec/expectations/is-scalar-expectation.rb +17 -0
- data/lib/cabeza-de-termo/json-spec/expectations/is-url-expectation.rb +21 -0
- data/lib/cabeza-de-termo/json-spec/expectations/negated-expectation.rb +31 -0
- data/lib/cabeza-de-termo/json-spec/expectations/runner/abstract-expectations-runner.rb +27 -0
- data/lib/cabeza-de-termo/json-spec/expectations/runner/can-be-absent-expectations-runner.rb +50 -0
- data/lib/cabeza-de-termo/json-spec/expectations/runner/can-be-null-expectations-runner.rb +48 -0
- data/lib/cabeza-de-termo/json-spec/expectations/runner/expectations-runner.rb +43 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-any-of.rb +62 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-anything.rb +16 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-each-field.rb +58 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-each.rb +58 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-expression.rb +314 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-field-name.rb +16 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-field.rb +76 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-list.rb +40 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-object.rb +82 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-scalar.rb +20 -0
- data/lib/cabeza-de-termo/json-spec/expressions/json-spec.rb +174 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/abstract-instantiator.rb +9 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/all-expectations-composite-instantiator.rb +12 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/any-expectation-composite-instantiator.rb +12 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/block-expectation-instantiator.rb +16 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/composite-instantiator.rb +45 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/modifier-composite-instantiator.rb +12 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/negated-expectation-instantiator.rb +20 -0
- data/lib/cabeza-de-termo/json-spec/instantiators/patial-application-instantiator.rb +26 -0
- data/lib/cabeza-de-termo/json-spec/json-spec.rb +2 -0
- data/lib/cabeza-de-termo/json-spec/message-formatters/block-message-formatter.rb +15 -0
- data/lib/cabeza-de-termo/json-spec/message-formatters/erb-message-formatter.rb +60 -0
- data/lib/cabeza-de-termo/json-spec/message-formatters/message-formatter.rb +9 -0
- data/lib/cabeza-de-termo/json-spec/metaprogramming/message-send.rb +37 -0
- data/lib/cabeza-de-termo/json-spec/metaprogramming/message.rb +37 -0
- data/lib/cabeza-de-termo/json-spec/metaprogramming/object-method.rb +14 -0
- data/lib/cabeza-de-termo/json-spec/modifiers/can-be-absent-modifier.rb +13 -0
- data/lib/cabeza-de-termo/json-spec/modifiers/can-be-null-modifier.rb +13 -0
- data/lib/cabeza-de-termo/json-spec/modifiers/expression-modifier.rb +9 -0
- data/lib/cabeza-de-termo/json-spec/modifiers/modifier-composite.rb +27 -0
- data/lib/cabeza-de-termo/json-spec/signals/signal.rb +6 -0
- data/lib/cabeza-de-termo/json-spec/signals/skip-branch-signal.rb +8 -0
- data/lib/cabeza-de-termo/json-spec/utilities/bind.rb +20 -0
- data/lib/cabeza-de-termo/json-spec/utilities/range.rb +70 -0
- data/lib/cabeza-de-termo/json-spec/value-holders/accessors-chain.rb +27 -0
- data/lib/cabeza-de-termo/json-spec/value-holders/missing-value.rb +21 -0
- data/lib/cabeza-de-termo/json-spec/value-holders/value-holder.rb +135 -0
- data/lib/cabeza-de-termo/json-spec/version.rb +5 -0
- data/lib/cabeza-de-termo/json-spec/walkers/expression-walker.rb +66 -0
- data/lib/cabeza-de-termo/json-spec/walkers/json-expectations-runner.rb +214 -0
- data/lib/cabeza-de-termo/json-spec/walkers/json-expression-explainer.rb +183 -0
- data/lib/cabeza-de-termo/json-spec/walkers/reporter/expectation-report.rb +63 -0
- data/lib/cabeza-de-termo/json-spec/walkers/reporter/json-expectations-reporter.rb +111 -0
- data/lib/cabeza-de-termo/json-spec/walkers/validator/json-validator-error.rb +29 -0
- data/lib/cabeza-de-termo/json-spec/walkers/validator/json-validator.rb +133 -0
- data/lib/cabeza-de-termo/json-spec/walkers/value-holders-stack-behaviour.rb +57 -0
- metadata +242 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
require 'cabeza-de-termo/json-spec/json-spec'
|
|
2
|
+
require_relative 'fixtures'
|
|
3
|
+
require_relative 'validation-printer'
|
|
4
|
+
|
|
5
|
+
# To run self example do
|
|
6
|
+
# ruby -I lib examples/example-5-custom-expectations.rb
|
|
7
|
+
#
|
|
8
|
+
class Example_5_CustomExpectations
|
|
9
|
+
def self.run()
|
|
10
|
+
self.new.run
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def run()
|
|
14
|
+
# Define our custom Expectations
|
|
15
|
+
CabezaDeTermo::JsonSpec::ExpectationsLibrary.define do
|
|
16
|
+
expectations do
|
|
17
|
+
define :to_be_valid_lincense do
|
|
18
|
+
expecting :to_be_in, ComposerJson.valid_licenses
|
|
19
|
+
message "'<%= format value %>' is not a valid lincense."
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
define :to_be_version do
|
|
23
|
+
with_class IsVersionExpectation
|
|
24
|
+
message "'<%= format value %>' is not a valid version."
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
define :to_be_namespace do
|
|
28
|
+
expecting :to_match, /^[a-zA-Z_\\]+\\/
|
|
29
|
+
message "'<%= format value %>' is not a valid namespace."
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
define :to_be_psr4_key do
|
|
33
|
+
expecting_any_of :to_be_equal_to, ''
|
|
34
|
+
or_also :to_be_namespace
|
|
35
|
+
|
|
36
|
+
message "'<%= format value %>' is not a valid PSR4 key."
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
define :to_end_with_slash do
|
|
40
|
+
expecting :to_match, /^.+\//
|
|
41
|
+
message "'<%= format value %>' does not end with a slash."
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
define :to_be_folder do
|
|
45
|
+
expecting :to_end_with_slash
|
|
46
|
+
message "'<%= format value %>' is not a valid folder."
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
validator = ComposerJson.new.spec.validate_string(Fixtures.named :simple)
|
|
52
|
+
|
|
53
|
+
ValidationPrinter.new.print_report_of validator
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
class IsVersionExpectation < CabezaDeTermo::JsonSpec::Expectation
|
|
58
|
+
def is_satisfied_by?(value_holder)
|
|
59
|
+
# left as exercise to the reader :P
|
|
60
|
+
true
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class ComposerJson
|
|
65
|
+
def spec()
|
|
66
|
+
CabezaDeTermo::JsonSpec::JsonSpec.new do |json_spec|
|
|
67
|
+
json_spec.expect_an(:object) do |object|
|
|
68
|
+
object.expect('name') .not_blank
|
|
69
|
+
object.expect('type') .not_blank
|
|
70
|
+
object.expect('description') .not_blank
|
|
71
|
+
object.expect('keywords') .to_be_as_defined_in(self, :keywords_spec)
|
|
72
|
+
object.expect('homepage').to_be_url
|
|
73
|
+
object.expect('license') .to_be_in(self.class.valid_licenses)
|
|
74
|
+
object.expect('authors') .to_be_as_defined_in(self, :authors_spec)
|
|
75
|
+
object.expect('require') .to_be_as_defined_in(self, :require_spec)
|
|
76
|
+
object.expect('require-dev') .to_be_as_defined_in(self, :require_spec)
|
|
77
|
+
object.expect('autoload') .to_be_as_defined_in(self, :autoload_spec)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def keywords_spec(json_spec)
|
|
83
|
+
json_spec .to_be_a(:list) .can_be_absent .not_empty do
|
|
84
|
+
each do
|
|
85
|
+
expect_a(:scalar) .not_blank
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def authors_spec(json_spec)
|
|
91
|
+
json_spec .to_be_a(:list) .not_empty do |list|
|
|
92
|
+
list.each do |each|
|
|
93
|
+
each.to_be_as_defined_in(self, :author_spec)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def author_spec(json_spec)
|
|
99
|
+
json_spec .expect_an(:object) do
|
|
100
|
+
expect('name') .not_blank
|
|
101
|
+
expect('email') .to_be_email
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def require_spec(json)
|
|
106
|
+
json .to_be_an(:object) .can_be_absent do
|
|
107
|
+
each_field do
|
|
108
|
+
expect_name .not_blank
|
|
109
|
+
expect_a(:scalar) .not_blank
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def autoload_spec(json)
|
|
115
|
+
json .to_be_an(:object) do |object|
|
|
116
|
+
object.expect('psr-0') .to_be_as_defined_in(self, :psr_spec)
|
|
117
|
+
object.expect('psr-4') .to_be_as_defined_in(self, :psr_spec)
|
|
118
|
+
object.expect('classmap') .to_be_as_defined_in(self, :classmaps_spec)
|
|
119
|
+
object.expect('files') .to_be_as_defined_in(self, :files_spec)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def psr_spec(json_spec)
|
|
124
|
+
json_spec .to_be_an(:object) .can_be_absent do
|
|
125
|
+
each_field do
|
|
126
|
+
expect_name
|
|
127
|
+
|
|
128
|
+
expect_a(:list) .not_empty do
|
|
129
|
+
each do
|
|
130
|
+
expect_a(:scalar) .not_blank
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def classmaps_spec(json_spec)
|
|
138
|
+
json_spec .to_be_a(:list) .can_be_absent .not_empty
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def files_spec(json_spec)
|
|
142
|
+
json_spec .to_be_a(:list) .can_be_absent .not_empty
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def self.valid_licenses()
|
|
146
|
+
['Apache-2.0', 'BSD-2-Clause', 'BSD-3-Clause',
|
|
147
|
+
'BSD-4-Clause' ,'GPL-2.0', 'GPL-2.0+', 'GPL-3.0',
|
|
148
|
+
'GPL-3.0+', 'LGPL-2.1', 'LGPL-2.1+', 'LGPL-3.0',
|
|
149
|
+
'LGPL-3.0+', 'MIT']
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
Example_5_CustomExpectations::run
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'cabeza-de-termo/json-spec/json-spec'
|
|
2
|
+
require_relative 'fixtures'
|
|
3
|
+
require_relative 'validation-printer'
|
|
4
|
+
|
|
5
|
+
# To run this example do
|
|
6
|
+
# ruby -I lib examples/example-6-custom-messages.rb
|
|
7
|
+
#
|
|
8
|
+
class Example_6_CustomMessages
|
|
9
|
+
def self.run()
|
|
10
|
+
self.new.run
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def run()
|
|
14
|
+
json_spec = CabezaDeTermo::JsonSpec::JsonSpec.new do
|
|
15
|
+
expect_an(:object) do
|
|
16
|
+
expect('name') .to_be_defined .not_blank
|
|
17
|
+
expect('type') .to_be_defined .not_blank
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
CabezaDeTermo::JsonSpec::ExpectationsLibrary.define do
|
|
22
|
+
expectations do
|
|
23
|
+
define :not_blank do
|
|
24
|
+
message "composer.json does not allow <%= field %> to be blank."
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
validator = json_spec.validate_string( '{ "name": "" }' )
|
|
30
|
+
|
|
31
|
+
ValidationPrinter.new.print_report_of validator
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
Example_6_CustomMessages.run
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
require 'cabeza-de-termo/json-spec/json-spec'
|
|
2
|
+
require_relative 'fixtures'
|
|
3
|
+
require_relative 'validation-printer'
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
# To run self example do
|
|
7
|
+
# ruby -I lib examples/example-7-full-example.rb
|
|
8
|
+
#
|
|
9
|
+
class Example_7_FullExample
|
|
10
|
+
def self.run()
|
|
11
|
+
self.new.run
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def run()
|
|
15
|
+
# Set our ExpectationsLibrary initializer before using it
|
|
16
|
+
CabezaDeTermo::JsonSpec::ExpectationsLibrary
|
|
17
|
+
.set_default_library_initializer( ComposerLibraryInitializer.new )
|
|
18
|
+
|
|
19
|
+
fixtures = [:simple, :empty, :'with-errors-and-non-expected-fields']
|
|
20
|
+
fixtures.each do |eachFixture|
|
|
21
|
+
runFixture(eachFixture)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def runFixture(fixture_name)
|
|
26
|
+
puts "--- Running the fixture '#{fixture_name}' ---\n".colorize(:blue)
|
|
27
|
+
|
|
28
|
+
validator = ComposerJson.new.spec.validate_string( Fixtures.named(fixture_name) )
|
|
29
|
+
|
|
30
|
+
ValidationPrinter.new.print_report_of validator
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
#
|
|
36
|
+
# This is a custom Expectation we implement and use to validate the composer.json version values.
|
|
37
|
+
#
|
|
38
|
+
class IsVersionExpectation < CabezaDeTermo::JsonSpec::Expectation
|
|
39
|
+
def is_satisfied_by?(value_holder)
|
|
40
|
+
# left as exercise to the reader :P
|
|
41
|
+
true
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
#
|
|
46
|
+
# This is the object that defines all the expectations, messages and modifiers that we
|
|
47
|
+
# need to validate a composer.json.
|
|
48
|
+
#
|
|
49
|
+
class ComposerLibraryInitializer
|
|
50
|
+
def new_library()
|
|
51
|
+
library = CabezaDeTermo::JsonSpec::DefaultLibraryInitializer.new.new_library
|
|
52
|
+
define_library(library)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def define_library(library)
|
|
56
|
+
library.define do
|
|
57
|
+
expectations do
|
|
58
|
+
# Custom expectations
|
|
59
|
+
|
|
60
|
+
define :to_be_valid_lincense do
|
|
61
|
+
expecting :to_be_in, ComposerJson.valid_licenses
|
|
62
|
+
message "'<%= format value %>' is not a valid lincense."
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
define :to_be_version do
|
|
66
|
+
with_class IsVersionExpectation
|
|
67
|
+
message "'<%= format value %>' is not a valid version."
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
define :to_be_namespace do
|
|
71
|
+
expecting :to_match, /^[a-zA-Z_\\]+\\$/
|
|
72
|
+
message "'<%= format value %>' is not a valid namespace."
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
define :to_be_psr4_key do
|
|
76
|
+
expecting_any_of :to_be_equal_to, ''
|
|
77
|
+
or_also :to_be_namespace
|
|
78
|
+
|
|
79
|
+
message "'<%= format value %>' is not a valid PSR4 key."
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
define :to_end_with_slash do
|
|
83
|
+
expecting :to_match, /^.+\/$/
|
|
84
|
+
message "'<%= format value %>' does not end with a slash."
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
define :to_be_folder do
|
|
88
|
+
expecting_all_of :to_be_string
|
|
89
|
+
and_also :to_end_with_slash
|
|
90
|
+
|
|
91
|
+
message "'<%= format value %>' is not a valid folder."
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Custom messages
|
|
95
|
+
define :to_be_defined do
|
|
96
|
+
message "composer.json expects <%= field %> to be defined."
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
define :not_blank do
|
|
100
|
+
message "composer.json expects <%= field %> to be a not blank."
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
define :to_be_email do
|
|
104
|
+
message "composer.json expects <%= field %> to be a valid email."
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# I'll add some ExpressionModifier examples someday ...
|
|
109
|
+
modifiers do
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
library
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
#
|
|
118
|
+
# This is the class where we define all the sections of the composer.json we are going
|
|
119
|
+
# to validate.
|
|
120
|
+
#
|
|
121
|
+
class ComposerJson
|
|
122
|
+
def spec()
|
|
123
|
+
CabezaDeTermo::JsonSpec::JsonSpec.new do |spec|
|
|
124
|
+
spec.expect_an(:object) do |object|
|
|
125
|
+
object.expect('name') .not_blank
|
|
126
|
+
object.expect('type') .not_blank
|
|
127
|
+
object.expect('description') .not_blank
|
|
128
|
+
object.expect('keywords') .to_be_as_defined_in(self, :keywords_spec)
|
|
129
|
+
object.expect('homepage') .to_be_url
|
|
130
|
+
object.expect('license') .to_be_valid_lincense
|
|
131
|
+
object.expect('authors') .to_be_as_defined_in(self, :authors_spec)
|
|
132
|
+
object.expect('require') .to_be_as_defined_in(self, :require_spec)
|
|
133
|
+
object.expect('require-dev') .to_be_as_defined_in(self, :require_spec)
|
|
134
|
+
object.expect('autoload') .to_be_as_defined_in(self, :autoload_spec)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def keywords_spec(json_spec)
|
|
140
|
+
json_spec.to_be_a(:list) .can_be_absent .not_empty do
|
|
141
|
+
each do
|
|
142
|
+
expect_a(:scalar) .not_blank
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def authors_spec(json_spec)
|
|
148
|
+
json_spec .to_be_a(:list) .not_empty do |list|
|
|
149
|
+
list.each do |each|
|
|
150
|
+
each.to_be_as_defined_in(self, :author_spec)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def author_spec(json_spec)
|
|
156
|
+
json_spec
|
|
157
|
+
.expect_an(:object) do
|
|
158
|
+
expect('name') .not_blank
|
|
159
|
+
expect('email') .to_be_email
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def require_spec(json_spec)
|
|
164
|
+
json_spec .to_be_an(:object) .can_be_absent do
|
|
165
|
+
each_field do
|
|
166
|
+
expect_name .not_blank
|
|
167
|
+
|
|
168
|
+
expect_a(:scalar) .to_be_version
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def autoload_spec(json_spec)
|
|
174
|
+
json_spec .to_be_an(:object) do |object|
|
|
175
|
+
object.expect('psr-0') .to_be_as_defined_in(self, :psr0_spec)
|
|
176
|
+
object.expect('psr-4') .to_be_as_defined_in(self, :psr4_spec)
|
|
177
|
+
object.expect('classmap') .to_be_as_defined_in(self, :classmaps_spec)
|
|
178
|
+
object.expect('files') .to_be_as_defined_in(self, :files_spec)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def psr4_spec(json_spec)
|
|
183
|
+
json_spec .to_be_an(:object) .can_be_absent do |object|
|
|
184
|
+
object.each_field do |field|
|
|
185
|
+
field.expect_name .to_be_psr4_key
|
|
186
|
+
|
|
187
|
+
field.to_be_as_defined_in(self, :folder_or_folder_list_spec)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def psr0_spec(json_spec)
|
|
193
|
+
json_spec .to_be_an(:object) .can_be_absent do |object|
|
|
194
|
+
object.each_field do |field|
|
|
195
|
+
field.expect_name .to_be_string
|
|
196
|
+
|
|
197
|
+
field.to_be_as_defined_in(self, :folder_or_folder_list_spec)
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def folder_or_folder_list_spec(json_spec)
|
|
203
|
+
json_spec
|
|
204
|
+
.expect(:any_of) do
|
|
205
|
+
expect_a(:scalar) .to_be_folder
|
|
206
|
+
or_also
|
|
207
|
+
expect_a(:list) .not_empty do
|
|
208
|
+
each do
|
|
209
|
+
expect_a(:scalar) .to_be_folder
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def classmaps_spec(json_spec)
|
|
216
|
+
json_spec .to_be_a(:list) .can_be_absent .not_empty
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def files_spec(json_spec)
|
|
220
|
+
json_spec .to_be_a(:list) .can_be_absent .not_empty
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def self.valid_licenses()
|
|
224
|
+
['Apache-2.0', 'BSD-2-Clause', 'BSD-3-Clause',
|
|
225
|
+
'BSD-4-Clause' ,'GPL-2.0', 'GPL-2.0+', 'GPL-3.0',
|
|
226
|
+
'GPL-3.0+', 'LGPL-2.1', 'LGPL-2.1+', 'LGPL-3.0',
|
|
227
|
+
'LGPL-3.0+', 'MIT']
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
Example_7_FullExample.run
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
class Fixtures
|
|
2
|
+
def self.all
|
|
3
|
+
{
|
|
4
|
+
simple:
|
|
5
|
+
'{
|
|
6
|
+
"name": "cabeza-de-termo/json-spec",
|
|
7
|
+
"type": "library",
|
|
8
|
+
"description": "A framework to declare expectations on a json format, and verify that a json object complies with those expectations. All using a very understandable, customizable and extensible idiom made entirely with PHP plain old objects.",
|
|
9
|
+
"keywords": ["json", "assertions", "expectations", "validation", "test"],
|
|
10
|
+
"homepage": "https://github.com/cabeza-de-termo/php-json-spec",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"authors": [
|
|
13
|
+
{
|
|
14
|
+
"name": "Martin Rubi",
|
|
15
|
+
"email": "martin.rubi@martinrubi.com"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"require": {
|
|
19
|
+
"php": ">=5.4.0"
|
|
20
|
+
},
|
|
21
|
+
"require-dev": {
|
|
22
|
+
"phpunit/phpunit": "^4",
|
|
23
|
+
"phpdocumentor/phpdocumentor": "2.*"
|
|
24
|
+
},
|
|
25
|
+
"autoload": {
|
|
26
|
+
"psr-4": {
|
|
27
|
+
"CabezaDeTermoJsonSpec\\\\": ["src/"],
|
|
28
|
+
"CabezaDeTermo\\\\JsonSpec\\\\Tests\\\\": ["tests/"]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}',
|
|
32
|
+
|
|
33
|
+
empty:
|
|
34
|
+
'{}',
|
|
35
|
+
|
|
36
|
+
:'with-errors-and-non-expected-fields' =>
|
|
37
|
+
'{
|
|
38
|
+
"name": "cabeza-de-termo/json-spec",
|
|
39
|
+
"type": "library",
|
|
40
|
+
"description": "A framework to declare expectations on a json format, and verify that a json object complies with those expectations. All using a very understandable, customizable and extensible idiom made entirely with PHP plain old objects.",
|
|
41
|
+
"keywords": ["json", "Expectations", "expectations", "validation", "phpunit"],
|
|
42
|
+
"homepage": "https://github.com/cabeza-de-termo/php-json-spec",
|
|
43
|
+
"time": "2015-10-31",
|
|
44
|
+
"license": "None",
|
|
45
|
+
"authors": [
|
|
46
|
+
{
|
|
47
|
+
"name": "Martin Rubi",
|
|
48
|
+
"email": "martin.rubi@martinrubi.com."
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"require": {
|
|
52
|
+
"php": ">=5.4.0"
|
|
53
|
+
},
|
|
54
|
+
"require-dev": {
|
|
55
|
+
"phpunit/phpunit": "^4",
|
|
56
|
+
"phpdocumentor/phpdocumentor": "2.*"
|
|
57
|
+
},
|
|
58
|
+
"autoload": {
|
|
59
|
+
"psr-4": {
|
|
60
|
+
"CabezaDeTermoJsonSpec\\\\": "src/",
|
|
61
|
+
"CabezaDeTermo\\\\JsonSpec\\\\Tests\\\\": ["tests/"],
|
|
62
|
+
"AClassWithNoNamespace": ["src/"],
|
|
63
|
+
"": 123
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
"psr-0": {
|
|
67
|
+
"CabezaDeTermoJsonSpec": [123]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}'
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def self.named(fixture_name)
|
|
75
|
+
all[fixture_name]
|
|
76
|
+
end
|
|
77
|
+
end
|