mechanize 2.7.6 → 2.8.2

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 (119) hide show
  1. checksums.yaml +5 -5
  2. data/.github/dependabot.yml +11 -0
  3. data/.github/workflows/ci-test.yml +53 -0
  4. data/.yardopts +8 -0
  5. data/{CHANGELOG.rdoc → CHANGELOG.md} +136 -87
  6. data/EXAMPLES.rdoc +1 -24
  7. data/Gemfile +1 -4
  8. data/{LICENSE.rdoc → LICENSE.txt} +4 -0
  9. data/README.md +77 -0
  10. data/Rakefile +18 -3
  11. data/examples/rubygems.rb +2 -2
  12. data/lib/mechanize.rb +3 -2
  13. data/lib/mechanize/chunked_termination_error.rb +1 -0
  14. data/lib/mechanize/content_type_error.rb +1 -0
  15. data/lib/mechanize/cookie.rb +1 -13
  16. data/lib/mechanize/cookie_jar.rb +4 -12
  17. data/lib/mechanize/directory_saver.rb +1 -0
  18. data/lib/mechanize/download.rb +2 -1
  19. data/lib/mechanize/element_matcher.rb +1 -0
  20. data/lib/mechanize/element_not_found_error.rb +1 -0
  21. data/lib/mechanize/file.rb +2 -1
  22. data/lib/mechanize/file_connection.rb +5 -3
  23. data/lib/mechanize/file_request.rb +1 -0
  24. data/lib/mechanize/file_response.rb +4 -1
  25. data/lib/mechanize/file_saver.rb +1 -0
  26. data/lib/mechanize/form.rb +2 -10
  27. data/lib/mechanize/form/button.rb +1 -0
  28. data/lib/mechanize/form/check_box.rb +1 -0
  29. data/lib/mechanize/form/field.rb +1 -0
  30. data/lib/mechanize/form/file_upload.rb +1 -0
  31. data/lib/mechanize/form/hidden.rb +1 -0
  32. data/lib/mechanize/form/image_button.rb +1 -0
  33. data/lib/mechanize/form/keygen.rb +1 -0
  34. data/lib/mechanize/form/multi_select_list.rb +1 -0
  35. data/lib/mechanize/form/option.rb +1 -0
  36. data/lib/mechanize/form/radio_button.rb +1 -0
  37. data/lib/mechanize/form/reset.rb +1 -0
  38. data/lib/mechanize/form/select_list.rb +1 -0
  39. data/lib/mechanize/form/submit.rb +1 -0
  40. data/lib/mechanize/form/text.rb +1 -0
  41. data/lib/mechanize/form/textarea.rb +1 -0
  42. data/lib/mechanize/headers.rb +1 -0
  43. data/lib/mechanize/history.rb +1 -0
  44. data/lib/mechanize/http.rb +1 -0
  45. data/lib/mechanize/http/agent.rb +16 -8
  46. data/lib/mechanize/http/auth_challenge.rb +1 -0
  47. data/lib/mechanize/http/auth_realm.rb +1 -0
  48. data/lib/mechanize/http/auth_store.rb +1 -0
  49. data/lib/mechanize/http/content_disposition_parser.rb +14 -2
  50. data/lib/mechanize/http/www_authenticate_parser.rb +3 -3
  51. data/lib/mechanize/image.rb +1 -0
  52. data/lib/mechanize/page.rb +4 -3
  53. data/lib/mechanize/page/base.rb +1 -0
  54. data/lib/mechanize/page/frame.rb +1 -0
  55. data/lib/mechanize/page/image.rb +1 -0
  56. data/lib/mechanize/page/label.rb +1 -0
  57. data/lib/mechanize/page/link.rb +8 -1
  58. data/lib/mechanize/page/meta_refresh.rb +1 -0
  59. data/lib/mechanize/parser.rb +1 -0
  60. data/lib/mechanize/pluggable_parsers.rb +1 -0
  61. data/lib/mechanize/prependable.rb +1 -0
  62. data/lib/mechanize/redirect_limit_reached_error.rb +1 -0
  63. data/lib/mechanize/redirect_not_get_or_head_error.rb +1 -0
  64. data/lib/mechanize/response_code_error.rb +2 -1
  65. data/lib/mechanize/response_read_error.rb +1 -0
  66. data/lib/mechanize/robots_disallowed_error.rb +1 -0
  67. data/lib/mechanize/test_case.rb +34 -29
  68. data/lib/mechanize/test_case/bad_chunking_servlet.rb +1 -0
  69. data/lib/mechanize/test_case/basic_auth_servlet.rb +1 -0
  70. data/lib/mechanize/test_case/content_type_servlet.rb +1 -0
  71. data/lib/mechanize/test_case/digest_auth_servlet.rb +1 -0
  72. data/lib/mechanize/test_case/file_upload_servlet.rb +1 -0
  73. data/lib/mechanize/test_case/form_servlet.rb +1 -0
  74. data/lib/mechanize/test_case/gzip_servlet.rb +4 -3
  75. data/lib/mechanize/test_case/header_servlet.rb +1 -0
  76. data/lib/mechanize/test_case/http_refresh_servlet.rb +1 -0
  77. data/lib/mechanize/test_case/infinite_redirect_servlet.rb +1 -0
  78. data/lib/mechanize/test_case/infinite_refresh_servlet.rb +1 -0
  79. data/lib/mechanize/test_case/many_cookies_as_string_servlet.rb +1 -0
  80. data/lib/mechanize/test_case/many_cookies_servlet.rb +1 -0
  81. data/lib/mechanize/test_case/modified_since_servlet.rb +1 -0
  82. data/lib/mechanize/test_case/ntlm_servlet.rb +1 -0
  83. data/lib/mechanize/test_case/one_cookie_no_spaces_servlet.rb +1 -0
  84. data/lib/mechanize/test_case/one_cookie_servlet.rb +1 -0
  85. data/lib/mechanize/test_case/quoted_value_cookie_servlet.rb +1 -0
  86. data/lib/mechanize/test_case/redirect_servlet.rb +1 -0
  87. data/lib/mechanize/test_case/referer_servlet.rb +1 -0
  88. data/lib/mechanize/test_case/refresh_with_empty_url.rb +1 -0
  89. data/lib/mechanize/test_case/refresh_without_url.rb +1 -0
  90. data/lib/mechanize/test_case/response_code_servlet.rb +1 -0
  91. data/lib/mechanize/test_case/robots_txt_servlet.rb +1 -0
  92. data/lib/mechanize/test_case/send_cookies_servlet.rb +1 -0
  93. data/lib/mechanize/test_case/server.rb +1 -0
  94. data/lib/mechanize/test_case/servlets.rb +1 -0
  95. data/lib/mechanize/test_case/verb_servlet.rb +5 -6
  96. data/lib/mechanize/unauthorized_error.rb +1 -0
  97. data/lib/mechanize/unsupported_scheme_error.rb +1 -0
  98. data/lib/mechanize/util.rb +2 -1
  99. data/lib/mechanize/version.rb +2 -1
  100. data/lib/mechanize/xml_file.rb +1 -0
  101. data/mechanize.gemspec +45 -35
  102. data/test/htdocs/dir with spaces/foo.html +1 -0
  103. data/test/htdocs/tc_links.html +1 -1
  104. data/test/test_mechanize.rb +19 -7
  105. data/test/test_mechanize_cookie.rb +19 -19
  106. data/test/test_mechanize_cookie_jar.rb +85 -53
  107. data/test/test_mechanize_download.rb +13 -1
  108. data/test/test_mechanize_file.rb +10 -0
  109. data/test/test_mechanize_file_connection.rb +21 -3
  110. data/test/test_mechanize_file_response.rb +25 -1
  111. data/test/test_mechanize_form.rb +12 -0
  112. data/test/test_mechanize_form_keygen.rb +1 -0
  113. data/test/test_mechanize_http_agent.rb +53 -8
  114. data/test/test_mechanize_http_content_disposition_parser.rb +27 -0
  115. data/test/test_mechanize_link.rb +24 -0
  116. data/test/test_mechanize_page_encoding.rb +28 -1
  117. metadata +117 -71
  118. data/.travis.yml +0 -36
  119. data/README.rdoc +0 -77
