tabbyx 0.1.4

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 (40) hide show
  1. checksums.yaml +7 -0
  2. data/bin/console +14 -0
  3. data/bin/setup +8 -0
  4. data/lib/tabbyx.rb +29 -0
  5. data/lib/tabbyx/calabash_android.rb +11 -0
  6. data/lib/tabbyx/calabash_ios.rb +4 -0
  7. data/lib/tabbyx/core/base.rb +54 -0
  8. data/lib/tabbyx/core/config.rb +36 -0
  9. data/lib/tabbyx/core/initialize.rb +35 -0
  10. data/lib/tabbyx/fixtures/constants.rb +21 -0
  11. data/lib/tabbyx/fixtures/global.rb +39 -0
  12. data/lib/tabbyx/helpers/csv_helper.rb +65 -0
  13. data/lib/tabbyx/helpers/debug_helper.rb +37 -0
  14. data/lib/tabbyx/helpers/excel_helper.rb +79 -0
  15. data/lib/tabbyx/helpers/http_batch_handler.rb +50 -0
  16. data/lib/tabbyx/helpers/http_helper.rb +46 -0
  17. data/lib/tabbyx/helpers/minitest_helper.rb +48 -0
  18. data/lib/tabbyx/helpers/screenshot_helpers.rb +128 -0
  19. data/lib/tabbyx/helpers/txt_helper.rb +35 -0
  20. data/lib/tabbyx/steps_android/assert_steps.rb +31 -0
  21. data/lib/tabbyx/steps_android/check_box_steps.rb +3 -0
  22. data/lib/tabbyx/steps_android/context_menu_steps.rb +17 -0
  23. data/lib/tabbyx/steps_android/date_picker_steps.rb +8 -0
  24. data/lib/tabbyx/steps_android/enter_text_steps.rb +23 -0
  25. data/lib/tabbyx/steps_android/location_steps.rb +7 -0
  26. data/lib/tabbyx/steps_android/navigation_steps.rb +47 -0
  27. data/lib/tabbyx/steps_android/press_button_steps.rb +39 -0
  28. data/lib/tabbyx/steps_android/progress_steps.rb +51 -0
  29. data/lib/tabbyx/steps_android/search_steps.rb +7 -0
  30. data/lib/tabbyx/steps_android/spinner_steps.rb +11 -0
  31. data/lib/tabbyx/steps_ios/assertions.rb +79 -0
  32. data/lib/tabbyx/steps_ios/date_picker.rb +39 -0
  33. data/lib/tabbyx/steps_ios/operations.rb +187 -0
  34. data/lib/tabbyx/steps_ios/wait.rb +48 -0
  35. data/lib/tabbyx/utils/adb_devices.rb +248 -0
  36. data/lib/tabbyx/utils/adb_screenshot.rb +22 -0
  37. data/lib/tabbyx/utils/code_coverage.rb +6 -0
  38. data/lib/tabbyx/utils/shell.rb +32 -0
  39. data/lib/tabbyx/version.rb +3 -0
  40. metadata +286 -0
