sparkling_watir 0.0.1 → 0.0.2

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: 8be8569b5d465e5b41cb77eebbab26537fdb755db47a0e486245e236535123fb
4
- data.tar.gz: 2b5d78461d1c67bb27a01137f6cb549cac39265c675e88e6690fc66e56cfd390
3
+ metadata.gz: bb2b6d1396c00f3a2e8456284f6b65dff1280bd79dd20d1e8f3188eb1006248f
4
+ data.tar.gz: 823a50280dec7f29ba2b2b9c4d0009f5568f206cff41ec2b723af53016c0b071
5
5
  SHA512:
6
- metadata.gz: d9c368c193abb1b26507a8598ce60afb25a7de718e9325c0e5cb2254169ce7a5cf9cc5582fa2b9a67236cc29da60a1bc516bdf4a89a267c0b37318a99288a0f3
7
- data.tar.gz: c2e9f30535754c03a862274c6360d8b76a13b5a139b3d32baf5eb65663615796d871d8d859b3b7c305e713002d2b31f0e390b458e28f7db668612a18fe6ffbe7
6
+ metadata.gz: 3d3298d8f14bf3c2b4928937be8199cd47852b37e30a3f44f6735dd7cf16c6504bc218a3ec4f1e1547333d3a4ab086226940317ab3ed45bf78d45e7360e6cf5e
7
+ data.tar.gz: f6a4244e7bda0712f10879d3c39f70f75f5232974ab5bedbe1df0a2abaed6e9f14149167f8839ddc4b93185f4fd694c526fa44ebfd31866fc7f9c7edf23362b5
@@ -11,11 +11,34 @@
11
11
  </content>
12
12
  <orderEntry type="inheritedJdk" />
13
13
  <orderEntry type="sourceFolder" forTests="false" />
14
+ <orderEntry type="library" scope="PROVIDED" name="appium_lib_core (v5.3.0, RVM: ruby-3.1.0) [gem]" level="application" />
15
+ <orderEntry type="library" scope="PROVIDED" name="ast (v2.4.2, RVM: ruby-3.1.0) [gem]" level="application" />
14
16
  <orderEntry type="library" scope="PROVIDED" name="bundler (v2.3.17, RVM: ruby-3.1.0) [gem]" level="application" />
17
+ <orderEntry type="library" scope="PROVIDED" name="childprocess (v4.1.0, RVM: ruby-3.1.0) [gem]" level="application" />
18
+ <orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.5.0, RVM: ruby-3.1.0) [gem]" level="application" />
19
+ <orderEntry type="library" scope="PROVIDED" name="eventmachine (v1.2.7, RVM: ruby-3.1.0) [gem]" level="application" />
20
+ <orderEntry type="library" scope="PROVIDED" name="faye-websocket (v0.11.1, RVM: ruby-3.1.0) [gem]" level="application" />
21
+ <orderEntry type="library" scope="PROVIDED" name="parallel (v1.22.1, RVM: ruby-3.1.0) [gem]" level="application" />
22
+ <orderEntry type="library" scope="PROVIDED" name="parser (v3.1.2.1, RVM: ruby-3.1.0) [gem]" level="application" />
23
+ <orderEntry type="library" scope="PROVIDED" name="rainbow (v3.1.1, RVM: ruby-3.1.0) [gem]" level="application" />
15
24
  <orderEntry type="library" scope="PROVIDED" name="rake (v13.0.6, RVM: ruby-3.1.0) [gem]" level="application" />
25
+ <orderEntry type="library" scope="PROVIDED" name="regexp_parser (v2.5.0, RVM: ruby-3.1.0) [gem]" level="application" />
26
+ <orderEntry type="library" scope="PROVIDED" name="rexml (v3.2.5, RVM: ruby-3.1.0) [gem]" level="application" />
16
27
  <orderEntry type="library" scope="PROVIDED" name="rspec (v3.11.0, RVM: ruby-3.1.0) [gem]" level="application" />
28
+ <orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.11.0, RVM: ruby-3.1.0) [gem]" level="application" />
29
+ <orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.11.0, RVM: ruby-3.1.0) [gem]" level="application" />
30
+ <orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.11.1, RVM: ruby-3.1.0) [gem]" level="application" />
31
+ <orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.11.0, RVM: ruby-3.1.0) [gem]" level="application" />
17
32
  <orderEntry type="library" scope="PROVIDED" name="rubocop (v0.93.1, RVM: ruby-3.1.0) [gem]" level="application" />
