Skip to content

Commit 30a60ef

Browse files
authored
add script to get diff commands (#9)
* add script to get diff commands * set hash based diff * change to hash based comparition * add rake task * fix ribocop * fix undefined method error * add some comments for doc * split match string * fix rubocop * replace method name
1 parent 445cf6a commit 30a60ef

File tree

8 files changed

+897
-58
lines changed

8 files changed

+897
-58
lines changed

Rakefile

+13-2
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,20 @@ YARD::Rake::YardocTask.new do |t|
5454
t.files = ['lib/**/*.rb']
5555
end
5656

57-
desc 'Execute RuboCop static code analysis'
57+
desc('Execute RuboCop static code analysis')
5858
RuboCop::RakeTask.new(:rubocop) do |t|
59-
t.patterns = %w(lib test)
59+
t.patterns = %w(lib test script)
6060
t.options = %w(-D)
6161
t.fail_on_error = true
6262
end
63+
64+
desc("print commands which haven't implemented yet.")
65+
namespace :commands do
66+
task :mjsonwp do |_t, _args|
67+
require './script/commands'
68+
c = Script::CommandsChecker.new
69+
c.get_mjsonwp_routes
70+
c.get_all_command_path './mjsonwp_routes.js'
71+
c.all_diff_commands_mjsonwp.each { |key, value| puts("command: #{key}, method: #{value}") }
72+
end
73+
end

lib/appium_lib_core/common/device.rb

+63-54
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,48 @@ module Device
264264
# ime_deactivate #=> Deactivate current IME engine
265265
#
266266

267+
# @!method set_context(context)
268+
# Change the context to the given context.
269+
# @param [String] context The context to change to
270+
#
271+
# @example
272+
#
273+
# @driver.set_context "NATIVE_APP"
274+
#
275+
276+
# @!method current_context
277+
# @return [String] The context currently being used.
278+
#
279+
# @example
280+
#
281+
# @driver.current_context
282+
#
283+
284+
# @!method available_contexts
285+
# @return [Array<String>] All usable contexts, as an array of strings.
286+
#
287+
# @example
288+
#
289+
# @driver.available_contexts
290+
#
291+
292+
# Perform a block within the given context, then switch back to the starting context.
293+
# @param [String] context The context to switch to for the duration of the block.
294+
#
295+
# @example
296+
#
297+
# result = @driver.within_context('NATIVE_APP') do
298+
# @driver.find_element :tag, "button"
299+
# end # The result of `find_element :tag, "button"`
300+
#
301+
302+
# Change to the default context. This is equivalent to `set_context nil`.
303+
#
304+
# @example
305+
#
306+
# @driver.switch_to_default_context
307+
#
308+
267309
####
268310
## class << self
269311
####
@@ -414,6 +456,7 @@ def update_settings(settings)
414456

415457
add_touch_actions
416458
add_ime_actions
459+
add_handling_context
417460
end
418461

419462
# def extended
@@ -505,63 +548,29 @@ def ime_deactivate
505548
end
506549
end
507550
end
508-
end # class << self
509-
510-
# @!method set_context(context)
511-
# Change the context to the given context.
512-
# @param [String] context The context to change to
513-
#
514-
# @example
515-
#
516-
# @driver.set_context "NATIVE_APP"
517-
#
518-
519-
# @!method current_context
520-
# @return [String] The context currently being used.
521-
#
522-
# @example
523-
#
524-
# @driver.current_context
525-
#
526551

527-
# @!method available_contexts
528-
# @return [Array<String>] All usable contexts, as an array of strings.
529-
#
530-
# @example
531-
#
532-
# @driver.available_contexts
533-
#
552+
def add_handling_context
553+
add_endpoint_method(:within_context) do
554+
def within_context(context)
555+
existing_context = current_context
556+
set_context context
557+
if block_given?
558+
result = yield
559+
set_context existing_context
560+
result
561+
else
562+
set_context existing_context
563+
end
564+
end
565+
end
534566

535-
# Perform a block within the given context, then switch back to the starting context.
536-
# @param [String] context The context to switch to for the duration of the block.
537-
#
538-
# @example
539-
#
540-
# result = @driver.within_context('NATIVE_APP') do
541-
# @driver.find_element :tag, "button"
542-
# end # The result of `find_element :tag, "button"`
543-
#
544-
def within_context(context)
545-
existing_context = current_context
546-
set_context context
547-
if block_given?
548-
result = yield
549-
set_context existing_context
550-
result
551-
else
552-
set_context existing_context
567+
add_endpoint_method(:switch_to_default_context) do
568+
def switch_to_default_context
569+
set_context nil
570+
end
571+
end
553572
end
554-
end
555-
556-
# Change to the default context. This is equivalent to `set_context nil`.
557-
#
558-
# @example
559-
#
560-
# @driver.switch_to_default_context
561-
#
562-
def switch_to_default_context
563-
set_context nil
564-
end
573+
end # class << self
565574
end # module Device
566575
end # module Core
567576
end # module Appium

script/commands.rb

+184
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
require 'net/http'
2+
require './lib/appium_lib_core'
3+
4+
module Script
5+
class CommandsChecker
6+
attr_reader :spec_commands
7+
attr_reader :implemented_mjsonwp_commands, :implemented_w3c_commands, :implemented_core_commands
8+
attr_reader :webdriver_oss_commands, :webdriver_w3c_commands
9+
10+
# Set commands implemented in this core library.
11+
#
12+
# - implemented_mjsonwp_commands: All commands include ::Selenium::WebDriver::Remote::OSS::Bridge::COMMANDS
13+
# - implemented_w3c_commands: All commands include ::Selenium::WebDriver::Remote::W3C::Bridge::COMMANDS
14+
# - implemented_core_commands: All commands except for selenium-webdriver's commands
15+
# - webdriver_oss_commands: ::Selenium::WebDriver::Remote::OSS::Bridge::COMMANDS
16+
# - webdriver_w3c_commands: ::Selenium::WebDriver::Remote::W3C::Bridge::COMMANDS
17+
#
18+
def initialize
19+
@implemented_mjsonwp_commands = convert_driver_commands Appium::Core::Commands::COMMANDS_EXTEND_MJSONWP
20+
@implemented_w3c_commands = convert_driver_commands Appium::Core::Commands::COMMANDS_EXTEND_W3C
21+
@implemented_core_commands = convert_driver_commands Appium::Core::Commands::COMMANDS
22+
23+
@webdriver_oss_commands = convert_driver_commands Appium::Core::Base::Commands::OSS
24+
@webdriver_w3c_commands = convert_driver_commands Appium::Core::Base::Commands::W3C
25+
end
26+
27+
# Get the bellow url's file.
28+
# https://raw.githubusercontent.com/appium/appium-base-driver/master/lib/mjsonwp/routes.js?raw=1
29+
#
30+
# @param [String] to_path: A file path to routes.js
31+
# @return [String] The file path in which has saved `routes.js`.
32+
#
33+
def get_mjsonwp_routes(to_path = './mjsonwp_routes.js')
34+
uri = URI 'https://raw.githubusercontent.com/appium/appium-base-driver/master/lib/mjsonwp/routes.js?raw=1'
35+
result = Net::HTTP.get uri
36+
37+
File.delete to_path
38+
File.write to_path, result
39+
to_path
40+
end
41+
42+
# @private
43+
HTTP_METHOD_MATCH = /GET:|POST:|DELETE:|PUT:|PATCH:/
44+
# @private
45+
WD_HUB_PREFIX_MATCH = "'/wd/hub/".freeze
46+
47+
# Read routes.js and set the values in @spec_commands
48+
#
49+
# @param [String] path: A file path to routes.js
50+
# @return [Hash] @spec_commands
51+
#
52+
def get_all_command_path(path = './mjsonwp_routes.js')
53+
raise "No file in #{path}" unless File.exist? path
54+
55+
current_command = ''
56+
@spec_commands = File.read(path).lines.each_with_object({}) do |line, memo|
57+
if line =~ /#{WD_HUB_PREFIX_MATCH}.+'/
58+
current_command = gsub_set(line.slice(/#{WD_HUB_PREFIX_MATCH}.+'/))
59+
memo[current_command] = []
60+
elsif line =~ HTTP_METHOD_MATCH
61+
memo[current_command] << line.slice(HTTP_METHOD_MATCH).chop.downcase.to_sym
62+
end
63+
memo
64+
end
65+
end
66+
67+
# All commands which haven't been implemented in ruby core library yet.
68+
# @return [Hash]
69+
#
70+
def all_diff_commands_mjsonwp
71+
result = compare_commands(@spec_commands, @implemented_mjsonwp_commands)
72+
73+
white_list.each { |v| result.delete v }
74+
w3c_spec.each { |v| result.delete v }
75+
76+
result
77+
end
78+
79+
# All commands which haven't been implemented in ruby core library yet.
80+
# @return [Hash]
81+
#
82+
def all_diff_commands_w3c
83+
result = compare_commands(@spec_commands, @implemented_w3c_commands)
84+
white_list.each { |v| result.delete v }
85+
mjsonwp_spec.each { |v| result.delete v }
86+
result
87+
end
88+
89+
# Commands, only this core library, which haven't been implemented in ruby core library yet.
90+
# @return [Hash]
91+
#
92+
def diff_except_for_webdriver
93+
result = compare_commands(@spec_commands, @implemented_core_commands)
94+
white_list.each { |v| result.delete v }
95+
result
96+
end
97+
98+
def diff_webdriver_oss
99+
result = compare_commands(@spec_commands, @webdriver_oss_commands)
100+
white_list.each { |v| result.delete v }
101+
w3c_spec.each { |v| result.delete v }
102+
result
103+
end
104+
105+
def diff_webdriver_w3c
106+
result = compare_commands(@spec_commands, @webdriver_w3c_commands)
107+
white_list.each { |v| result.delete v }
108+
mjsonwp_spec.each { |v| result.delete v }
109+
result
110+
end
111+
112+
def compare_commands(command1, with_command2)
113+
return {} if command1.nil?
114+
return command1 if with_command2.nil?
115+
116+
result = {}
117+
command1.each_key do |key|
118+
if with_command2.key? key
119+
diff = command1[key] - with_command2[key]
120+
result[key] = diff unless diff.empty?
121+
else
122+
result[key] = command1[key]
123+
end
124+
end
125+
result
126+
end
127+
128+
private
129+
130+
# rubocop:disable Lint/PercentStringArray
131+
def white_list
132+
%w(
133+
'/wd/hub/session'
134+
'/wd/hub/sessions'
135+
).map { |v| gsub_set(v) }
136+
end
137+
138+
# https://raw.githubusercontent.com/appium/appium-base-driver/master/lib/mjsonwp/routes.js
139+
def mjsonwp_spec
140+
%w(
141+
'/wd/hub/session/:sessionId/alert_text'
142+
'/wd/hub/session/:sessionId/accept_alert'
143+
'/wd/hub/session/:sessionId/dismiss_alert'
144+
).map { |v| gsub_set(v) }
145+
end
146+
147+
def w3c_spec
148+
%w(
149+
'/wd/hub/session/:sessionId/alert/text'
150+
'/wd/hub/session/:sessionId/alert/accept'
151+
'/wd/hub/session/:sessionId/alert/dismiss'
152+
'/wd/hub/session/:sessionId/element/:elementId/rect'
153+
).map { |v| gsub_set(v) }
154+
end
155+
# rubocop:enable Lint/PercentStringArray
156+
157+
def gsub_set(line)
158+
return nil if line.gsub(/(\A#{WD_HUB_PREFIX_MATCH}|'\z)/, '').nil?
159+
160+
line.gsub(/(\A#{WD_HUB_PREFIX_MATCH}|'\z)/, '')
161+
.sub(':sessionId', ':session_id')
162+
.sub('element/:elementId', 'element/:id')
163+
.sub(':windowhandle', ':window_handle')
164+
.sub('equals/:otherId', 'equals/:other')
165+
.sub('css/:propertyName', 'css/:property_name')
166+
.sub('element/:id/pageIndex', 'element/:id/page_index')
167+
end
168+
169+
def convert_driver_commands(from)
170+
from.each_with_object({}) do |command, memo|
171+
method = command[1][0]
172+
key = command[1][1]
173+
174+
if memo[key]
175+
memo[key] << method
176+
else
177+
memo[key] = [method]
178+
end
179+
180+
memo
181+
end
182+
end
183+
end
184+
end

test/functional/android/android/device_test.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ def test_ime_available_engins
264264

265265
def test_within_context
266266
result = @@driver.within_context('NATIVE_APP') do
267-
@@core.wait { @@driver.find_element :accessibility_id, 'App' }.click
267+
@@core.wait { @@driver.find_element :accessibility_id, 'App' }
268268
end
269269

270270
assert_equal 'App', result.text

test/functional/ios/ios/device_test.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ def test_hidekeyboard
186186

187187
def test_within_context
188188
result = @@driver.within_context('NATIVE_APP') do
189-
@@core.wait { @@driver.find_element :accessibility_id, 'Buttons' }.click
189+
@@core.wait { @@driver.find_element :accessibility_id, 'Buttons' }
190190
end
191191

192192
assert_equal 'Buttons', result.name

test/functional/ios/webdriver/device_test.rb

+6
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ def test_rotate
9393
@@driver.rotation = :portrait
9494
assert_equal :portrait, @@driver.orientation
9595
end
96+
97+
# TODO: add an async execuite test case
98+
# def test_async_execuite
99+
# @@driver.execute_async_script('mobile: tap', x: 0, y: 0, element: element.ref)
100+
# @@driver.execute_script('mobile: tap', x: 0, y: 0, element: element.ref)
101+
# end
96102
end
97103
end
98104
end

0 commit comments

Comments
 (0)