iCuke 0.4.12 → 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.
Files changed (114) hide show
  1. data/Rakefile +3 -3
  2. data/VERSION +1 -1
  3. data/app/AlertsViewController.h +59 -0
  4. data/app/AlertsViewController.m +341 -0
  5. data/app/AppDelegate.h +60 -0
  6. data/app/AppDelegate.m +101 -0
  7. data/app/ButtonsViewController.h +80 -0
  8. data/app/ButtonsViewController.m +448 -0
  9. data/app/Constants.h +58 -0
  10. data/app/ControlsViewController.h +72 -0
  11. data/app/ControlsViewController.m +379 -0
  12. data/app/ImagesViewController.h +62 -0
  13. data/app/ImagesViewController.m +137 -0
  14. data/app/{iCuke/iCuke-Info.plist → Info.plist} +4 -4
  15. data/app/MainViewController.h +57 -0
  16. data/app/MainViewController.m +262 -0
  17. data/app/Picker/CustomPickerDataSource.h +55 -0
  18. data/app/Picker/CustomPickerDataSource.m +135 -0
  19. data/app/Picker/CustomView.h +62 -0
  20. data/app/Picker/CustomView.m +119 -0
  21. data/app/PickerViewController.h +88 -0
  22. data/app/PickerViewController.m +402 -0
  23. data/app/Prefix.pch +5 -0
  24. data/app/ReadMe.txt +82 -0
  25. data/app/SearchBarController.h +58 -0
  26. data/app/SearchBarController.m +105 -0
  27. data/app/SegmentViewController.h +54 -0
  28. data/app/SegmentViewController.m +195 -0
  29. data/app/TextFieldController.h +67 -0
  30. data/app/TextFieldController.m +342 -0
  31. data/app/TextViewController.h +57 -0
  32. data/app/TextViewController.m +164 -0
  33. data/app/ToolbarViewController.h +74 -0
  34. data/app/ToolbarViewController.m +303 -0
  35. data/app/TransitionViewController.h +64 -0
  36. data/app/TransitionViewController.m +178 -0
  37. data/app/UICatalog.xcodeproj/project.pbxproj +615 -0
  38. data/app/WebViewController.h +57 -0
  39. data/app/WebViewController.m +173 -0
  40. data/app/en.lproj/AlertsViewController.xib +144 -0
  41. data/app/en.lproj/ButtonsViewController.xib +147 -0
  42. data/app/en.lproj/ControlsViewController.xib +147 -0
  43. data/app/en.lproj/ImagesViewController.xib +264 -0
  44. data/app/en.lproj/Localizable.strings +41 -0
  45. data/app/en.lproj/MainWindow.xib +306 -0
  46. data/app/en.lproj/PickerViewController.xib +415 -0
  47. data/app/en.lproj/SearchBarController.xib +142 -0
  48. data/app/en.lproj/SegmentViewController.xib +143 -0
  49. data/app/en.lproj/TextFieldController.xib +167 -0
  50. data/app/en.lproj/TextViewController.xib +149 -0
  51. data/app/en.lproj/ToolbarViewController.xib +491 -0
  52. data/app/en.lproj/TransitionViewController.xib +255 -0
  53. data/app/en.lproj/WebViewController.xib +141 -0
  54. data/app/images/12-6AM.png +0 -0
  55. data/app/images/12-6PM.png +0 -0
  56. data/app/images/6-12AM.png +0 -0
  57. data/app/images/6-12PM.png +0 -0
  58. data/app/images/Default.png +0 -0
  59. data/app/images/Icon.png +0 -0
  60. data/app/images/UIButton_custom.png +0 -0
  61. data/app/images/blueButton.png +0 -0
  62. data/app/images/orangeslide.png +0 -0
  63. data/app/images/scene1.jpg +0 -0
  64. data/app/images/scene2.jpg +0 -0
  65. data/app/images/scene3.jpg +0 -0
  66. data/app/images/scene4.jpg +0 -0
  67. data/app/images/scene5.jpg +0 -0
  68. data/app/images/segment_check.png +0 -0
  69. data/app/images/segment_search.png +0 -0
  70. data/app/images/segment_tools.png +0 -0
  71. data/app/images/slider_ball.png +0 -0
  72. data/app/images/whiteButton.png +0 -0
  73. data/app/images/yellowslide.png +0 -0
  74. data/app/main.m +58 -0
  75. data/ext/iCuke/DefaultsResponse.m +0 -1
  76. data/ext/iCuke/EventResponse.m +9 -1
  77. data/ext/iCuke/Rakefile +1 -1
  78. data/ext/iCuke/Recorder.h +3 -1
  79. data/ext/iCuke/Recorder.m +10 -5
  80. data/ext/iCuke/RecorderResponse.h +1 -0
  81. data/ext/iCuke/RecorderResponse.m +10 -1
  82. data/ext/iCuke/Viewer.m +5 -6
  83. data/ext/iCuke/iCukeHTTPServer.m +1 -1
  84. data/ext/iCuke/iCukeServer.m +24 -7
  85. data/ext/iCuke/libicuke.dylib +0 -0
  86. data/features/uicatalog.feature +20 -0
  87. data/iCuke.gemspec +81 -24
  88. data/lib/icuke/com.apple.Accessibility.plist +0 -0
  89. data/lib/icuke/core_ext.rb +26 -0
  90. data/lib/icuke/cucumber.rb +20 -12
  91. data/lib/icuke/headless.rb +55 -0
  92. data/lib/icuke/simulator.rb +7 -129
  93. data/lib/icuke/xcode.rb +136 -0
  94. metadata +82 -25
  95. data/app/iCuke/Classes/FlipsideView.h +0 -13
  96. data/app/iCuke/Classes/FlipsideView.m +0 -32
  97. data/app/iCuke/Classes/FlipsideViewController.h +0 -25
  98. data/app/iCuke/Classes/FlipsideViewController.m +0 -54
  99. data/app/iCuke/Classes/MainView.h +0 -15
  100. data/app/iCuke/Classes/MainView.m +0 -32
  101. data/app/iCuke/Classes/MainViewController.h +0 -16
  102. data/app/iCuke/Classes/MainViewController.m +0 -86
  103. data/app/iCuke/Classes/iCukeAppDelegate.h +0 -20
  104. data/app/iCuke/Classes/iCukeAppDelegate.m +0 -33
  105. data/app/iCuke/FlipsideView.xib +0 -444
  106. data/app/iCuke/MainView.xib +0 -520
  107. data/app/iCuke/MainWindow.xib +0 -355
  108. data/app/iCuke/SniffingView.h +0 -20
  109. data/app/iCuke/SniffingView.m +0 -191
  110. data/app/iCuke/iCuke.xcodeproj/project.pbxproj +0 -313
  111. data/app/iCuke/iCuke_Prefix.pch +0 -14
  112. data/app/iCuke/main.m +0 -16
  113. data/features/icuke.feature +0 -17
  114. /data/app/{iCuke/.gitignore → .gitignore} +0 -0
