capybara 3.32.2 → 3.33.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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +21 -1
  3. data/README.md +10 -3
  4. data/lib/capybara.rb +17 -7
  5. data/lib/capybara/cucumber.rb +1 -1
  6. data/lib/capybara/minitest.rb +2 -3
  7. data/lib/capybara/node/actions.rb +16 -20
  8. data/lib/capybara/node/matchers.rb +4 -6
  9. data/lib/capybara/queries/selector_query.rb +8 -1
  10. data/lib/capybara/queries/style_query.rb +1 -1
  11. data/lib/capybara/queries/text_query.rb +6 -0
  12. data/lib/capybara/registration_container.rb +44 -0
  13. data/lib/capybara/selector.rb +10 -1
  14. data/lib/capybara/selector/definition.rb +5 -4
  15. data/lib/capybara/selector/definition/button.rb +1 -0
  16. data/lib/capybara/selector/definition/fillable_field.rb +1 -1
  17. data/lib/capybara/selector/definition/link.rb +8 -0
  18. data/lib/capybara/selector/definition/table.rb +1 -1
  19. data/lib/capybara/selector/selector.rb +4 -0
  20. data/lib/capybara/selenium/driver.rb +2 -0
  21. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +7 -9
  22. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +7 -9
  23. data/lib/capybara/selenium/node.rb +3 -2
  24. data/lib/capybara/selenium/nodes/firefox_node.rb +1 -1
  25. data/lib/capybara/selenium/patches/logs.rb +3 -5
  26. data/lib/capybara/session.rb +3 -3
  27. data/lib/capybara/session/config.rb +3 -1
  28. data/lib/capybara/spec/public/test.js +7 -0
  29. data/lib/capybara/spec/session/click_button_spec.rb +11 -0
  30. data/lib/capybara/spec/session/has_button_spec.rb +16 -0
  31. data/lib/capybara/spec/session/has_current_path_spec.rb +2 -2
  32. data/lib/capybara/spec/session/has_field_spec.rb +16 -0
  33. data/lib/capybara/spec/session/has_select_spec.rb +4 -4
  34. data/lib/capybara/spec/session/has_selector_spec.rb +4 -4
  35. data/lib/capybara/spec/session/node_spec.rb +6 -6
  36. data/lib/capybara/spec/spec_helper.rb +1 -0
  37. data/lib/capybara/spec/test_app.rb +14 -18
  38. data/lib/capybara/spec/views/form.erb +2 -1
  39. data/lib/capybara/spec/views/with_dragula.erb +3 -1
  40. data/lib/capybara/spec/views/with_js.erb +1 -0
  41. data/lib/capybara/version.rb +1 -1
  42. data/spec/capybara_spec.rb +1 -1
  43. data/spec/dsl_spec.rb +14 -1
  44. data/spec/minitest_spec.rb +1 -1
  45. data/spec/rack_test_spec.rb +1 -0
  46. data/spec/rspec/shared_spec_matchers.rb +63 -51
  47. data/spec/selector_spec.rb +1 -1
  48. data/spec/selenium_spec_chrome.rb +0 -2
  49. data/spec/server_spec.rb +41 -49
  50. data/spec/shared_selenium_session.rb +10 -1
  51. data/spec/spec_helper.rb +1 -1
  52. metadata +4 -3
@@ -4,6 +4,7 @@ Capybara.add_selector(:button, locator_type: [String, Symbol]) do
4
4
  xpath(:value, :title, :type, :name) do |locator, **options|
5
5
  input_btn_xpath = XPath.descendant(:input)[XPath.attr(:type).one_of('submit', 'reset', 'image', 'button')]
6
6
  btn_xpath = XPath.descendant(:button)
7
+ btn_xpath += XPath.descendant[XPath.attr(:role).equals('button')] if enable_aria_role
7
8
  image_btn_xpath = XPath.descendant(:input)[XPath.attr(:type) == 'image']
8
9
 
9
10
  unless locator.nil?
@@ -18,7 +18,7 @@ Capybara.add_selector(:fillable_field, locator_type: [String, Symbol]) do
18
18
  end
19
19
  end
20
20
 
21
- filter_set(:_field, %i[disabled multiple name placeholder valid])
21
+ filter_set(:_field, %i[disabled multiple name placeholder valid validation_message])
22
22
 
