fear 0.9.0 → 1.2.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 (155) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/rubocop.yml +39 -0
  3. data/.github/workflows/spec.yml +42 -0
  4. data/.gitignore +0 -1
  5. data/.rubocop.yml +4 -12
  6. data/.simplecov +17 -0
  7. data/CHANGELOG.md +40 -0
  8. data/Gemfile +5 -2
  9. data/Gemfile.lock +130 -0
  10. data/LICENSE.txt +1 -1
  11. data/README.md +1293 -97
  12. data/Rakefile +369 -1
  13. data/benchmarks/README.md +1 -0
  14. data/benchmarks/dry_do_vs_fear_for.txt +11 -0
  15. data/benchmarks/dry_some_fmap_vs_fear_some_map.txt +11 -0
  16. data/benchmarks/factorial.txt +16 -0
  17. data/benchmarks/fear_gaurd_and1_vs_new.txt +13 -0
  18. data/benchmarks/fear_gaurd_and2_vs_and.txt +13 -0
  19. data/benchmarks/fear_gaurd_and3_vs_and_and.txt +13 -0
  20. data/benchmarks/fear_pattern_extracting_with_vs_without_cache.txt +11 -0
  21. data/benchmarks/fear_pattern_matching_construction_vs_execution.txt +13 -0
  22. data/benchmarks/pattern_matching_dry_vs_qo_vs_fear_try.txt +14 -0
  23. data/benchmarks/pattern_matching_qo_vs_fear_pattern_extraction.txt +11 -0
  24. data/benchmarks/pattern_matching_qo_vs_fear_try_execution.txt +11 -0
  25. data/examples/pattern_extracting.rb +17 -0
  26. data/examples/pattern_extracting_ruby2.7.rb +15 -0
  27. data/examples/pattern_matching_binary_tree_set.rb +101 -0
  28. data/examples/pattern_matching_number_in_words.rb +60 -0
  29. data/fear.gemspec +34 -23
  30. data/lib/dry/types/fear.rb +8 -0
  31. data/lib/dry/types/fear/option.rb +125 -0
  32. data/lib/fear.rb +65 -15
  33. data/lib/fear/await.rb +33 -0
  34. data/lib/fear/awaitable.rb +28 -0
  35. data/lib/fear/either.rb +131 -71
  36. data/lib/fear/either_api.rb +23 -0
  37. data/lib/fear/either_pattern_match.rb +53 -0
  38. data/lib/fear/empty_partial_function.rb +38 -0
  39. data/lib/fear/extractor.rb +112 -0
  40. data/lib/fear/extractor/anonymous_array_splat_matcher.rb +10 -0
  41. data/lib/fear/extractor/any_matcher.rb +17 -0
  42. data/lib/fear/extractor/array_head_matcher.rb +36 -0
  43. data/lib/fear/extractor/array_matcher.rb +40 -0
  44. data/lib/fear/extractor/array_splat_matcher.rb +16 -0
  45. data/lib/fear/extractor/empty_list_matcher.rb +20 -0
  46. data/lib/fear/extractor/extractor_matcher.rb +44 -0
  47. data/lib/fear/extractor/grammar.rb +203 -0
  48. data/lib/fear/extractor/grammar.treetop +129 -0
  49. data/lib/fear/extractor/identifier_matcher.rb +18 -0
  50. data/lib/fear/extractor/matcher.rb +53 -0
  51. data/lib/fear/extractor/matcher/and.rb +38 -0
  52. data/lib/fear/extractor/named_array_splat_matcher.rb +17 -0
  53. data/lib/fear/extractor/pattern.rb +58 -0
  54. data/lib/fear/extractor/typed_identifier_matcher.rb +26 -0
  55. data/lib/fear/extractor/value_matcher.rb +19 -0
  56. data/lib/fear/extractor_api.rb +35 -0
  57. data/lib/fear/failure.rb +46 -14
  58. data/lib/fear/failure_pattern_match.rb +10 -0
  59. data/lib/fear/for.rb +37 -95
  60. data/lib/fear/for_api.rb +68 -0
  61. data/lib/fear/future.rb +497 -0
  62. data/lib/fear/future_api.rb +21 -0
  63. data/lib/fear/left.rb +19 -2
  64. data/lib/fear/left_pattern_match.rb +11 -0
  65. data/lib/fear/none.rb +67 -3
  66. data/lib/fear/none_pattern_match.rb +14 -0
  67. data/lib/fear/option.rb +120 -56
  68. data/lib/fear/option_api.rb +40 -0
  69. data/lib/fear/option_pattern_match.rb +48 -0
  70. data/lib/fear/partial_function.rb +176 -0
  71. data/lib/fear/partial_function/and_then.rb +50 -0
  72. data/lib/fear/partial_function/any.rb +28 -0
  73. data/lib/fear/partial_function/combined.rb +53 -0
  74. data/lib/fear/partial_function/empty.rb +10 -0
  75. data/lib/fear/partial_function/guard.rb +80 -0
  76. data/lib/fear/partial_function/guard/and.rb +38 -0
  77. data/lib/fear/partial_function/guard/and3.rb +41 -0
  78. data/lib/fear/partial_function/guard/or.rb +38 -0
  79. data/lib/fear/partial_function/lifted.rb +23 -0
  80. data/lib/fear/partial_function/or_else.rb +64 -0
  81. data/lib/fear/partial_function_class.rb +38 -0
  82. data/lib/fear/pattern_match.rb +114 -0
  83. data/lib/fear/pattern_matching_api.rb +137 -0
  84. data/lib/fear/promise.rb +95 -0
  85. data/lib/fear/right.rb +20 -2
  86. data/lib/fear/right_biased.rb +6 -14
  87. data/lib/fear/right_pattern_match.rb +11 -0
  88. data/lib/fear/some.rb +55 -3
  89. data/lib/fear/some_pattern_match.rb +13 -0
  90. data/lib/fear/struct.rb +248 -0
  91. data/lib/fear/success.rb +35 -5
  92. data/lib/fear/success_pattern_match.rb +12 -0
  93. data/lib/fear/try.rb +136 -79
  94. data/lib/fear/try_api.rb +33 -0
  95. data/lib/fear/try_pattern_match.rb +33 -0
  96. data/lib/fear/unit.rb +32 -0
  97. data/lib/fear/utils.rb +39 -14
  98. data/lib/fear/version.rb +4 -1
  99. data/spec/dry/types/fear/option/constrained_spec.rb +22 -0
  100. data/spec/dry/types/fear/option/core_spec.rb +77 -0
  101. data/spec/dry/types/fear/option/default_spec.rb +21 -0
  102. data/spec/dry/types/fear/option/hash_spec.rb +58 -0
  103. data/spec/dry/types/fear/option/option_spec.rb +97 -0
  104. data/spec/fear/awaitable_spec.rb +17 -0
  105. data/spec/fear/done_spec.rb +8 -6
  106. data/spec/fear/either/mixin_spec.rb +17 -0
  107. data/spec/fear/either_pattern_match_spec.rb +37 -0
  108. data/spec/fear/either_pattern_matching_spec.rb +28 -0
  109. data/spec/fear/extractor/array_matcher_spec.rb +230 -0
  110. data/spec/fear/extractor/extractor_matcher_spec.rb +153 -0
  111. data/spec/fear/extractor/grammar_array_spec.rb +25 -0
  112. data/spec/fear/extractor/identified_matcher_spec.rb +49 -0
  113. data/spec/fear/extractor/identifier_matcher_spec.rb +68 -0
  114. data/spec/fear/extractor/pattern_spec.rb +34 -0
  115. data/spec/fear/extractor/typed_identifier_matcher_spec.rb +64 -0
  116. data/spec/fear/extractor/value_matcher_number_spec.rb +79 -0
  117. data/spec/fear/extractor/value_matcher_string_spec.rb +88 -0
  118. data/spec/fear/extractor/value_matcher_symbol_spec.rb +71 -0
  119. data/spec/fear/extractor_api_spec.rb +115 -0
  120. data/spec/fear/extractor_spec.rb +61 -0
  121. data/spec/fear/failure_spec.rb +145 -45
  122. data/spec/fear/for_spec.rb +57 -67
  123. data/spec/fear/future_spec.rb +691 -0
  124. data/spec/fear/guard_spec.rb +103 -0
  125. data/spec/fear/left_spec.rb +112 -46
  126. data/spec/fear/none_spec.rb +114 -16
  127. data/spec/fear/option/mixin_spec.rb +39 -0
  128. data/spec/fear/option_pattern_match_spec.rb +35 -0
  129. data/spec/fear/option_pattern_matching_spec.rb +34 -0
  130. data/spec/fear/option_spec.rb +121 -8
  131. data/spec/fear/partial_function/empty_spec.rb +38 -0
  132. data/spec/fear/partial_function_and_then_spec.rb +147 -0
  133. data/spec/fear/partial_function_composition_spec.rb +82 -0
  134. data/spec/fear/partial_function_or_else_spec.rb +276 -0
  135. data/spec/fear/partial_function_spec.rb +239 -0
  136. data/spec/fear/pattern_match_spec.rb +93 -0
  137. data/spec/fear/pattern_matching_api_spec.rb +31 -0
  138. data/spec/fear/promise_spec.rb +96 -0
  139. data/spec/fear/right_biased/left.rb +29 -32
  140. data/spec/fear/right_biased/right.rb +51 -54
  141. data/spec/fear/right_spec.rb +109 -41
  142. data/spec/fear/some_spec.rb +80 -15
  143. data/spec/fear/success_spec.rb +99 -32
  144. data/spec/fear/try/mixin_spec.rb +19 -0
  145. data/spec/fear/try_pattern_match_spec.rb +37 -0
  146. data/spec/fear/try_pattern_matching_spec.rb +34 -0
  147. data/spec/fear/utils_spec.rb +16 -14
  148. data/spec/spec_helper.rb +13 -7
  149. data/spec/struct_pattern_matching_spec.rb +36 -0
  150. data/spec/struct_spec.rb +226 -0
  151. data/spec/support/dry_types.rb +6 -0
  152. metadata +320 -29
  153. data/.travis.yml +0 -9
  154. data/lib/fear/done.rb +0 -22
  155. data/lib/fear/for/evaluation_context.rb +0 -91
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fear
4
+ # Try pattern matcher
5
+ #
6
+ # @note it has two optimized subclasses +Fear::SuccessPatternMatch+ and +Fear::FailurePatternMatch+
7
+ # @api private
8
+ class TryPatternMatch < Fear::PatternMatch
9
+ SUCCESS_EXTRACTOR = :get.to_proc
10
+ private_constant :SUCCESS_EXTRACTOR
11
+
12
+ FAILURE_EXTRACTOR = :exception.to_proc
13
+ private_constant :FAILURE_EXTRACTOR
14
+
15
+ # Match against +Fear::Success+
16
+ #
17
+ # @param conditions [<#==>]
18
+ # @return [Fear::TryPatternMatch]
19
+ def success(*conditions, &effect)
20
+ branch = Fear.case(Fear::Success, &SUCCESS_EXTRACTOR).and_then(Fear.case(*conditions, &effect))
21
+ or_else(branch)
22
+ end
23
+
24
+ # Match against +Fear::Failure+
25
+ #
26
+ # @param conditions [<#==>]
27
+ # @return [Fear::TryPatternMatch]
28
+ def failure(*conditions, &effect)
29
+ branch = Fear.case(Fear::Failure, &FAILURE_EXTRACTOR).and_then(Fear.case(*conditions, &effect))
30
+ or_else(branch)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fear
4
+ # Represents lack of value. It's typically returned when function completed without a value.
5
+ #
6
+ # @example
7
+ # if user.valid?
8
+ # Fear.right(Fear::Unit)
9
+ # else
10
+ # Fear.left(user.errors)
11
+ # end
12
+ #
13
+ # @example
14
+ # def sent_notifications(user)
15
+ # # ...
16
+ # Fear::Unit
17
+ # end
18
+ #
19
+ Unit = Object.new.tap do |unit|
20
+ # @return [String]
21
+ def unit.to_s
22
+ "#<Fear::Unit>"
23
+ end
24
+
25
+ # @return [String]
26
+ def unit.inspect
27
+ "#<Fear::Unit>"
28
+ end
29
+ end.freeze
30
+
31
+ public_constant :Unit
32
+ end
@@ -1,25 +1,50 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Fear
2
4
  # @private