data/ext/iCuke/Viewer.m CHANGED
@@ -2,9 +2,6 @@
2
2
 
3
3
  #import "Viewer.h"
4
4
 
5
- // AX API
6
- extern Boolean AXAPIEnabled(void);
7
-
8
5
  static Viewer *sharedViewer = nil;
9
6
 
10
7
  @interface NSObject (UIAccessibilityViewer)
@@ -27,7 +24,8 @@ static Viewer *sharedViewer = nil;
27
24
  if ([[self accessibilityLabel] length] > 0) {
28
25
  NSString *escaped_label = [self accessibilityLabel];
29
26
  escaped_label = [escaped_label stringByReplacingOccurrencesOfString: @"&" withString: @"&"];
30
- escaped_label = [escaped_label stringByReplacingOccurrencesOfString: @"'" withString: @"""];
27
+ escaped_label = [escaped_label stringByReplacingOccurrencesOfString: @"\"" withString: @"""];
28
+ escaped_label = [escaped_label stringByReplacingOccurrencesOfString: @"'" withString: @"'"];
31
29
  escaped_label = [escaped_label stringByReplacingOccurrencesOfString: @"\\" withString: @"'"];
32
30
  escaped_label = [escaped_label stringByReplacingOccurrencesOfString: @">" withString: @">"];
33
31
  escaped_label = [escaped_label stringByReplacingOccurrencesOfString: @"<" withString: @"&lt;"];
@@ -39,7 +37,8 @@ static Viewer *sharedViewer = nil;
39
37
  if ([[self accessibilityValue] length] > 0) {
40
38
  NSString *escaped_value = [self accessibilityValue];
41
39
  escaped_value = [escaped_value stringByReplacingOccurrencesOfString: @"&" withString: @"&amp;"];
42
- escaped_value = [escaped_value stringByReplacingOccurrencesOfString: @"'" withString: @"&quot;"];
40
+ escaped_value = [escaped_value stringByReplacingOccurrencesOfString: @"\"" withString: @"&quot;"];
41
+ escaped_value = [escaped_value stringByReplacingOccurrencesOfString: @"'" withString: @"&apos;"];
43
42
  escaped_value = [escaped_value stringByReplacingOccurrencesOfString: @"\\" withString: @"&#39;"];
44
43
  escaped_value = [escaped_value stringByReplacingOccurrencesOfString: @">" withString: @"&gt;"];
45
44
  escaped_value = [escaped_value stringByReplacingOccurrencesOfString: @"<" withString: @"&lt;"];
@@ -134,7 +133,7 @@ static Viewer *sharedViewer = nil;
134
133
  for (UIView *view in self.subviews) {
135
134
  [view appendToXml: xml];
136
135
  }
137
-
136
+
138
137
  [self appendChildrenToXml: xml];
139
138
  [self appendCloseToXml: xml];
140
139
  }
@@ -341,7 +341,7 @@ SYNTHESIZE_SINGLETON_FOR_CLASS(iCukeHTTPServer);
341
341
  [responseHandlers addObject:handler];
342
342
  [self stopReceivingForFileHandle:incomingFileHandle close:NO];
343
343
 
344
- [handler startResponse];
344
+ [handler startResponse];
345
345
  return;
346
346
  }
