frank-cucumber 0.5.1

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.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in frank-cucumber.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fileutils'
4
+
5
+ features_dir = File.join( FileUtils.pwd, "features" )
6
+
7
+ if File.exists?( features_dir )
8
+ puts "A features directory already exists. I won't overwrite it. Giving up."
9
+ exit 1
10
+ else
11
+ puts "I'm about to create a subdirectory called features which will contain all your Cucumber tests. Please hit return to confirm that's what you want."
12
+ exit 2 unless STDIN.gets.chomp == ''
13
+ end
14
+
15
+ source_dir = File.join( File.dirname(__FILE__), '..', 'features-skeleton' )
16
+
17
+ FileUtils.cp_r( source_dir, features_dir )
18
+
19
+ puts "features subdirectory created. Try executing 'cucumber' from the current directory to see how you new cucumber setup runs."
@@ -0,0 +1,5 @@
1
+ Feature: test frank-cuke integration
2
+
3
+ Scenario: a passing test
4
+ Given I simulate a memory warning
5
+ Then I see colors!
@@ -0,0 +1,19 @@
1
+ Given /^I wait (\d+) seconds$/ do |seconds|
2
+ seconds = seconds.to_i
3
+ sleep seconds
4
+ end
5
+
6
+ Then /^the test fails$/ do
7
+ (2+2).should == 5
8
+ end
9
+
10
+ Then /^the test passes!$/ do
11
+ (2+2).should == 4
12
+ end
13
+
14
+
15
+ Then /^I see colors!$/ do
16
+ announce red "RED"
17
+ announce blue "BLUE"
18
+ announce green "GREEEN!"
19
+ end
@@ -0,0 +1 @@
1
+ require 'frank-cucumber'
@@ -0,0 +1,12 @@
1
+ Feature:
2
+ As an iOS developer
3
+ I want to have a sample feature file
4
+ So I can see what my next step is in the wonderful world of Frank/Cucumber testing
5
+
6
+ Scenario:
7
+ Rotating the simulator for demonstration purposes
8
+ Given I launch the app
9
+ Given the device is in landscape orientation
10
+ Given the device is in portrait orientation
11
+ Given the device is in landscape orientation
12
+ Given the device is in portrait orientation
@@ -0,0 +1 @@
1
+ require 'frank-cucumber'
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "frank-cucumber/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "frank-cucumber"
7
+ s.version = Frank::Cucumber::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Pete Hodgson","Derek Longmuir"]
10
+ s.email = ["gems@thepete.net"]
11
+ s.homepage = "http://rubygems.org/gems/frank-cucumber"
12
+ s.summary = %q{Use cucumber to test native iOS apps via Frank}
13
+ s.description = %q{Use cucumber to test native iOS apps via Frank}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_dependency( "cucumber" )
21
+ s.add_dependency( "rspec", [">=2.0"] )
22
+ s.add_dependency( "json" ) # TODO: figure out how to be more permissive as to which JSON gems we allow
23
+ end
@@ -0,0 +1,9 @@
1
+ require 'frank-cucumber/color_helper'
2
+ require 'frank-cucumber/frank_helper'
3
+
4
+ World(Frank::Cucumber::ColorHelper)
5
+ World(Frank::Cucumber::FrankHelper)
6
+
7
+ AfterConfiguration do
8
+ require 'frank-cucumber/core_frank_steps'
9
+ end
@@ -0,0 +1,13 @@
1
+ module Frank module Cucumber
2
+
3
+ module ColorHelper
4
+ def colorize(text, color_code)
5
+ "\e[#{color_code}m#{text}\e[0m"
6
+ end
7
+
8
+ def red(text); colorize(text, 31); end
9
+ def green(text); colorize(text, 32); end
10
+ def blue(text); colorize(text, 34); end
11
+ end
12
+
13
+ end end
@@ -0,0 +1,300 @@
1
+ WAIT_TIMEOUT = 240
2
+
3
+ require 'rspec/expectations'
4
+
5
+ # -- See -- #
6
+ Then /^I wait to see "([^\"]*)"$/ do |expected_mark|
7
+ Timeout::timeout(WAIT_TIMEOUT) do
8
+ until view_with_mark_exists( expected_mark )
9
+ sleep 0.1
10
+ end
11
+ end
12
+ end
13
+
14
+ Then /^I wait to not see "([^\"]*)"$/ do |expected_mark|
15
+ sleep 3
16
+ Timeout::timeout(WAIT_TIMEOUT) do
17
+ while element_exists( "view marked:'#{expected_mark}'" )
18
+ sleep 0.1
19
+ end
20
+ end
21
+ end
22
+
23
+ Then /^I wait to see a navigation bar titled "([^\"]*)"$/ do |expected_mark|
24
+ Timeout::timeout(30) do
25
+ values = frankly_map( 'navigationItemView', 'accessibilityLabel' )
26
+ until values.include(expected_mark)
27
+ values = frankly_map( 'navigationItemView', 'accessibilityLabel' )
28
+ sleep 0.1
29
+ end
30
+ end
31
+ end
32
+
33
+ Then /^I wait to not see a navigation bar titled "([^\"]*)"$/ do |expected_mark|
34
+ Timeout::timeout(30) do
35
+ values = frankly_map( 'navigationItemView', 'accessibilityLabel' )
36
+ while values.include(expected_mark)
37
+ values = frankly_map( 'navigationItemView', 'accessibilityLabel' )
38
+ sleep 0.1
39
+ end
40
+ end
41
+ end
42
+
43
+ Then /^I should see a "([^\"]*)" button$/ do |expected_mark|
44
+ check_element_exists("button marked:'#{expected_mark}'")
45
+ end
46
+
47
+ Then /^I should see "([^\"]*)"$/ do |expected_mark|
48
+ check_element_exists("view marked:'#{expected_mark}'")
49
+ end
50
+
51
+ Then /^I should not see "([^\"]*)"$/ do |expected_mark|
52
+ check_element_does_not_exist("view marked:'#{expected_mark}'")
53
+ end
54
+
55
+ Then /I should see the following:/ do |table|
56
+ values = frankly_map( 'view', 'accessibilityLabel' )
57
+ table.raw.each do |expected_mark|
58
+ values.should include( expected_mark.first )
59
+ end
60
+ end
61
+
62
+ Then /I should not see the following:/ do |table|
63
+ values = frankly_map( 'view', 'accessibilityLabel' )
64
+ table.raw.each do |expected_mark|
65
+ values.should_not include( expected_mark.first )
66
+ end
67
+ end
68
+
69
+ Then /^I should see a navigation bar titled "([^\"]*)"$/ do |expected_mark|
70
+ values = frankly_map( 'navigationItemView', 'accessibilityLabel' )
71
+ values.should include(expected_mark)
72
+ end
73
+
74
+ Then /^I should see an alert view titled "([^\"]*)"$/ do |expected_mark|
75
+ values = frankly_map( 'alertView', 'message')
76
+ puts values
77
+ values.should include(expected_mark)
78
+ end
79
+
80
+ Then /^I should not see an alert view$/ do
81
+ check_element_does_not_exist( 'alertView' )
82
+ end
83
+
84
+ Then /^I should see an element of class "([^\"]*)" with name "([^\"]*)" with the following labels: "([^\"]*)"$/ do |className, classLabel, listOfLabels|
85
+ arrayOfLabels = listOfLabels.split(',');
86
+ arrayOfLabels.each do |label|
87
+ check_element_exists("view marked:'#{classLabel}' parent view:'#{className}' descendant view marked:'#{label}'")
88
+ end
89
+ end
90
+
91
+ Then /^I should see an element of class "([^\"]*)" with name "([^\"]*)" with a "([^\"]*)" button$/ do |className, classLabel, buttonName|
92
+ check_element_exists("view marked:'#{classLabel}' parent view:'#{className}' descendant button marked:'#{buttonName}'")
93
+ end
94
+
95
+ Then /^I should not see a hidden button marked "([^\"]*)"$/ do |expected_mark|
96
+ element_is_not_hidden("button marked:'#{expected_mark}'").should be_false
97
+ end
98
+
99
+ Then /^I should see a nonhidden button marked "([^\"]*)"$/ do |expected_mark|
100
+ element_is_not_hidden("button marked:'#{expected_mark}'").should be_true
101
+ end
102
+
103
+ Then /^I should see an element of class "([^\"]*)"$/ do |className|
104
+ element_is_not_hidden("view:'#{className}'")
105
+ end
106
+
107
+ Then /^I should not see an element of class "([^\"]*)"$/ do |className|
108
+ selector = "view:'#{className}'"
109
+ element_exists_and_is_not_hidden = element_exists( selector ) && element_is_not_hidden(selector)
110
+ element_exists_and_is_not_hidden.should be_false
111
+ end
112
+
113
+
114
+ # -- Type/Fill in -- #
115
+
116
+ When /^I type "([^\"]*)" into the "([^\"]*)" text field$/ do |text_to_type, field_name|
117
+ text_fields_modified = frankly_map( "textField placeholder:'#{field_name}'", "setText:", text_to_type )
118
+ raise "could not find text fields with placeholder '#{field_name}'" if text_fields_modified.empty?
119
+ #TODO raise warning if text_fields_modified.count > 1
120
+ end
121
+
122
+ # alias
123
+ When /^I fill in "([^\"]*)" with "([^\"]*)"$/ do |text_field, text_to_type|
124
+ When %Q|I type "#{text_to_type}" into the "#{text_field}" text field|
125
+ end
126
+
127
+ When /^I fill in text fields as follows:$/ do |table|
128
+ table.hashes.each do |row|
129
+ When %Q|I type "#{row['text']}" into the "#{row['field']}" text field|
130
+ end
131
+ end
132
+
133
+ # -- Rotate -- #
134
+ Given /^the device is in (a )?landscape orientation$/ do |ignored|
135
+ # for some reason the simulator sometimes starts of reporting its orientation as 'flat'. Workaround for this is to rotate the device then wait a bit
136
+ if 'flat' == frankly_current_orientation
137
+ rotate_simulator_right
138
+ sleep 1
139
+ end
140
+
141
+ unless frankly_oriented_landscape?
142
+ rotate_simulator_left
143
+ sleep 1
144
+ raise "expected orientation to be landscape after rotating left, but it is #{frankly_current_orientation}" unless frankly_oriented_landscape?
145
+ end
146
+ end
147
+
148
+ Given /^the device is in (a )?portrait orientation$/ do |ignored|
149
+ # for some reason the simulator sometimes starts of reporting its orientation as 'flat'. Workaround for this is to rotate the device then wait a bit
150
+ if 'flat' == frankly_current_orientation
151
+ rotate_simulator_right
152
+ sleep 1
153
+ end
154
+
155
+ unless frankly_oriented_portrait?
156
+ rotate_simulator_left
157
+ sleep 1
158
+ raise "Expected orientation to be portrait after rotating left, but it is #{frankly_current_orientation}" unless frankly_oriented_portrait?
159
+ end
160
+ end
161
+
162
+ When /^I simulate a memory warning$/ do
163
+ simulate_memory_warning
164
+ end
165
+
166
+ Then /^I rotate to the "([^\"]*)"$/ do |direction|
167
+ if direction == "right"
168
+ rotate_simulator_right
169
+ elsif direction == "left"
170
+ rotate_simulator_left
171
+ else
172
+ raise %Q|Rotation direction specified ("#{direction}") is invalid. Please specify right or left.|
173
+ end
174
+ sleep 1
175
+ end
176
+
177
+ # -- touch -- #
178
+ When /^I touch "([^\"]*)"$/ do |mark|
179
+ selector = "view marked:'#{mark}' first"
180
+ if element_exists(selector)
181
+ touch( selector )
182
+ else
183
+ raise "Could not touch [#{mark}], it does not exist."
184
+ end
185
+ sleep 1
186
+ end
187
+
188
+ When /^I touch "([^\"]*)" if exists$/ do |mark|
189
+ sleep 1
190
+ selector = "view marked:'#{mark}' first"
191
+ if element_exists(selector)
192
+ touch(selector)
193
+ sleep 1
194
+ end
195
+ end
196
+
197
+ When /^I touch the first table cell$/ do
198
+ touch("tableViewCell first")
199
+ end
200
+
201
+ When /^I touch the table cell marked "([^\"]*)"$/ do |mark|
202
+ touch("tableViewCell marked:'#{mark}'")
203
+ end
204
+
205
+ When /^I touch the (\d*)(?:st|nd|rd|th)? table cell$/ do |ordinal|
206
+ ordinal = ordinal.to_i - 1
207
+ touch("tableViewCell index:#{ordinal}")
208
+ end
209
+
210
+ Then /I touch the following:/ do |table|
211
+ values = frankly_map( 'view', 'accessibilityLabel' )
212
+ table.raw.each do |expected_mark|
213
+ touch( "view marked:'#{expected_mark}'" )
214
+ sleep 2
215
+ end
216
+ end
217
+
218
+ When /^I touch the button marked "([^\"]*)"$/ do |mark|
219
+ touch( "button marked:'#{mark}'" )
220
+ end
221
+
222
+ When /^I touch the "([^\"]*)" action sheet button$/ do |mark|
223
+ touch( "actionSheet threePartButton marked:'#{mark}'" )
224
+ end
225
+
226
+ When /^I touch the (\d*)(?:st|nd|rd|th)? action sheet button$/ do |ordinal|
227
+ ordinal = ordinal.to_i
228
+ touch( "actionSheet threePartButton tag:#{ordinal}" )
229
+ end
230
+
231
+ When /^I touch the (\d*)(?:st|nd|rd|th)? alert view button$/ do |ordinal|
232
+ ordinal = ordinal.to_i
233
+ touch( "alertView threePartButton tag:#{ordinal}" )
234
+ end
235
+
236
+ # -- switch -- #
237
+
238
+ When /^I flip switch "([^\"]*)" on$/ do |mark|
239
+ selector = "view:'UISwitch' marked:'#{mark}'"
240
+ views_switched = frankly_map( selector, 'setOn:animated:', true, true )
241
+ raise "could not find anything matching [#{uiquery}] to switch" if views_switched.empty?
242
+ end
243
+
244
+ When /^I flip switch "([^\"]*)" off$/ do |mark|
245
+ selector = "view:'UISwitch' marked:'#{mark}'"
246
+ views_switched = frankly_map( selector, 'setOn:animated:', false, true )
247
+ raise "could not find anything matching [#{uiquery}] to switch" if views_switched.empty?
248
+ end
249
+
250
+ When /^I flip switch "([^\"]*)"$/ do |mark|
251
+ touch("view:'UISwitch' marked:'#{mark}'")
252
+ end
253
+
254
+ Then /^switch "([^\"]*)" should be on$/ do |mark|
255
+ # switch_states = frankly_map( "view:'Switch' marked:'#{mark}'", "isOn" )
256
+ switch_states = frankly_map( "view accesibilityLabel:'#{mark}'", "isOn" )
257
+ puts "test #{switch_states.inspect}"
258
+
259
+ if switch_states == 0
260
+ puts "Switch #{mark} is ON"
261
+ else
262
+ puts "Switch #{mark} is OFF, flim switch ON"
263
+ Then %Q|I flip switch "#{mark}"|
264
+ end
265
+ end
266
+
267
+ Then /^switch "([^\"]*)" should be off$/ do |mark|
268
+ switch_states = frankly_map( "view:'UISwitch' marked:'#{mark}'", "isOn" )
269
+ puts "test #{switch_states.inspect}"
270
+
271
+ if switch_states == 0
272
+ puts "Switch #{mark} is ON, flip switch OFF"
273
+ Then %Q|I flip switch "#{mark}"|
274
+ else
275
+ puts "Switch #{mark} is OFF"
276
+ end
277
+ end
278
+
279
+
280
+ # -- misc -- #
281
+
282
+ When /^I wait for ([\d\.]+) second(?:s)?$/ do |num_seconds|
283
+ num_seconds = num_seconds.to_f
284
+ sleep num_seconds
285
+ end
286
+
287
+ Then /^a pop\-over menu is displayed with the following:$/ do |table|
288
+ sleep 1
289
+ table.raw.each do |expected_mark|
290
+ check_element_exists "actionSheet view marked:'#{expected_mark}'"
291
+ end
292
+ end
293
+
294
+ Then /^I navigate back$/ do
295
+ touch( "navigationItemButtonView" )
296
+ end
297
+
298
+ When /^I dump the DOM$/ do
299
+ dom = frankly_dump
300
+ end
@@ -0,0 +1,234 @@
1
+ require 'net/http'
2
+ require 'json'
3
+
4
+ module Frank module Cucumber
5
+
6
+ module FrankHelper
7
+
8
+ def touch( uiquery )
9
+ views_touched = frankly_map( uiquery, 'touch' )
10
+ raise "could not find anything matching [#{uiquery}] to touch" if views_touched.empty?
11
+ #TODO raise warning if views_touched.count > 1
12
+ end
13
+
14
+ def element_exists( query )
15
+ matches = frankly_map( query, 'accessibilityLabel' )
16
+ # TODO: raise warning if matches.count > 1
17
+ !matches.empty?
18
+ end
19
+
20
+ def check_element_exists( query )
21
+ #puts "checking #{query} exists..."
22
+ element_exists( query ).should be_true
23
+ end
24
+
25
+ def check_element_does_not_exist( query )
26
+ #puts "checking #{query} does not exist..."
27
+ element_exists( query ).should be_false
28
+ end
29
+
30
+ def view_with_mark_exists(expected_mark)
31
+ element_exists( "view marked:'#{expected_mark}'" )
32
+ end
33
+
34
+ def check_view_with_mark_exists(expected_mark)
35
+ check_element_exists( "view marked:'#{expected_mark}'" )
36
+ end
37
+
38
+ # a better name would be element_exists_and_is_not_hidden
39
+ def element_is_not_hidden(query)
40
+ matches = frankly_map( query, 'isHidden' )
41
+ matches.delete(true)
42
+ !matches.empty?
43
+ end
44
+
45
+ def app_exec(method_name, *method_args)
46
+ operation_map = {
47
+ :method_name => method_name,
48
+ :arguments => method_args
49
+ }
50
+
51
+ before = Time.now
52
+ res = post_to_uispec_server( 'app_exec', :operation => operation_map )
53
+ logger.debug( "MAP applying #{method_name} with args:( #{method_args.inspect} ) to 'Application Delegate' took #{Time.now - before} seconds" )
54
+
55
+ res = JSON.parse( res )
56
+ if res['outcome'] != 'SUCCESS'
57
+ raise "app_exec #{method_name} failed because: #{res['reason']}\n#{res['details']}"
58
+ end
59
+
60
+ res['results']
61
+ end
62
+
63
+
64
+ def frankly_map( query, method_name, *method_args )
65
+ operation_map = {
66
+ :method_name => method_name,
67
+ :arguments => method_args
68
+ }
69
+ res = post_to_uispec_server( 'map', :query => query, :operation => operation_map )
70
+ res = JSON.parse( res )
71
+ if res['outcome'] != 'SUCCESS'
72
+ raise "frankly_map #{query} #{method_name} failed because: #{res['reason']}\n#{res['details']}"
73
+ end
74
+
75
+ res['results']
76
+ end
77
+
78
+ def frankly_dump
79
+ res = get_to_uispec_server( 'dump' )
80
+ puts JSON.pretty_generate(JSON.parse(res)) rescue puts res #dumping a super-deep DOM causes errors
81
+ end
82
+
83
+ def frankly_oriented_portrait?
84
+ 'portrait' == frankly_current_orientation
85
+ end
86
+
87
+ def frankly_oriented_landscape?
88
+ 'landscape' == frankly_current_orientation
89
+ end
90
+
91
+ def frankly_current_orientation
92
+ res = get_to_uispec_server( 'orientation' )
93
+ JSON.parse( res )['orientation']
94
+ end
95
+
96
+ def wait_for_frank_to_come_up
97
+ num_consec_successes = 0
98
+ num_consec_failures = 0
99
+ Timeout.timeout(60) do
100
+ while num_consec_successes <= 6
101
+ if frankly_ping
102
+ num_consec_failures = 0
103
+ num_consec_successes += 1
104
+ print (num_consec_successes == 1 ) ? "\n" : "\r"
105
+ print "FRANK!".slice(0,num_consec_successes)
106
+ else
107
+ num_consec_successes = 0
108
+ num_consec_failures += 1
109
+ print (num_consec_failures == 1 ) ? "\n" : "\r"
110
+ print "PING FAILED" + "!"*num_consec_failures
111
+ end
112
+ STDOUT.flush
113
+ sleep 0.2
114
+ end
115
+ puts ''
116
+ end
117
+ end
118
+
119
+ def frankly_ping
120
+ get_to_uispec_server('')
121
+ return true
122
+ rescue Errno::ECONNREFUSED
123
+ return false
124
+ rescue EOFError
125
+ return false
126
+ end
127
+
128
+ #taken from Ian Dee's Encumber
129
+ def post_to_uispec_server( verb, command_hash )
130
+ url = frank_url_for( verb )
131
+ req = Net::HTTP::Post.new url.path
132
+ req.body = command_hash.to_json
133
+
134
+ make_http_request( url, req )
135
+ end
136
+
137
+ def get_to_uispec_server( verb )
138
+ url = frank_url_for( verb )
139
+ req = Net::HTTP::Get.new url.path
140
+ make_http_request( url, req )
141
+ end
142
+
143
+ def frank_url_for( verb )
144
+ url = URI.parse "http://localhost:37265/"
145
+ url.path = '/'+verb
146
+ url
147
+ end
148
+
149
+ def make_http_request( url, req )
150
+ http = Net::HTTP.new(url.host, url.port)
151
+
152
+ res = http.start do |sess|
153
+ sess.request req
154
+ end
155
+
156
+ res.body
157
+ end
158
+
159
+ def start_recording
160
+ %x{osascript<<APPLESCRIPT
161
+ tell application "QuickTime Player"
162
+ set sr to new screen recording
163
+ tell sr to start
164
+ end tell
165
+ APPLESCRIPT}
166
+
167
+ end
168
+
169
+ def stop_recording
170
+ %x{osascript<<APPLESCRIPT
171
+ tell application "QuickTime Player"
172
+ set sr to (document 1)
173
+ tell sr to stop
174
+ end tell
175
+ APPLESCRIPT}
176
+ end
177
+
178
+ def launch_app_in_simulator
179
+ %x{osascript<<APPLESCRIPT
180
+ application "iPhone Simulator" quit
181
+ tell application "Xcode"
182
+ set myprojectdocument to active project document
183
+ set myproject to project of myprojectdocument
184
+ tell myproject
185
+ launch
186
+ end tell
187
+ end tell
188
+ application "iPhone Simulator" activate
189
+ APPLESCRIPT}
190
+ sleep 5 # TODO: replace this with polling for the frank server
191
+ end
192
+
193
+ #Note this needs to have "Enable access for assistive devices"
194
+ #chcked in the Universal Access system preferences
195
+ def simulator_hardware_menu_press( menu_label )
196
+ %x{osascript<<APPLESCRIPT
197
+ activate application "iPhone Simulator"
198
+ tell application "System Events"
199
+ click menu item "#{menu_label}" of menu "Hardware" of menu bar of process "iPhone Simulator"
200
+ end tell
201
+ APPLESCRIPT}
202
+ end
203
+
204
+ def press_home_on_simulator
205
+ simulator_hardware_menu_press "Home"
206
+ end
207
+
208
+ def rotate_simulator_left
209
+ simulator_hardware_menu_press "Rotate Left"
210
+ end
211
+
212
+ def rotate_simulator_right
213
+ simulator_hardware_menu_press "Rotate Right"
214
+ end
215
+
216
+ def shake_simulator
217
+ simulator_hardware_menu_press "Shake Gesture"
218
+ end
219
+
220
+ def simulate_memory_warning
221
+ simulator_hardware_menu_press "Simulate Memory Warning"
222
+ end
223
+
224
+ def toggle_call_status_bar
225
+ simulator_hardware_menu_press "Toggle In-Call Status Bar"
226
+ end
227
+
228
+ def simulate_hardware_keyboard
229
+ simulator_hardware_menu_press "Simulate Hardware Keyboard"
230
+ end
231
+ end
232
+
233
+
234
+ end end
@@ -0,0 +1,5 @@
1
+ module Frank
2
+ module Cucumber
3
+ VERSION = "0.5.1"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: frank-cucumber
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 5
8
+ - 1
9
+ version: 0.5.1
10
+ platform: ruby
11
+ authors:
12
+ - Pete Hodgson
13
+ - Derek Longmuir
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-15 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: cucumber
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 2
42
+ - 0
43
+ version: "2.0"
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: json
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ type: :runtime
57
+ version_requirements: *id003
58
+ description: Use cucumber to test native iOS apps via Frank
59
+ email:
60
+ - gems@thepete.net
61
+ executables:
62
+ - frank-skeleton
63
+ extensions: []
64
+
65
+ extra_rdoc_files: []
66
+
67
+ files:
68
+ - .gitignore
69
+ - Gemfile
70
+ - Rakefile
71
+ - bin/frank-skeleton
72
+ - example/features/example.feature
73
+ - example/features/step_definitions/example_steps.rb
74
+ - example/features/support/env.rb
75
+ - features-skeleton/my_first.feature
76
+ - features-skeleton/support/env.rb
77
+ - frank-cucumber.gemspec
78
+ - lib/frank-cucumber.rb
79
+ - lib/frank-cucumber/color_helper.rb
80
+ - lib/frank-cucumber/core_frank_steps.rb
81
+ - lib/frank-cucumber/frank_helper.rb
82
+ - lib/frank-cucumber/version.rb
83
+ has_rdoc: true
84
+ homepage: http://rubygems.org/gems/frank-cucumber
85
+ licenses: []
86
+
87
+ post_install_message:
88
+ rdoc_options: []
89
+
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ requirements: []
107
+
108
+ rubyforge_project:
109
+ rubygems_version: 1.3.6
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: Use cucumber to test native iOS apps via Frank
113
+ test_files: []
114
+