3
5
  module Utils
4
- extend self
6
+ EMPTY_STRING = ""
7
+ public_constant :EMPTY_STRING
8
+
9
+ IDENTITY = :itself.to_proc
10
+ public_constant :IDENTITY
11
+
12
+ UNDEFINED = Object.new.freeze
13
+ public_constant :UNDEFINED
14
+
15
+ EMPTY_HASH = {}.freeze
16
+ public_constant :EMPTY_HASH
17
+
18
+ EMPTY_ARRAY = [].freeze
19
+ public_constant :EMPTY_ARRAY
5
20
 
6
- def assert_arg_or_block!(method_name, *args)
7
- unless block_given? ^ !args.empty?
8
- fail ArgumentError, "##{method_name} accepts either one argument or block"
21
+ class << self
22
+ def assert_arg_or_block!(method_name, *args)
23
+ unless block_given? ^ !args.empty?
24
+ raise ArgumentError, "##{method_name} accepts either one argument or block"
25
+ end
9
26
  end
10
- end
11
27
 
12
- def assert_type!(value, *types)
13
- if types.none? { |type| value.is_a?(type) }
14
- fail TypeError, "expected `#{value.inspect}` to be of #{types.join(', ')} class"
28
+ def with_block_or_argument(method_name, arg = UNDEFINED, block = nil)
29
+ if block.nil? ^ arg.equal?(UNDEFINED)
30
+ yield(block || arg)
31
+ else
32
+ raise ArgumentError, "#{method_name} accepts either block or partial function"
33
+ end
34
+ end
35
+
36
+ def assert_type!(value, *types)
37
+ if types.none? { |type| value.is_a?(type) }
38
+ raise TypeError, "expected `#{value.inspect}` to be of #{types.join(", ")} class"
39
+ end
15
40
  end