23
23
  node_filter(:with) do |node, with|
24
24
  val = node.value
@@ -5,6 +5,13 @@ Capybara.add_selector(:link, locator_type: [String, Symbol]) do
5
5
  xpath = XPath.descendant(:a)
6
6
  xpath = builder(xpath).add_attribute_conditions(href: href) unless href == false
7
7
 
8
+ if enable_aria_role
9
+ role_path = XPath.descendant[XPath.attr(:role).equals('link')]
10
+ role_path = builder(role_path).add_attribute_conditions(href: href) unless [true, false].include? href
11
+
12
+ xpath += role_path
13
+ end
14
+
8
15
  unless locator.nil?
9
16
  locator = locator.to_s
10
17
  matchers = [XPath.attr(:id) == locator,
@@ -18,6 +25,7 @@ Capybara.add_selector(:link, locator_type: [String, Symbol]) do
18
25
 
19
26
  xpath = xpath[find_by_attr(:title, title)]
20
27
  xpath = xpath[XPath.descendant(:img)[XPath.attr(:alt) == alt]] if alt
28
+
21
29
  xpath
22
30
  end
23
31
 
@@ -43,7 +43,7 @@ Capybara.add_selector(:table, locator_type: [String, Symbol]) do
43
43
  end
44
44
 
45
45
  expression_filter(:cols, valid_values: [Array]) do |xpath, cols|
46
- raise ArgumentError, ':cols must be an Array of Arrays' unless cols.all? { |col| col.is_a? Array }
46
+ raise ArgumentError, ':cols must be an Array of Arrays' unless cols.all?(Array)
47
47
 
48
48
  rows = cols.transpose
49
49
  col_conditions = rows.map { |row| match_row(row, match_size: true) }.reduce(:&)
@@ -48,6 +48,10 @@ module Capybara
48
48
  @config[:enable_aria_label]
49
49
  end
50
50
 
51
+ def enable_aria_role
52
+ @config[:enable_aria_role]
53
+ end
54
+
51
55
  def test_id
52
56
  @config[:test_id]
53
57
  end
@@ -85,6 +85,8 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
85
85
 
86
86
  def html
87
87
  browser.page_source
88
+ rescue Selenium::WebDriver::Error::JavascriptError => e
89
+ raise unless e.message.match?(/documentElement is null/)
88
90
  end
89
91
 
90
92
  def title
@@ -13,14 +13,12 @@ module Capybara::Selenium::Driver::ChromeDriver
13
13
 
14
14
  def fullscreen_window(handle)
15
15
  within_given_window(handle) do
16
- begin
17
- super
18
- rescue NoMethodError => e
19
- raise unless e.message.match?(/full_screen_window/)
20
-
21
- result = bridge.http.call(:post, "session/#{bridge.session_id}/window/fullscreen", {})
22
- result['value']
23
- end
16
+ super
17
+ rescue NoMethodError => e
18
+ raise unless e.message.match?(/full_screen_window/)
19
+
20
+ result = bridge.http.call(:post, "session/#{bridge.session_id}/window/fullscreen", {})
21
+ result['value']
24
22
  end
25
23
  end
26
24
 
@@ -65,7 +63,7 @@ private
65
63
  end
66
64
 
67
65
  def clear_all_storage?
68
- storage_clears.none? { |s| s == false }
66
+ storage_clears.none? false
69
67
  end
70
68
 
71
69
  def uniform_storage_clear?
@@ -13,14 +13,12 @@ module Capybara::Selenium::Driver::EdgeDriver
13
13
  return super if edgedriver_version < 75
14
14
 
15
15
  within_given_window(handle) do
16
- begin
17
- super
18
- rescue NoMethodError => e
19
- raise unless e.message.match?(/full_screen_window/)
20
-
21
- result = bridge.http.call(:post, "session/#{bridge.session_id}/window/fullscreen", {})
22
- result['value']
23
- end
16
+ super
17
+ rescue NoMethodError => e
18
+ raise unless e.message.match?(/full_screen_window/)
19
+
20
+ result = bridge.http.call(:post, "session/#{bridge.session_id}/window/fullscreen", {})
21
+ result['value']
24
22
  end
25
23
  end
26
24
 
@@ -74,7 +72,7 @@ private
74
72
  end
75
73
 
76
74
  def clear_all_storage?
77
- storage_clears.none? { |s| s == false }
75
+ storage_clears.none? false
78
76
  end
79
77
 
80
78
  def uniform_storage_clear?
@@ -281,7 +281,7 @@ private
281
281
  driver.execute_script 'arguments[0].select()', self unless clear == :none
282
282
  if rapid == true || ((value.length > auto_rapid_set_length) && rapid != false)
283
283
  send_keys(value[0..3])
284
- driver.execute_script RAPID_SET_TEXT, self, value[0...-3]
284
+ driver.execute_script RAPID_APPEND_TEXT, self, value[4...-3]
285
285
  send_keys(value[-3..-1])
286
286
  else
287
287
  send_keys(value)
@@ -534,8 +534,9 @@ private
534
534
  })(arguments[0], arguments[1], arguments[2])
