watir 7.2.2 → 7.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 635faa9aa111937b2d90f6ab1585a148d8eea5cf375b4a1dc4d3e164b3e24c38
4
- data.tar.gz: 31bb99fbba606a62c369c4a89b8c12764e00feff89048179e5958bf4b0abca3d
3
+ metadata.gz: a0bd050e4d97703802051446eb12d01751b5e63a10fe70353f0f955ac2bb9424
4
+ data.tar.gz: e573957fe4cd87d311af62b9a77ec8c6383f65f1e4ead17e5f117c40f31f87f8
5
5
  SHA512:
6
- metadata.gz: 131f2cccc8debc1afd14462f90fbafff4d5f349b4caa193247f2adf8efa6f91e03c8218ff8bec23a86d8c4c8e4de18b1c63b38f6cc5c9c878420a9bc01d816f3
7
- data.tar.gz: c4f5abb5e301fcee62f25a091f299933f2c10e1b703a3378fcd6d850012d989f3e5ac2f9d8fcec170fee44f97ec4758c5894d85e7a7a62d3efaf2f609a733676
6
+ metadata.gz: 9409ddc8d5914e07ce3f8ef316be713d09bdbea6d130dc1bdf6be693930825b25baefd9dc200f5386a1a53955b2bbef7f48375e911897db2db33be4a337b85f3
7
+ data.tar.gz: fe6668eae425bc81e1a396dd81f41196d72d217eedca95a752e20c038fa43e55c87a951620ae37fc834517cbadf4b7e42b360b86adcdbba0798f929caf2ec866
@@ -13,7 +13,7 @@ jobs:
13
13
  fail-fast: false
14
14
  matrix:
15
15
  os: [ubuntu-latest, macos-latest, windows-latest]
16
- ruby: [ 2.7, 3.2 ]
16
+ ruby: [ 3.0, 3.2 ]
17
17
  steps:
18
18
  - name: Checkout source tree
19
19
  uses: actions/checkout@v2
@@ -41,6 +41,14 @@ jobs:
41
41
  ruby-version: ${{ matrix.ruby }}
42
42
  - name: Install gems
43
43
  run: bundle install
44
+ - name: Remove driver directories Windows
45
+ if: matrix.os == 'windows-latest'
46
+ run: |
47
+ rm "$env:ChromeWebDriver" -r -v
48
+ - name: Remove driver directories Non-Windows
49
+ if: matrix.os != 'windows-latest'
50
+ run: |
51
+ sudo rm -rf $CHROMEWEBDRIVER
44
52
  - name: Run tests
45
53
  run: bundle exec rake spec:chrome
46
54
  env:
@@ -13,7 +13,7 @@ jobs:
13
13
  fail-fast: false
14
14
  matrix:
15
15
  os: [macos-latest, windows-latest]
16
- ruby: [ 2.7, 3.2 ]
16
+ ruby: [ 3.0, 3.2 ]
17
17
  steps:
18
18
  - name: Checkout source tree
19
19
  uses: actions/checkout@v2
@@ -32,5 +32,13 @@ jobs:
32
32
  ruby-version: ${{ matrix.ruby }}
33
33
  - name: Install gems
34
34
  run: bundle install
35
+ - name: Remove driver directories Windows
36
+ if: matrix.os == 'windows-latest'
37
+ run: |
38
+ rm "$env:EdgeWebDriver" -r -v
39
+ - name: Remove driver directories Non-Windows
40
+ if: matrix.os != 'windows-latest'
41
+ run: |
42
+ sudo rm -rf $EDGEWEBDRIVER
35
43
  - name: Run tests
36
- run: bundle exec rake spec:chrome
44
+ run: bundle exec rake spec:edge
@@ -13,7 +13,7 @@ jobs:
13
13
  fail-fast: false
14
14
  matrix:
15
15
  os: [ubuntu-latest, macos-latest, windows-latest]
16
- ruby: [ 2.7, 3.2 ]
16
+ ruby: [ 3.0, 3.2 ]
17
17
  steps:
18
18
  - name: Checkout source tree
19
19
  uses: actions/checkout@v2
@@ -41,7 +41,15 @@ jobs:
41
41
  ruby-version: ${{ matrix.ruby }}
42
42
  - name: Install gems
43
43
  run: bundle install
44
+ - name: Remove driver directories Windows
45
+ if: matrix.os == 'windows-latest'
46
+ run: |
47
+ rm "$env:GeckoWebDriver" -r -v
48
+ - name: Remove driver directories Non-Windows
49
+ if: matrix.os != 'windows-latest'
50
+ run: |
51
+ sudo rm -rf $GECKOWEBDRIVER
44
52
  - name: Run tests
45
- run: bundle exec rake spec:chrome
53
+ run: bundle exec rake spec:firefox
46
54
  env:
47
55
  DISPLAY: :99
@@ -12,7 +12,7 @@ jobs:
12
12
  strategy:
13
13
  fail-fast: false