347
347
 
@@ -8,22 +8,29 @@
8
8
 
9
9
  #import "iCukeServer.h"
10
10
  #include <unistd.h>
11
+ #include <stdlib.h>
12
+
13
+ static NSAutoreleasePool *pool;
11
14
 
12
15
  @implementation iCukeServer
13
16
 
14
17
  + (void)start {
18
+ pool = [[NSAutoreleasePool alloc] init];
19
+
15
20
  [[iCukeHTTPServer sharediCukeHTTPServer] start];
16
21
 
17
22
  NSFileManager *fileManager= [[NSFileManager alloc] init];
18
23
  NSArray *paths;
19
24
 
20
- NSString *preferences = [NSHomeDirectory() stringByAppendingPathComponent: @"Library/Preferences"];
25
+ if (!getenv("ICUKE_KEEP_PREFERENCES")) {
26
+ NSString *preferences = [NSHomeDirectory() stringByAppendingPathComponent: @"Library/Preferences"];
21
27
 
22
- paths = [fileManager contentsOfDirectoryAtPath: preferences error: NULL];
23
- for (NSString *path in paths) {
24
- if (![path hasPrefix: @"."]) {
25
- NSLog(@"Removing: %@", path);
26
- unlink([[preferences stringByAppendingPathComponent: path] cStringUsingEncoding: [NSString defaultCStringEncoding]]);
28
+ paths = [fileManager contentsOfDirectoryAtPath: preferences error: NULL];
29
+ for (NSString *path in paths) {
30
+ if (![path hasPrefix: @"."]) {
31
+ NSLog(@"Removing: %@", path);
32
+ unlink([[preferences stringByAppendingPathComponent: path] cStringUsingEncoding: [NSString defaultCStringEncoding]]);
33
+ }
27
34
  }
28
35
  }
29
36
 
@@ -37,10 +44,20 @@
37
44
  }
38
45
  }
39
46
 
47
+ + (void)stop {
48
+ [pool release];
49
+ }
50
+
40
51
  @end
41
52
 
42
53
  void start_server(void) __attribute__((constructor));
43
54
  void start_server(void)
44
55
  {
45
- [iCukeServer start];
56
+ [iCukeServer start];
57
+ }
58
+
59
+ void stop_server(void) __attribute__((destructor));
60
+ void stop_server(void)
61
+ {
62
+ [iCukeServer stop];
46
63
  }
Binary file
@@ -0,0 +1,20 @@
1
+ Feature: iPhone integration tests
2
+ In order to test my iphone application
3
+ As a developer
4
+ I want cucumber to be able to drive the simulator
5
+
6
+ Background:
7
+ Given "app/UICatalog.xcodeproj" is loaded in the simulator
8
+
9
+ Scenario: Pressing buttons
10
+ When I tap "Buttons"
11
+ And I tap "Gray"
12
+
13
+ Scenario: Switches and sliders
14
+ When I tap "Controls"
15
+ And I tap "Standard switch"
16
+
17
+ Scenario: Entering text
18
+ When I tap "TextFields"
19
+ And I type "A string with symb0ls $!@ and spaces in it" in "Normal"
20
+ Then I should see "A string with symb0ls $!@ and spaces in it"
data/iCuke.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{iCuke}
8
- s.version = "0.4.12"
8
+ s.version = "0.5.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Rob Holland"]
12
- s.date = %q{2010-04-23}
12
+ s.date = %q{2010-05-11}
13
13
  s.description = %q{Cucumber support for iPhone applications}
