iCuke 0.4.12 → 0.5.1

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