14
14
  matrix:
15
- ruby: [ 2.7, 3.2 ]
15
+ ruby: [ 3.0, 3.2 ]
16
16
  steps:
17
17
  - name: Checkout source tree
18
18
  uses: actions/checkout@v2
@@ -12,7 +12,7 @@ jobs:
12
12
  strategy:
13
13
  fail-fast: false
14
14
  matrix:
15
- ruby: [ 2.7, 3.2 ]
15
+ ruby: [ 3.0, 3.2 ]
16
16
  steps:
17
17
  - name: Checkout source tree
18
18
  uses: actions/checkout@v2
@@ -21,7 +21,7 @@ jobs:
21
21
  - name: Install Ruby
22
22
  uses: ruby/setup-ruby@v1
23
23
  with:
24
- ruby-version: 2.7
24
+ ruby-version: 3.0
25
25
  - name: Install gems
26
26
  run: bundle install
27
27
  - name: Run tests
@@ -33,7 +33,7 @@ jobs:
33
33
  strategy:
34
34
  fail-fast: false
35
35
  matrix:
36
- ruby: ['2.7', '3.0', '3.1', '3.2', 'jruby-9.4.0.0', 'truffleruby-22.3.0']
36
+ ruby: ['3.0', '3.1', '3.2', 'jruby-9.4.0.0', 'truffleruby-22.3.0']
37
37
  steps:
38
38
  - name: Checkout source tree
39
39
  uses: actions/checkout@v2
@@ -54,7 +54,7 @@ jobs:
54
54
  - name: Install Ruby
55
55
  uses: ruby/setup-ruby@v1
56
56
  with:
57
- ruby-version: 2.7
57
+ ruby-version: 3.0
58
58
  - name: Install gems
59
59
  run: bundle install
60
60
  - run: bundle exec rubocop
data/.rubocop.yml CHANGED
@@ -6,17 +6,20 @@ require:
6
6
  - rubocop-rspec
7
7
 
8
8
  AllCops:
9
- TargetRubyVersion: 2.7
9
+ TargetRubyVersion: 3.0
10
10
  NewCops: enable
11
11
  Exclude:
12
12
  - 'lib/watir/elements/html_elements.rb'
13
13
  - 'lib/watir/elements/svg_elements.rb'
14
14
 
15
+ Gemspec/DevelopmentDependencies:
16
+ Enabled: false
17
+
15
18
  Layout/SpaceInsideHashLiteralBraces:
16
19
  EnforcedStyle: no_space
17
20
 
18
21
  Metrics/AbcSize:
19
- Max: 22
22
+ Max: 23
20
23
  Exclude:
21
24
  - 'lib/watir/locators/element/selector_builder.rb'
22
25
  - 'lib/watir/locators/element/selector_builder/*.rb'
@@ -72,6 +75,9 @@ RSpec/BeforeAfterAll:
72
75
  RSpec/ExampleLength:
73
76
  Enabled: false
74
77
 
78
+ RSpec/IndexedLet:
79
+ Enabled: false
80
+
75
81
  RSpec/MultipleExpectations:
76
82
  Enabled: false
77
83
 
@@ -83,6 +89,9 @@ RSpec/NoExpectationExample:
83
89
  Exclude:
84
90
  - 'spec/watirspec/cookies_spec.rb'
85
91
 
92
+ Style/ArgumentsForwarding:
93
+ Enabled: false
94
+
86
95
  Style/BlockDelimiters:
87
96
  EnforcedStyle: braces_for_chaining
88
97
 
