File: composable_spec.rb

package info (click to toggle)
ruby-rspec 3.13.0c0e0m0s1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,856 kB
  • sloc: ruby: 70,868; sh: 1,423; makefile: 99
file content (122 lines) | stat: -rw-r--r-- 4,112 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
module RSpec
  module Matchers
    RSpec.describe Composable do
      RSpec::Matchers.define :matcher_using_surface_descriptions_in do |expected|
        match { false }
        failure_message { surface_descriptions_in(expected).to_s }
      end

      it "does not blow up when surfacing descriptions from an unreadable IO object" do
        expect {
          expect(3).to matcher_using_surface_descriptions_in(STDOUT)
        }.to fail_with(STDOUT.inspect)
      end

      it "does not blow up when surfacing descriptions from an unreadable Range object" do
        infinity = (1.0/0.0)
        infinite_range = -infinity..infinity
        expect {
          expect(1).to matcher_using_surface_descriptions_in(infinite_range)
        }.to fail_with(infinite_range.inspect)
      end

      it "does not blow up when surfacing descriptions from an Enumerable object whose #each includes the object itself" do
        array = ['something']
        array << array
        expect {
          expect(1).to matcher_using_surface_descriptions_in(array)
        }.to fail_with(array.to_s)
      end

      it "does not enumerate normal ranges" do
        range = 1..3
        expect {
          expect(1).to matcher_using_surface_descriptions_in(range)
        }.to fail_with(range.inspect)
      end

      it "doesn't mangle struct descriptions" do
        model = Struct.new(:a).new(1)
        expect {
          expect(1).to matcher_using_surface_descriptions_in(model)
        }.to fail_with(model.inspect)
      end

      RSpec::Matchers.define :all_but_one do |matcher|
        match do |actual|
          match_count = actual.count { |v| values_match?(matcher, v) }
          actual.size == match_count + 1
        end
      end

      context "when using a matcher instance that memoizes state multiple times in a composed expression" do
        it "works properly in spite of the memoization" do
          expect(["foo", "bar", "a"]).to all_but_one(have_string_length(3))
        end

        context "when passing a compound expression" do
          it "works properly in spite of the memoization" do
            expect(["A", "AB", "ABC"]).to all_but_one(
                have_string_length(1).or have_string_length(2)
            )
          end
        end
      end

      describe "cloning data structures containing matchers" do
        include Composable

        it "clones only the contained matchers" do
          matcher_1   = eq(1)
          matcher_2   = eq(2)
          object      = Object.new
          uncloneable = nil

          data_structure = {
            "foo"  => matcher_1,
            "bar"  => [matcher_2, uncloneable],
            "bazz" => object
          }

          cloned = with_matchers_cloned(data_structure)
          expect(cloned).not_to equal(data_structure)

          expect(cloned["foo"]).to be_a_clone_of(matcher_1)
          expect(cloned["bar"].first).to be_a_clone_of(matcher_2)
          expect(cloned["bazz"]).to equal(object)
        end

        it "copies custom matchers properly so they can work even though they have singleton behavior" do
          expect("foo").to with_matchers_cloned(have_string_length 3)
        end

        it 'does not blow up when passed an array containing an IO object' do
          stdout = STDOUT
          expect(with_matchers_cloned([stdout]).first).to equal(stdout)
        end
      end

      describe "when an unexpected call stack jump occurs" do
        RSpec::Matchers.define :cause_call_stack_jump do
          supports_block_expectations

          match do |block|
            begin
              block.call
              false
            rescue Exception # rubocop:disable Lint/RescueException
              true
            end
          end
        end

        it "issue a warning suggesting `expects_call_stack_jump?` has been improperly declared" do
          expect {
            x = 0
            expect { x += 1; exit }.to change { x }.and cause_call_stack_jump
          }.to raise_error(/no match results, [\.\w\s]+ declare `expects_call_stack_jump\?`/)
        end
      end
    end
  end
end