frank-cucumber 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
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
+