data/CHANGES.md CHANGED
@@ -1,3 +1,10 @@
1
+ ### 7.3.0 (2023-08-04)
2
+
3
+ * Fix implementation of headless to work with Selenium 4.11
4
+ * Remove support for Ruby 2.7
5
+ * `DateField` and `DateTimeField` accept inputs that behave like Date (#969)
6
+ * Add support for `http_only` and `same_site` cookie values (thanks Alexandre ZANNI #968)
7
+
1
8
  ### 7.2.2 (2023-01-03)
2
9
 
3
10
  * Fix bug with processing vendor name-spaced capabilities
@@ -105,13 +105,6 @@ module Watir
105
105
  options.proxy = proxy
106
106
  end
107
107
 
108
- def process_vendor_options(opts)
109
- return [] unless opts.is_a? Hash
110
-
111
- vendor = opts.select { |key, _val| key.to_s.include?(':') && opts.delete(key) }
112
- vendor.map { |k, v| Selenium::WebDriver::Remote::Capabilities.new(k => v) }
113
- end
114
-
115
108
  def convert_timeouts(browser_options)
116
109
  browser_options[:timeouts] ||= {}
117
110
  browser_options[:timeouts].each_key do |key|
@@ -139,7 +132,7 @@ module Watir
139
132
  options.args << '--no-sandbox'
140
133
  end
141
134
  when :firefox
142
- options.headless! if @options.delete(:headless)
135
+ options.args << '-headless' if @options.delete(:headless)
143
136
  when :safari
144
137
  Selenium::WebDriver::Safari.technology_preview! if @options.delete(:technology_preview)
145
138
  end
data/lib/watir/cookies.rb CHANGED
@@ -43,16 +43,19 @@ module Watir
43
43
  # Adds new cookie.
44
44
  #
45
45
  # @example
46
- # browser.cookies.add 'my_session', 'BAh7B0kiD3Nlc3Npb25faWQGOgZFRkk', secure: true
46
+ # browser.cookies.add 'my_session', 'BAh7B0kiD3Nlc3Npb25faWQGOgZFRkk', secure: true, http_only: true
47
47
  #
48
48
  # @param [String] name
49
49
  # @param [String] value
50
50
  # @param [Hash] opts
51
51
  # @option opts [Boolean] :secure
52
+ # @option opts [Boolean] :http_only
52
53
  # @option opts [String] :path
54
+ # @option opts [String] :same_site
53
55
  # @option opts [Time, DateTime, NilClass] :expires
54
56
  # @option opts [String] :domain
55
57
  #
58
+ # @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
56
59
 
57
60
  def add(name, value, opts = {})
58
61
  cookie = {
@@ -60,7 +63,9 @@ module Watir
60
63
  value: value
61
64
  }
62
65
  cookie[:secure] = opts[:secure] if opts.key?(:secure)
66
+ cookie[:http_only] = opts[:http_only] if opts.key?(:http_only)
63
67
  cookie[:path] = opts[:path] if opts.key?(:path)
68
+ cookie[:same_site] = opts[:same_site] if opts.key?(:same_site)
64
69
  expires = opts[:expires]
65
70
  if expires
66
71
  cookie[:expires] = expires.is_a?(String) ? ::Time.parse(expires) : expires
@@ -117,7 +122,7 @@ module Watir
117
122
  #
118
123
 
119
124
  def load(file = '.cookies')
120
- YAML.safe_load(File.read(file), permitted_classes: [::Symbol, ::Time]).each do |c|
125
+ YAML.safe_load_file(file, permitted_classes: [::Symbol, ::Time]).each do |c|
121
126
  add(c.delete(:name), c.delete(:value), c)
122
127
  end
123
128
  end
@@ -9,8 +9,8 @@ module Watir
9
9
  def set!(date)
10
10
  date = Date.parse date if date.is_a?(String)
11
11
 
12
- message = "DateField##{__callee__} only accepts instances of Date or Time"
13
- raise ArgumentError, message unless [Date, ::Time].include?(date.class)
12
+ message = "DateField##{__callee__} only accepts instances that respond to #strftime"
13
+ raise ArgumentError, message unless date.respond_to?(:strftime)
14
14
 
15
15
  date_string = date.strftime('%Y-%m-%d')
16
16
  element_call(:wait_for_writable) do
@@ -9,8 +9,8 @@ module Watir
9
9
  def set!(date)
10
10
  date = ::Time.parse date if date.is_a?(String)
11
11
 
12
- message = "DateTimeField##{__callee__} only accepts instances of DateTime or Time"
13
- raise ArgumentError, message unless [DateTime, ::Time].include?(date.class)
12
+ message = "DateTimeField##{__callee__} only accepts instances that respond to #strftime"
13
+ raise ArgumentError, message unless date.respond_to?(:strftime)
14
14
 
15
15
  date_time_string = date.strftime('%Y-%m-%dT%H:%M')
16
16
  element_call(:wait_for_writable) do
@@ -114,9 +114,9 @@ module Watir
114
114
  def parse_select_args(str_or_rx, text, value, label)
115
115
  selectors = {}
116
116
  selectors[:any] = str_or_rx unless str_or_rx.empty?
117
- selectors[:text] = Array[text] if text
118
- selectors[:value] = Array[value] if value
119
- selectors[:label] = Array[label] if label
117
+ selectors[:text] = [text] if text
118
+ selectors[:value] = [value] if value
119
+ selectors[:label] = [label] if label
120
120
 
121
121
  raise ArgumentError, "too many arguments used for Select#select: #{selectors}" if selectors.size > 1
122
122
 
@@ -7,7 +7,7 @@ module Watir
7
7
  include Exception
8
8
  attr_reader :custom_attributes, :built
9
9
 
10
- WILDCARD_ATTRIBUTE = /^(aria|data)_(.+)$/.freeze
10
+ WILDCARD_ATTRIBUTE = /^(aria|data)_(.+)$/
11
11
  VALID_WHATS = Hash.new([String, Regexp, TrueClass, FalseClass]).merge(adjacent: [::Symbol],
12
12
  xpath: [String],
13
13
  css: [String],
@@ -21,7 +21,7 @@ module Watir
21
21
  values_to_match[:text] = values_to_match.delete(key)
22
22
  end
23
23
  else
24
- return
24
+ return false
25
25
  end
26
26
 
27
27
  super
data/lib/watir/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Watir
4
- VERSION = '7.2.2'
4
+ VERSION = '7.3.0'
5
5
  end
data/lib/watir.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'net/http'
3
4
  require 'selenium-webdriver'
4
5
  require 'time'
5
6
 
@@ -39,7 +39,7 @@ module WatirSpec
39
39
  end
40
40
 
41
41
  def inspect_args
42
- selenium_opts = browser_args.last
42
+ selenium_opts = browser_args.last.dup
43
43
 
44
44
  options = selenium_opts.delete(:options)
45
45
  args = ["#{browser_args.first} tests:\n"]
data/lib/watirspec.rb CHANGED
@@ -33,7 +33,7 @@ module WatirSpec
33
33
 
34
34
  def load_support
35
35
  root = File.expand_path('../spec/watirspec', __dir__)
36
- Dir.glob("#{root}/support/**/*.rb").sort.each do |file|
36
+ Dir.glob("#{root}/support/**/*.rb").each do |file|
37
37
  require file
38
38
  end
39
39
  end
@@ -3,9 +3,8 @@
3
3
  module LocatorSpecHelper
4
4
  def browser
5
5
  @browser ||= instance_double(Watir::Browser, wd: driver)
6
- allow(@browser).to receive(:browser).and_return(@browser)
6
+ allow(@browser).to receive_messages(browser: @browser, locator_namespace: @locator_namespace || Watir::Locators)
7
7
  allow(@browser).to receive(:is_a?).with(Watir::Browser).and_return(true)
8
- allow(@browser).to receive(:locator_namespace).and_return(@locator_namespace || Watir::Locators)
9
8
  @browser
10
9
  end
11
10
 
@@ -30,8 +29,7 @@ module LocatorSpecHelper
30
29
 
31
30
  def element_matcher
32
31
  @element_matcher ||= instance_double(Watir::Locators::Element::Matcher)
33
- allow(@element_matcher).to receive(:query_scope).and_return(browser)
34
- allow(@element_matcher).to receive(:selector).and_return(@locator || {})
32
+ allow(@element_matcher).to receive_messages(query_scope: browser, selector: @locator || {})
35
33
  @element_matcher
36
34
  end
37
35
 
@@ -59,10 +57,8 @@ module LocatorSpecHelper
59
57
  klass = opts.delete(:watir_element) || Watir::HTMLElement
60
58
  el = instance_double(klass, opts)
61
59
 
62
- allow(el).to receive(:enabled?).and_return true
63
- allow(el).to receive(:selector_builder).and_return(selector_builder)
60
+ allow(el).to receive_messages(enabled?: true, selector_builder: selector_builder, selector: @selector || {})
64
61
  allow(el).to receive(:wd).and_return wd_element unless opts.key?(:wd)
65
- allow(el).to receive(:selector).and_return(@selector || {})
66
62
  el
67
63
  end
68
64
 
@@ -31,8 +31,7 @@ module Watir
31
31
 
32
32
  def halt_service(browser)
33
33
  allow(Selenium::WebDriver::Platform).to receive(:find_binary).and_return(true)
34
- allow(File).to receive(:file?).and_return(true)
35
- allow(File).to receive(:executable?).and_return(true)
34
+ allow(File).to receive_messages(file?: true, executable?: true)
36
35
  service_class(browser).driver_path = nil
37
36
  end
38
37
 
@@ -75,7 +74,7 @@ module Watir
75
74
  end
76
75
 
77
76
  it 'just capabilities has client & capabilities but not service' do
78
- caps = Selenium::WebDriver::Remote::Capabilities.send(browser_symbol)
77
+ caps = Selenium::WebDriver::Remote::Capabilities.new(browser_name: expected_browser(browser_symbol))
79
78
  capabilities = described_class.new(capabilities: caps)
80
79
  args = []
81
80
  expect {
@@ -110,7 +109,7 @@ module Watir
110
109
  actual_service = args.last[:service]
111
110
  expect(actual_service.instance_variable_get(:@port)).to eq 1234
112
111
  expect(actual_service.instance_variable_get(:@executable_path)).to eq '/path/to/driver'
113
- expect(actual_service.instance_variable_get(:@extra_args)).to include '--foo', '--bar'
112
+ expect(actual_service.instance_variable_get(:@args)).to include '--foo', '--bar'
114
113
  end
115
114
 
116
115
  it 'is a bad argument to service' do
@@ -159,7 +158,7 @@ module Watir
159
158
  end
160
159
 
161
160
  it 'accepts both capabilities and Options' do
162
- caps = Selenium::WebDriver::Remote::Capabilities.send(browser_symbol)
161
+ caps = Selenium::WebDriver::Remote::Capabilities.new(browser_name: expected_browser(browser_symbol))
163
162
  opts = options_class(browser_symbol).new
164
163
 
165
164
  expect {
@@ -392,7 +391,7 @@ module Watir
392
391
  it 'accepts capabilities object' do
393
392
  caps = described_class.new(:chrome,
394
393
  url: 'https://example.com/wd/hub',
395
- capabilities: Selenium::WebDriver::Remote::Capabilities.chrome)
394
+ capabilities: Selenium::WebDriver::Remote::Capabilities.new(browser_name: 'chrome'))
396
395
  args = []
397
396
  expect {
398
397
  args = caps.to_args
@@ -408,7 +407,7 @@ module Watir
408
407
  client = HttpClient.new
409
408
  caps = described_class.new(:chrome,
410
409
  url: 'https://example.com/wd/hub',
411
- capabilities: Selenium::WebDriver::Remote::Capabilities.chrome,
410
+ capabilities: Selenium::WebDriver::Remote::Capabilities.new(browser_name: 'chrome'),
412
411
  http_client: client)
413
412
  args = []
414
413
  expect {
@@ -451,7 +450,7 @@ module Watir
451
450
  expect {
452
451
  described_class.new(:chrome,
453
452
  url: 'https://example.com/wd/hub',
454
- capabilities: Selenium::WebDriver::Remote::Capabilities.chrome,
453
+ capabilities: Selenium::WebDriver::Remote::Capabilities.new(browser_name: 'chrome'),
455
454
  options: options)
456
455
  }.to raise_exception(ArgumentError, ':capabilities and :options are not both allowed')
457
456
  end
@@ -666,8 +666,7 @@ module Watir
666
666
  let(:scope_built) { {xpath: ".//*[local-name()='div'][@id='table-rows-test']"} }
667
667
 
668
668
  before do
669
- allow(query_scope).to receive(:selector_builder).and_return(selector_builder)
670
- allow(query_scope).to receive(:browser).and_return(browser)
669
+ allow(query_scope).to receive_messages(selector_builder: selector_builder, browser: browser)
671
670
  allow(selector_builder).to receive(:built).and_return(scope_built)
672
671
  end
673
672
 
@@ -742,8 +741,7 @@ module Watir
742
741
  selector_builder = described_class.new(attributes, query_scope)
743
742
 
744
743
  allow(selector_builder).to receive(:built).and_return(scope_built)
745
- allow(query_scope).to receive(:selector_builder).and_return(selector_builder)
746
- allow(query_scope).to receive(:browser).and_return(browser)
744
+ allow(query_scope).to receive_messages(selector_builder: selector_builder, browser: browser)
747
745
  allow(query_scope).to receive(:is_a?).with(Watir::Browser).and_return(false)
748
746
  allow(query_scope).to receive(:is_a?).with(Watir::ShadowRoot).and_return(false)
749
747
  allow(query_scope).to receive(:is_a?).with(Watir::IFrame).and_return(true)
@@ -353,7 +353,7 @@ module Watir
353
353
 
354
354
  it 'updates the page when location is changed with setTimeout + window.location' do
355
355
  browser.goto(WatirSpec.url_for('timeout_window_location.html'))
356
- browser.wait_while { |b| b.url.include? 'timeout_window_location.html' }
356
+ browser.wait_while { |b| b.url.match?(/timeout_window_location|blank/) }
357
357
  expect(browser.url).to include('non_control_elements.html')
358
358
  end
359
359
  end
@@ -387,7 +387,7 @@ module Watir
387
387
 
388
388
  it 'returns correct Ruby objects' do
389
389
  expect(browser.execute_script('return {a: 1, "b": 2}')).to eq({'a' => 1, 'b' => 2})
390
- expect(browser.execute_script('return [1, 2, "3"]')).to match_array([1, 2, '3'])
390
+ expect(browser.execute_script('return [1, 2, "3"]')).to contain_exactly(1, 2, '3')
391
391
  expect(browser.execute_script('return 1.2 + 1.3')).to eq 2.5
392
392
  expect(browser.execute_script('return 2 + 2')).to eq 4
393
393
  expect(browser.execute_script('return "hello"')).to eq 'hello'
@@ -424,7 +424,9 @@ module Watir
424
424
  expect(hash['element']).to be_a(Watir::Body)
425
425
  end
426
426
 
427
- it 'wraps elements in a deep object' do
427
+ it 'wraps elements in a deep object',
428
+ except: {browser: %i[chrome edge],
429
+ reason: 'https://bugs.chromium.org/p/chromedriver/issues/detail?id=4536'} do
428
430
  hash = browser.execute_script('return {elements: [document.body], body: {element: document.body }}')
429
431
 
430
432
  expect(hash['elements'].first).to be_a(Watir::Body)
@@ -21,7 +21,7 @@ module Watir
21
21
  let(:browser_symbol) { WatirSpec.implementation.browser_args.first }
22
22
  let(:actual_capabilities) { @browser.wd.capabilities }
23
23
  let(:actual_http) { @browser.wd.instance_variable_get(:@bridge).instance_variable_get(:@http) }
24
- let(:actual_service) { @browser.wd.instance_variable_get(:@service) }
24
+ let(:actual_service) { @browser.wd.instance_variable_get(:@service_manager) }
25
25
  let(:actual_listener) { @browser.wd.instance_variable_get(:@bridge).instance_variable_get(:@listener) }
26
26
 
27
27
  before(:all) do
@@ -83,7 +83,8 @@ module Watir
83
83
  end
84
84
 
85
85
  describe 'capabilities' do
86
- it 'accepts namespaced value' do
86
+ it 'accepts namespaced value', except: {browser: :ie,
87
+ reason: 'IE is more strict'} do
87
88
  options = {'key:value' => 'something'}
88
89
  @browser = described_class.new(browser_symbol, options: options)
89
90
 
@@ -110,18 +111,6 @@ module Watir
110
111
  expect(actual_http).to eq client
111
112
  end
112
113
 
113
- it 'just capabilities has capabilities and watir client without service' do
114
- caps = Remote::Capabilities.new(browser_name: browser_name)
115
-
116
- expect {
117
- @browser = described_class.new(capabilities: caps)
118
- }.to have_deprecated(:capabilities)
119
-
120
- expect(selenium_args[:capabilities]).to eq(caps)
121
- expect(selenium_args).not_to include(:service)
122
- expect(actual_http).to be_a HttpClient
123
- end
124
-
125
114
  it 'accepts page load and script timeouts in seconds' do
126
115
  options = {page_load_timeout: 11,
127
116
  script_timeout: 12}
@@ -205,7 +194,8 @@ module Watir
205
194
  expect(actual_listener).to eq listener
206
195
  end
207
196
 
208
- describe 'proxy' do
197
+ describe 'proxy', except: {browser: :ie,
198
+ reason: 'Bug in Selenium 4.11 Selenium Manager'} do
209
199
  it 'adds Selenium Proxy to empty Options', except: {browser: :safari,
210
200
  reason: 'Safari does not like proxies'} do
211
201
  proxy = Selenium::WebDriver::Proxy.new(http: '127.0.0.1:8080', ssl: '127.0.0.1:443')
@@ -80,6 +80,33 @@ module Watir
80
80
  expect(cookie[:path]).to eq '/set_cookie'
81
81
  end
82
82
 
83
+ it 'adds a cookie with samesite value' do
84
+ browser.goto WatirSpec.url_for 'index.html'
85
+
86
+ options = {same_site: 'Strict'}
87
+ browser.cookies.add 'samesite', 'strict', options
88
+
89
+ cookie = browser.cookies.to_a.find { |e| e[:name] == 'samesite' }
90
+
91
+ expect(cookie[:name]).to eq 'samesite'
92
+ expect(cookie[:value]).to eq 'strict'
93
+ expect(cookie[:same_site]).to eq 'Strict'
94
+ end
95
+
96
+ it 'adds a cookie with httponly value' do
97
+ browser.goto WatirSpec.url_for 'index.html'
98
+
99
+ options = {http_only: true}
100
+ browser.cookies.add 'httponly', 'true', options
101
+
102
+ cookie = browser.cookies.to_a.find { |e| e[:name] == 'httponly' }
103
+
104
+ expect(cookie[:name]).to eq 'httponly'
105
+ expect(cookie[:value]).to eq 'true'
106
+ expect(cookie[:http_only]).to be true
107
+ expect(browser.execute_script('return document.cookie')).to be_empty
108
+ end
109
+
83
110
  it 'adds a cookie with expiration' do
84
111
  browser.goto WatirSpec.url_for 'index.html'
85
112
 
@@ -145,7 +172,7 @@ module Watir
145
172
  browser.cookies.clear
146
173
  browser.cookies.load file
147
174
  expected = browser.cookies.to_a
148
- actual = YAML.safe_load(File.read(file), permitted_classes: [::Symbol])
175
+ actual = YAML.safe_load_file(file, permitted_classes: [::Symbol])
149
176
 
150
177
  expected.each { |cookie| cookie.delete(:expires) }
151
178
  actual.each { |cookie| cookie.delete(:expires) }
@@ -124,12 +124,29 @@ module Watir
124
124
 
125
125
  # Manipulation methods
126
126
  describe '#value=' do
127
- it 'sets the value of the element' do
127
+ it 'sets the value of the element to a Date' do
128
128
  date = browser.date_field(id: 'html5_date')
129
129
  date.value = Date.today
130
130
  expect(Date.parse(date.value)).to eq Date.today
131
131
  end
132
132
 
133
+ it 'sets the value of the element to a Time' do
134
+ date = browser.date_field(id: 'html5_date')
135
+ date.value = ::Time.now
136
+ expect(Date.parse(date.value)).to eq Date.today
137
+ end
138
+
139
+ it 'sets the value of the element to an arbitrary class that responds to #strftime' do
140
+ instance_like_date = ::Object.new
141
+ def instance_like_date.strftime(_)
142
+ '2022-10-11'
143
+ end
144
+
145
+ date = browser.date_field(id: 'html5_date')
146
+ date.value = instance_like_date
147
+ expect(date.value).to eq '2022-10-11'
148
+ end
149
+
133
150
  it 'sets the value when accessed through the enclosing Form' do
134
151
  date_field = browser.form(id: 'new_user').date_field(id: 'html5_date')
135
152
  date_field.value = Date.today
@@ -124,7 +124,7 @@ module Watir
124
124
 
125
125
  # Manipulation methods
126
126
  describe '#value=' do
127
- it 'sets the value of the element' do
127
+ it 'sets the value of the element to a Time' do
128
128
  date_time = ::Time.now
129
129
  date_time_field = browser.date_time_field(id: 'html5_datetime-local')
130
130
  date_time_field.value = date_time
@@ -132,6 +132,25 @@ module Watir
132
132
  .to eq date_time.strftime('%Y-%m-%dT%H:%M')
133
133
  end
134
134
 
135
+ it 'sets the value of the element to a DateTime' do
136
+ date_time = DateTime.now
137
+ date_time_field = browser.date_time_field(id: 'html5_datetime-local')
138
+ date_time_field.value = date_time
139
+ expect(::Time.parse(date_time_field.value).strftime('%Y-%m-%dT%H:%M'))
140
+ .to eq date_time.strftime('%Y-%m-%dT%H:%M')
141
+ end
142
+
143
+ it 'sets the value of the element to an arbitrary class that responds to #strftime' do
144
+ date_time = ::Object.new
145
+ def date_time.strftime(_)
146
+ '2022-10-11T12:13'
147
+ end
148
+
149
+ date_time_field = browser.date_time_field(id: 'html5_datetime-local')
150
+ date_time_field.value = date_time
151
+ expect(date_time_field.value).to eq '2022-10-11T12:13'
152
+ end
153
+
135
154
  it 'sets the value when accessed through the enclosing Form' do
136
155
  date_time = ::Time.now
137
156
  date_time_field = browser.form(id: 'new_user').date_time_field(id: 'html5_datetime-local')
@@ -39,7 +39,7 @@ module Watir
39
39
  end
40
40
  end
41
41
 
42
- describe 'locating', except: {browser: :firefox, reason: 'location not supported yet'} do
42
+ describe 'locating' do
43
43
  it 'locates a nested element' do
44
44
  shadow_root = browser.div(id: 'shadow_host').shadow_root
45
45
  expect(shadow_root.element.id).to eq('shadow_content')
@@ -85,6 +85,8 @@ module Watir
85
85
  it 'click! elements within the shadow dom' do
86
86
  shadow_root = browser.div(id: 'shadow_host').shadow_root
87
87
  shadow_root.link.click!
88
+
89
+ browser.wait_while(url: /shadow_dom|blank/)
88
90
  expect(browser.url).to include('scroll.html')
89
91
  end
90
92
 
@@ -1,36 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  if defined?(RSpec)
4
- RSpec::Matchers.define :have_deprecated do |deprecation|
5
- match do |actual|
6
- # Suppresses logging output to stdout while ensuring that it is still happening
7
- default_output = Selenium::WebDriver.logger.io
8
- io = StringIO.new
9
- Watir.logger.output = io
4
+ LEVELS = %w[warning info deprecated].freeze
10
5
 
11
- actual.call
6
+ LEVELS.each do |level|
7
+ RSpec::Matchers.define "have_#{level}" do |entry|
8
+ match do |actual|
9
+ # Suppresses logging output to stdout while ensuring that it is still happening
10
+ default_output = Watir.logger.io
11
+ io = StringIO.new
12
+ Watir.logger.output = io
12
13
 
13
- Watir.logger.output = default_output
14
- @deprecations_found = (io.rewind && io.read).scan(/DEPRECATION\] \[:([^\]]*)\]/).flatten.map(&:to_sym)
15
- expect(Array(deprecation).sort).to eq(@deprecations_found.sort)
16
- end
14
+ begin
15
+ actual.call
16
+ rescue StandardError => e
17
+ raise e, 'Can not evaluate output when statement raises an exception'
18
+ ensure
19
+ Watir.logger.output = default_output
20
+ end
17
21
 
18
- failure_message do
19
- but_message = if @deprecations_found.nil? || @deprecations_found.empty?
20
- 'no deprecations were found'
21
- else
22
- "instead these deprecations were found: [#{@deprecations_found.join(', ')}]"
23
- end
24
- "expected :#{deprecation} to have been deprecated, but #{but_message}"
25
- end
22
+ @entries_found = (io.rewind && io.read).scan(/\[:([^\]]*)\]/).flatten.map(&:to_sym)
23
+ expect(Array(entry).sort).to eq(@entries_found.sort)
24
+ end
26
25
 
27
- failure_message_when_negated do
28
- but_message = "it was found among these deprecations: [#{@deprecations_found.join(', ')}]"
29
- "expected :#{deprecation} not to have been deprecated, but #{but_message}"
30
- end
26
+ failure_message do
27
+ but_message = if @entries_found.nil? || @entries_found.empty?
28
+ "no #{entry} entries were reported"
29
+ else
30
+ "instead these entries were found: [#{@entries_found.join(', ')}]"
31
+ end
32
+ "expected :#{entry} to have been logged, but #{but_message}"
33
+ end
31
34
 
32
- def supports_block_expectations?
33
- true
35
+ failure_message_when_negated do
36
+ but_message = "it was found among these entries: [#{@entries_found.join(', ')}]"
37
+ "expected :#{entry} not to have been logged, but #{but_message}"
38
+ end
39
+
40
+ def supports_block_expectations?
41
+ true
42
+ end
34
43
  end
35
44
  end
36
45
 
@@ -146,6 +146,7 @@ module Watir
146
146
  browser.goto WatirSpec.url_for('window_switching.html')
147
147
  browser.a(id: 'open').click
148
148
  browser.windows.wait_until(size: 2)
149
+ browser.wait_until { |b| !b.window(title: 'about:blank').exist? }
149
150
  end
150
151
 
151
152
  it 'allows actions on first window after opening second',
@@ -474,7 +475,7 @@ module Watir
474
475
 
475
476
  browser.window.minimize
476
477
 
477
- browser.wait_until { |b| b.execute_script('return document.visibilityState;') != 'visible' }
478
+ browser.wait_until { |b| !%w[visible normal].include?(b.execute_script('return document.visibilityState;')) }
478
479
 
479
480
  expect(browser.execute_script('return document.visibilityState;')).to eq 'hidden'
480
481
  browser.window.maximize
data/watir.gemspec CHANGED
@@ -8,7 +8,7 @@ require 'watir/version'
8
8
  Gem::Specification.new do |s|
9
9
  s.name = 'watir'
10
10
  s.version = Watir::VERSION
11
- s.required_ruby_version = '>= 2.7.0'
11
+ s.required_ruby_version = '>= 3.0.0'
12
12
 
13
13
  s.platform = Gem::Platform::RUBY
14
14
  s.authors = ['Alex Rodionov', 'Titus Fortner', 'Justin Ko']
@@ -42,7 +42,7 @@ Gem::Specification.new do |s|
42
42
  s.add_development_dependency 'rubocop-rake', '~> 0.6'
43
43
  s.add_development_dependency 'rubocop-rspec', '~> 2.16'
44
44
  s.add_development_dependency 'selenium_statistics'
45
- s.add_development_dependency 'selenium-webdriver', '~> 4.7'
45
+ s.add_development_dependency 'selenium-webdriver', '~> 4.11'
46
46
  s.add_development_dependency 'simplecov-console'
47
47
  s.add_development_dependency 'webidl', '>= 0.2.2'
48
48
  s.add_development_dependency 'yard', '> 0.9.11'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: watir
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.2.2
4
+ version: 7.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Rodionov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-01-03 00:00:00.000000000 Z
13
+ date: 2023-08-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: regexp_parser
@@ -226,14 +226,14 @@ dependencies:
226
226
  requirements:
227
227
  - - "~>"
228
228
  - !ruby/object:Gem::Version
229
- version: '4.7'
229
+ version: '4.11'
230
230
  type: :development
231
231
  prerelease: false
232
232
  version_requirements: !ruby/object:Gem::Requirement
233
233
  requirements:
234
234
  - - "~>"
235
235
  - !ruby/object:Gem::Version
236
- version: '4.7'
236
+ version: '4.11'
237
237
  - !ruby/object:Gem::Dependency
238
238
  name: simplecov-console
239
239
  requirement: !ruby/object:Gem::Requirement
@@ -627,7 +627,6 @@ files:
627
627
  - spec/watirspec/window_switching_spec.rb
628
628
  - spec/watirspec_helper.rb
629
629
  - support/doctest_helper.rb
630
- - support/travis.sh
631
630
  - support/version_differ.rb
632
631
  - watir.gemspec
633
632
  homepage: https://github.com/watir/watir
@@ -643,7 +642,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
643
642
  requirements:
644
643
  - - ">="
645
644
  - !ruby/object:Gem::Version
646
- version: 2.7.0
645
+ version: 3.0.0
647
646
  required_rubygems_version: !ruby/object:Gem::Requirement
648
647
  requirements:
649
648
  - - ">="
data/support/travis.sh DELETED
@@ -1,15 +0,0 @@
1
- #!/bin/bash
2
-
3
- set -e
4
- set -x
5
-
6
- sh -e /etc/init.d/xvfb start
7
-
8
- if [[ "$RAKE_TASK" = "yard:doctest" ]]; then
9
- mkdir ~/.yard
10
- bundle exec yard config -a autoload_plugins yard-doctest
11
- fi
12
-
13
- pwd
14
- echo "$RUBY_VERSION" >> .ruby-version
15
- cat .ruby-version