File: result_spec.rb

package info (click to toggle)
ruby-capybara 3.36.0%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 2,380 kB
  • sloc: ruby: 23,399; javascript: 748; makefile: 11
file content (195 lines) | stat: -rw-r--r-- 6,009 bytes parent folder | download
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Capybara::Result do
  let :string do
    Capybara.string <<-STRING
      <ul>
        <li>Alpha</li>
        <li>Beta</li>
        <li>Gamma</li>
        <li>Delta</li>
      </ul>
    STRING
  end

  let :result do
    string.all '//li', minimum: 0 # pass minimum: 0 so lazy evaluation doesn't get triggered yet
  end

  it 'has a length' do
    expect(result.length).to eq(4)
  end

  it 'has a first element' do
    result.first.text == 'Alpha'
  end

  it 'has a last element' do
    result.last.text == 'Delta'
  end

  it 'can supports values_at method' do
    expect(result.values_at(0, 2).map(&:text)).to eq(%w[Alpha Gamma])
  end

  it 'can return an element by its index' do
    expect(result.at(1).text).to eq('Beta')
    expect(result[2].text).to eq('Gamma')
  end

  it 'can be mapped' do
    expect(result.map(&:text)).to eq(%w[Alpha Beta Gamma Delta])
  end

  it 'can be selected' do
    expect(result.count do |element|
      element.text.include? 't'
    end).to eq(2)
  end

  it 'can be reduced' do
    expect(result.reduce('') do |memo, element|
      memo + element.text[0]
    end).to eq('ABGD')
  end

  it 'can be sampled' do
    expect(result).to include(result.sample)
  end

  it 'can be indexed' do
    expect(result.index do |el|
      el.text == 'Gamma'
    end).to eq(2)
  end

  def recalc_result
    string.all '//li', minimum: 0 # pass minimum: 0 so lazy evaluation doesn't get triggered yet
  end

  it 'supports all modes of []' do
    expect(recalc_result[1].text).to eq 'Beta'
    expect(recalc_result[0, 2].map(&:text)).to eq %w[Alpha Beta]
    expect(recalc_result[1..3].map(&:text)).to eq %w[Beta Gamma Delta]
    expect(recalc_result[-1].text).to eq 'Delta'
    expect(recalc_result[-2, 3].map(&:text)).to eq %w[Gamma Delta]
    expect(recalc_result[1...3].map(&:text)).to eq %w[Beta Gamma]
    expect(recalc_result[1..7].map(&:text)).to eq %w[Beta Gamma Delta]
    expect(recalc_result[2...-1].map(&:text)).to eq %w[Gamma]
    expect(recalc_result[2..-1].map(&:text)).to eq %w[Gamma Delta] # rubocop:disable Style/SlicingWithRange
    expect(recalc_result[2..].map(&:text)).to eq %w[Gamma Delta]
  end

  it 'supports endless ranges' do
    expect(result[2..].map(&:text)).to eq %w[Gamma Delta]
  end

  eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.6
    it 'supports inclusive positive beginless ranges' do
      expect(result[..2].map(&:text)).to eq %w[Alpha Beta Gamma]
    end

    it 'supports inclusive negative beginless ranges' do
      expect(result[..-2].map(&:text)).to eq %w[Alpha Beta Gamma]
      expect(result[..-1].map(&:text)).to eq %w[Alpha Beta Gamma Delta]
    end

    it 'supports exclusive positive beginless ranges' do
      expect(result[...2].map(&:text)).to eq %w[Alpha Beta]
    end

    it 'supports exclusive negative beginless ranges' do
      expect(result[...-2].map(&:text)).to eq %w[Alpha Beta]
      expect(result[...-1].map(&:text)).to eq %w[Alpha Beta Gamma]
    end
  TEST

  it 'works with filter blocks' do
    result = string.all('//li') { |node| node.text == 'Alpha' }
    expect(result.size).to eq 1
  end

  # Not a great test but it indirectly tests what is needed
  it 'should evaluate filters lazily for idx' do
    skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
    # Not processed until accessed
    expect(result.instance_variable_get('@result_cache').size).to be 0

    # Only one retrieved when needed
    result.first
    expect(result.instance_variable_get('@result_cache').size).to be 1

    # works for indexed access
    result[0]
    expect(result.instance_variable_get('@result_cache').size).to be 1

    result[2]
    expect(result.instance_variable_get('@result_cache').size).to be 3

    # All cached when converted to array
    result.to_a
    expect(result.instance_variable_get('@result_cache').size).to eq 4
  end

  it 'should evaluate filters lazily for range' do
    skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
    result[0..1]
    expect(result.instance_variable_get('@result_cache').size).to be 2

    expect(result[0..7].size).to eq 4
    expect(result.instance_variable_get('@result_cache').size).to be 4
  end

  it 'should evaluate filters lazily for idx and length' do
    skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
    result[1, 2]
    expect(result.instance_variable_get('@result_cache').size).to be 3

    expect(result[2, 5].size).to eq 2
    expect(result.instance_variable_get('@result_cache').size).to be 4
  end

  it 'should only need to evaluate one result for any?' do
    skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
    result.any?
    expect(result.instance_variable_get('@result_cache').size).to be 1
  end

  it 'should evaluate all elements when #to_a called' do
    # All cached when converted to array
    result.to_a
    expect(result.instance_variable_get('@result_cache').size).to eq 4
  end

  describe '#each' do
    it 'lazily evaluates' do
      skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
      results = []
      result.each do |el|
        results << el
        expect(result.instance_variable_get('@result_cache').size).to eq results.size
      end

      expect(results.size).to eq 4
    end

    context 'without a block' do
      it 'returns an iterator' do
        expect(result.each).to be_a(Enumerator)
      end

      it 'lazily evaluates' do
        skip 'JRuby has an issue with lazy enumerator evaluation' if jruby_lazy_enumerator_workaround?
        result.each.with_index do |_el, idx|
          expect(result.instance_variable_get('@result_cache').size).to eq(idx + 1) # 0 indexing
        end
      end
    end
  end

  def jruby_lazy_enumerator_workaround?
    RUBY_PLATFORM == 'java'
  end
end