simple_jsonapi 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rubocop.yml +131 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +5 -0
- data/Jenkinsfile +92 -0
- data/LICENSE.txt +22 -0
- data/README.md +532 -0
- data/Rakefile +10 -0
- data/lib/simple_jsonapi.rb +112 -0
- data/lib/simple_jsonapi/definition/attribute.rb +45 -0
- data/lib/simple_jsonapi/definition/base.rb +50 -0
- data/lib/simple_jsonapi/definition/concerns/has_links_object.rb +36 -0
- data/lib/simple_jsonapi/definition/concerns/has_meta_object.rb +36 -0
- data/lib/simple_jsonapi/definition/error.rb +70 -0
- data/lib/simple_jsonapi/definition/error_source.rb +29 -0
- data/lib/simple_jsonapi/definition/link.rb +27 -0
- data/lib/simple_jsonapi/definition/meta.rb +27 -0
- data/lib/simple_jsonapi/definition/relationship.rb +60 -0
- data/lib/simple_jsonapi/definition/resource.rb +104 -0
- data/lib/simple_jsonapi/error_serializer.rb +76 -0
- data/lib/simple_jsonapi/errors/bad_request.rb +11 -0
- data/lib/simple_jsonapi/errors/exception_serializer.rb +6 -0
- data/lib/simple_jsonapi/errors/wrapped_error.rb +35 -0
- data/lib/simple_jsonapi/errors/wrapped_error_serializer.rb +35 -0
- data/lib/simple_jsonapi/helpers/exceptions.rb +39 -0
- data/lib/simple_jsonapi/helpers/serializer_inferrer.rb +136 -0
- data/lib/simple_jsonapi/helpers/serializer_methods.rb +36 -0
- data/lib/simple_jsonapi/node/attributes.rb +51 -0
- data/lib/simple_jsonapi/node/base.rb +91 -0
- data/lib/simple_jsonapi/node/data/collection.rb +25 -0
- data/lib/simple_jsonapi/node/data/singular.rb +26 -0
- data/lib/simple_jsonapi/node/document/base.rb +62 -0
- data/lib/simple_jsonapi/node/document/collection.rb +17 -0
- data/lib/simple_jsonapi/node/document/errors.rb +17 -0
- data/lib/simple_jsonapi/node/document/singular.rb +17 -0
- data/lib/simple_jsonapi/node/error.rb +55 -0
- data/lib/simple_jsonapi/node/error_source.rb +40 -0
- data/lib/simple_jsonapi/node/errors.rb +28 -0
- data/lib/simple_jsonapi/node/included.rb +45 -0
- data/lib/simple_jsonapi/node/object_links.rb +40 -0
- data/lib/simple_jsonapi/node/object_meta.rb +40 -0
- data/lib/simple_jsonapi/node/relationship.rb +79 -0
- data/lib/simple_jsonapi/node/relationship_data/base.rb +53 -0
- data/lib/simple_jsonapi/node/relationship_data/collection.rb +32 -0
- data/lib/simple_jsonapi/node/relationship_data/singular.rb +33 -0
- data/lib/simple_jsonapi/node/relationships.rb +60 -0
- data/lib/simple_jsonapi/node/resource/base.rb +21 -0
- data/lib/simple_jsonapi/node/resource/full.rb +49 -0
- data/lib/simple_jsonapi/node/resource/linkage.rb +25 -0
- data/lib/simple_jsonapi/parameters/fields_spec.rb +45 -0
- data/lib/simple_jsonapi/parameters/include_spec.rb +57 -0
- data/lib/simple_jsonapi/parameters/sort_spec.rb +107 -0
- data/lib/simple_jsonapi/serializer.rb +89 -0
- data/lib/simple_jsonapi/version.rb +3 -0
- data/simple_jsonapi.gemspec +29 -0
- data/test/errors/bad_request_test.rb +34 -0
- data/test/errors/error_serializer_test.rb +229 -0
- data/test/errors/exception_serializer_test.rb +25 -0
- data/test/errors/wrapped_error_serializer_test.rb +91 -0
- data/test/errors/wrapped_error_test.rb +44 -0
- data/test/parameters/fields_spec_test.rb +56 -0
- data/test/parameters/include_spec_test.rb +58 -0
- data/test/parameters/sort_spec_test.rb +65 -0
- data/test/resources/attributes_test.rb +109 -0
- data/test/resources/extras_test.rb +70 -0
- data/test/resources/id_and_type_test.rb +76 -0
- data/test/resources/inclusion_test.rb +134 -0
- data/test/resources/links_test.rb +63 -0
- data/test/resources/meta_test.rb +49 -0
- data/test/resources/relationships_test.rb +262 -0
- data/test/resources/sorting_test.rb +79 -0
- data/test/resources/sparse_fieldset_test.rb +160 -0
- data/test/root_objects_test.rb +165 -0
- data/test/test_helper.rb +31 -0
- metadata +235 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
module SimpleJsonapi::Node::Resource
|
2
|
+
# Represents a single resource object.
|
3
|
+
class Full < Base
|
4
|
+
# @param options see {Node::Resource::Base#initialize} for additional parameters
|
5
|
+
def initialize(**options)
|
6
|
+
super(options)
|
7
|
+
|
8
|
+
@attributes_node = build_child_node(
|
9
|
+
SimpleJsonapi::Node::Attributes,
|
10
|
+
resource: resource,
|
11
|
+
resource_type: resource_type,
|
12
|
+
attribute_definitions: serializer.attribute_definitions,
|
13
|
+
)
|
14
|
+
|
15
|
+
@relationships_node = build_child_node(
|
16
|
+
SimpleJsonapi::Node::Relationships,
|
17
|
+
resource: resource,
|
18
|
+
resource_type: resource_type,
|
19
|
+
relationship_definitions: serializer.relationship_definitions,
|
20
|
+
)
|
21
|
+
|
22
|
+
@links_node = build_child_node(
|
23
|
+
SimpleJsonapi::Node::ObjectLinks,
|
24
|
+
object: resource,
|
25
|
+
link_definitions: serializer.link_definitions,
|
26
|
+
)
|
27
|
+
|
28
|
+
@meta_node = build_child_node(
|
29
|
+
SimpleJsonapi::Node::ObjectMeta,
|
30
|
+
object: resource,
|
31
|
+
meta_definitions: serializer.meta_definitions,
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Hash{Symbol => Hash}]
|
36
|
+
def as_jsonapi
|
37
|
+
json = {}
|
38
|
+
json[:id] = resource_id
|
39
|
+
json[:type] = resource_type
|
40
|
+
|
41
|
+
json.merge!(@attributes_node.as_jsonapi)
|
42
|
+
json.merge!(@relationships_node.as_jsonapi)
|
43
|
+
json.merge!(@links_node.as_jsonapi)
|
44
|
+
json.merge!(@meta_node.as_jsonapi)
|
45
|
+
|
46
|
+
json
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module SimpleJsonapi::Node::Resource
|
2
|
+
# Represents a single resource linkage object.
|
3
|
+
#
|
4
|
+
# @!attribute [r] meta
|
5
|
+
# @return [Hash{Symbol => Object}]
|
6
|
+
class Linkage < Base
|
7
|
+
attr_reader :meta
|
8
|
+
|
9
|
+
# @param meta [Hash{Symbol => Object}]
|
10
|
+
# @param options see {Node::Resource::Base#initialize} for additional parameters
|
11
|
+
def initialize(meta: nil, **options)
|
12
|
+
super(options)
|
13
|
+
@meta = meta
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Hash{Symbol => Hash}]
|
17
|
+
def as_jsonapi
|
18
|
+
json = {}
|
19
|
+
json[:id] = resource_id
|
20
|
+
json[:type] = resource_type
|
21
|
+
json[:meta] = meta if meta.present?
|
22
|
+
json
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module SimpleJsonapi::Parameters
|
2
|
+
# Represents the +fields+ parameter as defined by the JSONAPI spec.
|
3
|
+
class FieldsSpec
|
4
|
+
# Wraps a +fields+ parameter in a {FieldsSpec} instance.
|
5
|
+
# @param fields [Hash{Symbol => String},FieldsSpec]
|
6
|
+
def self.wrap(fields)
|
7
|
+
if fields.is_a?(FieldsSpec)
|
8
|
+
fields
|
9
|
+
else
|
10
|
+
FieldsSpec.new(fields)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param specs [Hash{Symbol => String,Array<String>,Array<Symbol>}]
|
15
|
+
# The hash keys are resource types, and the values are lists of field names to render in the output.
|
16
|
+
def initialize(specs = {})
|
17
|
+
@data = {}
|
18
|
+
merge(specs) if specs.present?
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param specs [Hash{Symbol => String,Array<String>,Array<Symbol>}]
|
22
|
+
# The hash keys are resource types, and the values are lists of field names to render in the output.
|
23
|
+
# @return [self]
|
24
|
+
def merge(specs = {})
|
25
|
+
specs.each do |type, fields|
|
26
|
+
@data[type.to_sym] = Array
|
27
|
+
.wrap(fields)
|
28
|
+
.flat_map { |s| s.to_s.split(",") }
|
29
|
+
.map { |s| s.strip.to_sym }
|
30
|
+
end
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
# @param type [String,Symbol]
|
35
|
+
# @return [Array<Symbol>]
|
36
|
+
def [](type)
|
37
|
+
@data[type.to_sym]
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param type [String,Symbol]
|
41
|
+
def all_fields?(type)
|
42
|
+
@data[type.to_sym].nil?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module SimpleJsonapi::Parameters
|
2
|
+
# Represents the +include+ parameter as defined by the JSONAPI spec.
|
3
|
+
class IncludeSpec
|
4
|
+
# Wraps an +include+ parameter in an {IncludeSpec} instance.
|
5
|
+
# @param specs [IncludeSpec,String,Array<String>,Array<Symbol>]
|
6
|
+
def self.wrap(specs)
|
7
|
+
if specs.is_a?(IncludeSpec)
|
8
|
+
specs
|
9
|
+
else
|
10
|
+
IncludeSpec.new(specs)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param specs [String,Array<String>,Array<Symbol>]
|
15
|
+
# e.g. <code>"author,comments,comments.author"</code> or <code>["author", "comments", "comments.author"]</code>
|
16
|
+
def initialize(*specs)
|
17
|
+
@data = {}
|
18
|
+
merge(*specs) if specs.any?
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param specs [String,Array<String>,Array<Symbol>]
|
22
|
+
# e.g. <code>"author,comments,comments.author"</code> or <code>["author", "comments", "comments.author"]</code>
|
23
|
+
# @return [self]
|
24
|
+
def merge(*specs)
|
25
|
+
paths = specs.flatten.flat_map { |s| s.to_s.split(",") }
|
26
|
+
|
27
|
+
paths.each do |path|
|
28
|
+
terms = path.split(".")
|
29
|
+
|
30
|
+
nested_spec = @data[terms.first.to_sym] ||= IncludeSpec.new
|
31
|
+
if terms.size > 1
|
32
|
+
nested_spec.merge(terms.drop(1).join("."))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param relationship_name [String,Symbol]
|
40
|
+
# @return [IncludeSpec]
|
41
|
+
def [](relationship_name)
|
42
|
+
@data[relationship_name.to_sym]
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param relationship_name [String,Symbol]
|
46
|
+
def include?(relationship_name)
|
47
|
+
@data.key?(relationship_name.to_sym)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Hash]
|
51
|
+
def to_h
|
52
|
+
@data.each_with_object({}) do |(name, spec), hash|
|
53
|
+
hash[name] = spec.to_h
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module SimpleJsonapi::Parameters
|
2
|
+
# Represents the +sort+ parameter as defined by the JSONAPI spec.
|
3
|
+
class SortSpec
|
4
|
+
# Wraps a +sort+ parameter in a {SortSpec} instance.
|
5
|
+
# @param sorts [SortSpec,Hash{Symbol => String},Hash{Symbol => Array<String>}]
|
6
|
+
def self.wrap(sorts)
|
7
|
+
if sorts.is_a?(SortSpec)
|
8
|
+
sorts
|
9
|
+
else
|
10
|
+
SortSpec.new(sorts)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Creates a {SortSpec} that raises an error when it's called.
|
15
|
+
# @return [SortSpec]
|
16
|
+
def self.not_supported
|
17
|
+
@not_supported ||= new.tap do |spec|
|
18
|
+
spec.instance_variable_set(:@not_supported, true)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
delegate :inspect, :to_s, to: :@data
|
23
|
+
|
24
|
+
# @param specs [Hash{Symbol => String},Hash{Symbol => Array<String>}]
|
25
|
+
# e.g., { comments: "-date,author" }
|
26
|
+
def initialize(specs = {})
|
27
|
+
@not_supported = nil
|
28
|
+
@data = Hash.new { |_h, _k| [] }
|
29
|
+
merge(specs) if specs.present?
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param specs [Hash{Symbol => String},Hash{Symbol => Array<String>}]
|
33
|
+
# e.g., { comments: "-date,author" } or { comments: ["-date", "author"] }
|
34
|
+
# @return [self]
|
35
|
+
def merge(specs = {})
|
36
|
+
specs.each do |relationship_name, field_specs|
|
37
|
+
@data[relationship_name.to_sym] = Array
|
38
|
+
.wrap(field_specs)
|
39
|
+
.flat_map { |fs| fs.to_s.split(",") }
|
40
|
+
.map { |fs| SortFieldSpec.new(fs) }
|
41
|
+
.presence
|
42
|
+
end
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param relationship_name [String,Symbol]
|
47
|
+
# @return [SortFieldSpec]
|
48
|
+
def [](relationship_name)
|
49
|
+
if not_supported?
|
50
|
+
raise NotImplementedError, "Sorting nested relationships is not implemented."
|
51
|
+
else
|
52
|
+
@data[relationship_name.to_sym]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
def not_supported?
|
59
|
+
!!@not_supported
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Represents a single field (and direction) in a {SortSpec}.
|
64
|
+
# @!attribute [rw] field
|
65
|
+
# @return Symbol
|
66
|
+
# @!attribute [rw] dir
|
67
|
+
# @return [:asc,:desc]
|
68
|
+
class SortFieldSpec
|
69
|
+
attr_accessor :field, :dir
|
70
|
+
|
71
|
+
# @param spec [String]
|
72
|
+
def initialize(spec)
|
73
|
+
if spec =~ /\A(-?)(\w+)\Z/
|
74
|
+
self.field = $2.to_sym
|
75
|
+
self.dir = ($1 == '-' ? :desc : :asc)
|
76
|
+
else
|
77
|
+
raise ArgumentError, "field spec must match 'field' or '-field'"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def asc?
|
82
|
+
dir == :asc
|
83
|
+
end
|
84
|
+
|
85
|
+
def desc?
|
86
|
+
dir == :desc
|
87
|
+
end
|
88
|
+
|
89
|
+
def dup
|
90
|
+
SortFieldSpec.new(to_s)
|
91
|
+
end
|
92
|
+
|
93
|
+
def ==(other)
|
94
|
+
other.respond_to?(:field) && other.respond_to?(:dir) && [field, dir] == [other.field, other.dir]
|
95
|
+
end
|
96
|
+
alias_method :eql?, :==
|
97
|
+
|
98
|
+
def hash
|
99
|
+
[field, dir].hash
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_s
|
103
|
+
"#{'-' if desc?}#{field}"
|
104
|
+
end
|
105
|
+
alias_method :inspect, :to_s
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# Subclass {Serializer} to create serializers for specific types of resources.
|
2
|
+
class SimpleJsonapi::Serializer
|
3
|
+
include SimpleJsonapi::SerializerMethods
|
4
|
+
|
5
|
+
class << self
|
6
|
+
# @overload (see Definition::Resource#id)
|
7
|
+
# @return (see Definition::Resource#id)
|
8
|
+
def id(*args, &block)
|
9
|
+
definition.id(*args, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
# @overload (see Definition::Resource#type)
|
13
|
+
# @return (see Definition::Resource#type)
|
14
|
+
def type(*args, &block)
|
15
|
+
definition.type(*args, &block)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @overload (see Definition::Resource#id)
|
19
|
+
# @return (see Definition::Resource#id)
|
20
|
+
# @overload attribute(name, options = {})
|
21
|
+
# @overload attribute(name, options = {}, &block)
|
22
|
+
# @return (see Definition::Resource#attribute)
|
23
|
+
def attribute(name, **options, &block)
|
24
|
+
definition.attribute(name, **options, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @overload (see Definition::Resource#has_one)
|
28
|
+
# @param (see Definition::Resource#has_one)
|
29
|
+
# @yieldparam (see Definition::Resource#has_one)
|
30
|
+
# @yieldreturn (see Definition::Resource#has_one)
|
31
|
+
# @return (see Definition::Resource#has_one)
|
32
|
+
def has_one(name, **options, &block)
|
33
|
+
definition.has_one(name, **options, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @overload (see Definition::Resource#has_many)
|
37
|
+
# @param (see Definition::Resource#has_many)
|
38
|
+
# @yieldparam (see Definition::Resource#has_many)
|
39
|
+
# @yieldreturn (see Definition::Resource#has_many)
|
40
|
+
# @return (see Definition::Resource#has_many)
|
41
|
+
def has_many(name, **options, &block)
|
42
|
+
definition.has_many(name, **options, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @overload (see Definition::Concerns::HasLinksObject#link)
|
46
|
+
# @return (see Definition::Concerns::HasLinksObject#link)
|
47
|
+
def link(name, *args, **options, &block)
|
48
|
+
definition.link(name, *args, **options, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
# @overload (see Definition::Concerns::HasMetaObject#meta)
|
52
|
+
# @return (see Definition::Concerns::HasMetaObject#meta)
|
53
|
+
def meta(name, *args, **options, &block)
|
54
|
+
definition.meta(name, *args, **options, &block)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
self.definition = SimpleJsonapi::Definition::Resource.new
|
59
|
+
|
60
|
+
# @return (see Definition::Resource#id_definition)
|
61
|
+
def id_definition
|
62
|
+
definition.id_definition
|
63
|
+
end
|
64
|
+
|
65
|
+
# @return (see Definition::Resource#type_definition)
|
66
|
+
def type_definition
|
67
|
+
definition.type_definition
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return (see Definition::Resource#attribute_definitions)
|
71
|
+
def attribute_definitions
|
72
|
+
definition.attribute_definitions
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return (see Definition::Resource#relationship_definitions)
|
76
|
+
def relationship_definitions
|
77
|
+
definition.relationship_definitions
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return (see Definition::Concerns::HasLinksObject#link_definitions)
|
81
|
+
def link_definitions
|
82
|
+
definition.link_definitions
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return (see Definition::Concerns::HasMetaObject#meta_definitions)
|
86
|
+
def meta_definitions
|
87
|
+
definition.meta_definitions
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
require 'simple_jsonapi/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'simple_jsonapi'
|
8
|
+
spec.version = SimpleJsonapi::VERSION
|
9
|
+
spec.license = "MIT"
|
10
|
+
spec.authors = ['PatientsLikeMe']
|
11
|
+
spec.email = ['engineers@patientslikeme.com']
|
12
|
+
spec.homepage = 'https://www.patientslikeme.com'
|
13
|
+
|
14
|
+
spec.summary = 'A library for building JSONAPI documents in Ruby.'
|
15
|
+
spec.description = 'A library for building JSONAPI documents in Ruby.'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.test_files = spec.files.grep(%r{^test/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_runtime_dependency 'activesupport', '~> 5.1'
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.10'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
spec.add_development_dependency 'minitest'
|
26
|
+
spec.add_development_dependency 'minitest-reporters'
|
27
|
+
spec.add_development_dependency 'pry'
|
28
|
+
spec.add_development_dependency 'mocha'
|
29
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class BadRequestTest < Minitest::Spec
|
4
|
+
let(:error) do
|
5
|
+
SimpleJsonapi::Errors::BadRequest.new(
|
6
|
+
id: "the id",
|
7
|
+
status: "the status",
|
8
|
+
code: "the code",
|
9
|
+
title: "the title",
|
10
|
+
detail: "the detail",
|
11
|
+
source_pointer: "the source pointer",
|
12
|
+
source_parameter: "the source parameter",
|
13
|
+
about_link: "the about link",
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe SimpleJsonapi::Errors::BadRequest do
|
18
|
+
describe "properties" do
|
19
|
+
it "are assigned specific values" do
|
20
|
+
assert_equal "400", error.status
|
21
|
+
assert_equal "bad_request", error.code
|
22
|
+
assert_equal "Bad request", error.title
|
23
|
+
end
|
24
|
+
|
25
|
+
it "are stored" do
|
26
|
+
assert_equal "the id", error.id
|
27
|
+
assert_equal "the detail", error.detail
|
28
|
+
assert_equal "the source pointer", error.source_pointer
|
29
|
+
assert_equal "the source parameter", error.source_parameter
|
30
|
+
assert_equal "the about link", error.about_link
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|