@@ -0,0 +1,39 @@
1
+ Given /^我点击按钮"([^\"]*)"$/ do |text|
2
+ tap_when_element_exists("android.widget.Button {text CONTAINS[c] '#{text}'}")
3
+ end
4
+
5
+ Then /^我点击第(\d+)个按钮$/ do |index|
6
+ tap_when_element_exists("android.widget.Button index:#{index.to_i-1}")
7
+ end
8
+
9
+ Then /^我点击第(\d+)个图片按钮$/ do |index|
10
+ tap_when_element_exists("android.widget.ImageButton index:#{index.to_i-1}")
11
+ end
12
+
13
+ Then /^我点击id为"([^\"]*)"的页面$/ do |id|
14
+ tap_when_element_exists("* id:'#{id}'")
15
+ end
16
+
17
+ Then /^我点击"([^\"]*)"$/ do |identifier|
18
+ tap_when_element_exists("* marked:'#{identifier}'")
19
+ end
20
+
21
+ Then /^点击屏幕上的x: (\d+)%,y:(\d+)%$/ do |x, y|
22
+ perform_action('click_on_screen', x, y)
23
+ end
24
+
25
+ Then /^我点击包含"([^\"]*)"的文本$/ do |text|
26
+ tap_when_element_exists("* {text CONTAINS[c] '#{text}'}")
27
+ end
28
+
29
+ Then /^我选择列表的第(\d+)个$/ do |index|
30
+ step_deprecated
31
+
32
+ tap_when_element_exists("android.widget.ListView index:0 android.widget.TextView index:#{index.to_i-1}")
33
+ end
34
+
35
+ Then /^我长按选择列表的第(\d+)个$/ do |index|
36
+ step_deprecated
37
+
38
+ long_press_when_element_exists("android.widget.ListView index:0 android.widget.TextView index:#{index.to_i-1}")
39
+ end
@@ -0,0 +1,51 @@
1
+ Then /^我等待进度条的出现$/ do
2
+ wait_for_element_does_not_exist("android.widget.ProgressBar")
3
+ end
4
+
5
+ Then /^我等待(\d+)秒$/ do |seconds|
6
+ sleep(seconds.to_i)
7
+ end
8
+
9
+ Then /^我等待文本"([^\"]*)"出现$/ do |text|
10
+ wait_for_text(text)
11
+ end
12
+
13
+ Then /^我等待(\d+)秒直到"([^\"]*)"出现$/ do |timeout, text|
14
+ wait_for_text(text, timeout: timeout.to_i)
15
+ end
16
+
17
+ Then /^我等待直到看见"([^\"]*)"$/ do |text|
18
+ wait_for_text(text)
19
+ end
20
+
21
+ Then /^我等待"([^\"]*)的出现,最多等待(\d+)秒"$/ do | text,timeout|
22
+ wait_for_text(text, timeout: timeout.to_i)
23
+ end
24
+
25
+ Then /^我等待按钮"([^\"]*)"出现$/ do |identifier|
26
+ wait_for_element_exists("android.widget.Button marked:'#{identifier}'");
27
+ end
28
+
29
+ Then /^我等待id为"([^\"]*)"出现$/ do |id|
30
+ wait_for_element_exists("* id:'#{id}'")
31
+ end
32
+
33
+ Then /^我等待文本"([^\"]*)"出现$/ do |text|
34
+ wait_for_element_exists("* marked:'#{text}'")
35
+ end
36
+
37
+
38
+ Then /^我等待activity"([^\"]*)"出现$/ do |activity_name|
39
+ wait_for_activity(activity_name)
40
+ end
41
+
42
+ Then /^我等待activity"([^\"]*)"出现,最多等待(\d+)秒$/ do |activity_name,timeout|
43
+ wait_for_activity(activity_name, timeout: timeout.to_i)
44
+ end
45
+
46
+ # @param - the "tag" associated with the tab, or the text within the tab label
47
+ Then /^我等待tab"([^\"]*)"出现$/ do |tab|
48
+ wait_for do
49
+ query("android.widget.TabWidget descendant TextView {text LIKE[c] '#{tab}'}", :isSelected).first
50
+ end
51
+ end
@@ -0,0 +1,7 @@
1
+ Then /^我输入"([^\"]*)"到搜索框$/ do |text|
2
+ enter_text("android.widget.SearchView index:0", text)
3
+ end
4
+
5
+ Then /^我输入"([^\"]*)"到第(\d+)个搜索框$/ do |text, number|
6
+ enter_text("android.widget.SearchView index:#{number.to_i-1}", text)
7
+ end
@@ -0,0 +1,11 @@
1
+ Then /^我从下拉框"([^\"]*)"中选择"([^\"]*)" $/ do |spinner_identifier, item_identifier|
2
+ spinner = query("android.widget.Spinner marked:'#{spinner_identifier}'")
3
+
4
+ if spinner.empty?
5
+ tap_when_element_exists("android.widget.Spinner * marked:'#{spinner_identifier}'")
6
+ else
7
+ touch(spinner)
8
+ end
9
+
10
+ tap_when_element_exists("android.widget.PopupWindow$PopupViewContainer * marked:'#{item_identifier}'")
11
+ end
@@ -0,0 +1,79 @@
1
+
2
+ ### Assertions ###
3
+ Then /^我必须看见"([^\"]*)"$/ do |expected_mark|
4
+ until element_exists("view marked:'#{expected_mark}'") ||
5
+ element_exists("view text:'#{expected_mark}'")
6
+ screenshot_and_raise "No element found with mark or text: #{expected_mark}"
7
+ end
8
+ end
9
+
10
+ Then /^我看不到"([^\"]*)"$/ do |expected_mark|
11
+ res = query("view marked: '#{expected_mark}'")
12
+ res.concat query("view text: '#{expected_mark}'")
13
+ unless res.empty?
14
+ screenshot_and_raise "Expected no element with text nor accessibilityLabel: #{expected_mark}, found #{res.join(', ')}"
15
+ end
16
+ end
17
+
18
+ Then /^我必须看见"([^\"]*)"按钮/ do |expected_mark|
19
+ check_element_exists("button marked: '#{expected_mark}'")
20
+ end
21
+ Then /^我不能看见"([^\"]*)"按钮/ do |expected_mark|
22
+ check_element_does_not_exist("button marked: '#{expected_mark}'")
23
+ end
24
+
25
+ Then /^我看不见文本"([^\"]*)"$/ do |text|
26
+ macro %(我看不到"#{text}")
27
+ end
28
+
29
+ Then /^我看见"([^\"]*)"$/ do |text|
30
+ macro %(我必须看见"#{text}")
31
+ end
32
+
33
+ Then /^文本必须以"([^\"]*)"开头$/ do |text|
34
+ if query("view {text BEGINSWITH '#{text}'}").empty?
35
+ screenshot_and_raise "No text found starting with: #{text}"
36
+ end
37
+ end
38
+
39
+ Then /^文本必须包含"([^\"]*)"$/ do |text|
40
+ if query("view {text LIKE '*#{text}*'}").empty?
41
+ screenshot_and_raise "No text found containing: #{text}"
42
+ end
43
+ end
44
+
45
+ Then /^文本必须以"([^\"]*)"结尾$/ do |text|
46
+ if query("view {text ENDSWITH '#{text}'}").empty?
47
+ screenshot_and_raise "No text found ending with: #{text}"
48
+ end
49
+ end
50
+
51
+ Then /^我看见(\d+)个输入框?$/ do |count|
52
+ cnt = query(:textField).count
53
+ if cnt < count.to_i
54
+ screenshot_and_raise "Expected at least #{count} text/input fields, found #{cnt}"
55
+ end
56
+ end
57
+
58
+ Then /^我看见一个"([^\"]*)"输入框$/ do |expected_mark|
59
+ unless element_exists("textField placeholder: '#{expected_mark}'") ||
60
+ element_exists("textField marked: '#{expected_mark}'")
61
+ screenshot_and_raise "Expected textfield with placeholder or accessibilityLabel: #{expected_mark}"
62
+ end
63
+ end
64
+
65
+ Then /^我看不到输入框"([^\"]*)"$/ do |expected_mark|
66
+ res = query("textField placeholder: '#{expected_mark}'")
67
+ res.concat query("textField marked: '#{expected_mark}'")
68
+ unless res.empty?
69
+ screenshot_and_raise "Expected no textfield with placeholder nor accessibilityLabel: #{expected_mark}, found #{res}"
70
+ end
71
+ end
72
+
73
+ Then /^我看见一张地图$/ do
74
+ check_element_exists("view: 'MKMapView'")
75
+ end
76
+
77
+ Then /^我看见当前用户地理位置$/ do
78
+ check_element_exists("view: 'MKUserLocationView'")
79
+ end
@@ -0,0 +1,39 @@
1
+
2
+ ### Date Picker ###
3
+
4
+ # time_str can be in any format that Time can parse
5
+ Then(/^我选择时间"([^"]*)"$/) do |time_str|
6
+ target_time = Time.parse(time_str)
7
+ current_date = date_time_from_picker
8
+ current_date = DateTime.new(current_date.year,
9
+ current_date.mon,
10
+ current_date.day,
11
+ target_time.hour,
12
+ target_time.min,
13
+ 0,
14
+ target_time.gmt_offset)
15
+ picker_set_date_time current_date
16
+ sleep(STEP_PAUSE)
17
+ end
18
+
19
+ # date_str can be in any format that Date can parse
20
+ Then(/^我选择日期"([^"]*)"$/) do |date_str|
21
+ target_date = Date.parse(date_str)
22
+ current_time = date_time_from_picker
23
+ date_time = DateTime.new(target_date.year,
24
+ target_date.mon,
25
+ target_date.day,
26
+ current_time.hour,
27
+ current_time.min,
28
+ 0,
29
+ Time.now.sec,
30
+ current_time.offset)
31
+ picker_set_date_time date_time
32
+ sleep(STEP_PAUSE)
33
+ end
34
+
35
+ # date_str can be in any format that Date can parse
36
+ Then(/^我选择日期"([^"]*)",时间"([^"]*)"$/) do |date_str, time_str|
37
+ macro %(我选择时间"#{time_str}")
38
+ macro %(我选择日期"#{date_str}")
39
+ end
@@ -0,0 +1,187 @@
1
+
2
+ ### Touch ###
3
+ Then /^我点击屏幕位置x:(\d+)y:(\d+)$/ do |x, y|
4
+ touch(nil, { offset: { x: x.to_i, y: y.to_i } })
5
+ sleep(STEP_PAUSE)
6
+ end
7
+
8
+ Then /^我点击"([^\"]*)"$/ do |name|
9
+ touch("view marked: '#{name}'")
10
+ sleep(STEP_PAUSE)
11
+ end
12
+
13
+ Then /^我点击第(\d+)个按钮$/ do |index|
14
+ index = index.to_i
15
+ screenshot_and_raise("Index should be positive (was: #{index})") if index <= 0
16
+ touch("button index: #{index - 1}")
17
+ sleep(STEP_PAUSE)
18
+ end
19
+
20
+ Then /^我点击"([^\"]*)"按钮/ do |name|
21
+ touch("button marked: '#{name}'")
22
+ sleep(STEP_PAUSE)
23
+ end
24
+
25
+ Then /^我点击第(\d+)个文本输入框$/ do |index|
26
+ index = index.to_i
27
+ screenshot_and_raise("Index should be positive (was: #{index})") if index <= 0
28
+ touch("textField index: #{index - 1}")
29
+ sleep(STEP_PAUSE)
30
+ end
31
+
32
+ Then /^我点击文本输入框"([^\"]*)"$/ do |name|
33
+ placeholder_query = "textField placeholder: '#{name}'"
34
+ marked_query = "textField marked: '#{name}'"
35
+ if !query(placeholder_query).empty?
36
+ touch(placeholder_query)
37
+ elsif !query(marked_query).empty?
38
+ touch(marked_query)
39
+ else
40
+ screenshot_and_raise "Could not find text field with placeholder '#{name}' or marked as '#{name}'"
41
+ end
42
+ sleep(STEP_PAUSE)
43
+ end
44
+
45
+ # Note in tables views: this means visible cell index!
46
+ Then /^我选择列表第(\d+)个$/ do |index|
47
+ index = index.to_i
48
+ screenshot_and_raise("Index should be positive (was: #{index})") if index <= 0
49
+ touch("tableViewCell index: #{index - 1}")
50
+ sleep(STEP_PAUSE)
51
+ end
52
+
53
+ Then /^我选择列表中的"([^\"]*)"$/ do |cell_name|
54
+ if query("tableViewCell marked: '#{cell_name}'").empty?
55
+ touch("tableViewCell text: '#{cell_name}'")
56
+ else
57
+ touch("tableViewCell marked: '#{cell_name}'")
58
+ end
59
+ sleep(STEP_PAUSE)
60
+ end
61
+
62
+ Then /^我切换设置开关$/ do
63
+ touch('switch')
64
+ sleep(STEP_PAUSE)
65
+ end
66
+
67
+ Then /^我打开"([^\"]*)"开关/ do |name|
68
+ touch("switch marked: '#{name}'")
69
+ sleep(STEP_PAUSE)
70
+ end
71
+
72
+ Then /^我点击用户当前地理位置$/ do
73
+ touch("view: 'MKUserLocationView'")
74
+ sleep(STEP_PAUSE)
75
+ end
76
+
77
+ Then /^我点击回车键$/ do
78
+ tap_keyboard_action_key
79
+ sleep(STEP_PAUSE)
80
+ end
81
+
82
+ ### Entering text ###
83
+ Then /^我输入"([^\"]*)"到输入框"([^\"]*)"$/ do |text_to_type, field_name|
84
+ touch("textField marked: '#{field_name}'")
85
+ wait_for_keyboard
86
+ keyboard_enter_text text_to_type
87
+ sleep(STEP_PAUSE)
88
+ end
89
+
90
+ Then /^我输入"([^\"]*)"到文本框"([^\"]*)"$/ do |text_to_type, field_name|
91
+ touch("textField marked: '#{field_name}'")
92
+ wait_for_keyboard
93
+ keyboard_enter_text text_to_type
94
+ sleep(STEP_PAUSE)
95
+ end
96
+
97
+ Then /^我输入"([^\"]*)"到第(\d+)个文本框$/ do |text, index|
98
+ index = index.to_i
99
+ screenshot_and_raise("Index should be positive (was: #{index})") if index <= 0
100
+ touch("textField index: #{index - 1}")
101
+ wait_for_keyboard
102
+ keyboard_enter_text text
103
+ sleep(STEP_PAUSE)
104
+ end
105
+
106
+ Then /^我清空第(\d+)个输入框$/ do |index|
107
+ index = index.to_i
108
+ screenshot_and_raise("Index should be positive (was: #{index})") if index <= 0
109
+ clear_text("textField index: #{index - 1}")
110
+ end
111
+
112
+ Then /^我返回到上级页面$/ do
113
+ touch('navigationItemButtonView first')
114
+ sleep(STEP_PAUSE)
115
+ end
116
+
117
+ Then /^抓取当前屏幕$/ do
118
+ sleep(STEP_PAUSE)
119
+ screenshot_embed
120
+ end
121
+
122
+ Then /^我向(左|右|上|下)滑动$/ do |dir|
123
+ swipe(dir)
124
+ sleep(STEP_PAUSE)
125
+ end
126
+
127
+ Then /^我在第(\d+)个可滑动页面上向(左|右|上|下)滑动$/ do |index,dir|
128
+ index = index.to_i
129
+ screenshot_and_raise("Index should be positive (was: #{index})") if index <= 0
130
+ swipe(dir, { query: "scrollView index: #{index - 1}" })
131
+ sleep(STEP_PAUSE)
132
+ end
133
+
134
+ Then /^我在第(\d+)个可滑动页面上的位置x:(\d+)y:(\d+)向(左|右|上|下)滑动$/ do |index, x, y,dir|
135
+ index = index.to_i
136
+ screenshot_and_raise("Index should be positive (was: #{index})") if index <= 0
137
+ swipe(dir, { offset: { x: x.to_i, y: y.to_i }, query: "scrollView index: #{index - 1}" })
138
+ sleep(STEP_PAUSE)
139
+ end
140
+
141
+ Then /^我在页面"([^\"]*)"上向(左|右|上|下)滑动$/ do |mark,dir|
142
+ swipe(dir, { query: "view marked: '#{mark}'" })
143
+ sleep(STEP_PAUSE)
144
+ end
145
+
146
+ Then /^我在列表的第(\d+)个元素上滑动$/ do |index|
147
+ index = index.to_i
148
+ screenshot_and_raise("Index should be positive (was: #{index})") if index <= 0
149
+ cell_swipe({ query: "tableViewCell index: #{index - 1}" })
150
+ sleep(STEP_PAUSE)
151
+ end
152
+
153
+ ### Pinch ###
154
+ Then /^我(放大|缩小)屏幕$/ do |in_out|
155
+ pinch(in_out)
156
+ sleep(STEP_PAUSE)
157
+ end
158
+
159
+ Then /^我在页面"([^\"]*)"上(放大|缩小)$/ do |name,in_out|
160
+ pinch(in_out, { query: "view marked: '#{name}'" })
161
+ sleep(STEP_PAUSE)
162
+ end
163
+
164
+ # Note "up/left/right" seems to be missing on the web base
165
+ Then /^向(左|右|上|下)滚动$/ do |dir|
166
+ scroll('scrollView index: 0', dir)
167
+ sleep(STEP_PAUSE)
168
+ end
169
+
170
+ Then /^在页面"([^\"]*)"上向(左|右|上|下)滚动$/ do | name,dir|
171
+ scroll("view marked: '#{name}'", dir)
172
+ sleep(STEP_PAUSE)
173
+ end
174
+
175
+
176
+ ### Device orientation ###
177
+ Then /^我向(左|右)转动设备$/ do |dir|
178
+ rotate(dir.to_sym)
179
+ sleep 5 # Servo wait
180
+ end
181
+
182
+ Then /^将App推到后台并等待(\d+)秒$/ do |secs|
183
+ secs = secs.to_f
184
+ send_app_to_background(secs)
185
+ sleep(secs + 10)
186
+ end
187
+
@@ -0,0 +1,48 @@
1
+
2
+ ### See ###
3
+ Then /^我等待直到看见"([^\"]*)"$/ do |expected_mark|
4
+ wait_for(WAIT_TIMEOUT) { view_with_mark_exists(expected_mark) }
5
+ end
6
+
7
+ Then /^我等待直到看不见"([^\"]*)"$/ do |expected_mark|
8
+ sleep 1 # wait for previous screen to disappear
9
+ wait_for(WAIT_TIMEOUT) { !element_exists("view marked: '#{expected_mark}'") }
10
+ end
11
+
12
+ Then /^我等待看不见"([^\"]*)"$/ do |expected_mark|
13
+ macro %(我等待直到看不见"#{expected_mark}")
14
+ end
15
+
16
+ Then /^我等待"([^\"]*)"出现$/ do |name|
17
+ macro %(我等待直到看见"#{name}")
18
+ end
19
+
20
+ Then /^我等待"([^\"]*)"按钮出现$/ do |name|
21
+ wait_for(WAIT_TIMEOUT) { element_exists("button marked: '#{name}'") }
22
+ end
23
+
24
+ Then /^我等待看到浏览导航栏"([^\"]*)"$/ do |expected_mark|
25
+ msg = "Waited for '#{WAIT_TIMEOUT}' seconds but did not see the navbar with title '#{expected_mark}'"
26
+ wait_for(timeout: WAIT_TIMEOUT, timeout_message: msg ) do
27
+ all_items = query("navigationItemView marked: '#{expected_mark}'")
28
+ button_items = query('navigationItemButtonView')
29
+ non_button_items = all_items.delete_if { |item| button_items.include?(item) }
30
+ !non_button_items.empty?
31
+ end
32
+ end
33
+
34
+ Then /^我等待"([^\"]*)" (?:输入框|文本框)$/ do |placeholder_or_view_mark|
35
+ wait_for(WAIT_TIMEOUT) do
36
+ element_exists("textField placeholder: '#{placeholder_or_view_mark}'") ||
37
+ element_exists("textField marked: '#{placeholder_or_view_mark}'")
38
+ end
39
+ end
40
+
41
+ Then /^我等待(\d+) (?:输入框|文本框)(?:s)?$/ do |count|
42
+ wait_for(WAIT_TIMEOUT) { query(:textField).count >= count.to_i }
43
+ end
44
+
45
+ When /^我等待([\d\.]+)秒(?:s)?$/ do |num_seconds|
46
+ sleep num_seconds.to_f
47
+ end
48
+