media_types 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +70 -63
- data/Gemfile.lock +43 -41
- data/LICENSE +21 -0
- data/README.md +276 -32
- data/lib/media_types.rb +46 -2
- data/lib/media_types/constructable.rb +8 -2
- data/lib/media_types/dsl.rb +60 -17
- data/lib/media_types/dsl/errors.rb +18 -0
- data/lib/media_types/errors.rb +19 -0
- data/lib/media_types/scheme.rb +123 -18
- data/lib/media_types/scheme/errors.rb +60 -0
- data/lib/media_types/scheme/links.rb +15 -0
- data/lib/media_types/scheme/output_type_guard.rb +1 -3
- data/lib/media_types/scheme/rules.rb +54 -3
- data/lib/media_types/scheme/rules_exhausted_guard.rb +10 -0
- data/lib/media_types/scheme/validation_options.rb +5 -4
- data/lib/media_types/testing/assertions.rb +20 -0
- data/lib/media_types/validations.rb +7 -4
- data/lib/media_types/version.rb +1 -1
- data/media_types.gemspec +1 -1
- metadata +12 -9
- data/lib/media_types/minitest/assert_media_type_format.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d034c7e7a7fd3a142dd997efab0d1c3e61f2cbe3170078544f4f456c485ad4ec
|
4
|
+
data.tar.gz: 20dbb0fbdf7e9f93c79575239de5e9a4e2220dbd7d3a0fe1d41145c1b2a97b54
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b589dbf3292df73632d3d8c98b6b73ed2dec08099b64406b4a1ca2c2cbe19b5cf7161efefc2b05c3bff634b03b6056c6a8f4770ac038e559710415bbad663e10
|
7
|
+
data.tar.gz: 2ce0c0747e94f01de399e28cd262b921912097c9bfea2d205abcb11937f116d078366ebcee8a8f0999c12cada9a7b1ce1093ad51d80d397cfc73d5cd145424f8
|
data/CHANGELOG.md
CHANGED
@@ -1,41 +1,48 @@
|
|
1
|
-
#
|
1
|
+
# Changelog
|
2
2
|
|
3
|
-
|
4
|
-
- Attribute keys no longer match indifferently.
|
5
|
-
- Fixed infinite loop when validating non-hash, non-array items.
|
3
|
+
## 2.1.0
|
6
4
|
|
7
|
-
|
5
|
+
- Add `override_suffix` to force a specific suffix
|
6
|
+
- Fix all deprecation warnings
|
8
7
|
|
9
|
-
|
10
|
-
- Suffixes are now set for a given view and version instead of as a block.
|
11
|
-
- Added `suffix :yoursuffix` command to override the default `:json` suffix.
|
12
|
-
- Removed defaults block.
|
13
|
-
- Removed registrations block.
|
8
|
+
## 2.0.1
|
14
9
|
|
15
|
-
|
10
|
+
- Views can now be accessed indifferently.
|
11
|
+
- Attribute keys no longer match indifferently.
|
12
|
+
- Fixed infinite loop when validating non-hash, non-array items.
|
16
13
|
|
17
|
-
|
18
|
-
- `media_type` has been replaced with `use_name`.
|
19
|
-
- It is no longer possible to set a default version. Please use `version <x> do` instead.
|
20
|
-
- You no longer need to specify a custom format string. If you set an organisation with `def self.organisation` or set a module wide organisation with `MediaTypes::set_organisation <module>, '<organisation>'` the library will generate identifiers for you.
|
21
|
-
- `self.base_format` has been replaced by `identifier_format do |type:, view:, version:, suffix:|`.
|
22
|
-
- Added the `empty` validation to mark an empty object as valid.
|
23
|
-
- Added the `identifier` function to get the [Media Type Identifier](https://en.wikipedia.org/wiki/Media_type) for the validator.
|
24
|
-
- Added `version(x)` and `view(x)` functions.
|
25
|
-
- Added an `available_validations` functions that returns all defined validations.
|
26
|
-
- Fixed an issue where validations could accidentally merge if defined with a bad `base_format`.
|
27
|
-
- Fixed an issue where undefined validations would accept an empty object.
|
14
|
+
## 2.0.0
|
28
15
|
|
29
|
-
|
16
|
+
- Removed ability to set default suffix. All suffixes now default to `+json`.
|
17
|
+
- Suffixes are now set for a given view and version instead of as a block.
|
18
|
+
- Added `suffix :yoursuffix` command to override the default `:json` suffix.
|
19
|
+
- Removed defaults block.
|
20
|
+
- Removed registrations block.
|
21
|
+
|
22
|
+
## 1.0.0
|
23
|
+
|
24
|
+
- Added the ability to do inline tests when defining validations using `assert_pass '<json>'` and `assert_fail '<json>'`.
|
25
|
+
- `media_type` has been replaced with `use_name`.
|
26
|
+
- It is no longer possible to set a default version. Please use `version <x> do` instead.
|
27
|
+
- You no longer need to specify a custom format string. If you set an organisation with `def self.organisation` or set a module wide organisation with `MediaTypes::set_organisation <module>, '<organisation>'` the library will generate identifiers for you.
|
28
|
+
- `self.base_format` has been replaced by `identifier_format do |type:, view:, version:, suffix:|`.
|
29
|
+
- Added the `empty` validation to mark an empty object as valid.
|
30
|
+
- Added the `identifier` function to get the [Media Type Identifier](https://en.wikipedia.org/wiki/Media_type) for the validator.
|
31
|
+
- Added `version(x)` and `view(x)` functions.
|
32
|
+
- Added an `available_validations` functions that returns all defined validations.
|
33
|
+
- Fixed an issue where validations could accidentally merge if defined with a bad `base_format`.
|
34
|
+
- Fixed an issue where undefined validations would accept an empty object.
|
35
|
+
|
36
|
+
## 0.6.2
|
30
37
|
|
31
38
|
- Fix handling empty collections
|
32
39
|
|
33
|
-
|
40
|
+
## 0.6.1
|
34
41
|
|
35
42
|
- Fix no `validations` error on `validatable?` (now returns `false`)
|
36
43
|
- Update `bundler` to `2.x`
|
37
44
|
|
38
|
-
|
45
|
+
## 0.6.0
|
39
46
|
|
40
47
|
- Change default expected type for `attribute` to Object
|
41
48
|
- Remove default `actionpack` calls for `.register`
|
@@ -43,28 +50,28 @@
|
|
43
50
|
- Add integration for registering with `http` (http.rb)
|
44
51
|
- Fix stack overflow for cyclic schema
|
45
52
|
|
46
|
-
|
53
|
+
## 0.5.5
|
47
54
|
|
48
55
|
- Fix an issue with `attribute(optional:, &block)` not passing `optional:` to the created `collection`.
|
49
56
|
|
50
|
-
|
57
|
+
## 0.5.4
|
51
58
|
|
52
59
|
- Fix formatter reworked template when fields are not present
|
53
60
|
|
54
|
-
|
61
|
+
## 0.5.3
|
55
62
|
|
56
63
|
- Remove `require 'awesome_print'` in library code as it's marked as a development dependency onlvy
|
57
64
|
|
58
|
-
|
65
|
+
## 0.5.2
|
59
66
|
|
60
67
|
- Add requires in files with missing requires
|
61
68
|
|
62
|
-
|
69
|
+
## 0.5.1
|
63
70
|
|
64
71
|
- Fix merging optional attributes
|
65
72
|
- Change `#inspect` to look like a tree
|
66
73
|
|
67
|
-
|
74
|
+
## 0.5.0
|
68
75
|
|
69
76
|
- Change internal representation of key to symbol
|
70
77
|
- Change default type from `nil` to `Object`, removing special behaviour for nil
|
@@ -83,11 +90,11 @@
|
|
83
90
|
- Raise error if `self.base_format` is not available at time of `Dsl.media_type` call
|
84
91
|
- Fix `expected_type` guard for arrays, nil, or arrays with nil.
|
85
92
|
|
86
|
-
|
93
|
+
## 0.4.1
|
87
94
|
|
88
95
|
- Use strings for `:_links`, matching the other validation keys
|
89
96
|
|
90
|
-
|
97
|
+
## 0.4.0
|
91
98
|
|
92
99
|
- Simplify `assert_media_type_format` by dumping views completely
|
93
100
|
- Add test for `merge`
|
@@ -95,59 +102,59 @@
|
|
95
102
|
- Add test for `validatable?`
|
96
103
|
- Add block passing to `Scheme.new`
|
97
104
|
|
98
|
-
|
105
|
+
## 0.3.0
|
99
106
|
|
100
107
|
- Add `merge` dsl to merge two `Scheme`
|
101
108
|
|
102
|
-
|
109
|
+
## 0.2.6
|
103
110
|
|
104
111
|
- Change validation to accept both symbolised and stringified input ánd validations
|
105
112
|
|
106
|
-
|
113
|
+
## 0.2.5
|
107
114
|
|
108
115
|
- Add automatic require for `media_types/scheme/any_of`
|
109
116
|
|
110
|
-
|
117
|
+
## 0.2.4
|
111
118
|
|
112
119
|
- Change messages for `assert_media_types_registered` to be more informative and consistent
|
113
120
|
|
114
|
-
|
121
|
+
## 0.2.3
|
115
122
|
|
116
123
|
- Fix an issue with `Hash#compact` which was introduce in 2.4+. Now works with Ruby 2.3
|
117
124
|
|
118
|
-
|
125
|
+
## 0.2.2
|
119
126
|
|
120
127
|
- Fix an issue with `Registrar#versions`
|
121
128
|
- Fix link in the gemspec to Github
|
122
129
|
|
123
|
-
|
130
|
+
## 0.2.1
|
124
131
|
|
125
|
-
- Fix an issue with `Constructable#valid?` and `Constructable#validate!`
|
132
|
+
- Fix an issue with `Constructable#valid?` and `Constructable#validate!`
|
126
133
|
|
127
|
-
|
134
|
+
## 0.2.0
|
128
135
|
|
129
136
|
Breaking changes to update public API and usage
|
130
137
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
138
|
+
- Remove `Base` class (use `MediaTypes::Dsl` instead)
|
139
|
+
- Remove a lot of configuration options as they are deemed unneeded
|
140
|
+
- Remove `active_support` dependency
|
141
|
+
- Rename `ConstructableMimeType` to `Constructable`
|
142
|
+
- Moved global scheme types to `Scheme` as subtype
|
143
|
+
- Add `MediaTypes::Dsl`
|
144
|
+
- Add `validations` block to capture schemes
|
145
|
+
- Add `registrations` block to capture register intent
|
146
|
+
- Add `defaults` block to capture mime type defaults
|
147
|
+
- Add `MediaTypes.register` class method to call `Mime::Type.register`
|
148
|
+
- Add `Registerable` capture class
|
149
|
+
- Add type / base setting for `Constructable`
|
150
|
+
- Add versioned validations
|
151
|
+
- Add forced types of `collection`s
|
152
|
+
- Add `attribute` with block
|
153
|
+
- Add `EnumerationOfType` for schema typed arrays
|
154
|
+
- Add `AnyOf` for scheme enum types
|
155
|
+
- Add non-block calls for `Scheme` dsl
|
156
|
+
- Add yard documentation to `/docs`
|
157
|
+
|
158
|
+
## 0.1.0
|
152
159
|
|
153
160
|
:baby: initial release
|
data/Gemfile.lock
CHANGED
@@ -1,41 +1,43 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
media_types (2.0
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
ansi (1.5.0)
|
10
|
-
awesome_print (1.
|
11
|
-
builder (3.2.4)
|
12
|
-
docile (1.
|
13
|
-
minitest (5.14.
|
14
|
-
minitest-reporters (1.4.
|
15
|
-
ansi
|
16
|
-
builder
|
17
|
-
minitest (>= 5.0)
|
18
|
-
ruby-progressbar
|
19
|
-
oj (3.
|
20
|
-
rake (13.0.
|
21
|
-
ruby-progressbar (1.
|
22
|
-
simplecov (0.
|
23
|
-
docile (~> 1.1)
|
24
|
-
simplecov-html (~> 0.11)
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
media_types (2.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ansi (1.5.0)
|
10
|
+
awesome_print (1.9.2)
|
11
|
+
builder (3.2.4)
|
12
|
+
docile (1.4.0)
|
13
|
+
minitest (5.14.4)
|
14
|
+
minitest-reporters (1.4.3)
|
15
|
+
ansi
|
16
|
+
builder
|
17
|
+
minitest (>= 5.0)
|
18
|
+
ruby-progressbar
|
19
|
+
oj (3.13.1)
|
20
|
+
rake (13.0.6)
|
21
|
+
ruby-progressbar (1.11.0)
|
22
|
+
simplecov (0.21.2)
|
23
|
+
docile (~> 1.1)
|
24
|
+
simplecov-html (~> 0.11)
|
25
|
+
simplecov_json_formatter (~> 0.1)
|
26
|
+
simplecov-html (0.12.3)
|
27
|
+
simplecov_json_formatter (0.1.3)
|
28
|
+
|
29
|
+
PLATFORMS
|
30
|
+
x64-mingw32
|
31
|
+
|
32
|
+
DEPENDENCIES
|
33
|
+
awesome_print
|
34
|
+
bundler (>= 2)
|
35
|
+
media_types!
|
36
|
+
minitest (~> 5.0)
|
37
|
+
minitest-reporters
|
38
|
+
oj
|
39
|
+
rake (>= 12.0)
|
40
|
+
simplecov
|
41
|
+
|
42
|
+
BUNDLED WITH
|
43
|
+
2.2.7
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2020 Derk-Jan Karrenbeld
|
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
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
[![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)
|
5
5
|
[![Maintainability](https://api.codeclimate.com/v1/badges/6f2dc1fb37ecb98c4363/maintainability)](https://codeclimate.com/github/SleeplessByte/media-types-ruby/maintainability)
|
6
6
|
|
7
|
-
Media Types based on scheme, with versioning, views, suffixes and validations.
|
7
|
+
Media Types based on scheme, with versioning, views, suffixes and validations.
|
8
8
|
|
9
9
|
This library makes it easy to define schemas that can be used to validate JSON objects based on their Content-Type.
|
10
10
|
|
@@ -114,13 +114,13 @@ If you include 'MediaTypes::Dsl' in your class you can use the following functio
|
|
114
114
|
|
115
115
|
Adds an attribute to the schema, if a +block+ is given, uses that to test against instead of +type+
|
116
116
|
|
117
|
-
| param
|
118
|
-
|
119
|
-
| key
|
120
|
-
| opts
|
121
|
-
| type
|
122
|
-
| optional: | `TrueClass`, `FalseClass` | if true, key may be absent, defaults to `false`
|
123
|
-
| &block
|
117
|
+
| param | type | description |
|
118
|
+
| --------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
119
|
+
| key | `Symbol` | the attribute name |
|
120
|
+
| opts | `Hash` | options to pass to `Scheme` or `Attribute` |
|
121
|
+
| type | `Class`, `===`, Scheme | The type of the value can be anything that responds to `===`, or scheme to use if no `&block` is given. Defaults to `Object` without a `&block` and to Hash with a `&block`. |
|
122
|
+
| optional: | `TrueClass`, `FalseClass` | if true, key may be absent, defaults to `false` |
|
123
|
+
| &block | `Block` | defines the scheme of the value of this attribute |
|
124
124
|
|
125
125
|
#### Add an attribute named foo, expecting a string
|
126
126
|
```Ruby
|
@@ -158,12 +158,12 @@ MyMedia.valid?({ foo: { bar: 'my-string' }})
|
|
158
158
|
### `any`
|
159
159
|
Allow for any key. The `&block` defines the Schema for each value.
|
160
160
|
|
161
|
-
| param
|
162
|
-
|
163
|
-
| scheme
|
164
|
-
| allow_empty:
|
165
|
-
| expected_type: | `Class`,
|
166
|
-
| &block
|
161
|
+
| param | type | description |
|
162
|
+
| -------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------ |
|
163
|
+
| scheme | `Scheme`, `NilClass` | scheme to use if no `&block` is given |
|
164
|
+
| allow_empty: | `TrueClass`, `FalsClass` | if true, empty (no key/value present) is allowed |
|
165
|
+
| expected_type: | `Class`, | forces the validated value to have this type, defaults to `Hash`. Use `Object` if either `Hash` or `Array` is fine |
|
166
|
+
| &block | `Block` | defines the scheme of the value of this attribute |
|
167
167
|
|
168
168
|
#### Add a collection named foo, expecting any key with a defined value
|
169
169
|
```Ruby
|
@@ -207,14 +207,14 @@ MyMedia.valid?({ foo: [{ required: 'test', bar: 42 }] })
|
|
207
207
|
### `collection`
|
208
208
|
Expect a collection such as an array or hash. The `&block` defines the Schema for each item in that collection.
|
209
209
|
|
210
|
-
| param
|
211
|
-
|
212
|
-
| key
|
213
|
-
| scheme
|
214
|
-
| allow_empty:
|
215
|
-
| expected_type: | `Class`,
|
216
|
-
| optional:
|
217
|
-
| &block
|
210
|
+
| param | type | description |
|
211
|
+
| -------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
212
|
+
| key | `Symbol` | key of the collection (same as `#attribute`) |
|
213
|
+
| scheme | `Scheme`, `NilClass`, `Class` | scheme to use if no `&block` is given or `Class` of each item in the collection |
|
214
|
+
| allow_empty: | `TrueClass`, `FalseClass` | if true, empty (no key/value present) is allowed |
|
215
|
+
| expected_type: | `Class`, | forces the validated value to have this type, defaults to `Array`. Use `Object` if either `Array` or `Hash` is fine. |
|
216
|
+
| optional: | `TrueClass`, `FalseClass` | if true, key may be absent, defaults to `false` |
|
217
|
+
| &block | `Block` | defines the scheme of the value of this attribute |
|
218
218
|
|
219
219
|
|
220
220
|
#### Collection with an array of string
|
@@ -253,12 +253,12 @@ MyMedia.valid?({ foo: [{ required: 'test', number: 42 }, { required: 'other', nu
|
|
253
253
|
|
254
254
|
Expect a link with a required `href: String` attribute
|
255
255
|
|
256
|
-
| param
|
257
|
-
|
258
|
-
| key
|
259
|
-
| allow_nil: | `TrueClass`, `FalseClass` | if true, value may be nil
|
260
|
-
| optional:
|
261
|
-
| &block
|
256
|
+
| param | type | description |
|
257
|
+
| ---------- | ------------------------- | -------------------------------------------------------------------------------------- |
|
258
|
+
| key | `Symbol` | key of the link (same as `#attribute`) |
|
259
|
+
| allow_nil: | `TrueClass`, `FalseClass` | if true, value may be nil |
|
260
|
+
| optional: | `TrueClass`, `FalseClass` | if true, key may be absent, defaults to `false` |
|
261
|
+
| &block | `Block` | defines the scheme of the value of this attribute, in addition to the `href` attribute |
|
262
262
|
|
263
263
|
#### Links as defined in HAL, JSON-Links and other specs
|
264
264
|
```Ruby
|
@@ -266,7 +266,7 @@ class MyMedia
|
|
266
266
|
include MediaTypes::Dsl
|
267
267
|
|
268
268
|
validations do
|
269
|
-
link :
|
269
|
+
link :self
|
270
270
|
link :image
|
271
271
|
end
|
272
272
|
end
|
@@ -365,7 +365,7 @@ Allows passing in validation options as a second parameter.
|
|
365
365
|
|
366
366
|
Example: `Venue.version(42).validatable?`
|
367
367
|
|
368
|
-
Tests
|
368
|
+
Tests whether the current configuration of the schema has a validation defined.
|
369
369
|
|
370
370
|
### `register`
|
371
371
|
|
@@ -403,10 +403,254 @@ Example: `Venue.available_validations`
|
|
403
403
|
|
404
404
|
Returns a list of all the schemas that are defined.
|
405
405
|
|
406
|
+
## Ensuring Your MediaTypes Work
|
407
|
+
|
408
|
+
### Overview & Rationale
|
409
|
+
|
410
|
+
If the MediaTypes you create enforce a specification you _do not expect them to_, it will cause problems that will be very difficult to fix, as other code, which utilises your MediaType, would break when you change the specification. This is because the faulty MediaType definition will start to make other code dependent on the specification it defines. For example, consider what would happen if you release a MediaType which defines an attribute `foo` to be a `String`, and run a server which defines such a specification. Later, you realise you _actually_ wanted `foo` to be `Numeric`. What can you do?
|
411
|
+
|
412
|
+
Well, during this time, other people started to write code which conformed to the specification defined by the faulty MediaType. So, it's going to be extremely difficult to revert your mistake. For this reason, it is vital that, when using this library, your MediaTypes define the _correct_ specification.
|
413
|
+
|
414
|
+
To this end, we provide you with a few avenues to check whether MediaTypes define the specifications you actually intend by checking examples of JSON you expect to be compliant/non-compliant with the MediaType definitions you write out.
|
415
|
+
|
416
|
+
These are as follows:
|
417
|
+
|
418
|
+
1. The library provides [two methods](README.md#media-type-checking-in-test-suites) (`assert_pass` and `assert_fail`), which allow specifying JSON fixtures that are compliant (`assert_pass`) or non-compliant (`assert_fail`).
|
419
|
+
2. The library provides a way to validate those fixtures against the MediaType specification with the [`assert_mediatype`](README.md#media-type-checking-in-test-suites) method.
|
420
|
+
3. The library automatically performs a MediaType's checks defined by (1) the first time an object is validated against the MediaType, and throws an error if any of the checks fail.
|
421
|
+
4. The library provides a way to run the checks carried out by (3) on load, using the method [`assert_sane!`](README.md#validation-checks) so that an application will not run if any of the MediaType's checks don't pass.
|
422
|
+
|
423
|
+
These four options are examined in detail below.
|
424
|
+
|
425
|
+
### MediaType Checking in Test Suites
|
426
|
+
|
427
|
+
The library provides the `assert_mediatype` method, which allows running the checks for a particular `MediaType` within Minitest with `assert_pass` and `assert_fail`.
|
428
|
+
If you are using Minitest, you can make `assert_mediatype` available by calling `include MediaTypes::Testing::Assertions` in the test class (e.g. `Minitest::Runnable`):
|
429
|
+
|
430
|
+
```ruby
|
431
|
+
module Minitest
|
432
|
+
class Test < Minitest::Runnable
|
433
|
+
include MediaTypes::Testing::Assertions
|
434
|
+
end
|
435
|
+
end
|
436
|
+
```
|
437
|
+
|
438
|
+
The example below demonstrates how to use `assert_pass` and `assert_fail` within a MediaType, and how to use the `assert_mediatype` method in MiniTest tests to validate them.
|
439
|
+
|
440
|
+
```ruby
|
441
|
+
class MyMedia
|
442
|
+
include MediaTypes::Dsl
|
443
|
+
|
444
|
+
def self.organisation
|
445
|
+
'acme'
|
446
|
+
end
|
447
|
+
|
448
|
+
use_name 'test'
|
449
|
+
|
450
|
+
validations do
|
451
|
+
# Using "any Numeric" this MediaType doesn't care what key names you use.
|
452
|
+
# However, it does care that those keys point to a Numeric value.
|
453
|
+
any Numeric
|
454
|
+
|
455
|
+
assert_pass '{"foo": 42}'
|
456
|
+
assert_pass <<-FIXTURE
|
457
|
+
{ "foo": 42, "bar": 43 }
|
458
|
+
FIXTURE
|
459
|
+
|
460
|
+
# The keyword "any" means there are no required keys, so having no keys should also pass.
|
461
|
+
assert_pass '{}'
|
462
|
+
|
463
|
+
# This MediaType should not accept anything other then a Numeric value.
|
464
|
+
assert_fail <<-FIXTURE
|
465
|
+
{ "foo": { "bar": "string" } }
|
466
|
+
FIXTURE
|
467
|
+
assert_fail '{"foo": {}}'
|
468
|
+
assert_fail '{"foo": null}'
|
469
|
+
assert_fail '{"foo": [42]}'
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
class MyMediaTest < Minitest::Test
|
474
|
+
include MediaTypes::Testing::Assertions
|
475
|
+
|
476
|
+
def test_mediatype_specification
|
477
|
+
assert_mediatype MyMedia
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
class MyMediaTest < Minitest::Test
|
482
|
+
include MediaTypes::Testing::Assertions
|
483
|
+
|
484
|
+
def test_mediatype_specification
|
485
|
+
assert_mediatype MyMedia
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
```
|
490
|
+
|
491
|
+
### Testing Without Minitest
|
492
|
+
|
493
|
+
If you are using another testing framework, you will not be able to use the `assert_mediatype` method. Instead, you can test your MediaTypes by using the `assert_sane!` method (documented below) and rescuing the errors it will throw when it fails. The snippet below shows an example adaptation for MiniTest, which you can use as a guide.
|
494
|
+
|
495
|
+
```ruby
|
496
|
+
def test_mediatype(mediatype)
|
497
|
+
mediatype.assert_sane!
|
498
|
+
assert mediatype.media_type_validations.scheme.asserted_sane?
|
499
|
+
rescue MediaTypes::AssertionError => e
|
500
|
+
flunk e.message
|
501
|
+
end
|
502
|
+
end
|
503
|
+
```
|
504
|
+
|
505
|
+
### Validation Checks
|
506
|
+
|
507
|
+
The `assert_pass` and `assert_fail` methods take a JSON string (as shown below). The first time the `validate!` method is called on a MediaType, the assertions for that media type are run.
|
508
|
+
This is done as a last line of defence against introducing faulty MediaTypes into your software. Ideally, you want to carry out these checks on load rather than on a running application. This functionality is provided by the `assert_sane!` method, which can be called on a particular MediaType:
|
509
|
+
|
510
|
+
```ruby
|
511
|
+
MyMedia.assert_sane!
|
512
|
+
# true
|
513
|
+
```
|
514
|
+
|
515
|
+
### Intermediate Checks
|
516
|
+
|
517
|
+
The fixtures provided to the `assert_pass` and `assert_fail` methods are evaluated within the context of the block they are placed in. It's therefore possible to write a test for a (complex) optional attribute, without that test cluttering the fixtures for the entire mediatype.
|
518
|
+
|
519
|
+
```ruby
|
520
|
+
class MyMedia
|
521
|
+
include MediaTypes::Dsl
|
522
|
+
|
523
|
+
expect_string_keys
|
524
|
+
|
525
|
+
def self.organisation
|
526
|
+
'acme'
|
527
|
+
end
|
528
|
+
|
529
|
+
use_name 'test'
|
530
|
+
|
531
|
+
validations do
|
532
|
+
attribute :foo, Hash, optional: true do
|
533
|
+
attribute :bar, Numeric
|
534
|
+
|
535
|
+
# This passes, since in this context the "bar" key is required to have a Numeric value.
|
536
|
+
assert_pass '{"bar": 42}'
|
537
|
+
end
|
538
|
+
attribute :rep, Numeric
|
539
|
+
|
540
|
+
# This passes, since the attribute "foo" is optional.
|
541
|
+
assert_pass '{"rep": 42}'
|
542
|
+
end
|
543
|
+
end
|
544
|
+
```
|
545
|
+
|
546
|
+
## Key Type Validation
|
547
|
+
|
548
|
+
When interacting with Ruby objects defined by your MediaType, you want to avoid getting `nil` values, just because the the wrong key type is being used (e.g. `obj['foo']` instead of `obj[:foo]`).
|
549
|
+
To this end, the library provides the ability to specify the expected type of keys in a MediaType; by default symbol keys are expected.
|
550
|
+
|
551
|
+
### Setting Key Type Expectations
|
552
|
+
|
553
|
+
Key type expectations can be set at the module level. Each MediaType within this module will inherit the expectation set by that module.
|
554
|
+
|
555
|
+
```ruby
|
556
|
+
module Acme
|
557
|
+
MediaTypes.expect_string_keys(self)
|
558
|
+
|
559
|
+
# The MyMedia class expects string keys, as inherited from the Acme module.
|
560
|
+
class MyMedia
|
561
|
+
include MediaTypes::Dsl
|
562
|
+
|
563
|
+
def self.organisation
|
564
|
+
'acme'
|
565
|
+
end
|
566
|
+
|
567
|
+
use_name 'test'
|
568
|
+
|
569
|
+
validations do
|
570
|
+
any Numeric
|
571
|
+
end
|
572
|
+
end
|
573
|
+
end
|
574
|
+
```
|
575
|
+
|
576
|
+
If you validate an object with a different key type than expected, an error will be thrown:
|
577
|
+
|
578
|
+
```ruby
|
579
|
+
Acme::MyMedia.validate! { "something": 42 }
|
580
|
+
# => passes, because all keys are a string
|
581
|
+
|
582
|
+
Acme::MyMedia.validate! { something: 42 }
|
583
|
+
# => throws a ValidationError , because 'something' is a symbol key
|
584
|
+
```
|
585
|
+
|
586
|
+
## Overriding Key Type Expectations
|
587
|
+
|
588
|
+
A key type expectation set by a Module can be overridden by calling either `expect_symbol_keys` or `expect_string_keys` inside the MediaType class.
|
589
|
+
|
590
|
+
```ruby
|
591
|
+
module Acme
|
592
|
+
MediaTypes.expect_string_keys(self)
|
593
|
+
|
594
|
+
class MyOverridingMedia
|
595
|
+
include MediaTypes::Dsl
|
596
|
+
|
597
|
+
def self.organisation
|
598
|
+
'acme'
|
599
|
+
end
|
600
|
+
|
601
|
+
use_name 'test'
|
602
|
+
|
603
|
+
# Expect keys to be symbols
|
604
|
+
expect_symbol_keys
|
605
|
+
|
606
|
+
validations do
|
607
|
+
any Numeric
|
608
|
+
end
|
609
|
+
end
|
610
|
+
end
|
611
|
+
```
|
612
|
+
|
613
|
+
Now the MediaType throws an error when string keys are used.
|
614
|
+
|
615
|
+
```ruby
|
616
|
+
Acme::MyOverridingMedia.validate! { something: 42 }
|
617
|
+
# => passes, because all keys are a symbol
|
618
|
+
|
619
|
+
Acme::MyOverridingMedia.validate! { "something": 42 }
|
620
|
+
# => throws a ValidationError , because 'something' is a string key
|
621
|
+
```
|
622
|
+
|
623
|
+
### Setting The JSON Parser With The Wrong Key Type
|
624
|
+
|
625
|
+
If you parse JSON with the wrong key type, as shown below, the resultant object will fail the validations.
|
626
|
+
|
627
|
+
```ruby
|
628
|
+
class MyMedia
|
629
|
+
include MediaTypes::Dsl
|
630
|
+
|
631
|
+
def self.organisation
|
632
|
+
'acme'
|
633
|
+
end
|
634
|
+
|
635
|
+
use_name 'test'
|
636
|
+
|
637
|
+
# Expect keys to be symbols
|
638
|
+
expect_symbol_keys
|
639
|
+
|
640
|
+
validations do
|
641
|
+
any Numeric
|
642
|
+
end
|
643
|
+
end
|
644
|
+
|
645
|
+
json = JSON.parse('{"foo": {}}', { symbolize_names: false })
|
646
|
+
# If MyMedia expects symbol keys
|
647
|
+
MyMedia.valid?(json)
|
648
|
+
# Returns false
|
649
|
+
```
|
650
|
+
|
406
651
|
## Related
|
407
652
|
|
408
|
-
- [`MediaTypes::Serialization`](https://github.com/XPBytes/media_types-serialization): :cyclone: Add media types supported serialization
|
409
|
-
- [`MediaTypes::Validation`](https://github.com/XPBytes/media_types-validation): :heavy_exclamation_mark: Response validations according to a media-type
|
653
|
+
- [`MediaTypes::Serialization`](https://github.com/XPBytes/media_types-serialization): :cyclone: Add media types supported serialization to Rails.
|
410
654
|
|
411
655
|
## Development
|
412
656
|
|