535
535
  JS
536
536
 
537
- RAPID_SET_TEXT = <<~'JS'
537
+ RAPID_APPEND_TEXT = <<~'JS'
538
538
  (function(el, value) {
539
+ value = el.value + value;
539
540
  if (el.maxLength && el.maxLength != -1){
540
541
  value = value.slice(0, el.maxLength);
541
542
  }
@@ -42,7 +42,7 @@ class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
42
42
 
43
43
  def send_keys(*args)
44
44
  # https://github.com/mozilla/geckodriver/issues/846
45
- return super(*args.map { |arg| arg == :space ? ' ' : arg }) if args.none? { |arg| arg.is_a? Array }
45
+ return super(*args.map { |arg| arg == :space ? ' ' : arg }) if args.none?(Array)
46
46
 
47
47
  native.click
48
48
  _send_keys(args).perform
@@ -33,11 +33,9 @@ module Capybara
33
33
  end
34
34
 
35
35
  Array(data).map do |l|
36
- begin
37
- ::Selenium::WebDriver::LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
38
- rescue KeyError
39
- next
40
- end
36
+ ::Selenium::WebDriver::LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
37
+ rescue KeyError
38
+ next
41
39
  end
42
40
  rescue ::Selenium::WebDriver::Error::UnknownCommandError
43
41
  raise NotImplementedError, LOG_MSG
@@ -97,8 +97,8 @@ module Capybara
97
97
 
98
98
  def driver
99
99
  @driver ||= begin
100
- unless Capybara.drivers.key?(mode)
101
- other_drivers = Capybara.drivers.keys.map(&:inspect)
100
+ unless Capybara.drivers[mode]
101
+ other_drivers = Capybara.drivers.names.map(&:inspect)
102
102
  raise Capybara::DriverNotFoundError, "no driver called #{mode.inspect} was found, available drivers: #{other_drivers.join(', ')}"
103
103
  end
104
104
  driver = Capybara.drivers[mode].call(app)
@@ -192,7 +192,7 @@ module Capybara
192
192
  # @return [String] A snapshot of the DOM of the current document, as it looks right now (potentially modified by JavaScript).
193
193
  #
194
194
  def html
195
- driver.html
195
+ driver.html || ''
196
196
  end
197
197
  alias_method :body, :html
198
198
  alias_method :source, :html
@@ -8,7 +8,7 @@ module Capybara
8
8
  automatic_reload match exact exact_text raise_server_errors visible_text_only
9
9
  automatic_label_click enable_aria_label save_path asset_host default_host app_host
10
10
  server_host server_port server_errors default_set_options disable_animation test_id
11
- predicates_wait default_normalize_ws w3c_click_offset].freeze
11
+ predicates_wait default_normalize_ws w3c_click_offset enable_aria_role].freeze
12
12
 
13
13
  attr_accessor(*OPTIONS)
14
14
 
@@ -37,6 +37,8 @@ module Capybara
37
37
  # See {Capybara.configure}
38
38
  # @!method enable_aria_label
39
39
  # See {Capybara.configure}
40
+ # @!method enable_aria_role
41
+ # See {Capybara.configure}
40
42
  # @!method save_path
41
43
  # See {Capybara.configure}
42
44
  # @!method asset_host
@@ -108,6 +108,13 @@ $(function() {
108
108
  }, 4000);
109
109
  return false;
110
110
  });