33
+ <orderEntry type="library" scope="PROVIDED" name="rubocop-ast (v1.21.0, RVM: ruby-3.1.0) [gem]" level="application" />
34
+ <orderEntry type="library" scope="PROVIDED" name="ruby-progressbar (v1.11.0, RVM: ruby-3.1.0) [gem]" level="application" />
35
+ <orderEntry type="library" scope="PROVIDED" name="rubyzip (v2.3.2, RVM: ruby-3.1.0) [gem]" level="application" />
36
+ <orderEntry type="library" scope="PROVIDED" name="selenium-webdriver (v4.4.0, RVM: ruby-3.1.0) [gem]" level="application" />
37
+ <orderEntry type="library" scope="PROVIDED" name="unicode-display_width (v1.8.0, RVM: ruby-3.1.0) [gem]" level="application" />
18
38
  <orderEntry type="library" scope="PROVIDED" name="watir (v7.1.0, RVM: ruby-3.1.0) [gem]" level="application" />
39
+ <orderEntry type="library" scope="PROVIDED" name="websocket (v1.2.9, RVM: ruby-3.1.0) [gem]" level="application" />
40
+ <orderEntry type="library" scope="PROVIDED" name="websocket-driver (v0.7.5, RVM: ruby-3.1.0) [gem]" level="application" />
41
+ <orderEntry type="library" scope="PROVIDED" name="websocket-extensions (v0.1.5, RVM: ruby-3.1.0) [gem]" level="application" />
19
42
  </component>
20
43
  <component name="RakeTasksCache">
21
44
  <option name="myRootTask">
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sparkling_watir (0.0.1)
4
+ sparkling_watir (0.0.2)
5
5
  appium_lib_core (~> 5.3.0)
6
6
  watir (~> 7.1.0)
7
7
 
data/README.md CHANGED
@@ -1,11 +1,15 @@
1
1
  # SparklingWatir
2
2
 
3
3
  Watir for testing your Mobile Devices. Powered by Appium.