16
- end
17
41
 
18
- def return_or_call_proc(value)
19
- if value.respond_to?(:call)
20
- value.call
21
- else
22
- value
42
+ def return_or_call_proc(value)
43
+ if value.respond_to?(:call)
44
+ value.()
45
+ else
46
+ value
47
+ end
23
48
  end
24
49
  end
25
50
  end
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Fear
2
- VERSION = '0.9.0'.freeze
4
+ VERSION = "1.2.0"
5
+ public_constant :VERSION
3
6
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "support/dry_types"
4
+
5
+ RSpec.describe Dry::Types::Constrained, :option do
6
+ context "with a option type" do
7
+ subject(:type) do
8
+ Dry::Types["nominal.string"].constrained(size: 4).option
9
+ end
10
+
11
+ it_behaves_like "Dry::Types::Nominal without primitive"
12
+
13
+ it "passes when constraints are not violated" do
14
+ expect(type[nil]).to be_none
15
+ expect(type["hell"]).to be_some_of("hell")
16
+ end
17
+
18
+ it "raises when a given constraint is violated" do
19
+ expect { type["hel"] }.to raise_error(Dry::Types::ConstraintError, /hel/)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "support/dry_types"
4
+
5
+ RSpec.describe Dry::Types::Nominal, :option do
6
+ describe "with opt-in option types" do
7
+ context "with strict string" do
8
+ let(:string) { Dry::Types["option.strict.string"] }
9
+
10
+ it_behaves_like "Dry::Types::Nominal without primitive" do
11
+ let(:type) { string }
12
+ end
13
+
14
+ it "accepts nil" do
15
+ expect(string[nil]).to be_none
16
+ end
17
+
18
+ it "accepts a string" do
19
+ expect(string["something"]).to be_some_of("something")
20
+ end
21
+ end
22
+
23
+ context "with coercible string" do
24
+ let(:string) { Dry::Types["option.coercible.string"] }
25
+
26
+ it_behaves_like "Dry::Types::Nominal without primitive" do
27
+ let(:type) { string }
28
+ end
29
+
30
+ it "accepts nil" do
31
+ expect(string[nil]).to be_none
32
+ end
33
+
34
+ it "accepts a string" do
35
+ expect(string[:something]).to be_some_of("something")
36
+ end
37
+ end
38
+ end
39
+
40
+ describe "defining coercible Option String" do
41
+ let(:option_string) { Dry::Types["coercible.string"].option }
42
+
43
+ it_behaves_like "Dry::Types::Nominal without primitive" do
44
+ let(:type) { option_string }
45
+ end
46
+
47
+ it "accepts nil" do
48
+ expect(option_string[nil]).to be_none
49
+ end
50
+
51
+ it "accepts an object coercible to a string" do
52
+ expect(option_string[123]).to be_some_of("123")
53
+ end
54
+ end
55
+
56
+ describe "defining Option String" do
57
+ let(:option_string) { Dry::Types["strict.string"].option }
58
+
59
+ it_behaves_like "Dry::Types::Nominal without primitive" do
60
+ let(:type) { option_string }
61
+ end
62
+
63
+ it "accepts nil and returns None instance" do
64
+ value = option_string[nil]
65
+
66
+ expect(value).to be_none
67
+ expect(value.map(&:downcase).map(&:upcase)).to be_none
68
+ end
69
+
70
+ it "accepts a string and returns Some instance" do
71
+ value = option_string["SomeThing"]
72
+
73
+ expect(value).to be_some_of("SomeThing")
74
+ expect(value.map(&:downcase).map(&:upcase)).to be_some_of("SOMETHING")
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "support/dry_types"
4
+
5
+ RSpec.describe Dry::Types::Nominal, "#default", :option do
6
+ context "with a maybe" do
7
+ subject(:type) { Dry::Types["strict.integer"].option }
8
+
9
+ it_behaves_like "Dry::Types::Nominal without primitive" do
10
+ let(:type) { Dry::Types["strict.integer"].option.default(0) }
11
+ end
12
+
13
+ it "does not allow nil" do
14
+ expect { type.default(nil) }.to raise_error(ArgumentError, /nil/)
15
+ end
16
+
17
+ it "accepts a non-nil value" do
18
+ expect(type.default(0)[0]).to be_some_of(0)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "support/dry_types"
4
+
5
+ RSpec.describe Dry::Types::Hash, :option do
6
+ let(:email) { Dry::Types["option.strict.string"] }
7
+
8
+ context "Symbolized constructor" do
9
+ subject(:hash) do
10
+ Dry::Types["nominal.hash"].schema(
11
+ name: "string",
12
+ email: email,
13
+ ).with_key_transform(&:to_sym)
14
+ end
15
+
16
+ describe "#[]" do
17
+ it "sets None as a default value for option" do
18
+ result = hash["name" => "Jane"]
19
+
20
+ expect(result[:email]).to be_none
21
+ end
22
+ end
23
+ end
24
+
25
+ context "Schema constructor" do
26
+ subject(:hash) do
27
+ Dry::Types["nominal.hash"].schema(
28
+ name: "string",
29
+ email: email,
30
+ )
31
+ end
32
+
33
+ describe "#[]" do
34
+ it "sets None as a default value for option types" do
35
+ result = hash[name: "Jane"]
36
+
37
+ expect(result[:email]).to be_none
38
+ end
39
+ end
40
+ end
41
+
42
+ context "Strict with defaults" do
43
+ subject(:hash) do
44
+ Dry::Types["nominal.hash"].schema(
45
+ name: "string",
46
+ email: email,
47
+ )
48
+ end
49
+
50
+ describe "#[]" do
51
+ it "sets None as a default value for option types" do
52
+ result = hash[name: "Jane"]
53
+
54
+ expect(result[:email]).to be_none
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "support/dry_types"
4
+
5
+ RSpec.describe Dry::Types::Nominal, "#option", :option do
6
+ context "with a nominal" do
7
+ subject(:type) { Dry::Types["nominal.string"].option }
8
+
9
+ it_behaves_like "Dry::Types::Nominal without primitive"
10
+
11
+ it "returns None when value is nil" do
12
+ expect(type[nil]).to be_none
13
+ end
14
+
15
+ it "returns Some when value exists" do
16
+ expect(type["hello"]).to be_some_of("hello")
17
+ end
18
+
19
+ it "returns original if input is already a option" do
20
+ expect(type[Fear.some("hello")]).to be_some_of("hello")
21
+ end
22
+
23
+ it "aliases #[] as #call" do
24
+ expect(type.("hello")).to be_some_of("hello")
25
+ end
26
+
27
+ it "does not have primitive" do
28
+ expect(type).to_not respond_to(:primitive)
29
+ end
30
+ end
31
+
32
+ context "with a strict type" do
33
+ subject(:type) { Dry::Types["strict.integer"].option }
34
+
35
+ it_behaves_like "Dry::Types::Nominal without primitive"
36
+
37
+ it "returns None when value is nil" do
38
+ expect(type[nil]).to be_none
39
+ end
40
+
41
+ it "returns Some when value exists" do
42
+ expect(type[231]).to be_some_of(231)
43
+ end
44
+ end
45
+
46
+ context "with a sum" do
47
+ subject(:type) { Dry::Types["nominal.bool"].option }
48
+
49
+ it_behaves_like "Dry::Types::Nominal without primitive"
50
+
51
+ it "returns None when value is nil" do
52
+ expect(type[nil]).to be_none
53
+ end
54
+
55
+ it "returns Some when value exists" do
56
+ expect(type[true]).to be_some_of(true)
57
+ expect(type[false]).to be_some_of(false)
58
+ end
59
+
60
+ it "does not have primitive" do
61
+ expect(type).to_not respond_to(:primitive)
62
+ end
63
+ end
64
+
65
+ context "with keys" do
66
+ subject(:type) do
67
+ Dry::Types["hash"].schema(foo: Dry::Types["integer"]).key(:foo)
68
+ end
69
+
70
+ it "gets wrapped by key type" do
71
+ expect(type.option).to be_a(Dry::Types::Schema::Key)
72
+ expect(type.option[nil]).to be_none
73
+ expect(type.option[1]).to be_some_of(1)
74
+ end
75
+ end
76
+
77
+ describe "#try" do
78
+ subject(:type) { Dry::Types["coercible.integer"].option }
79
+
80
+ it "maps successful result" do
81
+ expect(type.try("1")).to eq(Dry::Types::Result::Success.new(Fear.some(1)))
82
+ expect(type.try(nil)).to eq(Dry::Types::Result::Success.new(Fear.none))
83
+ expect(type.try("a")).to be_a(Dry::Types::Result::Failure)
84
+ end
85
+ end
86
+
87
+ describe "#call" do
88
+ describe "safe calls" do
89
+ subject(:type) { Dry::Types["coercible.integer"].option }
90
+
91
+ specify do
92
+ expect(type.("a") { :fallback }).to be(:fallback)
93
+ expect(type.(Fear.some(1)) { :fallback }).to eq(Fear.some(1))
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Fear::Awaitable do
4
+ subject(:awaitable) { Object.new.extend(Fear::Awaitable) }
5
+
6
+ describe "#__ready__" do
7
+ it "must implement the method" do
8
+ expect { awaitable.__ready__(1) }.to raise_error(NotImplementedError)
9
+ end
10
+ end
11
+
12
+ describe "#__result__" do
13
+ it "must implement the method" do
14
+ expect { awaitable.__result__(1) }.to raise_error(NotImplementedError)
15
+ end
16
+ end
17
+ end
@@ -1,17 +1,19 @@
1
- RSpec.describe Fear::Done do
2
- describe '#to_s' do
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Fear::Unit do
4
+ describe "#to_s" do
3
5
  subject { described_class.to_s }
4
6
 
5
- it { is_expected.to eq('Done') }
7
+ it { is_expected.to eq("#<Fear::Unit>") }
6
8
  end
7
9
 
8
- describe '#inspect' do
10
+ describe "#inspect" do
9
11
  subject { described_class.inspect }
10
12
 
11
- it { is_expected.to eq('Done') }
13
+ it { is_expected.to eq("#<Fear::Unit>") }
12
14
  end
13
15
 
14
- describe '#==' do
16
+ describe "#==" do
15
17
  it { is_expected.to eq(described_class) }
16
18
  end
17
19
  end