data/EXAMPLES.rdoc CHANGED
@@ -24,29 +24,6 @@ example, <code>do ... end.submit</code> is the same as <code>{ ...
24
24
  end
25
25
  end
26
26
 
27
- == Rubyforge
28
-
29
- require 'rubygems'
30
- require 'mechanize'
31
-
32
- a = Mechanize.new
33
- a.get('http://rubyforge.org/') do |page|
34
- # Click the login link
35
- login_page = a.click(page.link_with(:text => /Log In/))
36
-
37
- # Submit the login form
38
- my_page = login_page.form_with(:action => '/account/login.php') do |f|
39
- f.form_loginname = ARGV[0]
40
- f.form_pw = ARGV[1]
41
- end.click_button
42
-
43
- my_page.links.each do |link|
44
- text = link.text.strip
45
- next unless text.length > 0
46
- puts text
47
- end
48
- end
49
-
50
27
  == File Upload
51
28
 
52
29
  Upload a file to flickr.
@@ -129,7 +106,7 @@ This example also demonstrates subclassing Mechanize.
129
106
 
130
107
  class TestMech < Mechanize
131
108
  def process
132
- get 'http://rubyforge.org/'
109
+ get 'http://rubygems.org/'
133
110
  search_form = page.forms.first
134
111
  search_form.words = 'WWW'
135
112
  submit search_form
data/Gemfile CHANGED
@@ -1,6 +1,3 @@
1
- source 'https://rubygems.org'
2
-
3
- # In order to be able to install on 1.9.3 and 2.0.0
4
- ruby RUBY_VERSION
1
+ source "https://rubygems.org"
5
2
 
6
3
  gemspec
@@ -1,5 +1,9 @@
1
1
  (The MIT License)
2
2
 
3
+ Copyright (c) 2005 by Michael Neumann (mneumann@ntecs.de)
4
+
5
+ Copyright (c) 2006-2021 by Eric Hodel, Akinori MUSHA, Aaron Patterson, Lee Jarvis, Mike Dalessio
6
+
3
7
  Permission is hereby granted, free of charge, to any person obtaining
4
8
  a copy of this software and associated documentation files (the
5
9
  'Software'), to deal in the Software without restriction, including
data/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # Mechanize
2
+
3
+ * https://www.rubydoc.info/gems/mechanize/
4
+ * https://github.com/sparklemotion/mechanize
5
+
6
+ [![Test suite](https://github.com/sparklemotion/mechanize/actions/workflows/ci-test.yml/badge.svg)](https://github.com/sparklemotion/mechanize/actions/workflows/ci-test.yml)
7
+
8
+
9
+ ## Description
10
+
11
+ The Mechanize library is used for automating interaction with websites. Mechanize automatically stores and sends cookies, follows redirects, and can follow links and submit forms. Form fields can be populated and submitted. Mechanize also keeps track of the sites that you have visited as a history.
12
+
13
+
14
+ ## Dependencies
15
+
16
+ * Ruby >= 2.5
17
+ * Gems:
18
+ * `addressable`
19
+ * `domain_name`
20
+ * `http-cookie`
21
+ * `mime-types`
22
+ * `net-http-digest_auth`
23
+ * `net-http-persistent`
24
+ * `nokogiri`
25
+ * `rubyntlm`
26
+ * `webrick`
27
+ * `webrobots`
28
+
29
+
30
+ ## Support:
31
+
32
+ The bug tracker is available here:
33
+
34
+ * https://github.com/sparklemotion/mechanize/issues
35
+
36
+
37
+ ## Examples
38
+
39
+ If you are just starting, check out [GUIDE.rdoc](https://github.com/sparklemotion/mechanize/blob/main/GUIDE.rdoc) or [EXAMPLES.rdoc](https://github.com/sparklemotion/mechanize/blob/main/EXAMPLES.rdoc).
40
+
41
+
42
+ ## Developers
43
+
44
+ Use bundler to install dependencies:
45
+
46
+ ```
47
+ bundle install
48
+ ```
49
+
50
+ Run all tests with:
51
+
52
+ ```
53
+ bundle exec rake test
54
+ ```
55
+
56
+ See also Mechanize::TestCase to read about the built-in testing infrastructure.
57
+
58
+
59
+ ## Authors
60
+
61
+ * Eric Hodel
62
+ * Akinori MUSHA
63
+ * Aaron Patterson
64
+ * Lee Jarvis
65
+ * Mike Dalessio
66
+
67
+
68
+ ## Acknowledgments
69
+
70
+ This library was heavily influenced by its namesake in the Perl world. A big
71
+ thanks goes to [Andy Lester](http://petdance.com), the author of the original Perl module WWW::Mechanize which is available [here](http://search.cpan.org/dist/WWW-Mechanize/). Ruby Mechanize would not be around without you!
72
+
73
+ Thank you to Michael Neumann for starting the Ruby version. Thanks to everyone who's helped out in various ways. Finally, thank you to the people using this library!
74
+
75
+ ## License
76
+
77
+ This library is distributed under the MIT license. Please see [LICENSE.txt](https://github.com/sparklemotion/mechanize/blob/main/LICENSE.txt).
data/Rakefile CHANGED
@@ -23,9 +23,9 @@ task('ssl_cert') do |p|
23
23
  end
24
24
 
25
25
  RDoc::Task.new do |rdoc|
26
- rdoc.main = "README.rdoc"
26
+ rdoc.main = "README.md"
27
27
  rdoc.rdoc_dir = 'doc'
28
- rdoc.rdoc_files.include( "CHANGELOG.rdoc", "EXAMPLES.rdoc", "GUIDE.rdoc", "LICENSE.rdoc", "README.rdoc", "lib/**/*.rb")
28
+ rdoc.rdoc_files.include( "CHANGELOG.md", "EXAMPLES.rdoc", "GUIDE.rdoc", "LICENSE.txt", "README.md", "lib/**/*.rb")
29
29
  end
30
30
 
31
31
  desc "Run tests"
@@ -38,4 +38,19 @@ task publish_docs: %w[rdoc] do
38
38
  sh 'rsync', '-avzO', '--delete', 'doc/', 'docs-push.seattlerb.org:/data/www/docs.seattlerb.org/mechanize/'
39
39
  end
40
40
 
41
- task default: :test
41
+ desc "Run rubocop checks"
42
+ task :rubocop => ["rubocop:security", "rubocop:frozen_string_literals"]
43
+
44
+ namespace "rubocop" do
45
+ desc "Run rubocop security check"
46
+ task :security do
47
+ sh "rubocop lib --only Security"
48
+ end
49
+
50
+ desc "Run rubocop string literals check"
51
+ task :frozen_string_literals do
52
+ sh "rubocop lib --auto-correct-all --only Style/FrozenStringLiteralComment"
53
+ end
54
+ end
55
+
56
+ task default: [:rubocop, :test]
data/examples/rubygems.rb CHANGED
@@ -1,4 +1,4 @@
1
- # This example logs a user in to rubyforge and prints out the body of the
1
+ # This example logs a user in to rubygems and prints out the body of the
2
2
  # page after logging the user in.
3
3
  require 'rubygems'
4
4
  require 'mechanize'
@@ -9,7 +9,7 @@ mech = Mechanize.new
9
9
  mech.log = Logger.new $stderr
10
10
  mech.agent.http.debug_output = $stderr
11
11
 
12
- # Load the rubyforge website
12
+ # Load the rubygems website
13
13
  page = mech.get('https://rubygems.org/')
14
14
  page = mech.click page.link_with(:text => /Sign in/) # Click the login link
15
15
  form = page.forms[1] # Select the first form
data/lib/mechanize.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'mechanize/version'
2
3
  require 'fileutils'
3
4
  require 'forwardable'
@@ -175,7 +176,7 @@ class Mechanize
175
176
  # as SSL parameters or proxies:
176
177
  #
177
178
  # agent = Mechanize.new do |a|
178
- # a.proxy_host = 'proxy.example'
179
+ # a.proxy_addr = 'proxy.example'
179
180
  # a.proxy_port = 8080
180
181
  # end
181
182
  #
@@ -396,7 +397,7 @@ class Mechanize
396
397
  io = if io_or_filename.respond_to? :write then
397
398
  io_or_filename
398
399
  else
399
- open io_or_filename, 'wb'
400
+ ::File.open(io_or_filename, 'wb')
400
401
  end
401
402
 
402
403
  case page
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # Raised when Mechanize detects the chunked transfer-encoding may be
3
4
  # incorrectly terminated.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # This error is raised when a pluggable parser tries to parse a content type
3
4
  # that it does not know how to handle. For example if Mechanize::Page were to
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  warn 'mechanize/cookie will be deprecated. Please migrate to the http-cookie APIs.' if $VERBOSE
2
3
 
3
4
  require 'http/cookie'
@@ -50,19 +51,6 @@ class Mechanize
50
51
 
51
52
  Cookie = ::HTTP::Cookie
52
53
 
53
- # Compatibility for Ruby 1.8/1.9
54
- unless Cookie.respond_to?(:prepend, true)
55
- require 'mechanize/prependable'
56
-
57
- class Cookie
58
- extend Prependable
59
-
60
- class << self
61
- extend Prependable
62
- end
63
- end
64
- end
65
-
66
54
  class Cookie
67
55
  prepend CookieIMethods
68
56
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  warn 'mechanize/cookie_jar will be deprecated. Please migrate to the http-cookie APIs.' if $VERBOSE
2
3
 
3
4
  require 'http/cookie_jar'
@@ -65,7 +66,7 @@ class Mechanize
65
66
  class CookieJar < ::HTTP::CookieJar
66
67
  def save(output, *options)
67
68
  output.respond_to?(:write) or
68
- return open(output, 'w') { |io| save(io, *options) }
69
+ return ::File.open(output, 'w') { |io| save(io, *options) }
69
70
 
70
71
  opthash = {
71
72
  :format => :yaml,
@@ -119,7 +120,7 @@ class Mechanize
119
120
 
120
121
  def load(input, *options)
121
122
  input.respond_to?(:write) or
122
- return open(input, 'r') { |io| load(io, *options) }
123
+ return ::File.open(input, 'r') { |io| load(io, *options) }
123
124
 
124
125
  opthash = {
125
126
  :format => :yaml,
@@ -148,7 +149,7 @@ class Mechanize
148
149
  return super(input, opthash) if opthash[:format] != :yaml
149
150
 
150
151
  begin
151
- data = YAML.load(input)
152
+ data = YAML.load(input) # rubocop:disable Security/YAMLLoad
152
153
  rescue ArgumentError
153
154
  @logger.warn "unloadable YAML cookie data discarded" if @logger
154
155
  return self
@@ -175,15 +176,6 @@ class Mechanize
175
176
  end
176
177
  end
177
178
 
178
- # Compatibility for Ruby 1.8/1.9
179
- unless ::HTTP::CookieJar.respond_to?(:prepend, true)
180
- require 'mechanize/prependable'
181
-
182
- class ::HTTP::CookieJar
183
- extend Prependable
184
- end
185
- end
186
-
187
179
  class ::HTTP::CookieJar
188
180
  prepend CookieJarIMethods
189
181
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # Unlike Mechanize::FileSaver, the directory saver places all downloaded files
3
4
  # in a single pre-specified directory.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # Download is a pluggable parser for downloading files without loading them
3
4
  # into memory first. You may subclass this class to handle content types you
@@ -71,7 +72,7 @@ class Mechanize::Download
71
72
  dirname = File.dirname filename
72
73
  FileUtils.mkdir_p dirname
73
74
 
74
- open filename, 'wb' do |io|
75
+ ::File.open(filename, 'wb')do |io|
75
76
  until @body_io.eof? do
76
77
  io.write @body_io.read 16384
77
78
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Mechanize::ElementMatcher
2
3
 
3
4
  def elements_with singular, plural = "#{singular}s"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # Raised when an an element was not found on the Page
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # This is the base class for the Pluggable Parsers. If Mechanize cannot find
3
4
  # an appropriate class to use for the content type, this class will be used.
@@ -82,7 +83,7 @@ class Mechanize::File
82
83
  dirname = File.dirname filename
83
84
  FileUtils.mkdir_p dirname
84
85
 
85
- open filename, 'wb' do |f|
86
+ ::File.open(filename, 'wb')do |f|
86
87
  f.write body
87
88
  end
88
89
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # Wrapper to make a file URI work like an http URI
3
4
 
@@ -10,8 +11,9 @@ class Mechanize::FileConnection
10
11
  end
11
12
 
12
13
  def request uri, request
13
- yield Mechanize::FileResponse.new Mechanize::Util.uri_unescape uri.path
14
+ file_path = uri.select(:host, :path)
15
+ .select { |part| part && (part.length > 0) }
16
+ .join(":")
17
+ yield Mechanize::FileResponse.new(Mechanize::Util.uri_unescape(file_path))
14
18
  end
15
-
16
19
  end
17
-
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # A wrapper for a file URI that makes a request that works like a
3
4
  # Net::HTTPRequest
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # Fake response for dealing with file:/// requests
3
4
 
4
5
  class Mechanize::FileResponse
5
6
 
7
+ attr_reader :file_path
8
+
6
9
  def initialize(file_path)
7
10
  @file_path = file_path
8
11
  @uri = nil
@@ -15,7 +18,7 @@ class Mechanize::FileResponse
15
18
  if directory?
16
19
  yield dir_body
17
20
  else
18
- open @file_path, 'rb' do |io|
21
+ ::File.open(@file_path, 'rb') do |io|
19
22
  yield io.read
20
23
  end
21
24
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # This is a pluggable parser that automatically saves every file it
3
4
  # encounters. Unlike Mechanize::DirectorySaver, the file saver saves the
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'mechanize/element_matcher'
2
3
 
3
4
  # This class encapsulates a form parsed out of an HTML page. Each type of
@@ -305,7 +306,7 @@ class Mechanize::Form
305
306
  successful_controls = []
306
307
 
307
308
  (fields + checkboxes).reject do |f|
308
- f.node["disabled"]
309
+ f.node["disabled"] || f.node["name"] == ""
309
310
  end.sort.each do |f|
310
311
  case f
311
312
  when Mechanize::Form::CheckBox
@@ -643,15 +644,6 @@ class Mechanize::Form
643
644
  end
644
645
  end
645
646
 
646
- unless ::String.method_defined?(:b)
647
- # Define String#b for Ruby < 2.0
648
- class ::String
649
- def b
650
- dup.force_encoding(Encoding::ASCII_8BIT)
651
- end
652
- end
653
- end
654
-
655
647
  def rand_string(len = 10)
656
648
  chars = ("a".."z").to_a + ("A".."Z").to_a
657
649
  string = ::String.new
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # A Submit button in a Form
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # This class represents a check box found in a Form. To activate the CheckBox
3
4
  # in the Form, set the checked method to true.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  ##
2
3
  # This class represents a field in a form. It handles the following input
3
4
  # tags found in a form:
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # This class represents a file upload field found in a form. To use this
2
3
  # class, set FileUpload#file_data= to the data of the file you want to upload
3
4
  # and FileUpload#mime_type= to the appropriate mime type of the file.