111
+ $('#aria-button').click(function() {
112
+ var span = $(this);
113
+ setTimeout(function() {
114
+ $(span).after('<span role="button">ARIA button has been clicked</span>')
115
+ }, 1000);
116
+ return false;
117
+ });
111
118
  $('#waiter').change(function() {
112
119
  activeRequests = 1;
113
120
  setTimeout(function() {
@@ -193,6 +193,17 @@ Capybara::SpecHelper.spec '#click_button' do
193
193
  end
194
194
  end
195
195
 
196
+ context 'when Capybara.enable_aria_role = true' do
197
+ it 'should click on a button role', requires: [:js] do
198
+ Capybara.enable_aria_role = true
199
+ @session.using_wait_time(1.5) do
200
+ @session.visit('/with_js')
201
+ @session.click_button('ARIA button')
202
+ expect(@session).to have_button('ARIA button has been clicked')
203
+ end
204
+ end
205
+ end
206
+
196
207
  context 'with fields associated with the form using the form attribute', requires: [:form_attribute] do
197
208
  let(:results) { extract_results(@session) }
198
209
 
@@ -39,6 +39,14 @@ Capybara::SpecHelper.spec '#has_button?' do
39
39
  expect(@session).to have_button('awe123', type: 'submit')
40
40
  expect(@session).not_to have_button('awe123', type: 'reset')
41
41
  end
42
+
43
+ it 'should be true for role=button when enable_aria_role: true' do
44
+ expect(@session).to have_button('ARIA button', enable_aria_role: true)
45
+ end
46
+
47
+ it 'should be false for role=button when enable_aria_role: false' do
48
+ expect(@session).not_to have_button('ARIA button', enable_aria_role: false)
49
+ end
42
50
  end
43
51
 
44
52
  Capybara::SpecHelper.spec '#has_no_button?' do
@@ -66,4 +74,12 @@ Capybara::SpecHelper.spec '#has_no_button?' do
66
74
  it 'should be false for disabled buttons if disabled: false' do
67
75
  expect(@session).to have_no_button('Disabled button', disabled: false)
68
76
  end
77
+
78
+ it 'should be true for role=button when enable_aria_role: false' do
79
+ expect(@session).to have_no_button('ARIA button', enable_aria_role: false)
80
+ end
81
+
82
+ it 'should be false for role=button when enable_aria_role: true' do
83
+ expect(@session).not_to have_no_button('ARIA button', enable_aria_role: true)
84
+ end
69
85
  end
@@ -128,11 +128,11 @@ Capybara::SpecHelper.spec '#has_no_current_path?' do
128
128
  # Without ignore_query option
129
129
  expect do
130
130
  expect(@session).not_to have_current_path('/with_js')
131
- end. not_to raise_exception
131
+ end.not_to raise_exception
132
132
 
133
133
  # With ignore_query option
134
134
  expect do
135
135
  expect(@session).not_to have_current_path('/with_js', ignore_query: true)
136
- end. not_to raise_exception
136
+ end.not_to raise_exception
137
137
  end
138
138
  end
@@ -60,6 +60,22 @@ Capybara::SpecHelper.spec '#has_field' do
60
60
  end
61
61
  end
62
62
 
63
+ context 'with validation message', requires: [:html_validation] do
64
+ it 'should accept a regexp' do
65
+ @session.fill_in('form_zipcode', with: '1234')
66
+ expect(@session).to have_field('form_zipcode', validation_message: /match the requested format/)
67
+ expect(@session).not_to have_field('form_zipcode', validation_message: /random/)
68
+ end
69
+
70
+ it 'should accept a string' do
71
+ @session.fill_in('form_zipcode', with: '1234')
72
+ expect(@session).to have_field('form_zipcode', validation_message: 'Please match the requested format.')
73
+ expect(@session).not_to have_field('form_zipcode', validation_message: 'match the requested format.')
74
+ @session.fill_in('form_zipcode', with: '12345')
75
+ expect(@session).to have_field('form_zipcode', validation_message: '')
76
+ end
77
+ end
78
+
63
79
  context 'with type' do
64
80
  it 'should be true if a field with the given type is on the page' do
65
81
  expect(@session).to have_field('First Name', type: 'text')
@@ -63,7 +63,7 @@ Capybara::SpecHelper.spec '#has_select?' do
63
63
  end
64
64
 
65
65
  it "should be true even when the selected option invisible, regardless of the select's visibility" do
66
- expect(@session).to have_select('Icecream', visible: false, selected: 'Chocolate')
66
+ expect(@session).to have_select('Icecream', visible: :hidden, selected: 'Chocolate')
67
67
  expect(@session).to have_select('Sorbet', selected: 'Vanilla')
68
68
  end
69
69
  end
@@ -88,7 +88,7 @@ Capybara::SpecHelper.spec '#has_select?' do
88
88
  end
89
89
 
90
90
  it "should be true even when the selected values are invisible, regardless of the select's visibility" do
91
- expect(@session).to have_select('Dessert', visible: false, with_options: %w[Pudding Tiramisu])
91
+ expect(@session).to have_select('Dessert', visible: :hidden, with_options: %w[Pudding Tiramisu])
92
92
  expect(@session).to have_select('Cake', with_selected: ['Chocolate Cake', 'Sponge Cake'])
93
93
  end
94
94
 
@@ -113,7 +113,7 @@ Capybara::SpecHelper.spec '#has_select?' do
113
113
  end
114
114
 
115
115
  it 'should be true even when the options are invisible, if the select itself is invisible' do
116
- expect(@session).to have_select('Icecream', visible: false, options: %w[Chocolate Vanilla Strawberry])
116
+ expect(@session).to have_select('Icecream', visible: :hidden, options: %w[Chocolate Vanilla Strawberry])
117
117
  end
118
118
  end
119
119
 
@@ -158,7 +158,7 @@ Capybara::SpecHelper.spec '#has_select?' do
158
158
  end
159
159
 
160
160
  it 'should be true even when the options are invisible, if the select itself is invisible' do
161
- expect(@session).to have_select('Icecream', visible: false, with_options: %w[Vanilla Strawberry])
161
+ expect(@session).to have_select('Icecream', visible: :hidden, with_options: %w[Vanilla Strawberry])
162
162
  end
163
163
  end
164
164
 
@@ -61,12 +61,12 @@ Capybara::SpecHelper.spec '#has_selector?' do
61
61
  end
62
62
 
63
63
  it 'should respect visibility setting' do
64
- expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: false)
65
- expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: true)
64
+ expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :all)
65
+ expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :visible)
66
66
  Capybara.ignore_hidden_elements = false
67
- expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: false)
67
+ expect(@session).to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :all)
68
68
  Capybara.visible_text_only = true
69
- expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: true)
69
+ expect(@session).not_to have_selector(:id, 'hidden-text', text: 'Some of this text is hidden!', visible: :visible)
70
70
  end
71
71
 
72
72
  it 'should discard all matches where the given regexp is not matched' do
@@ -271,12 +271,12 @@ Capybara::SpecHelper.spec 'node' do
271
271
 
272
272
  it 'works when details is toggled open and closed' do
273
273
  @session.find(:css, '#closed_details > summary').click
274
- expect(@session).to have_css('#closed_details *', visible: true, count: 5)
274
+ expect(@session).to have_css('#closed_details *', visible: :visible, count: 5)
275
275
  .and(have_no_css('#closed_details *', visible: :hidden))
276
276
 
277
277
  @session.find(:css, '#closed_details > summary').click
278
278
  descendants_css = '#closed_details > *:not(summary), #closed_details > *:not(summary) *'
279
- expect(@session).to have_no_css(descendants_css, visible: true)
279
+ expect(@session).to have_no_css(descendants_css, visible: :visible)
280
280
  .and(have_css(descendants_css, visible: :hidden, count: 3))
281
281
  end
282
282
  end
@@ -446,7 +446,7 @@ Capybara::SpecHelper.spec 'node' do
446
446
 
447
447
  it 'should work with Dragula' do
448
448
  @session.visit('/with_dragula')
449
- @session.within(:css, '#sortable') do
449
+ @session.within(:css, '#sortable.ready') do
450
450
  src = @session.find('div', text: 'Item 1')
451
451
  target = @session.find('div', text: 'Item 3')
452
452
  src.drag_to target
@@ -758,7 +758,7 @@ Capybara::SpecHelper.spec 'node' do
758
758
  @session.visit('with_js')
759
759
  @session.find(:css, '#click-test').click(x: 5, y: 5)
760
760
  link = @session.find(:link, 'has-been-clicked')
761
- locations = link.text.match(/^Has been clicked at (?<x>[\d\.-]+),(?<y>[\d\.-]+)$/)
761
+ locations = link.text.match(/^Has been clicked at (?<x>[\d.-]+),(?<y>[\d.-]+)$/)
762
762
  # Resulting click location should be very close to 0, 0 relative to top left corner of the element, but may not be exact due to
763
763
  # integer/float conversions and rounding.
764
764
  expect(locations[:x].to_f).to be_within(1).of(5)
@@ -884,7 +884,7 @@ Capybara::SpecHelper.spec 'node' do
884
884
  @session.visit('with_js')
885
885
  @session.find(:css, '#click-test').double_click(x: 10, y: 5)
886
886
  link = @session.find(:link, 'has-been-double-clicked')
887
- locations = link.text.match(/^Has been double clicked at (?<x>[\d\.-]+),(?<y>[\d\.-]+)$/)
887
+ locations = link.text.match(/^Has been double clicked at (?<x>[\d.-]+),(?<y>[\d.-]+)$/)
888
888
  # Resulting click location should be very close to 10, 5 relative to top left corner of the element, but may not be exact due
889
889
  # to integer/float conversions and rounding.
890
890
  expect(locations[:x].to_f).to be_within(1).of(10)
@@ -970,7 +970,7 @@ Capybara::SpecHelper.spec 'node' do
970
970
  @session.visit('with_js')
971
971
  @session.find(:css, '#click-test').right_click(x: 10, y: 10)
972
972
  link = @session.find(:link, 'has-been-right-clicked')
973
- locations = link.text.match(/^Has been right clicked at (?<x>[\d\.-]+),(?<y>[\d\.-]+)$/)
973
+ locations = link.text.match(/^Has been right clicked at (?<x>[\d.-]+),(?<y>[\d.-]+)$/)
974
974
  # Resulting click location should be very close to 10, 10 relative to top left corner of the element, but may not be exact due
975
975
  # to integer/float conversions and rounding
976
976
  expect(locations[:x].to_f).to be_within(1).of(10)
@@ -30,6 +30,7 @@ module Capybara
30
30
  Capybara.visible_text_only = false
31
31
  Capybara.match = :smart
32
32
  Capybara.enable_aria_label = false
33
+ Capybara.enable_aria_role = false
33
34
  Capybara.default_set_options = {}
34
35
  Capybara.disable_animation = false
35
36
  Capybara.test_id = nil
@@ -188,28 +188,24 @@ class TestApp < Sinatra::Base
188
188
  end
189
189
 
190
190
  post '/upload' do
191
- begin
192
- buffer = []
193
- buffer << "Content-type: #{params.dig(:form, :document, :type)}"
194
- buffer << "File content: #{params.dig(:form, :document, :tempfile).read}"
195
- buffer.join(' | ')
196
- rescue StandardError
197
- 'No file uploaded'
198
- end
191
+ buffer = []
192
+ buffer << "Content-type: #{params.dig(:form, :document, :type)}"
193
+ buffer << "File content: #{params.dig(:form, :document, :tempfile).read}"
194
+ buffer.join(' | ')
195
+ rescue StandardError
196
+ 'No file uploaded'
199
197
  end
200
198
 
201
199
  post '/upload_multiple' do
202
- begin
203
- docs = params.dig(:form, :multiple_documents)
204
- buffer = [docs.size.to_s]
205
- docs.each do |doc|
206
- buffer << "Content-type: #{doc[:type]}"
207
- buffer << "File content: #{doc[:tempfile].read}"
208
- end
209
- buffer.join(' | ')
210
- rescue StandardError
211
- 'No files uploaded'
200
+ docs = params.dig(:form, :multiple_documents)
201
+ buffer = [docs.size.to_s]
202
+ docs.each do |doc|
203
+ buffer << "Content-type: #{doc[:type]}"
204
+ buffer << "File content: #{doc[:tempfile].read}"
212
205
  end
206
+ buffer.join(' | ')
207
+ rescue StandardError
208
+ 'No files uploaded'
213
209
  end
214
210
 
215
211
  get '/apple-touch-icon-precomposed.png' do