rspec-grape-entity 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/.github/workflows/rspec.yml +26 -0
- data/.github/workflows/rubocop.yml +30 -0
- data/.gitignore +17 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/Gemfile +13 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +695 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/rspec-grape-entity.rb +3 -0
- data/lib/rspec_grape_entity/describe_exposure.rb +125 -0
- data/lib/rspec_grape_entity/dsl.rb +16 -0
- data/lib/rspec_grape_entity/its_exposure.rb +72 -0
- data/lib/rspec_grape_entity/matchers/be_a_exposure_type_matcher.rb +33 -0
- data/lib/rspec_grape_entity/matchers/be_merged_matcher.rb +21 -0
- data/lib/rspec_grape_entity/matchers/be_safe_matcher.rb +21 -0
- data/lib/rspec_grape_entity/matchers/be_using_class_matcher.rb +21 -0
- data/lib/rspec_grape_entity/matchers/have_conditions_met_matcher.rb +36 -0
- data/lib/rspec_grape_entity/matchers/have_formatting_matcher.rb +39 -0
- data/lib/rspec_grape_entity/matchers/have_key_matcher.rb +21 -0
- data/lib/rspec_grape_entity/matchers/have_root_matcher.rb +33 -0
- data/lib/rspec_grape_entity/matchers/include_documentation_matcher.rb +26 -0
- data/lib/rspec_grape_entity/matchers/matcher_helpers.rb +24 -0
- data/lib/rspec_grape_entity/matchers/override_exposure_matcher.rb +21 -0
- data/lib/rspec_grape_entity/version.rb +5 -0
- data/lib/rspec_grape_entity.rb +28 -0
- data/rspec-grape-entity.gemspec +37 -0
- data/spec/describe_exposure_spec.rb +29 -0
- data/spec/entities/test_entity_spec.rb +150 -0
- data/spec/its_exposure_spec.rb +16 -0
- data/spec/matchers/be_a_exposure_type_matcher_spec.rb +106 -0
- data/spec/matchers/be_merged_matcher_spec.rb +19 -0
- data/spec/matchers/be_safe_matcher_spec.rb +19 -0
- data/spec/matchers/be_using_class_matcher_spec.rb +15 -0
- data/spec/matchers/have_conditions_met_matcher_spec.rb +40 -0
- data/spec/matchers/have_formatting_matcher_spec.rb +25 -0
- data/spec/matchers/have_key_matcher_spec.rb +23 -0
- data/spec/matchers/have_root_matcher_spec.rb +47 -0
- data/spec/matchers/include_documentation_matcher_spec.rb +31 -0
- data/spec/matchers/matcher_helpers_spec.rb +76 -0
- data/spec/matchers/override_exposure_matcher_spec.rb +19 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/test_entity.rb +23 -0
- data/spec/support/user_entity.rb +12 -0
- metadata +181 -0
@@ -0,0 +1,150 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe TestEntity, type: :grape_entity do
|
6
|
+
let(:object) do
|
7
|
+
OpenStruct.new id: 1,
|
8
|
+
record_status: "active",
|
9
|
+
user: OpenStruct.new,
|
10
|
+
read: true,
|
11
|
+
update: false,
|
12
|
+
destroy: false,
|
13
|
+
created_at: Time.utc(2022, 1, 1, 15, 0, 0),
|
14
|
+
updated_at: Time.now,
|
15
|
+
has_date: true
|
16
|
+
end
|
17
|
+
|
18
|
+
it { expect(described_class).to have_root("test_items").with_singular("test_item") }
|
19
|
+
|
20
|
+
context "when using its_exposure" do
|
21
|
+
let(:object_without_date) { OpenStruct.new has_date: false }
|
22
|
+
|
23
|
+
its_exposure(:id) { is_expected.to be_a_delegator_exposure }
|
24
|
+
its_exposure(:id) { is_expected.to include_documentation type: Integer, desc: "The record id" }
|
25
|
+
its_exposure(:id) { is_expected.not_to be_safe }
|
26
|
+
its_exposure(:id) { is_expected.not_to be_merged }
|
27
|
+
its_exposure(:id) { is_expected.not_to override_exposure }
|
28
|
+
its_exposure(:record_status) { is_expected.to be_a_delegator_exposure }
|
29
|
+
its_exposure(:record_status) { is_expected.to have_key :status }
|
30
|
+
its_exposure(:record_status) { is_expected.to have_conditions_met(object).with_options(all: :something) }
|
31
|
+
its_exposure(:record_status) { is_expected.to_not have_conditions_met object }
|
32
|
+
its_exposure(:record_status) { is_expected.not_to be_safe }
|
33
|
+
its_exposure(:record_status) { is_expected.not_to be_merged }
|
34
|
+
its_exposure(:record_status) { is_expected.not_to override_exposure }
|
35
|
+
its_exposure(:user) { is_expected.to be_a_represent_exposure }
|
36
|
+
its_exposure(:user) { is_expected.to be_using_class UserEntity }
|
37
|
+
its_exposure(:user) { is_expected.to have_conditions_met(object).with_options(type: :admin) }
|
38
|
+
its_exposure(:user) { is_expected.not_to have_conditions_met(object).with_options(type: :user) }
|
39
|
+
its_exposure(:user) { is_expected.not_to have_conditions_met object }
|
40
|
+
its_exposure(:custom_data) { is_expected.to be_a_block_exposure }
|
41
|
+
its_exposure(:custom_data) { is_expected.not_to be_safe }
|
42
|
+
its_exposure(:custom_data) { is_expected.to be_merged }
|
43
|
+
its_exposure(:custom_data) { is_expected.not_to override_exposure }
|
44
|
+
its_exposure(:permissions) { is_expected.to be_a_nesting_exposure }
|
45
|
+
its_exposure(:permissions) { is_expected.not_to be_safe }
|
46
|
+
its_exposure(:permissions) { is_expected.not_to be_merged }
|
47
|
+
its_exposure(:permissions) { is_expected.to override_exposure }
|
48
|
+
its_exposure("permissions.read") { is_expected.to be_a_delegator_exposure }
|
49
|
+
its_exposure("permissions.read") { is_expected.not_to be_safe }
|
50
|
+
its_exposure("permissions.read") { is_expected.not_to be_merged }
|
51
|
+
its_exposure("permissions.read") { is_expected.not_to override_exposure }
|
52
|
+
its_exposure("permissions.update") { is_expected.to be_a_delegator_exposure }
|
53
|
+
its_exposure("permissions.update") { is_expected.not_to be_safe }
|
54
|
+
its_exposure("permissions.update") { is_expected.not_to be_merged }
|
55
|
+
its_exposure("permissions.update") { is_expected.not_to override_exposure }
|
56
|
+
its_exposure("permissions.destroy") { is_expected.to be_a_delegator_exposure }
|
57
|
+
its_exposure("permissions.destroy") { is_expected.not_to be_safe }
|
58
|
+
its_exposure("permissions.destroy") { is_expected.not_to be_merged }
|
59
|
+
its_exposure("permissions.destroy") { is_expected.not_to override_exposure }
|
60
|
+
its_exposure("created_at") { is_expected.to be_a_formatter_block_exposure }
|
61
|
+
its_exposure("created_at") { is_expected.to have_formatting("2022-01-01T15:00:00Z").with_object(object) }
|
62
|
+
its_exposure("created_at") { is_expected.not_to be_safe }
|
63
|
+
its_exposure("created_at") { is_expected.not_to be_merged }
|
64
|
+
its_exposure("created_at") { is_expected.not_to override_exposure }
|
65
|
+
its_exposure("created_at") { is_expected.to have_conditions_met object }
|
66
|
+
its_exposure("created_at") { is_expected.to_not have_conditions_met object_without_date }
|
67
|
+
end
|
68
|
+
|
69
|
+
context "when using describe_exposure" do
|
70
|
+
shared_examples "has permissions" do |permission|
|
71
|
+
describe_exposure "permissions.#{permission}" do
|
72
|
+
it { is_expected.to be_a_delegator_exposure }
|
73
|
+
it { is_expected.not_to be_safe }
|
74
|
+
it { is_expected.not_to be_merged }
|
75
|
+
it { is_expected.not_to override_exposure }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe_exposure :id do
|
80
|
+
it { is_expected.to be_a_delegator_exposure }
|
81
|
+
it { is_expected.to include_documentation type: Integer, desc: "The record id" }
|
82
|
+
it { is_expected.not_to be_safe }
|
83
|
+
it { is_expected.not_to be_merged }
|
84
|
+
it { is_expected.not_to override_exposure }
|
85
|
+
end
|
86
|
+
|
87
|
+
describe_exposure :record_status do
|
88
|
+
it { is_expected.to be_a_delegator_exposure }
|
89
|
+
it { is_expected.to have_key :status }
|
90
|
+
it { is_expected.to have_conditions_met(object).with_options(all: :something) }
|
91
|
+
it { is_expected.to_not have_conditions_met object }
|
92
|
+
it { is_expected.not_to be_safe }
|
93
|
+
it { is_expected.not_to be_merged }
|
94
|
+
it { is_expected.not_to override_exposure }
|
95
|
+
end
|
96
|
+
|
97
|
+
describe_exposure :user do
|
98
|
+
it { is_expected.to be_a_represent_exposure }
|
99
|
+
it { is_expected.to be_using_class UserEntity }
|
100
|
+
|
101
|
+
context "when type is an admin" do
|
102
|
+
it { is_expected.to have_conditions_met(object).with_options(type: :admin) }
|
103
|
+
end
|
104
|
+
|
105
|
+
context "when type is not an admin" do
|
106
|
+
it { is_expected.not_to have_conditions_met(object).with_options(type: :user) }
|
107
|
+
end
|
108
|
+
|
109
|
+
context "when no type is declared" do
|
110
|
+
it { is_expected.not_to have_conditions_met object }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe_exposure :custom_data do
|
115
|
+
it { is_expected.to be_a_block_exposure }
|
116
|
+
it { is_expected.not_to be_safe }
|
117
|
+
it { is_expected.to be_merged }
|
118
|
+
it { is_expected.not_to override_exposure }
|
119
|
+
end
|
120
|
+
|
121
|
+
describe_exposure :permissions do
|
122
|
+
it { is_expected.to be_a_nesting_exposure }
|
123
|
+
it { is_expected.not_to be_safe }
|
124
|
+
it { is_expected.not_to be_merged }
|
125
|
+
it { is_expected.to override_exposure }
|
126
|
+
end
|
127
|
+
|
128
|
+
it_behaves_like "has permissions", "read"
|
129
|
+
it_behaves_like "has permissions", "update"
|
130
|
+
it_behaves_like "has permissions", "destroy"
|
131
|
+
|
132
|
+
describe_exposure :created_at do
|
133
|
+
it { is_expected.to be_a_formatter_block_exposure }
|
134
|
+
it { is_expected.to have_formatting("2022-01-01T15:00:00Z").with_object(object) }
|
135
|
+
it { is_expected.not_to be_safe }
|
136
|
+
it { is_expected.not_to be_merged }
|
137
|
+
it { is_expected.not_to override_exposure }
|
138
|
+
|
139
|
+
context "when has date" do
|
140
|
+
it { is_expected.to have_conditions_met object }
|
141
|
+
end
|
142
|
+
|
143
|
+
context "when does not have date" do
|
144
|
+
let(:object) { OpenStruct.new has_date: false }
|
145
|
+
|
146
|
+
it { is_expected.not_to have_conditions_met object }
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe RSpec::Grape::Entity::ItsExposure do
|
6
|
+
include RSpec::Grape::Entity::DSL
|
7
|
+
|
8
|
+
let(:entity) { TestEntity }
|
9
|
+
|
10
|
+
its_exposure(:id)
|
11
|
+
its_exposure("id")
|
12
|
+
its_exposure(:id) { is_expected.to be_a Grape::Entity::Exposure::DelegatorExposure }
|
13
|
+
its_exposure(:unknown) { is_expected.to be_nil }
|
14
|
+
its_exposure("permissions.read") { is_expected.to be_a Grape::Entity::Exposure::DelegatorExposure }
|
15
|
+
its_exposure("unknown.unknown") { expect { __attribute_exposure }.to raise_error NoMethodError }
|
16
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe RSpec::Grape::Entity::Matchers::BeAExposureTypeMatcher do
|
6
|
+
include RSpec::Grape::Entity::Matchers::BeAExposureTypeMatcher
|
7
|
+
|
8
|
+
let(:entity) { TestEntity }
|
9
|
+
subject(:exposure) { entity.find_exposure attribute }
|
10
|
+
|
11
|
+
context "when a block exposure" do
|
12
|
+
let(:attribute) { :custom_data }
|
13
|
+
it { is_expected.to be_a_exposure_type :block }
|
14
|
+
it { is_expected.not_to be_a_exposure_type :delegator }
|
15
|
+
it { is_expected.not_to be_a_exposure_type :formatter }
|
16
|
+
it { is_expected.not_to be_a_exposure_type :formatter_block }
|
17
|
+
it { is_expected.not_to be_a_exposure_type :nesting }
|
18
|
+
it { is_expected.not_to be_a_exposure_type :represent }
|
19
|
+
it { is_expected.to be_a_block_exposure }
|
20
|
+
it { is_expected.not_to be_a_delegator_exposure }
|
21
|
+
it { is_expected.not_to be_a_formatter_exposure }
|
22
|
+
it { is_expected.not_to be_a_formatter_block_exposure }
|
23
|
+
it { is_expected.not_to be_a_nesting_exposure }
|
24
|
+
it { is_expected.not_to be_a_represent_exposure }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when a delegator exposure" do
|
28
|
+
let(:attribute) { :id }
|
29
|
+
it { is_expected.not_to be_a_exposure_type :block }
|
30
|
+
it { is_expected.to be_a_exposure_type :delegator }
|
31
|
+
it { is_expected.not_to be_a_exposure_type :formatter }
|
32
|
+
it { is_expected.not_to be_a_exposure_type :formatter_block }
|
33
|
+
it { is_expected.not_to be_a_exposure_type :nesting }
|
34
|
+
it { is_expected.not_to be_a_exposure_type :represent }
|
35
|
+
it { is_expected.not_to be_a_block_exposure }
|
36
|
+
it { is_expected.to be_a_delegator_exposure }
|
37
|
+
it { is_expected.not_to be_a_formatter_exposure }
|
38
|
+
it { is_expected.not_to be_a_formatter_block_exposure }
|
39
|
+
it { is_expected.not_to be_a_nesting_exposure }
|
40
|
+
it { is_expected.not_to be_a_represent_exposure }
|
41
|
+
end
|
42
|
+
|
43
|
+
context "when a formatter exposure" do
|
44
|
+
let(:attribute) { :updated_at }
|
45
|
+
it { is_expected.not_to be_a_exposure_type :block }
|
46
|
+
it { is_expected.not_to be_a_exposure_type :delegator }
|
47
|
+
it { is_expected.to be_a_exposure_type :formatter }
|
48
|
+
it { is_expected.not_to be_a_exposure_type :formatter_block }
|
49
|
+
it { is_expected.not_to be_a_exposure_type :nesting }
|
50
|
+
it { is_expected.not_to be_a_exposure_type :represent }
|
51
|
+
it { is_expected.not_to be_a_block_exposure }
|
52
|
+
it { is_expected.not_to be_a_delegator_exposure }
|
53
|
+
it { is_expected.to be_a_formatter_exposure }
|
54
|
+
it { is_expected.not_to be_a_formatter_block_exposure }
|
55
|
+
it { is_expected.not_to be_a_nesting_exposure }
|
56
|
+
it { is_expected.not_to be_a_represent_exposure }
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when a formatter block exposure" do
|
60
|
+
let(:attribute) { :created_at }
|
61
|
+
it { is_expected.not_to be_a_exposure_type :block }
|
62
|
+
it { is_expected.not_to be_a_exposure_type :delegator }
|
63
|
+
it { is_expected.not_to be_a_exposure_type :formatter }
|
64
|
+
it { is_expected.to be_a_exposure_type :formatter_block }
|
65
|
+
it { is_expected.not_to be_a_exposure_type :nesting }
|
66
|
+
it { is_expected.not_to be_a_exposure_type :represent }
|
67
|
+
it { is_expected.not_to be_a_block_exposure }
|
68
|
+
it { is_expected.not_to be_a_delegator_exposure }
|
69
|
+
it { is_expected.not_to be_a_formatter_exposure }
|
70
|
+
it { is_expected.to be_a_formatter_block_exposure }
|
71
|
+
it { is_expected.not_to be_a_nesting_exposure }
|
72
|
+
it { is_expected.not_to be_a_represent_exposure }
|
73
|
+
end
|
74
|
+
|
75
|
+
context "when a nesting exposure" do
|
76
|
+
let(:attribute) { :permissions }
|
77
|
+
it { is_expected.not_to be_a_exposure_type :block }
|
78
|
+
it { is_expected.not_to be_a_exposure_type :delegator }
|
79
|
+
it { is_expected.not_to be_a_exposure_type :formatter }
|
80
|
+
it { is_expected.not_to be_a_exposure_type :formatter_block }
|
81
|
+
it { is_expected.to be_a_exposure_type :nesting }
|
82
|
+
it { is_expected.not_to be_a_exposure_type :represent }
|
83
|
+
it { is_expected.not_to be_a_block_exposure }
|
84
|
+
it { is_expected.not_to be_a_delegator_exposure }
|
85
|
+
it { is_expected.not_to be_a_formatter_exposure }
|
86
|
+
it { is_expected.not_to be_a_formatter_block_exposure }
|
87
|
+
it { is_expected.to be_a_nesting_exposure }
|
88
|
+
it { is_expected.not_to be_a_represent_exposure }
|
89
|
+
end
|
90
|
+
|
91
|
+
context "when a represent exposure" do
|
92
|
+
let(:attribute) { :user }
|
93
|
+
it { is_expected.not_to be_a_exposure_type :block }
|
94
|
+
it { is_expected.not_to be_a_exposure_type :delegator }
|
95
|
+
it { is_expected.not_to be_a_exposure_type :formatter }
|
96
|
+
it { is_expected.not_to be_a_exposure_type :formatter_block }
|
97
|
+
it { is_expected.not_to be_a_exposure_type :nesting }
|
98
|
+
it { is_expected.to be_a_exposure_type :represent }
|
99
|
+
it { is_expected.not_to be_a_block_exposure }
|
100
|
+
it { is_expected.not_to be_a_delegator_exposure }
|
101
|
+
it { is_expected.not_to be_a_formatter_exposure }
|
102
|
+
it { is_expected.not_to be_a_formatter_block_exposure }
|
103
|
+
it { is_expected.not_to be_a_nesting_exposure }
|
104
|
+
it { is_expected.to be_a_represent_exposure }
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe RSpec::Grape::Entity::Matchers::BeMergedMatcher do
|
6
|
+
include RSpec::Grape::Entity::Matchers::BeMergedMatcher
|
7
|
+
|
8
|
+
let(:entity) { TestEntity }
|
9
|
+
|
10
|
+
context "when merged" do
|
11
|
+
subject(:exposure) { entity.find_exposure :custom_data }
|
12
|
+
it { is_expected.to be_merged }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when not merged" do
|
16
|
+
subject(:exposure) { entity.find_exposure :id }
|
17
|
+
it { is_expected.not_to be_merged }
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe RSpec::Grape::Entity::Matchers::BeSafeMatcher do
|
6
|
+
include RSpec::Grape::Entity::Matchers::BeSafeMatcher
|
7
|
+
|
8
|
+
let(:entity) { TestEntity }
|
9
|
+
|
10
|
+
context "when safe" do
|
11
|
+
subject(:exposure) { entity.find_exposure :user }
|
12
|
+
it { is_expected.to be_safe }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when not safe" do
|
16
|
+
subject(:exposure) { entity.find_exposure :id }
|
17
|
+
it { is_expected.not_to be_safe }
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe RSpec::Grape::Entity::Matchers::BeUsingClassMatcher do
|
6
|
+
include RSpec::Grape::Entity::Matchers::BeUsingClassMatcher
|
7
|
+
|
8
|
+
let(:entity) { TestEntity }
|
9
|
+
|
10
|
+
context "when using a represent entity" do
|
11
|
+
subject(:exposure) { entity.find_exposure :user }
|
12
|
+
it { is_expected.to be_using_class UserEntity }
|
13
|
+
it { is_expected.not_to be_using_class TestEntity }
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe RSpec::Grape::Entity::Matchers::HaveConditionsMetMatcher do
|
6
|
+
include RSpec::Grape::Entity::Matchers::HaveConditionsMetMatcher
|
7
|
+
|
8
|
+
let(:entity) { TestEntity }
|
9
|
+
let(:object) { OpenStruct.new has_date: true }
|
10
|
+
|
11
|
+
context "when condition a symbol" do
|
12
|
+
subject(:exposure) { entity.find_exposure :record_status }
|
13
|
+
|
14
|
+
it { is_expected.to have_conditions_met(object).with_options(all: true) }
|
15
|
+
it { is_expected.to_not have_conditions_met(object) }
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when condition a hash" do
|
19
|
+
subject(:exposure) { entity.find_exposure :user }
|
20
|
+
|
21
|
+
it { is_expected.to have_conditions_met(object).with_options(type: :admin) }
|
22
|
+
it { is_expected.to_not have_conditions_met(object).with_options(type: :user) }
|
23
|
+
it { is_expected.to_not have_conditions_met(object) }
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when condition a proc" do
|
27
|
+
subject(:exposure) { entity.find_exposure :created_at }
|
28
|
+
|
29
|
+
let(:false_object) { OpenStruct.new date: false }
|
30
|
+
|
31
|
+
it { is_expected.to have_conditions_met(object) }
|
32
|
+
it { is_expected.not_to have_conditions_met(false_object) }
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when no conditions defined" do
|
36
|
+
subject(:exposure) { entity.find_exposure :id }
|
37
|
+
|
38
|
+
it { is_expected.to have_conditions_met(object) }
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe RSpec::Grape::Entity::Matchers::HaveFormattingMatcher do
|
6
|
+
include RSpec::Grape::Entity::Matchers::HaveFormattingMatcher
|
7
|
+
|
8
|
+
let(:entity) { TestEntity }
|
9
|
+
let(:object) do
|
10
|
+
OpenStruct.new created_at: Time.utc(2022, 1, 22, 17, 0, 0),
|
11
|
+
updated_at: Time.utc(2022, 2, 4, 6, 0, 0)
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when formatter is a symbol" do
|
15
|
+
subject(:exposure) { entity.find_exposure :updated_at }
|
16
|
+
|
17
|
+
it { is_expected.to have_formatting :iso_timestamp }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when formatter is a block" do
|
21
|
+
subject(:exposure) { entity.find_exposure :created_at }
|
22
|
+
|
23
|
+
it { is_expected.to have_formatting("2022-01-22T17:00:00Z").with_object(object) }
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe RSpec::Grape::Entity::Matchers::HaveKeyMatcher do
|
6
|
+
include RSpec::Grape::Entity::Matchers::HaveKeyMatcher
|
7
|
+
|
8
|
+
let(:entity) { TestEntity }
|
9
|
+
|
10
|
+
context "when alias is not defined" do
|
11
|
+
subject(:exposure) { entity.find_exposure :id }
|
12
|
+
|
13
|
+
it { is_expected.to have_key :id }
|
14
|
+
it { is_expected.not_to have_key :external_id }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when alias is defined" do
|
18
|
+
subject(:exposure) { entity.find_exposure :record_status }
|
19
|
+
|
20
|
+
it { is_expected.to have_key :status }
|
21
|
+
it { is_expected.not_to have_key :record_status }
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe RSpec::Grape::Entity::Matchers::HaveRootMatcher do
|
6
|
+
include RSpec::Grape::Entity::Matchers::HaveRootMatcher
|
7
|
+
|
8
|
+
context "when root is not defined" do
|
9
|
+
let(:described_class) do
|
10
|
+
Class.new Grape::Entity
|
11
|
+
end
|
12
|
+
|
13
|
+
it { expect(described_class).to have_root(nil) }
|
14
|
+
it { expect(described_class).to have_root(nil).with_singular(nil) }
|
15
|
+
it { expect(described_class).not_to have_root("tests") }
|
16
|
+
it { expect(described_class).not_to have_root("tests").with_singular(nil) }
|
17
|
+
it { expect(described_class).not_to have_root("tests").with_singular("test") }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when collection root is only defined" do
|
21
|
+
let(:described_class) do
|
22
|
+
Class.new Grape::Entity do
|
23
|
+
root "tests"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it { expect(described_class).not_to have_root(nil) }
|
28
|
+
it { expect(described_class).not_to have_root(nil).with_singular(nil) }
|
29
|
+
it { expect(described_class).to have_root("tests") }
|
30
|
+
it { expect(described_class).to have_root("tests").with_singular(nil) }
|
31
|
+
it { expect(described_class).not_to have_root("tests").with_singular("test") }
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when both root and collection_root is defined" do
|
35
|
+
let(:described_class) do
|
36
|
+
Class.new Grape::Entity do
|
37
|
+
root "tests", "test"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it { expect(described_class).not_to have_root(nil) }
|
42
|
+
it { expect(described_class).not_to have_root(nil).with_singular(nil) }
|
43
|
+
it { expect(described_class).not_to have_root("tests") }
|
44
|
+
it { expect(described_class).not_to have_root("tests").with_singular(nil) }
|
45
|
+
it { expect(described_class).to have_root("tests").with_singular("test") }
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe RSpec::Grape::Entity::Matchers::IncludeDocumentationMatcher do
|
6
|
+
include RSpec::Grape::Entity::Matchers::IncludeDocumentationMatcher
|
7
|
+
|
8
|
+
let(:entity) { TestEntity }
|
9
|
+
|
10
|
+
context "when has documentation" do
|
11
|
+
subject(:exposure) { entity.find_exposure :id }
|
12
|
+
|
13
|
+
it { is_expected.to include_documentation type: Integer, desc: "The record id" }
|
14
|
+
it { is_expected.to include_documentation type: Integer }
|
15
|
+
it { is_expected.to include_documentation desc: "The record id" }
|
16
|
+
it { is_expected.to include_documentation :type, :desc }
|
17
|
+
it { is_expected.to include_documentation :desc }
|
18
|
+
it { is_expected.to include_documentation :type }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when does not have documentation" do
|
22
|
+
subject(:exposure) { entity.find_exposure :permissions }
|
23
|
+
|
24
|
+
it { is_expected.not_to include_documentation type: Integer, desc: "Permissions" }
|
25
|
+
it { is_expected.not_to include_documentation type: Integer }
|
26
|
+
it { is_expected.not_to include_documentation desc: "The record id" }
|
27
|
+
it { is_expected.not_to include_documentation :type, :desc }
|
28
|
+
it { is_expected.not_to include_documentation :desc }
|
29
|
+
it { is_expected.not_to include_documentation :type }
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe RSpec::Grape::Entity::Matchers::MatcherHelpers do
|
6
|
+
let(:entity) { TestEntity }
|
7
|
+
subject(:helper) { Class.new { extend RSpec::Grape::Entity::Matchers::MatcherHelpers } }
|
8
|
+
|
9
|
+
describe ".entity_class_name" do
|
10
|
+
subject { helper.entity_class_name entity }
|
11
|
+
|
12
|
+
context "when a class constant" do
|
13
|
+
it { is_expected.to eq "TestEntity" }
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when an instance of an entity" do
|
17
|
+
let(:entity) { TestEntity.new(nil) }
|
18
|
+
it { is_expected.to eq "TestEntity" }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe ".exposure_attribute" do
|
23
|
+
let(:exposure) { entity.find_exposure :id }
|
24
|
+
subject { helper.exposure_attribute exposure, attribute }
|
25
|
+
|
26
|
+
context "when a valid exposure attribute" do
|
27
|
+
let(:attribute) { :key }
|
28
|
+
it { is_expected.to_not be_nil }
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when an invalid exposure attribute" do
|
32
|
+
let(:attribute) { :not_a_real_attribute }
|
33
|
+
it { expect { subject }.to raise_error NoMethodError }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe ".exposure_type" do
|
38
|
+
subject { helper.exposure_type exposure_type }
|
39
|
+
|
40
|
+
context "when a block exposure" do
|
41
|
+
let(:exposure_type) { :block }
|
42
|
+
it { is_expected.to be Grape::Entity::Exposure::BlockExposure }
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when a delegator exposure" do
|
46
|
+
let(:exposure_type) { :delegator }
|
47
|
+
it { is_expected.to be Grape::Entity::Exposure::DelegatorExposure }
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when a formatter exposure" do
|
51
|
+
let(:exposure_type) { :formatter }
|
52
|
+
it { is_expected.to be Grape::Entity::Exposure::FormatterExposure }
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when a formatter block exposure" do
|
56
|
+
let(:exposure_type) { :formatter_block }
|
57
|
+
it { is_expected.to be Grape::Entity::Exposure::FormatterBlockExposure }
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when a nesting exposure" do
|
61
|
+
let(:exposure_type) { :nesting }
|
62
|
+
it { is_expected.to be Grape::Entity::Exposure::NestingExposure }
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when a represent exposure" do
|
66
|
+
let(:exposure_type) { :represent }
|
67
|
+
it { is_expected.to be Grape::Entity::Exposure::RepresentExposure }
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when an invalid exposure type" do
|
71
|
+
let(:exposure_type) { :invalid_exposure_type }
|
72
|
+
|
73
|
+
it { expect { subject }.to raise_error NameError }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe RSpec::Grape::Entity::Matchers::OverrideExposureMatcher do
|
6
|
+
include RSpec::Grape::Entity::Matchers::OverrideExposureMatcher
|
7
|
+
|
8
|
+
let(:entity) { TestEntity }
|
9
|
+
|
10
|
+
context "when overriding" do
|
11
|
+
subject(:exposure) { entity.find_exposure :permissions }
|
12
|
+
it { is_expected.to override_exposure }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when not overriding" do
|
16
|
+
subject(:exposure) { entity.find_exposure :id }
|
17
|
+
it { is_expected.not_to override_exposure }
|
18
|
+
end
|
19
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ostruct"
|
4
|
+
require "time"
|
5
|
+
|
6
|
+
require "rspec-grape-entity"
|
7
|
+
|
8
|
+
require_relative "support/user_entity"
|
9
|
+
require_relative "support/test_entity"
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
# Enable flags like --only-failures and --next-failure
|
13
|
+
config.example_status_persistence_file_path = ".rspec_status"
|
14
|
+
|
15
|
+
# Disable RSpec exposing methods globally on `Module` and `main`
|
16
|
+
config.disable_monkey_patching!
|
17
|
+
|
18
|
+
config.expect_with :rspec do |c|
|
19
|
+
c.syntax = :expect
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class TestEntity < Grape::Entity
|
4
|
+
root "test_items", "test_item"
|
5
|
+
|
6
|
+
format_with :iso_timestamp, &:iso8601
|
7
|
+
|
8
|
+
expose :id, documentation: { type: Integer, desc: "The record id" }
|
9
|
+
expose :record_status, as: :status, if: :all
|
10
|
+
expose :user, safe: true, using: UserEntity, if: { type: :admin }
|
11
|
+
expose :custom_data, merge: true do |_, _|
|
12
|
+
{
|
13
|
+
foo: :bar
|
14
|
+
}
|
15
|
+
end
|
16
|
+
expose :permissions, override: true do
|
17
|
+
expose :read
|
18
|
+
expose :update
|
19
|
+
expose :destroy
|
20
|
+
end
|
21
|
+
expose :created_at, format_with: ->(date) { date.iso8601 }, if: ->(instance, _) { instance.has_date }
|
22
|
+
expose :updated_at, format_with: :iso_timestamp
|
23
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class UserEntity < Grape::Entity
|
4
|
+
format_with :iso_timestamp, &:iso8601
|
5
|
+
|
6
|
+
expose :username
|
7
|
+
expose :name do
|
8
|
+
expose :first_name, as: :first, documentation: { type: String, desc: "User's last name" }
|
9
|
+
expose :last_name, as: :last, documentation: { type: String, desc: "User's last name" }
|
10
|
+
end
|
11
|
+
expose :joined_at, format_with: :iso_timestamp
|
12
|
+
end
|