4
- This project is a revamp of Tap watir https://github.com/watir/tap_watir.
4
+ This project is a revamp of [Tap watir](https://github.com/watir/tap_watir).
5
5
 
6
6
  All the inspiration from this project is taking from Tap Watir, so all the credit goes
7
7
  to the original creators and contributors
8
8
 
9
+ If you don't know the watir project here is the [link to the project](http://watir.com/)
10
+
11
+ This project is still in an alpha stage and under active development.
12
+
9
13
  ## Installation
10
14
 
11
15
  Add this line to your application's Gemfile:
@@ -22,6 +26,16 @@ Or install it yourself as:
22
26
 
23
27
  $ gem install sparkling_watir
24
28
 
29
+ If you want to run the tests on iOS just create a simulator that is an iPhone 8 with os 15.5 or you can change
30
+ the capabilities in spec/config/caps and you can download the testing app [here](https://github.com/cloudgrey-io/the-app/releases/tag/v1.10.0)
31
+
32
+ All the credit for the testing app goes to Jonathan Lipps.
33
+
34
+ If you want to switch between android and iOS capabilties just run:
35
+
36
+ $ rake platform[android] or rake platform[ios]
37
+
38
+
25
39
  ## License
26
40
 
27
41
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -0,0 +1,8 @@
1
+ require 'yaml'
2
+
3
+ desc 'Changes the default platform'
4
+ task :platform, [:platform] do |_t, args|
5
+ config = YAML.load_file('./spec/config/caps.yml')
6
+ config['default_platform'] = args.platform
7
+ File.open('./spec/config/caps.yml', 'w') { |file| YAML.dump(config, file) }
8
+ end
@@ -1,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
+ require_relative 'gestures'
3
+ require_relative 'wait'
2
4
 
3
5
  module SparklingWatir
4
-
5
6
  #
6
7
  # This is a element in the native app context
7
8
  #
8
9
  class Element
10
+ include Gestures
11
+ include Waitable
12
+
9
13
  def initialize(driver, selector)
10
14
  @driver = driver
11
15
  @selector = selector
@@ -48,7 +52,7 @@ module SparklingWatir
48
52
  end
49
53
 
50
54
  def bounds
51
- {x: coordinates.x + size.width, y: coordinates.y + size.height}
55
+ { x: coordinates.x + size.width, y: coordinates.y + size.height }
52
56
  end
53
57
 
54
58
  private
@@ -0,0 +1,39 @@
1
+ require 'appium_lib_core/common/touch_action/touch_actions'
2
+ require 'selenium/webdriver/common/interactions/interactions'
3
+
4
+ module SparklingWatir
5
+ module Gestures
6
+
7
+ VIEWPORT = ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT
8
+
9
+ def action(kind, name)
10
+ @driver.action.add_pointer_input(kind, name)
11
+ end
12
+
13
+ def perform(*actions)
14
+ @driver.perform_actions actions
15
+ end
16
+
17
+ def tap
18
+ tap = action(:touch, 'tap')
19
+ tap.create_pointer_move(duration: 0.1, x: bounds[:x], y: bounds[:y] - 1, origin: VIEWPORT)
20
+ tap.create_pointer_down(:left)
21
+ tap.create_pointer_up(:left)
22
+ perform tap
23
+ end
24
+
25
+ alias press tap
26
+
27
+ def double_tap
28
+ double_tap = action(:touch, 'double_tap')
29
+ double_tap.create_pointer_move(duration: 0.1, x: bounds[:x], y: bounds[:y] - 1, origin: VIEWPORT)
30
+ double_tap.create_pointer_down(:left)
31
+ double_tap.create_pointer_up(:left)
32
+ double_tap.create_pause(0.5)
33
+ double_tap.create_pointer_down(:left)
34
+ double_tap.create_pointer_up(:left)
35
+
36
+ perform double_tap
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,50 @@
1
+ module SparklingWatir
2
+ module Wait
3
+ class Timer
4
+ def initialize(timeout: nil)
5
+ @end_time = timeout ? current_time + timeout : nil
6
+ @remaining_time = @end_time - current_time if @end_time
7
+ end
8
+
9
+ #
10
+ # Executes given block until it returns true or exceeds timeout.
11
+ # @param [Integer] timeout
12
+ # @yield block
13
+ # @api private
14
+ #
15
+
16
+ def wait(timeout, &block)
17
+ end_time = @end_time || current_time + timeout
18
+ loop do
19
+ yield(block)
20
+ @remaining_time = end_time - current_time
21
+ break if @remaining_time.negative?
22
+ end
23
+ end
24
+
25
+ def remaining_time
26
+ @end_time - current_time
27
+ end
28
+
29
+ def reset!
30
+ @end_time = nil
31
+ end
32
+
33
+ def locked?
34
+ !@end_time.nil?
35
+ end
36
+
37
+ private
38
+
39
+ if defined?(Process::CLOCK_MONOTONIC)
40
+ def current_time
41
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
42
+ end
43
+ else
44
+ def current_time
45
+ ::Time.now.to_f
46
+ end
47
+ end
48
+ end # Timer
49
+ end # Wait
50
+ end # SparklingWatir
@@ -0,0 +1,149 @@
1
+ require_relative 'wait/timer'
2
+
3
+ module SparklingWatir
4
+ module Wait
5
+ class TimeoutError < StandardError; end
6
+
7
+ INTERVAL = 0.1
8
+
9
+ class << self
10
+ #
11
+ # @!attribute timer
12
+ # Access TapWatir timer implementation in use.
13
+ # @see Timer
14
+ # @return [#wait]
15
+ #
16
+
17
+ attr_writer :timer
18
+
19
+ def timer
20
+ @timer ||= Timer.new
21
+ end
22
+
23
+ #
24
+ # Waits until the block evaluates to true or times out.
25
+ #
26
+ # @example
27
+ # TODO: Add examples
28
+ #
29
+ # @param [Integer] timeout How long to wait in seconds
30
+ # @param [String] message Message to raise if timeout is exceeded
31
+ # @param [Object, NilClass] object Object to evaluate block against
32
+ # @raise [TimeoutError] if timeout is exceeded
33
+ #
34
+
35
+ def until(timeout: nil, message: nil, interval: nil, object: nil)
36
+ timeout ||= Watir.default_timeout
37
+ run_with_timer(timeout, interval) do
38
+ result = yield(object)
39
+ return result if result
40
+ end
41
+ raise TimeoutError, message_for(timeout, object, message)
42
+ end
43
+
44
+ #
45
+ # Wait while the block evaluates to true or times out.
46
+ #
47
+ # @example
48
+ # TODO: Add examples
49
+ #
50
+ # @param [Integer] timeout How long to wait in seconds
51
+ # @param [String] message Message to raise if timeout is exceeded
52
+ # @param [Object, NilClass] object Object to evaluate block against
53
+ # @raise [TimeoutError] if timeout is exceeded
54
+ #
55
+
56
+ def while(timeout: nil, message: nil, interval: nil, object: nil)
57
+ timeout ||= Watir.default_timeout
58
+ run_with_timer(timeout, interval) { return unless yield(object) }
59
+ raise TimeoutError, message_for(timeout, object, message)
60
+ end
61
+
62
+ private
63
+
64
+ def message_for(timeout, object, message)
65
+ message = message.call(object) if message.is_a?(Proc)
66
+ err = "timed out after #{timeout} seconds"
67
+ err << ", #{message}" if message
68
+
69
+ err
70
+ end
71
+
72
+ def run_with_timer(timeout, interval)
73
+ if timeout.zero?
74
+ yield
75
+ else
76
+ timer.wait(timeout) do
77
+ yield
78
+ sleep interval || INTERVAL
79
+ end
80
+ end
81
+ end
82
+ end # self
83
+ end # Wait
84
+
85
+ module Waitable
86
+ #
87
+ # Waits until the condition is true.
88
+ #
89
+ # @example
90
+ # TODO: Add examples
91
+ #
92
+
93
+ def wait_until(timeout: nil, message: nil, interval: nil, **opt, &blk)
94
+ message ||= proc { |obj| "waiting for true condition on #{obj.inspect}" }
95
+
96
+ # TODO: Consider throwing argument error for mixing block & options
97
+ proc = create_proc(opt, &blk)
98
+
99
+ Wait.until(timeout: timeout, message: message, interval: interval, object: self, &proc)
100
+
101
+ self
102
+ end
103
+
104
+ #
105
+ # @example
106
+ # Add examples
107
+ #
108
+ def wait_while(timeout: nil, message: nil, interval: nil, **opt, &blk)
109
+ message ||= proc { |obj| "waiting for false condition on #{obj.inspect}" }
110
+
111
+ # TODO: Add examples
112
+ proc = create_proc(opt, &blk)
113
+
114
+ Wait.while(timeout: timeout, message: message, interval: interval, object: self, &proc)
115
+
116
+ self
117
+ end
118
+
119
+ private
120
+
121
+ def create_proc(opt)
122
+ proc do
123
+ reset! if opt.delete(:element_reset) && is_a?(Element)
124
+ (opt.empty? || match_attributes(opt).call) && (!block_given? || yield(self))
125
+ end
126
+ end
127
+
128
+ def match_attributes(opt)
129
+ proc do
130
+ opt.keys.all? do |key|
131
+ expected = opt[key]
132
+ actual = if is_a?(Element) && !respond_to?(key)
133
+ attribute_value(key)
134
+ else
135
+ send(key)
136
+ end
137
+ case expected
138
+ when Regexp
139
+ expected =~ actual
140
+ when Numeric
141
+ expected == actual
142
+ else
143
+ expected.to_s == actual
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end # Waitable
149
+ end # SparklingWatir
@@ -2,36 +2,37 @@ require 'appium_lib_core'
2
2
  require 'watir'
3
3
 
4
4
  module SparklingWatir
5
- #
6
- # For driving a native application or a native app context
7
- #
8
- class App
9
- attr_accessor :driver
5
+ #
6
+ # For driving a native application or a native app context
7
+ #
8
+ class App
9
+ attr_accessor :driver
10
10
 
11
- def initialize(opts)
12
- url = opts[:caps].delete(:url)
13
- @driver = Appium::Core::Driver.for(opts).start_driver(server_url: url)
14
- end
11
+ def initialize(opts)
12
+ url = opts[:caps].delete(:url)
13
+ @driver = Appium::Core::Driver.for(opts).start_driver(server_url: url)
14
+ end
15
15
 
16
- def quit
17
- @driver.quit
18
- end
19
- alias close quit
16
+ def quit
17
+ @driver.quit
18
+ end
20
19
 
21
- def element(selector)
22
- Element.new(driver, selector)
23
- end
20
+ alias close quit
24
21
 
25
- def method_missing(method_name, *arguments, &block)
26
- if driver.respond_to? method_name
27
- driver.send method_name, *arguments, &block
28
- else
29
- super
30
- end
31
- end
22
+ def element(selector)
23
+ Element.new(driver, selector)
24
+ end
32
25
 
33
- def respond_to_missing?(method_name, include_private = false)
34
- driver.respond_to?(method_name) || super
26
+ def method_missing(method_name, *arguments, &block)
27
+ if driver.respond_to? method_name
28
+ driver.send method_name, *arguments, &block
29
+ else
30
+ super
35
31
  end
36
32
  end
33
+
34
+ def respond_to_missing?(method_name, include_private = false)
35
+ driver.respond_to?(method_name) || super
36
+ end
37
+ end
37
38
  end
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'sparkling_watir'
8
- spec.version = '0.0.1'
8
+ spec.version = '0.0.2'
9
9
  spec.authors = ['Agustin Pequeno']
10
10
  spec.email = ['agustin.pe94@gmail.com']
11
11
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sparkling_watir
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Agustin Pequeno
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-11 00:00:00.000000000 Z
11
+ date: 2022-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -115,6 +115,9 @@ files:
115
115
  - Rakefile
116
116
  - lib/sparkling_watir.rb
117
117
  - lib/sparkling_watir/element.rb
118
+ - lib/sparkling_watir/gestures.rb
119
+ - lib/sparkling_watir/wait.rb
120
+ - lib/sparkling_watir/wait/timer.rb
118
121
  - sparkling_watir.gemspec
119
122
  homepage:
120
123
  licenses: