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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/rspec.yml +26 -0
  3. data/.github/workflows/rubocop.yml +30 -0
  4. data/.gitignore +17 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +13 -0
  7. data/Gemfile +13 -0
  8. data/LICENSE +21 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +695 -0
  11. data/Rakefile +12 -0
  12. data/bin/console +15 -0
  13. data/bin/setup +8 -0
  14. data/lib/rspec-grape-entity.rb +3 -0
  15. data/lib/rspec_grape_entity/describe_exposure.rb +125 -0
  16. data/lib/rspec_grape_entity/dsl.rb +16 -0
  17. data/lib/rspec_grape_entity/its_exposure.rb +72 -0
  18. data/lib/rspec_grape_entity/matchers/be_a_exposure_type_matcher.rb +33 -0
  19. data/lib/rspec_grape_entity/matchers/be_merged_matcher.rb +21 -0
  20. data/lib/rspec_grape_entity/matchers/be_safe_matcher.rb +21 -0
  21. data/lib/rspec_grape_entity/matchers/be_using_class_matcher.rb +21 -0
  22. data/lib/rspec_grape_entity/matchers/have_conditions_met_matcher.rb +36 -0
  23. data/lib/rspec_grape_entity/matchers/have_formatting_matcher.rb +39 -0
  24. data/lib/rspec_grape_entity/matchers/have_key_matcher.rb +21 -0
  25. data/lib/rspec_grape_entity/matchers/have_root_matcher.rb +33 -0
  26. data/lib/rspec_grape_entity/matchers/include_documentation_matcher.rb +26 -0
  27. data/lib/rspec_grape_entity/matchers/matcher_helpers.rb +24 -0
  28. data/lib/rspec_grape_entity/matchers/override_exposure_matcher.rb +21 -0
  29. data/lib/rspec_grape_entity/version.rb +5 -0
  30. data/lib/rspec_grape_entity.rb +28 -0
  31. data/rspec-grape-entity.gemspec +37 -0
  32. data/spec/describe_exposure_spec.rb +29 -0
  33. data/spec/entities/test_entity_spec.rb +150 -0
  34. data/spec/its_exposure_spec.rb +16 -0
  35. data/spec/matchers/be_a_exposure_type_matcher_spec.rb +106 -0
  36. data/spec/matchers/be_merged_matcher_spec.rb +19 -0
  37. data/spec/matchers/be_safe_matcher_spec.rb +19 -0
  38. data/spec/matchers/be_using_class_matcher_spec.rb +15 -0
  39. data/spec/matchers/have_conditions_met_matcher_spec.rb +40 -0
  40. data/spec/matchers/have_formatting_matcher_spec.rb +25 -0
  41. data/spec/matchers/have_key_matcher_spec.rb +23 -0
  42. data/spec/matchers/have_root_matcher_spec.rb +47 -0
  43. data/spec/matchers/include_documentation_matcher_spec.rb +31 -0
  44. data/spec/matchers/matcher_helpers_spec.rb +76 -0
  45. data/spec/matchers/override_exposure_matcher_spec.rb +19 -0
  46. data/spec/spec_helper.rb +21 -0
  47. data/spec/support/test_entity.rb +23 -0
  48. data/spec/support/user_entity.rb +12 -0
  49. metadata +181 -0
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rspec_grape_entity"
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module DescribeExposure
7
+ # Creates a group named by the entity exposure `attribute`.
8
+ #
9
+ # @example
10
+ #
11
+ # class MyEntity < Grape::Entity
12
+ # expose :size, safe: true
13
+ # expose :name do
14
+ # expose :first_name, as: :first
15
+ # expose :last_name, as: :last
16
+ # end
17
+ # end
18
+ #
19
+ # # This ...
20
+ # describe MyEntity, type: :entity do
21
+ # describe_exposure :size do
22
+ # ...
23
+ # end
24
+ # end
25
+ #
26
+ # # ... generates the same runtime structure as this:
27
+ # describe MyEntity, type: :entity do
28
+ # describe "size" do
29
+ # let(:entity) { described_class }
30
+ # let(:exposure) { entity.find_exposure :size }
31
+ #
32
+ # ...
33
+ # end
34
+ # end
35
+ #
36
+ # The attribute can be a `Symbol` or a `String`. Given a `String`
37
+ # with dots, the result is as though you concatenated that `String`
38
+ # onto the entities nested exposures.
39
+ #
40
+ # @example
41
+ #
42
+ # describe MyEntity, type: :entity do
43
+ # describe_exposure "name.first_name" do
44
+ # ...
45
+ # end
46
+ # end
47
+ #
48
+ # With an implicit exposure, `is_expected` can be used as an alternative
49
+ # to `should` (e.g. for one-liner use).
50
+ #
51
+ # @example
52
+ #
53
+ # describe MyEntity do
54
+ # describe_exposure :size do
55
+ # it { should be_safe }
56
+ # it { is_expected.to be_safe }
57
+ # end
58
+ # end
59
+ def describe_exposure(attribute, *options, &block)
60
+ raise "Block not given" unless block_given?
61
+
62
+ options << {} unless options.last.is_a?(Hash)
63
+ describe_caller = options.last.fetch(:caller) do
64
+ caller.reject { |file_line| file_line =~ %r{/lib/rspec_grape_entity/describe_exposure} }
65
+ end
66
+
67
+ parent_described_class = described_class
68
+
69
+ describe attribute, caller: describe_caller do
70
+ include RSpec::Grape::Entity::Matchers::BeAExposureTypeMatcher
71
+ include RSpec::Grape::Entity::Matchers::BeMergedMatcher
72
+ include RSpec::Grape::Entity::Matchers::BeSafeMatcher
73
+ include RSpec::Grape::Entity::Matchers::BeUsingClassMatcher
74
+ include RSpec::Grape::Entity::Matchers::HaveConditionsMetMatcher
75
+ include RSpec::Grape::Entity::Matchers::HaveFormattingMatcher
76
+ include RSpec::Grape::Entity::Matchers::HaveKeyMatcher
77
+ include RSpec::Grape::Entity::Matchers::IncludeDocumentationMatcher
78
+ include RSpec::Grape::Entity::Matchers::OverrideExposureMatcher
79
+
80
+ let(:described_class) { parent_described_class }
81
+ let(:entity) { described_class } unless method_defined? :entity
82
+
83
+ let(:__attribute_exposure) do
84
+ exposure_chain = attribute.to_s.split(".")
85
+ exposure = entity.find_exposure exposure_chain.shift.to_sym
86
+ exposure_chain.inject(exposure) do |inner_exposure, attr|
87
+ inner_exposure.find_nested_exposure attr.to_sym
88
+ end
89
+ end
90
+
91
+ # rubocop:disable Lint/NestedMethodDefinition
92
+ def is_expected
93
+ expect(__attribute_exposure)
94
+ end
95
+
96
+ def will(matcher = nil, message = nil)
97
+ raise ArgumentError, "`will` only supports block expectations" unless matcher.supports_block_expectations?
98
+
99
+ expect { __attribute_exposure }.to matcher, message
100
+ end
101
+
102
+ def will_not(matcher = nil, message = nil)
103
+ unless matcher.supports_block_expectations?
104
+ raise ArgumentError, "`will_not` only supports block expectations"
105
+ end
106
+
107
+ expect { __attribute_exposure }.to_not matcher, message
108
+ end
109
+
110
+ def should(matcher = nil, message = nil)
111
+ RSpec::Expectations::PositiveExpectationHandler.handle_matcher(__attribute_exposure, matcher, message)
112
+ end
113
+
114
+ def should_not(matcher = nil, message = nil)
115
+ RSpec::Expectations::NegativeExpectationHandler.handle_matcher(__attribute_exposure, matcher, message)
116
+ end
117
+ # rubocop:enable Lint/NestedMethodDefinition
118
+
119
+ instance_eval(&block)
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module DSL
7
+ def self.included(klass)
8
+ klass.class_eval do
9
+ extend DescribeExposure
10
+ extend ItsExposure
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module ItsExposure
7
+ # Creates a nested example group named by the entity exposure `attribute`,
8
+ # and then generates an example using the submitted block.
9
+ #
10
+ # @example
11
+ #
12
+ # class MyEntity < Grape::Entity
13
+ # expose :size, safe: true
14
+ # expose :name do
15
+ # expose :first_name, as: :first
16
+ # expose :last_name, as: :last
17
+ # end
18
+ # end
19
+ #
20
+ # # This ...
21
+ # describe MyEntity do
22
+ # its_exposure(:size) { is_expected.to be_safe }
23
+ # end
24
+ #
25
+ # # ... generates the same runtime structure as this:
26
+ # describe MyEntity do
27
+ # describe "size" do
28
+ # let(:entity) { described_class }
29
+ #
30
+ # it "is_expected.to be_safe" do
31
+ # exposure = entity.find_exposure :size
32
+ # expect(exposure).to be_safe
33
+ # end
34
+ # end
35
+ # end
36
+ #
37
+ # The attribute can be a `Symbol` or a `String`. Given a `String`
38
+ # with dots, the result is as though you concatenated that `String`
39
+ # onto the entities nested exposures.
40
+ #
41
+ # @example
42
+ #
43
+ # describe MyEntity do
44
+ # its_exposure("name.first_name") { should have_key :first }
45
+ # end
46
+ #
47
+ # With an implicit exposure, `is_expected` can be used as an alternative
48
+ # to `should` (e.g. for one-liner use).
49
+ #
50
+ # @example
51
+ #
52
+ # describe MyEntity do
53
+ # its_exposure(:size) { is_expected.to eq(0) }
54
+ # end
55
+ def its_exposure(attribute, *options, &block)
56
+ its_caller = caller.reject { |file_line| file_line =~ %r{/lib/rspec_grape_entity/its_exposure} }
57
+
58
+ describe_exposure attribute, caller: its_caller do
59
+ options << {} unless options.last.is_a?(Hash)
60
+ options.last.merge!(caller: its_caller)
61
+
62
+ if block
63
+ example(nil, *options, &block)
64
+ else
65
+ example(nil, *options) { is_expected.not_to be_nil }
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module Matchers
7
+ module BeAExposureTypeMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ EXPOSURE_TYPES = %i[block delegator formatter_block formatter nesting represent].freeze
11
+
12
+ matcher :be_a_exposure_type do |expected|
13
+ include MatcherHelpers
14
+
15
+ match { |actual| actual.is_a? exposure_type(expected) }
16
+ description { "be exposure type #{expected}" }
17
+ failure_message { |actual| "expect that #{actual} to be a #{expected} exposure" }
18
+ end
19
+
20
+ EXPOSURE_TYPES.each do |type|
21
+ matcher :"be_a_#{type}_exposure" do
22
+ include MatcherHelpers
23
+
24
+ match { |actual| actual.is_a? exposure_type(type) }
25
+ description { "be a #{type} exposure" }
26
+ failure_message { |actual| "expect that #{actual} to be a #{type} exposure" }
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module Matchers
7
+ module BeMergedMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ matcher :be_merged do
11
+ include MatcherHelpers
12
+
13
+ match { |actual| exposure_attribute(actual, :for_merge) }
14
+ description { "be merged" }
15
+ failure_message { |actual| "expect that #{actual} would merge contents" }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module Matchers
7
+ module BeSafeMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ matcher :be_safe do
11
+ include MatcherHelpers
12
+
13
+ match { |actual| exposure_attribute(actual, :is_safe) }
14
+ description { "be safe" }
15
+ failure_message { |actual| "expect that #{actual} to be safe" }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module Matchers
7
+ module BeUsingClassMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ matcher :be_using_class do |expected|
11
+ include MatcherHelpers
12
+
13
+ match { |actual| expect(exposure_attribute(actual, :using_class)).to be expected }
14
+ description { "be using entity class #{entity_class_name expected}" }
15
+ failure_message { |actual| "expect that #{actual} would be using class #{entity_class_name expected}" }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module Matchers
7
+ module HaveConditionsMetMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ matcher :have_conditions_met do |object|
11
+ include MatcherHelpers
12
+
13
+ match do |actual|
14
+ entity_instance = entity.new object
15
+ actual.conditions_met? entity_instance, options
16
+ end
17
+
18
+ description { "have the conditions met" }
19
+
20
+ failure_message do |actual|
21
+ "expect that #{actual} would have the conditions met for object #{object} with options #{options}"
22
+ end
23
+
24
+ chain :with_options do |options|
25
+ @options = options
26
+ end
27
+
28
+ def options
29
+ @options ||= {}
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module Matchers
7
+ module HaveFormattingMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ matcher :have_formatting do |expected|
11
+ include MatcherHelpers
12
+
13
+ match do |actual|
14
+ if actual.is_a? ::Grape::Entity::Exposure::FormatterBlockExposure
15
+ instance = entity.new object
16
+ actual.value(instance, {}) == expected
17
+ else
18
+ exposure_attribute(actual, :format_with) == expected
19
+ end
20
+ end
21
+
22
+ description { "have the formatting #{expected}" }
23
+
24
+ failure_message do |actual|
25
+ if actual.is_a? ::Grape::Entity::Exposure::FormatterBlockExposure
26
+ instance = entity.new object
27
+ "expect that \"#{actual.value instance, {}}\" would have the formatting \"#{expected}\""
28
+ else
29
+ "expect that \"#{actual}\" would have the formatting \"#{expected}\""
30
+ end
31
+ end
32
+
33
+ chain :with_object, :object
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module Matchers
7
+ module HaveKeyMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ matcher :have_key do |expected|
11
+ include MatcherHelpers
12
+
13
+ match { |actual| exposure_attribute(actual, :key) == expected }
14
+ description { "have the key #{expected}" }
15
+ failure_message { |actual| "expect that #{actual} would have the key #{expected}" }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module Matchers
7
+ module HaveRootMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ matcher :have_root do |plural|
11
+ include MatcherHelpers
12
+
13
+ match do |actual|
14
+ actual_plural = actual.root_element :collection_root
15
+ actual_singular = actual.root_element :root
16
+
17
+ values_match?(plural, actual_plural) &&
18
+ values_match?(singular, actual_singular)
19
+ end
20
+
21
+ description { "have the formatting #{expected}" }
22
+
23
+ failure_message do |actual|
24
+ "expect that \"#{actual}\" would have the root collection \"#{plural}\" and root \"#{singular}\""
25
+ end
26
+
27
+ chain :with_singular, :singular
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module Matchers
7
+ module IncludeDocumentationMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ matcher :include_documentation do |expected|
11
+ include MatcherHelpers
12
+
13
+ match { |actual| expect(documentation(actual)).to include expected }
14
+ match_when_negated { |actual| expect(documentation(actual)).to_not include expected }
15
+ description { "include documentation #{expected}" }
16
+ failure_message { |actual| "expect #{documentation actual} would include the documentation #{expected}" }
17
+
18
+ def documentation(actual)
19
+ exposure_attribute(actual, :documentation) || {}
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module Matchers
7
+ module MatcherHelpers
8
+ def entity_class_name(entity)
9
+ entity.try(:name) || entity.class.name
10
+ end
11
+
12
+ def exposure_attribute(exposure, name)
13
+ exposure.send name
14
+ end
15
+
16
+ def exposure_type(type)
17
+ type = type.to_s.split("_").map { |w| w[0].upcase + w[1..] }.join
18
+ Object.const_get "Grape::Entity::Exposure::#{type}Exposure"
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec
4
+ module Grape
5
+ module Entity
6
+ module Matchers
7
+ module OverrideExposureMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ matcher :override_exposure do
11
+ include MatcherHelpers
12
+
13
+ match { |actual| exposure_attribute(actual, :override) }
14
+ description { "override exposure" }
15
+ failure_message { |actual| "expect that #{actual} would override exposure" }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpecGrapeEntity
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "grape-entity"
4
+ require "rspec/expectations"
5
+
6
+ require_relative "rspec_grape_entity/matchers/matcher_helpers"
7
+ require_relative "rspec_grape_entity/matchers/be_a_exposure_type_matcher"
8
+ require_relative "rspec_grape_entity/matchers/be_merged_matcher"
9
+ require_relative "rspec_grape_entity/matchers/be_safe_matcher"
10
+ require_relative "rspec_grape_entity/matchers/be_using_class_matcher"
11
+ require_relative "rspec_grape_entity/matchers/have_conditions_met_matcher"
12
+ require_relative "rspec_grape_entity/matchers/have_formatting_matcher"
13
+ require_relative "rspec_grape_entity/matchers/have_key_matcher"
14
+ require_relative "rspec_grape_entity/matchers/have_root_matcher"
15
+ require_relative "rspec_grape_entity/matchers/include_documentation_matcher"
16
+ require_relative "rspec_grape_entity/matchers/override_exposure_matcher"
17
+ require_relative "rspec_grape_entity/describe_exposure"
18
+ require_relative "rspec_grape_entity/its_exposure"
19
+ require_relative "rspec_grape_entity/dsl"
20
+ require_relative "rspec_grape_entity/version"
21
+
22
+ RSpec.configure do |rspec|
23
+ rspec.extend RSpec::Grape::Entity::DescribeExposure, type: :grape_entity
24
+ rspec.extend RSpec::Grape::Entity::ItsExposure, type: :grape_entity
25
+ rspec.include RSpec::Grape::Entity::Matchers::HaveRootMatcher, type: :grape_entity
26
+ rspec.backtrace_exclusion_patterns << %r{/lib/rspec_grape_entity/describe_exposure}
27
+ rspec.backtrace_exclusion_patterns << %r{/lib/rspec_grape_entity/its_exposure}
28
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require "rspec_grape_entity/version"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "rspec-grape-entity"
9
+ spec.version = RSpecGrapeEntity::VERSION
10
+ spec.platform = Gem::Platform::RUBY
11
+ spec.authors = ["James Fawks"]
12
+ spec.email = ["jefawks3@gmail.com"]
13
+ spec.summary = "RSpec extension gem for grape-entity"
14
+ spec.description = 'Provides "it_exposes" and "describe_exposure" methods to test Grape Entities'
15
+ spec.homepage = "https://github.com/jefawks3/rspec-grape-entity"
16
+ spec.license = "MIT"
17
+
18
+ spec.metadata = {
19
+ "bug_tracker_uri" => "https://github.com/jefawks3/rspec-grape-entity/issues",
20
+ "changelog_uri" => "https://github.com/jefawks3/rspec-grape-entity/releases",
21
+ "documentation_uri" => "https://github.com/jefawks3/rspec-grape-entity",
22
+ "source_code_uri" => "https://github.com/jefawks3/rspec-grape-entity"
23
+ }
24
+
25
+ spec.required_ruby_version = ">= 2.7.0"
26
+
27
+ spec.add_runtime_dependency "grape-entity", ">= 0.10.0"
28
+ spec.add_runtime_dependency "rspec-core", ">= 3.0.0"
29
+ spec.add_runtime_dependency "rspec-expectations", ">= 3.0.0"
30
+
31
+ spec.add_development_dependency "bundler", "> 1.3.0"
32
+ spec.add_development_dependency "rake", "~> 13.0.0"
33
+
34
+ spec.files = `git ls-files`.split("\n")
35
+ spec.test_files = `git ls-files -- {test,spec}/*`.split("\n")
36
+ spec.require_paths = ["lib"]
37
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe RSpec::Grape::Entity::DescribeExposure do
6
+ extend RSpec::Grape::Entity::DescribeExposure
7
+
8
+ let(:entity) { TestEntity }
9
+
10
+ describe_exposure :id do
11
+ it { is_expected.to be_a Grape::Entity::Exposure::DelegatorExposure }
12
+ end
13
+
14
+ describe_exposure "id" do
15
+ it { is_expected.to be_a Grape::Entity::Exposure::DelegatorExposure }
16
+ end
17
+
18
+ describe_exposure "unknown" do
19
+ it { is_expected.to be_nil }
20
+ end
21
+
22
+ describe_exposure "permissions.read" do
23
+ it { is_expected.to be_a Grape::Entity::Exposure::DelegatorExposure }
24
+ end
25
+
26
+ describe_exposure "unknown.unknown" do
27
+ it { expect { __attribute_exposure }.to raise_error NoMethodError }
28
+ end
29
+ end