jpie 1.1.1 → 1.1.2
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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/json_api/testing/rspec.rb +12 -1
- data/lib/json_api/testing/shared_examples/responses.rb +53 -1
- data/lib/json_api/testing/sti_helpers.rb +141 -0
- data/lib/json_api/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8c205d5463d3fffd9ccf158d1ef8df04e34e50fd6a7385f9b727a46676181c00
|
|
4
|
+
data.tar.gz: 1c8e628e95a5296baa459c89cbc7d2bd119f4bb5e0456f5d9d3e4c8322b08a92
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 17bb979968aba9d606fdb537c5ebba08e8d29b39e9ffd2dbaefeaaeafc4a41b1ebb686429cd20ffd10db9276320d0e70e7cc94551a418863dbdd633542df67f6
|
|
7
|
+
data.tar.gz: 8fad54116b4eaa6c2e77f9e8034f477a3c9cb4911cc749ff00bf06cc30d801751ff0351771040dd94f6a639776aa0396775637e1d1fa4583a91a965e844ca8e8
|
data/Gemfile.lock
CHANGED
|
@@ -9,14 +9,22 @@
|
|
|
9
9
|
# This will:
|
|
10
10
|
# 1. Load all shared example module definitions
|
|
11
11
|
# 2. Load all shared examples for resources and responses
|
|
12
|
-
# 3.
|
|
12
|
+
# 3. Load STI testing helpers for request specs
|
|
13
|
+
# 4. Make the modules available at the top level for convenient usage
|
|
13
14
|
#
|
|
14
15
|
# After requiring, you can use shared examples like:
|
|
15
16
|
#
|
|
16
17
|
# it_behaves_like [ Jpie, Resource, :has_attributes ].to_s, :name, :email
|
|
17
18
|
# it_behaves_like [ Jpie, Response, :data ].to_s, type: "users"
|
|
19
|
+
# it_behaves_like [ Jpie, Response, :sti_types ].to_s, expected_subtypes: ["user_messages"]
|
|
20
|
+
#
|
|
21
|
+
# And STI helpers in request specs:
|
|
22
|
+
#
|
|
23
|
+
# expect_sti_types_in_included(expected_subtypes: ["user_messages"])
|
|
24
|
+
# expect_sti_resources_included(sti_type: "user_messages", expected_ids: [msg.id])
|
|
18
25
|
|
|
19
26
|
require_relative "shared_examples/modules"
|
|
27
|
+
require_relative "sti_helpers"
|
|
20
28
|
|
|
21
29
|
# Load shared examples
|
|
22
30
|
Dir[File.join(__dir__, "shared_examples", "*.rb")].each do |file|
|
|
@@ -30,4 +38,7 @@ RSpec.configure do |config|
|
|
|
30
38
|
define_method(const) { Object.const_get(const) }
|
|
31
39
|
end
|
|
32
40
|
end)
|
|
41
|
+
|
|
42
|
+
# Include STI helpers for request specs
|
|
43
|
+
config.include JSONAPI::Testing::StiHelpers, type: :request
|
|
33
44
|
end
|
|
@@ -60,7 +60,8 @@ RSpec.shared_examples [Jpie, Response, :relationships].to_s do |*relationships|
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
RSpec.shared_examples [Jpie, Response,
|
|
63
|
+
RSpec.shared_examples [Jpie, Response,
|
|
64
|
+
:included,].to_s do |type: nil, count: nil, sti_subtypes: nil, exclude_base_type: nil|
|
|
64
65
|
it "includes compound document data" do
|
|
65
66
|
included = response.parsed_body["included"]
|
|
66
67
|
expect(included).to be_an(Array)
|
|
@@ -71,6 +72,20 @@ RSpec.shared_examples [Jpie, Response, :included].to_s do |type: nil, count: nil
|
|
|
71
72
|
expect(matching).not_to be_empty, "Expected included to contain type '#{type}'"
|
|
72
73
|
expect(matching.size).to eq(count) if count
|
|
73
74
|
end
|
|
75
|
+
|
|
76
|
+
if sti_subtypes
|
|
77
|
+
included_types = included.pluck("type").uniq
|
|
78
|
+
sti_subtypes.each do |subtype|
|
|
79
|
+
expect(included_types).to include(subtype.to_s),
|
|
80
|
+
"Expected included to contain STI subtype '#{subtype}', got: #{included_types}"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
if exclude_base_type
|
|
85
|
+
included_types ||= included.pluck("type").uniq
|
|
86
|
+
expect(included_types).not_to include(exclude_base_type.to_s),
|
|
87
|
+
"Expected included NOT to contain base type '#{exclude_base_type}', but it did"
|
|
88
|
+
end
|
|
74
89
|
end
|
|
75
90
|
end
|
|
76
91
|
|
|
@@ -111,3 +126,40 @@ RSpec.shared_examples [Jpie, Response, :errors].to_s do |count: nil|
|
|
|
111
126
|
end
|
|
112
127
|
end
|
|
113
128
|
end
|
|
129
|
+
|
|
130
|
+
RSpec.shared_examples [Jpie, Response, :sti_types].to_s do |expected_subtypes:, exclude_base_type: nil|
|
|
131
|
+
it "returns STI subtypes correctly" do
|
|
132
|
+
data = response.parsed_body["data"]
|
|
133
|
+
data = [data] unless data.is_a?(Array)
|
|
134
|
+
types = data.pluck("type").uniq
|
|
135
|
+
|
|
136
|
+
expected_subtypes.each do |subtype|
|
|
137
|
+
expect(types).to include(subtype.to_s),
|
|
138
|
+
"Expected data to contain STI subtype '#{subtype}', got: #{types}"
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
if exclude_base_type
|
|
142
|
+
expect(types).not_to include(exclude_base_type.to_s),
|
|
143
|
+
"Expected data NOT to contain base type '#{exclude_base_type}', but it did"
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
RSpec.shared_examples [Jpie, Response, :sti_included].to_s do |expected_subtypes:, exclude_base_type: nil|
|
|
149
|
+
it "includes STI subtypes correctly" do
|
|
150
|
+
included = response.parsed_body["included"] || []
|
|
151
|
+
expect(included).not_to be_empty, "Expected included to be present"
|
|
152
|
+
|
|
153
|
+
included_types = included.pluck("type").uniq
|
|
154
|
+
|
|
155
|
+
expected_subtypes.each do |subtype|
|
|
156
|
+
expect(included_types).to include(subtype.to_s),
|
|
157
|
+
"Expected included to contain STI subtype '#{subtype}', got: #{included_types}"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
if exclude_base_type
|
|
161
|
+
expect(included_types).not_to include(exclude_base_type.to_s),
|
|
162
|
+
"Expected included NOT to contain base type '#{exclude_base_type}', but it did"
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JSONAPI
|
|
4
|
+
module Testing
|
|
5
|
+
# Helper methods for testing STI (Single Table Inheritance) resources in JSON:API responses.
|
|
6
|
+
#
|
|
7
|
+
# These helpers simplify testing that STI subtypes are correctly serialized
|
|
8
|
+
# and included in JSON:API responses.
|
|
9
|
+
#
|
|
10
|
+
# Usage in request specs:
|
|
11
|
+
#
|
|
12
|
+
# it "includes user messages", :aggregate_failures do
|
|
13
|
+
# get conversation_path(conversation), params: { include: "messages" }, as: :jsonapi
|
|
14
|
+
# expect_sti_types_in_included(expected_subtypes: ["user_messages"])
|
|
15
|
+
# expect_sti_resources_included(sti_type: "user_messages", expected_ids: [message.id])
|
|
16
|
+
# end
|
|
17
|
+
module StiHelpers
|
|
18
|
+
# Verify that included resources contain expected STI subtypes.
|
|
19
|
+
#
|
|
20
|
+
# @param expected_subtypes [Array<String, Symbol>] Expected STI subtype names
|
|
21
|
+
# @param exclude_base_type [String, Symbol, nil] Base type that should NOT be present (optional)
|
|
22
|
+
# @return [void]
|
|
23
|
+
#
|
|
24
|
+
# @example Verify subtypes are present
|
|
25
|
+
# expect_sti_types_in_included(expected_subtypes: ["user_messages", "ai_messages"])
|
|
26
|
+
#
|
|
27
|
+
# @example Verify subtypes and exclude base type
|
|
28
|
+
# expect_sti_types_in_included(
|
|
29
|
+
# expected_subtypes: ["user_messages"],
|
|
30
|
+
# exclude_base_type: "messages"
|
|
31
|
+
# )
|
|
32
|
+
def expect_sti_types_in_included(expected_subtypes:, exclude_base_type: nil)
|
|
33
|
+
included = response.parsed_body["included"] || []
|
|
34
|
+
included_types = included.pluck("type").uniq
|
|
35
|
+
|
|
36
|
+
expected_subtypes.each do |subtype|
|
|
37
|
+
expect(included_types).to include(subtype.to_s),
|
|
38
|
+
"Expected included to contain STI type '#{subtype}', got: #{included_types}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
return if exclude_base_type.blank?
|
|
42
|
+
|
|
43
|
+
expect(included_types).not_to include(exclude_base_type.to_s),
|
|
44
|
+
"Expected included NOT to contain base type '#{exclude_base_type}', but it did"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Find all resources of a specific STI type in the included array.
|
|
48
|
+
#
|
|
49
|
+
# @param sti_type [String, Symbol] The STI subtype to find
|
|
50
|
+
# @return [Array<Hash>] Array of resource objects matching the STI type
|
|
51
|
+
#
|
|
52
|
+
# @example Find all user messages in included
|
|
53
|
+
# messages = find_sti_resources_in_included("user_messages")
|
|
54
|
+
# expect(messages.first["attributes"]["content"]).to eq("Hello")
|
|
55
|
+
def find_sti_resources_in_included(sti_type)
|
|
56
|
+
included = response.parsed_body["included"] || []
|
|
57
|
+
included.select { |item| item["type"] == sti_type.to_s }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Verify that specific STI resources are included by ID.
|
|
61
|
+
#
|
|
62
|
+
# @param sti_type [String, Symbol] The STI subtype
|
|
63
|
+
# @param expected_ids [Array<Integer, String>] Expected resource IDs
|
|
64
|
+
# @return [void]
|
|
65
|
+
#
|
|
66
|
+
# @example Verify specific messages are included
|
|
67
|
+
# expect_sti_resources_included(
|
|
68
|
+
# sti_type: "user_messages",
|
|
69
|
+
# expected_ids: [message1.id, message2.id]
|
|
70
|
+
# )
|
|
71
|
+
def expect_sti_resources_included(sti_type:, expected_ids:)
|
|
72
|
+
resources = find_sti_resources_in_included(sti_type)
|
|
73
|
+
actual_ids = resources.map { |r| r["id"] }
|
|
74
|
+
expected_ids_str = expected_ids.map(&:to_s)
|
|
75
|
+
|
|
76
|
+
expect(actual_ids).to match_array(expected_ids_str),
|
|
77
|
+
"Expected #{sti_type} resources with IDs #{expected_ids_str}, got: #{actual_ids}"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Verify STI types in data array (not included).
|
|
81
|
+
#
|
|
82
|
+
# @param expected_subtypes [Array<String, Symbol>] Expected STI subtype names
|
|
83
|
+
# @param exclude_base_type [String, Symbol, nil] Base type that should NOT be present (optional)
|
|
84
|
+
# @return [void]
|
|
85
|
+
#
|
|
86
|
+
# @example Verify data contains correct STI types
|
|
87
|
+
# expect_sti_types_in_data(
|
|
88
|
+
# expected_subtypes: ["user_messages", "ai_messages"],
|
|
89
|
+
# exclude_base_type: "messages"
|
|
90
|
+
# )
|
|
91
|
+
def expect_sti_types_in_data(expected_subtypes:, exclude_base_type: nil)
|
|
92
|
+
data = response.parsed_body["data"]
|
|
93
|
+
data = [data] unless data.is_a?(Array)
|
|
94
|
+
types = data.pluck("type").uniq
|
|
95
|
+
|
|
96
|
+
expected_subtypes.each do |subtype|
|
|
97
|
+
expect(types).to include(subtype.to_s),
|
|
98
|
+
"Expected data to contain STI subtype '#{subtype}', got: #{types}"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
return if exclude_base_type.blank?
|
|
102
|
+
|
|
103
|
+
expect(types).not_to include(exclude_base_type.to_s),
|
|
104
|
+
"Expected data NOT to contain base type '#{exclude_base_type}', but it did"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Find all resources of a specific STI type in the data array.
|
|
108
|
+
#
|
|
109
|
+
# @param sti_type [String, Symbol] The STI subtype to find
|
|
110
|
+
# @return [Array<Hash>] Array of resource objects matching the STI type
|
|
111
|
+
#
|
|
112
|
+
# @example Find all user messages in data
|
|
113
|
+
# messages = find_sti_resources_in_data("user_messages")
|
|
114
|
+
def find_sti_resources_in_data(sti_type)
|
|
115
|
+
data = response.parsed_body["data"]
|
|
116
|
+
data = [data] unless data.is_a?(Array)
|
|
117
|
+
data.select { |item| item["type"] == sti_type.to_s }
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Verify that specific STI resources are present in data by ID.
|
|
121
|
+
#
|
|
122
|
+
# @param sti_type [String, Symbol] The STI subtype
|
|
123
|
+
# @param expected_ids [Array<Integer, String>] Expected resource IDs
|
|
124
|
+
# @return [void]
|
|
125
|
+
#
|
|
126
|
+
# @example Verify specific messages are in data
|
|
127
|
+
# expect_sti_resources_in_data(
|
|
128
|
+
# sti_type: "user_messages",
|
|
129
|
+
# expected_ids: [message1.id, message2.id]
|
|
130
|
+
# )
|
|
131
|
+
def expect_sti_resources_in_data(sti_type:, expected_ids:)
|
|
132
|
+
resources = find_sti_resources_in_data(sti_type)
|
|
133
|
+
actual_ids = resources.map { |r| r["id"] }
|
|
134
|
+
expected_ids_str = expected_ids.map(&:to_s)
|
|
135
|
+
|
|
136
|
+
expect(actual_ids).to match_array(expected_ids_str),
|
|
137
|
+
"Expected #{sti_type} resources with IDs #{expected_ids_str}, got: #{actual_ids}"
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
data/lib/json_api/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jpie
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Emil Kampp
|
|
@@ -148,6 +148,7 @@ files:
|
|
|
148
148
|
- lib/json_api/testing/shared_examples/modules.rb
|
|
149
149
|
- lib/json_api/testing/shared_examples/resources.rb
|
|
150
150
|
- lib/json_api/testing/shared_examples/responses.rb
|
|
151
|
+
- lib/json_api/testing/sti_helpers.rb
|
|
151
152
|
- lib/json_api/testing/test_helper.rb
|
|
152
153
|
- lib/json_api/version.rb
|
|
153
154
|
- lib/rubocop/cop/custom/hash_value_omission.rb
|