14
14
  s.email = %q{rob@the-it-refinery.co.uk}
15
15
  s.extensions = ["ext/iCuke/Rakefile"]
@@ -24,26 +24,79 @@ Gem::Specification.new do |s|
24
24
  "README.rdoc",
25
25
  "Rakefile",
26
26
  "VERSION",
27
- "app/iCuke/.gitignore",
28
- "app/iCuke/Classes/FlipsideView.h",
29
- "app/iCuke/Classes/FlipsideView.m",
30
- "app/iCuke/Classes/FlipsideViewController.h",
31
- "app/iCuke/Classes/FlipsideViewController.m",
32
- "app/iCuke/Classes/MainView.h",
33
- "app/iCuke/Classes/MainView.m",
34
- "app/iCuke/Classes/MainViewController.h",
35
- "app/iCuke/Classes/MainViewController.m",
36
- "app/iCuke/Classes/iCukeAppDelegate.h",
37
- "app/iCuke/Classes/iCukeAppDelegate.m",
38
- "app/iCuke/FlipsideView.xib",
39
- "app/iCuke/MainView.xib",
40
- "app/iCuke/MainWindow.xib",
41
- "app/iCuke/SniffingView.h",
42
- "app/iCuke/SniffingView.m",
43
- "app/iCuke/iCuke-Info.plist",
44
- "app/iCuke/iCuke.xcodeproj/project.pbxproj",
45
- "app/iCuke/iCuke_Prefix.pch",
46
- "app/iCuke/main.m",
27
+ "app/.gitignore",
28
+ "app/AlertsViewController.h",
29
+ "app/AlertsViewController.m",
30
+ "app/AppDelegate.h",
31
+ "app/AppDelegate.m",
32
+ "app/ButtonsViewController.h",
33
+ "app/ButtonsViewController.m",
34
+ "app/Constants.h",
35
+ "app/ControlsViewController.h",
36
+ "app/ControlsViewController.m",
37
+ "app/ImagesViewController.h",
38
+ "app/ImagesViewController.m",
39
+ "app/Info.plist",
40
+ "app/MainViewController.h",
41
+ "app/MainViewController.m",
42
+ "app/Picker/CustomPickerDataSource.h",
43
+ "app/Picker/CustomPickerDataSource.m",
44
+ "app/Picker/CustomView.h",
45
+ "app/Picker/CustomView.m",
46
+ "app/PickerViewController.h",
47
+ "app/PickerViewController.m",
48
+ "app/Prefix.pch",
49
+ "app/ReadMe.txt",
50
+ "app/SearchBarController.h",
51
+ "app/SearchBarController.m",
52
+ "app/SegmentViewController.h",
53
+ "app/SegmentViewController.m",
54
+ "app/TextFieldController.h",
55
+ "app/TextFieldController.m",
56
+ "app/TextViewController.h",
57
+ "app/TextViewController.m",
58
+ "app/ToolbarViewController.h",
59
+ "app/ToolbarViewController.m",
60
+ "app/TransitionViewController.h",
61
+ "app/TransitionViewController.m",
62
+ "app/UICatalog.xcodeproj/project.pbxproj",
63
+ "app/WebViewController.h",
64
+ "app/WebViewController.m",
65
+ "app/en.lproj/AlertsViewController.xib",
66
+ "app/en.lproj/ButtonsViewController.xib",
67
+ "app/en.lproj/ControlsViewController.xib",
68
+ "app/en.lproj/ImagesViewController.xib",
69
+ "app/en.lproj/Localizable.strings",
70
+ "app/en.lproj/MainWindow.xib",
71
+ "app/en.lproj/PickerViewController.xib",
72
+ "app/en.lproj/SearchBarController.xib",
73
+ "app/en.lproj/SegmentViewController.xib",
74
+ "app/en.lproj/TextFieldController.xib",
75
+ "app/en.lproj/TextViewController.xib",
76
+ "app/en.lproj/ToolbarViewController.xib",
77
+ "app/en.lproj/TransitionViewController.xib",
78
+ "app/en.lproj/WebViewController.xib",
79
+ "app/images/12-6AM.png",
80
+ "app/images/12-6PM.png",
81
+ "app/images/6-12AM.png",
82
+ "app/images/6-12PM.png",
83
+ "app/images/Default.png",
84
+ "app/images/Icon.png",
85
+ "app/images/UIButton_custom.png",
86
+ "app/images/blueButton.png",
87
+ "app/images/orangeslide.png",
88
+ "app/images/scene1.jpg",
89
+ "app/images/scene2.jpg",
90
+ "app/images/scene3.jpg",
91
+ "app/images/scene4.jpg",
92
+ "app/images/scene5.jpg",
93
+ "app/images/segment_check.png",
94
+ "app/images/segment_search.png",
95
+ "app/images/segment_tools.png",
96
+ "app/images/slider_ball.png",
97
+ "app/images/whiteButton.png",
98
+ "app/images/yellowslide.png",
99
+ "app/main.m",
47
100
  "ext/iCuke/.gitignore",
48
101
  "ext/iCuke/DefaultsResponse.h",
49
102
  "ext/iCuke/DefaultsResponse.m",
@@ -79,13 +132,17 @@ Gem::Specification.new do |s|
79
132
  "ext/iCuke/json/SBJsonWriter.h",
80
133
  "ext/iCuke/json/SBJsonWriter.m",
81
134
  "ext/iCuke/libicuke.dylib",
82
- "features/icuke.feature",
83
135
  "features/support/env.rb",
136
+ "features/uicatalog.feature",
84
137
  "iCuke.gemspec",
85
138
  "lib/icuke.rb",
139
+ "lib/icuke/com.apple.Accessibility.plist",
140
+ "lib/icuke/core_ext.rb",
86
141
  "lib/icuke/cucumber.rb",
142
+ "lib/icuke/headless.rb",
87
143
  "lib/icuke/simulate.rb",
88
- "lib/icuke/simulator.rb"
144
+ "lib/icuke/simulator.rb",
145
+ "lib/icuke/xcode.rb"
89
146
  ]
90
147
  s.homepage = %q{http://github.com/unboxed/iCuke}
91
148
  s.rdoc_options = ["--charset=UTF-8"]
@@ -0,0 +1,26 @@
1
+ require 'net/http'
2
+
3
+ module RequestWithSocketCheck
4
+ def self.included(base)
5
+ base.instance_eval do
6
+ alias_method :request_without_socket_check, :request
7
+ alias_method :request, :request_with_socket_check
8
+ end
9
+ end
10
+
11
+ def request_with_socket_check(*args)
12
+ begin
13
+ request_without_socket_check(*args)
14
+ rescue NoMethodError => e
15
+ if e.message =~ /undefined method `closed\?' for nil/
16
+ raise Errno::ECONNREFUSED
17
+ else
18
+ raise e
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ if Net::HTTP::Revision.to_i == 25851
25
+ Net::HTTP.send :include, RequestWithSocketCheck
26
+ end
@@ -48,19 +48,23 @@ class ICukeWorld
48
48
  element =
49
49
  page.xpath(
50
50
  %Q{//*[#{trait(:button, :updates_frequently, :keyboard_key)} and @label="#{label}" and frame]},
51
- %Q{//*[#{trait(:link)} and @value="#{label}" and frame]}
51
+ %Q{//*[#{trait(:link)} and @value="#{label}" and frame]},
52
+ %Q{//*[@label="#{label}" and frame]}
52
53
  ).first
53
54
 
54
- raise %Q{No element labelled "#{label}" found in: #{response}} unless element
55
+ raise %Q{No element labelled "#{label}" found in: #{page}} unless element
55
56
 
56
57
  # This seems brittle, revist how to fetch the frame without relying on it being the only child
57
58
  frame = element.child
58
59
 
60
+ x = frame['x'].to_f
61
+ y = frame['y'].to_f
62
+
59
63
  # Hit the element in the middle
60
- x = frame['x'].to_f + (frame['width'].to_f / 2)
61
- y = frame['y'].to_f + (frame['height'].to_f / 2)
64
+ x += (frame['width'].to_f / 2)
65
+ y += (frame['height'].to_f / 2)
62
66
 
63
- raise %Q{Element "#{label}" is off screen in: #{response}} unless onscreen?(x, y)
67
+ raise %Q{Element "#{label}" is off screen in: #{page}} unless onscreen?(x, y)
64
68
 
65
69
  @simulator.fire_event(Tap.new(x, y, options))
66
70
 
@@ -73,7 +77,7 @@ class ICukeWorld
73
77
 
74
78
  def swipe(direction, options = {})
75
79
  modifier = [:up, :left].include?(direction) ? -1 : 1
76
-
80
+
77
81
  # Just swipe from the middle of an iPhone-dimensioned screen for now
78
82
  x = 320 / 2
79
83
  y = 480 / 2
@@ -81,9 +85,9 @@ class ICukeWorld
81
85
  y2 = y
82
86
 
83
87
  if [:up, :down].include?(direction)
84
- y2 = y + (100 * modifier)
88
+ y2 = y + (y * modifier)
85
89
  else
86
- x2 = x + (100 * modifier)
90
+ x2 = x + (x * modifier)
87
91
  end
88
92
 
89
93
  @simulator.fire_event(Swipe.new(x, y, x2, y2, options))
@@ -145,7 +149,7 @@ class ICukeWorld
145
149
  previous_response = response.dup
146
150
  while page.xpath(%Q{//*[contains(., "#{text}") or contains(@label, "#{text}") or contains(@value, "#{text}")]}).empty? do
147
151
  scroll(options[:direction])
148
- raise %Q{Content "#{text}" not found in: #{response}} if response == previous_response
152
+ raise %Q{Content "#{text}" not found in: #{page}} if response == previous_response
149
153
  end
150
154
  end
151
155
 
@@ -174,6 +178,10 @@ World do
174
178
  ICukeWorld.new
175
179
  end
176
180
 
181
+ After do
182
+ quit
183
+ end
184
+
177
185
  LIBICUKE = File.expand_path(File.dirname(__FILE__) + '/../../ext/iCuke/libicuke.dylib')
178
186
 
179
187
  Given /^(?:"([^\"]*)" from )?"([^\"]*)" is loaded in the simulator(?: using sdk (.*))?$/ do |target, project, sdk|
@@ -183,11 +191,11 @@ Given /^(?:"([^\"]*)" from )?"([^\"]*)" is loaded in the simulator(?: using sdk
183
191
  end
184
192
 
185
193
  Then /^I should see "([^\"]*)"(?: within "([^\"]*)")?$/ do |text, scope|
186
- raise %Q{Content "#{text}" not found in: #{response}} unless can_see?(text, scope)
194
+ raise %Q{Content "#{text}" not found in: #{page}} unless can_see?(text, scope)
187
195
  end
188
196
 
189
197
  Then /^I should not see "([^\"]*)"(?: within "([^\"]*)")?$/ do |text, scope|
190
- raise %Q{Content "#{text}" was found but was not expected in: #{response}} if can_see?(text, scope)
198
+ raise %Q{Content "#{text}" was found but was not expected in: #{page}} if can_see?(text, scope)
191
199
  end
192
200
 
193
201
  When /^I tap "([^\"]*)"$/ do |label|
@@ -211,5 +219,5 @@ Then /^I put the phone into recording mode$/ do
211
219
  end
212
220
 
213
221
  Then /^show me the screen$/ do
214
- puts response
222
+ puts page.to_s
215
223
  end
@@ -0,0 +1,55 @@
1
+ require 'tmpdir'
2
+ require 'background_process'
3
+
4
+ module ICuke
5
+ class Simulator
6
+ include Timeout
7
+
8
+ def launch(project_file, options = {})
9
+ options = {
10
+ :configuration => 'Debug',
11
+ :env => {}
12
+ }.merge(options)
13
+
14
+ app_name = File.basename(project_file, '.xcodeproj')
15
+ directory = "#{File.dirname(project_file)}/build/#{options[:configuration]}-iphonesimulator"
16
+
17
+ ENV['DYLD_ROOT_PATH'] = '/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.2.sdk'
18
+ ENV['DYLD_FRAMEWORK_PATH'] = directory
19
+ ENV['IPHONE_SIMULATOR_ROOT'] = '/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.2.sdk'
20
+ home = Dir.mktmpdir
21
+ FileUtils.mkdir_p File.join(home, 'Library', 'Preferences')
22
+ FileUtils.cp File.join(File.dirname(__FILE__), 'com.apple.Accessibility.plist'), File.join(home, 'Library', 'Preferences')
23
+ FileUtils.mkdir File.join(home, 'Documents')
24
+ ENV['CFFIXED_USER_HOME'] = home
25
+ ENV['ICUKE_KEEP_PREFERENCES'] = '1'
26
+
27
+ options[:env].each_pair do |k, v|
28
+ ENV[k] = v
29
+ end
30
+
31
+ command = "#{directory}/#{app_name}.app/#{app_name} -RegisterForSystemEvents"
32
+ @pid = fork {
33
+ STDIN.close
34
+ STDERR.close
35
+ STDOUT.close
36
+
37
+ exec(command)
38
+ }
39
+
40
+ timeout(30) do
41
+ begin
42
+ view
43
+ rescue Errno::ECONNREFUSED
44
+ sleep(0.5)
45
+ retry
46
+ end
47
+ end
48
+ end
49
+
50
+ def quit
51
+ Process.kill('TERM', @pid)
52
+ Process.wait(@pid)
53
+ end
54
+ end
55
+ end
@@ -1,84 +1,13 @@
1
+ require 'icuke/core_ext'
2
+ if ENV['ICUKE_HEADLESS']
3
+ require 'icuke/headless'
4
+ else
5
+ require 'icuke/xcode'
6
+ end
7
+
1
8
  require 'httparty'
2
- require 'appscript'
3
- require 'timeout'
4
9
 
5
10
  module ICuke
6
- class XCode
7
- def self.app
8
- @app ||= Appscript.app('Xcode.app')
9
- end
10
-
11
- def self.open_project(project_file)
12
- unless open_project?(project_file)
13
- app.launch
14
- app.open project_file
15
- end
16
- app.active_project_document.project
17
- end
18
-
19
- def self.open_project?(project_file)
20
- running? and
21
- app.active_project_document.get and
22
- app.active_project_document.project.path.get == project_file
23
- end
24
-
25
- def self.interface
26
- Appscript.app('System Events').application_processes['Xcode']
27
- end
28
-
29
- def self.running?
30
- app.is_running?
31
- end
32
-
33
- def self.quit
34
- IPhoneSimulator.quit
35
- app.quit if running?
36
- sleep(0.2) until !running?
37
- end
38
-
39
- def self.status
40
- interface.windows[1].static_texts[0].value.get
41
- end
42
-
43
- def self.launched_app?
44
- status =~ /launched$/
45
- end
46
-
47
- def self.installing_app?
48
- status =~ /^Installing/
49
- end
50
-
51
- def self.with_settings(project, settings, &block)
52
- initial_settings = {}
53
-
54
- settings.each_key { |setting| initial_settings[setting] = project.send(setting).get }
55
- settings.each_pair do |setting, value|
56
- project.send(setting).set value
57
- end
58
-
59
- yield
60
- ensure
61
- initial_settings.each_pair do |setting, value|
62
- project.send(setting).set value
63
- end if running?
64
- end
65
- end
66
-
67
- class IPhoneSimulator
68
- def self.app
69
- @app ||= Appscript.app('iPhone Simulator.app')
70
- end
71
-
72
- def self.quit
73
- app.quit if running?
74
- sleep(0.2) until !running?
75
- end
76
-
77
- def self.running?
78
- app.is_running?
79
- end
80
- end
81
-
82
11
  class Simulator
83
12
  include Timeout
84
13
  include HTTParty
@@ -86,57 +15,6 @@ module ICuke
86
15
 
87
16
  class Error < StandardError; end
88
17
 
89
- def launch(project_file, options = {})
90
- options = {
91
- :target => nil,
92
- :configuration => 'Debug'
93
- }.merge(options)
94
-
95
- # If we don't kill the simulator first the rest of this function becomes
96
- # a no-op and we don't land on the applications first page
97
- IPhoneSimulator.quit
98
-
99
- begin
100
- project = XCode.open_project(project_file)
101
-
102
- settings = {
103
- :active_build_configuration_type => project.build_configuration_types[options[:configuration]]
104
- }
105
- if options[:target]
106
- settings[:active_target] = project.targets[options[:target]]
107
- end
108
-
109
- XCode.with_settings(project, settings) do
110
- executable = project.active_executable.get
111
- options[:env].each_pair do |name, value|
112
- executable.make :new => :environment_variable,
113
- :with_properties => { :name => name, :value => value, :active => true }
114
- end
115
-
116
- project.launch_
117
-
118
- sleep(0.5) while XCode.installing_app?
119
-
120
- unless XCode.launched_app?
121
- XCode.quit
122
- retry
123
- end
124
-
125
- timeout(30) do
126
- begin
127
- view
128
- rescue Errno::ECONNREFUSED
129
- sleep(0.5)
130
- end
131
- end
132
- end
133
- end
134
- end
135
-
136
- def quit
137
- IPhoneSimulator.quit
138
- end
139
-
140
18
  def view
141
19
  get('/view')
142
20
  end