zucchini-ios 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.gitignore +1 -0
  2. data/CHANGELOG.md +50 -0
  3. data/README.md +7 -2
  4. data/lib/screenshot.rb +2 -1
  5. data/lib/uia/base.coffee +12 -3
  6. data/lib/uia/screen.coffee +7 -1
  7. data/lib/version.rb +1 -1
  8. data/spec/lib/config_spec.rb +54 -0
  9. data/spec/lib/detector_spec.rb +52 -0
  10. data/spec/lib/feature_spec.rb +69 -0
  11. data/spec/lib/generator_spec.rb +27 -0
  12. data/spec/lib/report_spec.rb +31 -0
  13. data/spec/lib/screenshot_spec.rb +109 -0
  14. data/spec/sample_screenshots/01_LandscapeLeft_Screenshot.png +0 -0
  15. data/spec/sample_screenshots/02_LandscapeRight_Screenshot.png +0 -0
  16. data/spec/sample_screenshots/03_PortraitUpsideDown_Screenshot.png +0 -0
  17. data/spec/sample_setup/feature_one/feature.zucchini +1 -0
  18. data/spec/sample_setup/feature_one/masks/retina_ios5/06_sign up_spinner.png +0 -0
  19. data/spec/sample_setup/feature_one/reference/retina_ios5/06_sign up_spinner.png +0 -0
  20. data/spec/sample_setup/feature_one/reference/retina_ios5/06_sign up_spinner_error.png +0 -0
  21. data/spec/sample_setup/feature_one/run_data/Run 1/06_sign up_spinner.png +0 -0
  22. data/spec/sample_setup/feature_three/feature.zucchini +1 -0
  23. data/spec/sample_setup/feature_two/feature.zucchini +1 -0
  24. data/spec/sample_setup/feature_two/masks/retina_ios5/06_sign up_spinner.png +0 -0
  25. data/spec/sample_setup/feature_two/reference/retina_ios5/06_sign up_spinner.png +0 -0
  26. data/spec/sample_setup/feature_two/reference/retina_ios5/06_sign up_spinner_error.png +0 -0
  27. data/spec/sample_setup/feature_two/run_data/Run 1/06_sign up_spinner.png +0 -0
  28. data/spec/sample_setup/support/config.yml +16 -0
  29. data/spec/sample_setup/support/lib/helpers.coffee +3 -0
  30. data/spec/sample_setup/support/masks/retina_ios5.png +0 -0
  31. data/spec/sample_setup/support/screens/splash.coffee +8 -0
  32. data/spec/sample_setup_2/support/config.yml +15 -0
  33. data/spec/sample_setup_3/support/config.yml +13 -0
  34. data/spec/spec_helper.rb +18 -0
  35. data/zucchini-ios.gemspec +28 -0
  36. metadata +125 -73
  37. data/Gemfile.lock +0 -30
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  .rvmrc
2
2
  .DS_Store
3
+ Gemfile.lock
data/CHANGELOG.md ADDED
@@ -0,0 +1,50 @@
1
+ ## 0.6.1 / 2013-07-28
2
+ * Add Rotate device screen action - [@phatmann][], [#19][]
3
+ * Fix screenshot code to work with the latest version of ImageMagick - [@phatmann][], [#17][]
4
+ * Raise error if screen anchor is not found - [@phatmann][], [#16][]
5
+
6
+ ## 0.6.0 / 2013-03-30
7
+ * Add a mask for retina iPad - [@phatmann][], [#8][]
8
+ * Fix alert Confirm / Cancel actions so that they match to end of line - [@phatmann][], [#9][]
9
+ * Allow app path to be set via an environment variable - [@phatmann][], [#10][]
10
+ * Screenshot orientation matching device orientation - [@Jaco][]-Pretorius, [#13][]
11
+
12
+ ## 0.5.9 / 2013-02-04
13
+ * Add default device flag - [@insanehunter][], [#6][]
14
+
15
+ ## 0.5.8 / 2013-02-03
16
+ * Add `zucchini approve` command to use screenshots from the last run as references - [@insanehunter][], [#5][]
17
+
18
+ ## 0.5.7 / 2012-12-16
19
+ * Always generate report, even if it is not displayed - [@vaskas][]
20
+ * Add `Select the date` action - [@NathanSudell][]
21
+ * Work around Instruments 4.5 throw-related crash - [@vaskas][]
22
+ * Add `--silent (-s)` flag to prevent report from opening - [@vaskas][]
23
+ * Add `Type` and `Clear` textfield actions - [@NathanSudell][], [#3][]
24
+ * Add `Confirm the alert` and `Cancel the alert` action - [@NathanSudell][], [#1][]
25
+
26
+ ## 0.5.6 / 2012-12-02
27
+ * Fix clamp 0.5.0 compatibility - [@vaskas][]
28
+ * Fix imagemagick 6.7.7-6 (possibly, other versions too) - [@vaskas][]
29
+ * Fix Instruments template detection for Xcode 4.5 - [@vaskas][]
30
+ * Fixed config to take relative paths to the app - [@coomans][]
31
+ * Quote path params in call to instruments - [@kconnor][]
32
+ <!--- The following link definition list is generated by PimpMyChangelog --->
33
+ [#1]: https://github.com/src/zucchini/issues/1
34
+ [#3]: https://github.com/src/zucchini/issues/3
35
+ [#5]: https://github.com/src/zucchini/issues/5
36
+ [#6]: https://github.com/src/zucchini/issues/6
37
+ [#8]: https://github.com/src/zucchini/issues/8
38
+ [#9]: https://github.com/src/zucchini/issues/9
39
+ [#10]: https://github.com/src/zucchini/issues/10
40
+ [#13]: https://github.com/src/zucchini/issues/13
41
+ [#16]: https://github.com/src/zucchini/issues/16
42
+ [#17]: https://github.com/src/zucchini/issues/17
43
+ [#19]: https://github.com/src/zucchini/issues/19
44
+ [@Jaco-Pretorius]: https://github.com/Jaco-Pretorius
45
+ [@NathanSudell]: https://github.com/NathanSudell
46
+ [@coomans]: https://github.com/coomans
47
+ [@insanehunter]: https://github.com/insanehunter
48
+ [@kconnor]: https://github.com/kconnor
49
+ [@phatmann]: https://github.com/phatmann
50
+ [@vaskas]: https://github.com/vaskas
data/README.md CHANGED
@@ -35,7 +35,7 @@ zucchini generate --feature /path/to/my_project/features/my_feature
35
35
 
36
36
  Start hacking by modifying features/my_feature/feature.zucchini and features/support/screens/welcome.coffee.
37
37
 
38
- Alternatively, check out the [zucchini-demo](https://github.com/rajbeniwal/zucchini-demo) project featuring an easy to explore Zucchini setup around Apple's CoreDataBooks sample.
38
+ Alternatively, check out the [zucchini-demo](https://github.com/zucchini-src/zucchini-demo) project featuring an easy to explore Zucchini setup around Apple's CoreDataBooks sample.
39
39
 
40
40
  Running on the device
41
41
  --------------------------------
@@ -77,8 +77,13 @@ devices:
77
77
  app: ./Build/Products/Debug-iphoneos/CoreDataBooks.app
78
78
  ```
79
79
 
80
+ If you do not want to hard-code the app path in your config files, you can use the environment variable `ZUCCHINI_APP`:
80
81
 
81
- Run it as usual:
82
+ ```
83
+ ZUCCHINI_APP="/path/to/app" zucchini...
84
+ ```
85
+
86
+ Run Zucchini and watch the simulator go!
82
87
 
83
88
  ```
84
89
  ZUCCHINI_DEVICE="iOS Simulator" zucchini run /path/to/my_feature
data/lib/screenshot.rb CHANGED
@@ -63,7 +63,8 @@ class Zucchini::Screenshot
63
63
 
64
64
  compare_command = "compare -metric AE -fuzz 2% -dissimilarity-threshold 1 -subimage-search"
65
65
  out = `#{compare_command} \"#{@masked_paths[:specifically]}\" \"#{@test_path}\" \"#{@diff_path}\" 2>&1`
66
- @diff = (out == "0\n") ? [:passed, nil] : [:failed, out]
66
+ out.chomp!
67
+ @diff = (out == '0') ? [:passed, nil] : [:failed, out]
67
68
  @diff = [:pending, @diff[1]] if @pending
68
69
  else
69
70
  @diff = [:failed, "no reference or pending screenshot for #{@device[:screen]}\n"]
data/lib/uia/base.coffee CHANGED
@@ -35,17 +35,16 @@ UIAElement.prototype.$ = (name) ->
35
35
  elem
36
36
 
37
37
  target.waitForElement = (element) ->
38
- return unless element
38
+ return false unless element
39
39
  found = false
40
40
  counter = 0
41
41
  while not found and (counter < 10)
42
42
  if element.isValid() and element.isVisible()
43
43
  found = true
44
- puts "Got the awaited element: #{element}"
45
- @delay 1
46
44
  else
47
45
  @delay 0.5
48
46
  counter++
47
+ return found
49
48
 
50
49
  isNullElement = (elem) -> elem.toString() == "[object UIAElementNil]"
51
50
 
@@ -71,6 +70,16 @@ class Zucchini
71
70
  catch e
72
71
  raise "Screen '#{screenName}' not defined"
73
72
 
73
+ if screen.anchor
74
+ element = screen.anchor()
75
+ found = target.waitForElement(element)
76
+
77
+ if found
78
+ puts "Found anchor for screen '#{screenName}'"
79
+ target.delay 1
80
+ else
81
+ raise "Could not find anchor for screen '#{screenName}'"
82
+
74
83
  for line in lines.slice(1)
75
84
  functionFound = false
76
85
  for regExpText, func of screen.actions
@@ -11,7 +11,6 @@ class Screen
11
11
  target.captureScreenWithName("#{orientation}_#{name}")
12
12
 
13
13
  constructor: (@name) ->
14
- if @anchor then target.waitForElement @anchor()
15
14
 
16
15
  elements: {}
17
16
  actions :
@@ -67,3 +66,10 @@ class Screen
67
66
  raise "Counldn't find the month #{dateParts[2]}" unless counter <12
68
67
  # Set Year
69
68
  view.pickers()[0].wheels()[2].selectValue(dateParts[3])
69
+
70
+ 'Show elements' : ->
71
+ view.logElementTree()
72
+
73
+ 'Rotate device to "([^"]*)"$': (orientation) ->
74
+ orientation = if orientation == "landscape" then UIA_DEVICE_ORIENTATION_LANDSCAPERIGHT else UIA_DEVICE_ORIENTATION_PORTRAIT
75
+ target.setDeviceOrientation(orientation)
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Zucchini
2
- VERSION = "0.6.0"
2
+ VERSION = "0.6.1"
3
3
  end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zucchini::Config do
4
+ describe "app" do
5
+ context "app environment variable" do
6
+ before(:all) { ENV['ZUCCHINI_APP'] = 'foo.app' }
7
+
8
+ it "should use environment variable if app not in config" do
9
+ Zucchini::Config.base_path = "spec/sample_setup_3"
10
+ Zucchini::Config.app.should include 'foo.app'
11
+ end
12
+
13
+ it "should not use environment variable if app in config" do
14
+ Zucchini::Config.base_path = "spec/sample_setup"
15
+ Zucchini::Config.app.should include 'MyApp.app'
16
+ end
17
+ end
18
+ end
19
+
20
+ describe "device" do
21
+ before(:all) { Zucchini::Config.base_path = "spec/sample_setup" }
22
+
23
+ context "device present in config.yml" do
24
+ it "should return the device hash" do
25
+ Zucchini::Config.device("My iDevice").should eq({:name =>"My iDevice", :udid =>"lolffb28d74a6fraj2156090784avasc50725dd0", :screen =>"ipad_ios5"})
26
+ end
27
+ end
28
+
29
+ context "device not present in config.yml" do
30
+ it "should raise an error" do
31
+ expect { Zucchini::Config.device("My Android Phone")}.to raise_error "Device not listed in config.yml"
32
+ end
33
+ end
34
+
35
+ context "default device" do
36
+ it "should use default device if device name argument is nil" do
37
+ Zucchini::Config.device(nil).should eq({:name =>"Default Device", :screen =>"low_ios5", :udid => nil})
38
+ end
39
+
40
+ it "should raise error if no default device provided" do
41
+ Zucchini::Config.base_path = "spec/sample_setup_2"
42
+ expect { Zucchini::Config.device(nil) }.to raise_error "Neither default device nor ZUCCHINI_DEVICE environment variable was set"
43
+ end
44
+ end
45
+ end
46
+
47
+ describe "url" do
48
+ before(:all) { Zucchini::Config.base_path = "spec/sample_setup" }
49
+
50
+ it "should return a full URL string for a given server name" do
51
+ Zucchini::Config.url('backend', '/api').should eq "http://192.168.1.2:8080/api"
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zucchini::Detector do
4
+ before do
5
+ detector.path = "spec/sample_setup/feature_one"
6
+ ENV['ZUCCHINI_DEVICE'] = 'My iDevice'
7
+ end
8
+
9
+ let (:detector) { Zucchini::Detector.new(nil) }
10
+
11
+ describe "execute" do
12
+ subject { lambda { detector.execute } }
13
+
14
+ context "feature directory doesn't exist" do
15
+ before { detector.path = "spec/sample_setup/erroneous_feature" }
16
+ it { should raise_error "Directory spec/sample_setup/erroneous_feature does not exist" }
17
+ end
18
+
19
+ context "device hasn't been found" do
20
+ before { ENV['ZUCCHINI_DEVICE'] = 'My Android Phone' }
21
+ it { should raise_error "Device not listed in config.yml" }
22
+ end
23
+ end
24
+
25
+ describe "detect features" do
26
+ subject { lambda { detector.detect_features(@path) } }
27
+
28
+ context "path to a single feature" do
29
+ before { @path = "spec/sample_setup/feature_one" }
30
+ it "should detect it" do
31
+ subject.call[0].path.should eq @path
32
+ end
33
+ end
34
+
35
+ context "path to a directory with features" do
36
+ before { @path = File.expand_path("spec/sample_setup") }
37
+ it "should detect all features in it" do
38
+ subject.call.length.should eq 3
39
+ end
40
+ end
41
+
42
+ context "path to a non-feature directory" do
43
+ before do
44
+ @path = File.expand_path("spec/sample_setup/bad_feature")
45
+ FileUtils.mkdir(@path)
46
+ end
47
+
48
+ it { should raise_error }
49
+ after { FileUtils.rmdir(@path) }
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zucchini::Feature do
4
+ let(:path) { './spec/sample_setup/feature_one' }
5
+ let(:feature) { Zucchini::Feature.new(path) }
6
+
7
+ after(:all) { FileUtils.rm_rf Dir.glob("#{path}/run_data/feature.*") }
8
+
9
+ describe "#compile_js" do
10
+ before { feature.compile_js }
11
+
12
+ it "should strip comments from the feature file" do
13
+ File.read("#{feature.run_data_path}/feature.coffee").index('#').should be_nil
14
+ end
15
+
16
+ describe "feature.js output" do
17
+ subject { File.read("#{feature.run_data_path}/feature.js") }
18
+
19
+ it "should include screen definitions" do
20
+ should match /SplashScreen = \(function/
21
+ end
22
+
23
+ it "should include Zucchini runtime" do
24
+ should match /Zucchini.run = /
25
+ end
26
+
27
+ it "should include custom libraries from support/lib" do
28
+ should match /Helpers.example = /
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "approve" do
34
+ subject { lambda { feature.approve "reference" } }
35
+
36
+ context "no previous run data" do
37
+ before { feature.path = './spec/sample_setup/feature_three' }
38
+ it { should raise_error "Directory ./spec/sample_setup/feature_three doesn't contain previous run data" }
39
+ end
40
+
41
+ context "copies screenshots to reference directory" do
42
+ before do
43
+ feature.path = './spec/sample_setup/feature_three'
44
+ feature.device = {screen: 'retina_ios5'}
45
+
46
+ # Copying some random image to run screenshots.
47
+ @screenshot_path = "#{feature.path}/run_data/Run\ 1/screenshot.png"
48
+ FileUtils.mkdir_p(File.dirname(@screenshot_path))
49
+ FileUtils.copy_file("./spec/sample_setup/feature_one/reference/retina_ios5/06_sign up_spinner.png", @screenshot_path)
50
+ end
51
+
52
+ it "should copy screenshot to reference directory" do
53
+ feature.approve "reference"
54
+ (File.exists? "#{feature.path}/reference/retina_ios5/screenshot.png").should eq true
55
+ end
56
+
57
+ it "should copy screenshot to pending directory" do
58
+ feature.approve "pending"
59
+ (File.exists? "#{feature.path}/pending/retina_ios5/screenshot.png").should eq true
60
+ end
61
+
62
+ after do
63
+ FileUtils.rm_rf("#{feature.path}/run_data")
64
+ FileUtils.rm_rf("#{feature.path}/reference")
65
+ FileUtils.rm_rf("#{feature.path}/pending")
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zucchini::Generator do
4
+ let(:project_path) { "/tmp/z_test_project" }
5
+ let(:feature_path) { "#{project_path}/features/rspec_feature" }
6
+ let(:generator) { Zucchini::Generator.new(nil) }
7
+
8
+ after(:all) { FileUtils.rm_rf(project_path) }
9
+
10
+ context "generate a project" do
11
+ before { generator.path = project_path }
12
+ it "should create a project directory" do
13
+ generator.stub!(:project?).and_return(true)
14
+ generator.execute
15
+ File.exists?("#{project_path}/features/support/config.yml").should be_true
16
+ end
17
+ end
18
+
19
+ context "generate a feature" do
20
+ before { generator.path = feature_path }
21
+ it "should create a feature directory" do
22
+ generator.stub!(:feature?).and_return(true)
23
+ generator.execute
24
+ File.exists?("#{feature_path}/feature.zucchini").should be_true
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zucchini::Report do
4
+ let (:device) { { :name => "iPad 2", :screen => "ipad_ios5", :udid => "rspec012345" } }
5
+ let (:feature) do
6
+ fake_screenshots = (1..7).to_a.map do |num|
7
+ screenshot = Zucchini::Screenshot.new("#{num}.screen_#{num}.png", device)
8
+ screenshot.diff = (num > 3) ? [:passed, nil] : [:failed, "120\n"]
9
+ screenshot
10
+ end
11
+
12
+ feature = Zucchini::Feature.new("/my/sample/feature")
13
+ feature.device = device
14
+ feature.stub!(:screenshots).and_return(fake_screenshots)
15
+ feature
16
+ end
17
+
18
+ let(:html_path) { '/tmp/zucchini_rspec_report.html' }
19
+ after { FileUtils.rm(html_path) }
20
+
21
+ subject { Zucchini::Report.new([feature], false, html_path) }
22
+ before { Zucchini::Report.any_instance.stub(:log) }
23
+
24
+ its(:text) { should eq "feature:\n4 passed, 3 failed, 0 pending\n\nFailed:\n 1.screen_1.png: 120\n 2.screen_2.png: 120\n 3.screen_3.png: 120\n" }
25
+
26
+ it "should produce a a correct HTML report" do
27
+ report = subject.html
28
+ report.scan(/<dl class="passed.*screen/).length.should eq 4
29
+ report.scan(/<dl class="failed.*screen/).length.should eq 3
30
+ end
31
+ end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+ require 'digest/md5'
3
+ require 'tmpdir'
4
+
5
+ def md5(blob)
6
+ Digest::MD5.hexdigest(blob)
7
+ end
8
+
9
+ describe Zucchini::Screenshot do
10
+ let (:device) { { :name => "iPhone 4S", :screen => "retina_ios5", :udid => "rspec987654" } }
11
+ let (:base_path) { "spec/sample_setup/feature_one" }
12
+ let (:original_path) { "#{base_path}/run_data/Run\ 1/06_sign\ up_spinner.png" }
13
+
14
+ let (:screenshot) do
15
+ screenshot = Zucchini::Screenshot.new(original_path, device)
16
+ screenshot.masked_paths = { :globally => "#{base_path}/globally_masked.png", :specifically => "#{base_path}/specifically_masked.png" }
17
+ screenshot.mask
18
+ screenshot
19
+ end
20
+
21
+ after(:all) do
22
+ screenshot.masked_paths.each { |k, path| FileUtils.rm(path) }
23
+ FileUtils.rm_rf("#{base_path}/run_data/Masked")
24
+ FileUtils.rm_rf(screenshot.diff_path)
25
+ end
26
+
27
+ describe "mask" do
28
+ before do
29
+ @md5 = {
30
+ :original => md5(File.read(original_path)),
31
+ :globally_masked => md5(File.read(screenshot.masked_paths[:globally])),
32
+ :specifically_masked => md5(File.read(screenshot.masked_paths[:specifically]))
33
+ }
34
+ end
35
+
36
+ it "should apply a standard global mask based on the screen" do
37
+ File.exists?(screenshot.masked_paths[:globally]).should be true
38
+ @md5[:globally_masked].should_not be_equal @md5[:original]
39
+ end
40
+
41
+ it "should apply a screenshot-specific mask if it exists" do
42
+ File.exists?(screenshot.masked_paths[:specifically]).should be true
43
+ @md5[:specifically_masked].should_not be_equal @md5[:original]
44
+ @md5[:specifically_masked].should_not be_equal @md5[:globally_masked]
45
+ end
46
+ end
47
+
48
+ describe "compare" do
49
+ context "images are identical" do
50
+ it "should have a passed indicator in the diff" do
51
+ screenshot.compare
52
+ screenshot.diff.should eq [:passed, nil]
53
+ end
54
+ end
55
+
56
+ context "images are different" do
57
+ it "should have a failed indicator in the diff" do
58
+ screenshot.stub!(:mask_reference)
59
+ screenshot.test_path = "#{base_path}/reference/#{device[:screen]}/06_sign\ up_spinner_error.png"
60
+ screenshot.compare
61
+ screenshot.diff.should eq [:failed, "3017"]
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "mask reference" do
67
+ it "should create masked versions of reference screenshots" do
68
+ screenshot.mask_reference
69
+
70
+ File.exists?(screenshot.test_path).should be_true
71
+ md5(File.read(screenshot.test_path)).should_not be_equal md5(File.read("#{base_path}/reference/#{device[:screen]}/06_sign\ up_spinner.png"))
72
+ end
73
+ end
74
+
75
+ describe "rotate" do
76
+ let (:sample_screenshots_path) { "spec/sample_screenshots" }
77
+ let (:reference_screenshot_path) { File.join(sample_screenshots_path, "rotated/01_Screenshot.png") }
78
+ let (:reference_md5) { md5(File.read(reference_screenshot_path)) }
79
+ let (:temp_dir) { Dir.mktmpdir }
80
+ before do
81
+ `cp #{File.join(sample_screenshots_path, "*")} #{temp_dir}`
82
+ end
83
+
84
+ it "should rotate the landscape-left screenshot" do
85
+ screenshot = Zucchini::Screenshot.new(File.join(temp_dir,'01_LandscapeLeft_Screenshot.png'), nil, true)
86
+ screenshot.rotate
87
+ File.exists?(File.join(temp_dir,'01_LandscapeLeft_Screenshot.png')).should be_false
88
+ File.exists?(File.join(temp_dir,'01_Screenshot.png')).should be_true
89
+ end
90
+
91
+ it "should rotate the landscape-right screenshot" do
92
+ screenshot = Zucchini::Screenshot.new(File.join(temp_dir,'02_LandscapeRight_Screenshot.png'), nil, true)
93
+ screenshot.rotate
94
+ File.exists?(File.join(temp_dir,'02_LandscapeRight_Screenshot.png')).should be_false
95
+ File.exists?(File.join(temp_dir,'02_Screenshot.png')).should be_true
96
+ end
97
+
98
+ it "should rotate the upside-down screenshot" do
99
+ screenshot = Zucchini::Screenshot.new(File.join(temp_dir,'03_PortraitUpsideDown_Screenshot.png'), nil, true)
100
+ screenshot.rotate
101
+ File.exists?(File.join(temp_dir,'02_PortraitUpsideDown_Screenshot.png')).should be_false
102
+ File.exists?(File.join(temp_dir,'03_Screenshot.png')).should be_true
103
+ end
104
+
105
+ after do
106
+ FileUtils.remove_entry temp_dir
107
+ end
108
+ end
109
+ end
@@ -0,0 +1 @@
1
+ # Start on the "Splash" screen
@@ -0,0 +1 @@
1
+ # Start on the "Menu" screen
@@ -0,0 +1 @@
1
+ # Start on the "Menu" screen
@@ -0,0 +1,16 @@
1
+ app: MyApp.app
2
+
3
+ devices:
4
+ My iDevice:
5
+ UDID : lolffb28d74a6fraj2156090784avasc50725dd0
6
+ screen: ipad_ios5
7
+
8
+ Default Device:
9
+ screen : low_ios5
10
+ default: true
11
+
12
+
13
+ servers:
14
+ backend:
15
+ host: 192.168.1.2
16
+ port: 8080
@@ -0,0 +1,3 @@
1
+ class Helpers
2
+ @example: ->
3
+ puts "Helpers.example method is available in your screen classes"
@@ -0,0 +1,8 @@
1
+ class SplashScreen extends Screen
2
+ anchor: -> view.elements()["Welcome"]
3
+
4
+ constructor: ->
5
+ super 'splash'
6
+
7
+ extend @elements,
8
+ 'Go' : -> view.buttons()["Go"]
@@ -0,0 +1,15 @@
1
+ app: MyApp.app
2
+
3
+ devices:
4
+ My iDevice:
5
+ UDID : lolffb28d74a6fraj2156090784avasc50725dd0
6
+ screen: ipad_ios5
7
+
8
+ Default Device:
9
+ screen : low_ios5
10
+
11
+
12
+ servers:
13
+ backend:
14
+ host: 192.168.1.2
15
+ port: 8080
@@ -0,0 +1,13 @@
1
+ devices:
2
+ My iDevice:
3
+ UDID : lolffb28d74a6fraj2156090784avasc50725dd0
4
+ screen: ipad_ios5
5
+
6
+ Default Device:
7
+ screen : low_ios5
8
+ default: true
9
+
10
+ servers:
11
+ backend:
12
+ host: 192.168.1.2
13
+ port: 8080
@@ -0,0 +1,18 @@
1
+ require 'clamp'
2
+ require 'fileutils'
3
+
4
+ $LOAD_PATH << File.expand_path("#{File.dirname(__FILE__)}/..")
5
+ require 'lib/config'
6
+ require 'lib/screenshot'
7
+ require 'lib/report'
8
+ require 'lib/feature'
9
+ require 'lib/detector'
10
+ require 'lib/runner'
11
+ require 'lib/generator'
12
+ require 'lib/approver'
13
+
14
+ RSpec.configure do |config|
15
+ config.color_enabled = true
16
+ config.tty = true
17
+ #config.formatter = :documentation
18
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'version'
4
+ require 'date'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "zucchini-ios"
8
+ s.version = Zucchini::VERSION
9
+ s.date = Date.today.to_s
10
+ s.platform = Gem::Platform::RUBY
11
+ s.authors = ["Vasily Mikhaylichenko", "Rajesh Kumar", "Kevin O'Neill"]
12
+ s.license = "BSD"
13
+ s.email = ["vaskas@zucchiniframework.org"]
14
+ s.homepage = "http://www.zucchiniframework.org"
15
+ s.summary = %q{Functional testing framework for iOS-powered devices}
16
+ s.description = %q{Zucchini follows simple walkthrough scenarios for your iOS app, takes screenshots and compares them to the reference ones.}
17
+
18
+ s.add_runtime_dependency "clamp"
19
+ s.add_development_dependency "rspec"
20
+ s.add_development_dependency "watchr"
21
+
22
+ s.files = `git ls-files | grep -vE '(web|.watchr)'`.split("\n")
23
+ s.test_files = `git ls-files -- spec/*`.split("\n")
24
+ s.executables = %w(zucchini)
25
+ s.require_paths = ["lib"]
26
+
27
+ s.required_ruby_version = '>= 1.9.2'
28
+ end
metadata CHANGED
@@ -1,74 +1,79 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: zucchini-ios
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 6
8
- - 0
9
- version: 0.6.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.1
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Vasily Mikhaylichenko
13
9
  - Rajesh Kumar
14
10
  - Kevin O'Neill
15
11
  autorequire:
16
12
  bindir: bin
17
13
  cert_chain: []
18
-
19
- date: 2013-03-31 00:00:00 +11:00
20
- default_executable:
21
- dependencies:
22
- - !ruby/object:Gem::Dependency
14
+ date: 2013-07-28 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
23
17
  name: clamp
24
- prerelease: false
25
- requirement: &id001 !ruby/object:Gem::Requirement
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- segments:
30
- - 0
31
- version: "0"
18
+ requirement: !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
23
+ version: '0'
32
24
  type: :runtime
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: rspec
36
25
  prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- segments:
42
- - 0
43
- version: "0"
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ! '>='
30
+ - !ruby/object:Gem::Version
31
+ version: '0'
32
+ - !ruby/object:Gem::Dependency
33
+ name: rspec
34
+ requirement: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
44
40
  type: :development
45
- version_requirements: *id002
46
- - !ruby/object:Gem::Dependency
47
- name: watchr
48
41
  prerelease: false
49
- requirement: &id003 !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- segments:
54
- - 0
55
- version: "0"
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ - !ruby/object:Gem::Dependency
49
+ name: watchr
50
+ requirement: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
56
  type: :development
57
- version_requirements: *id003
58
- description: Zucchini follows simple walkthrough scenarios for your iOS app, takes screenshots and compares them to the reference ones.
59
- email:
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ description: Zucchini follows simple walkthrough scenarios for your iOS app, takes
65
+ screenshots and compares them to the reference ones.
66
+ email:
60
67
  - vaskas@zucchiniframework.org
61
- executables:
68
+ executables:
62
69
  - zucchini
63
70
  extensions: []
64
-
65
71
  extra_rdoc_files: []
66
-
67
- files:
72
+ files:
68
73
  - .gitignore
69
74
  - .travis.yml
75
+ - CHANGELOG.md
70
76
  - Gemfile
71
- - Gemfile.lock
72
77
  - LICENSE.md
73
78
  - README.md
74
79
  - Rakefile
@@ -91,6 +96,33 @@ files:
91
96
  - lib/uia/base.coffee
92
97
  - lib/uia/screen.coffee
93
98
  - lib/version.rb
99
+ - spec/lib/config_spec.rb
100
+ - spec/lib/detector_spec.rb
101
+ - spec/lib/feature_spec.rb
102
+ - spec/lib/generator_spec.rb
103
+ - spec/lib/report_spec.rb
104
+ - spec/lib/screenshot_spec.rb
105
+ - spec/sample_screenshots/01_LandscapeLeft_Screenshot.png
106
+ - spec/sample_screenshots/02_LandscapeRight_Screenshot.png
107
+ - spec/sample_screenshots/03_PortraitUpsideDown_Screenshot.png
108
+ - spec/sample_setup/feature_one/feature.zucchini
109
+ - spec/sample_setup/feature_one/masks/retina_ios5/06_sign up_spinner.png
110
+ - spec/sample_setup/feature_one/reference/retina_ios5/06_sign up_spinner.png
111
+ - spec/sample_setup/feature_one/reference/retina_ios5/06_sign up_spinner_error.png
112
+ - spec/sample_setup/feature_one/run_data/Run 1/06_sign up_spinner.png
113
+ - spec/sample_setup/feature_three/feature.zucchini
114
+ - spec/sample_setup/feature_two/feature.zucchini
115
+ - spec/sample_setup/feature_two/masks/retina_ios5/06_sign up_spinner.png
116
+ - spec/sample_setup/feature_two/reference/retina_ios5/06_sign up_spinner.png
117
+ - spec/sample_setup/feature_two/reference/retina_ios5/06_sign up_spinner_error.png
118
+ - spec/sample_setup/feature_two/run_data/Run 1/06_sign up_spinner.png
119
+ - spec/sample_setup/support/config.yml
120
+ - spec/sample_setup/support/lib/helpers.coffee
121
+ - spec/sample_setup/support/masks/retina_ios5.png
122
+ - spec/sample_setup/support/screens/splash.coffee
123
+ - spec/sample_setup_2/support/config.yml
124
+ - spec/sample_setup_3/support/config.yml
125
+ - spec/spec_helper.rb
94
126
  - templates/feature/feature.zucchini
95
127
  - templates/feature/masks/retina_ios5/.gitkeep
96
128
  - templates/feature/pending/retina_ios5/.gitkeep
@@ -104,37 +136,57 @@ files:
104
136
  - templates/project/features/support/masks/low_ios4.png
105
137
  - templates/project/features/support/masks/retina_ios5.png
106
138
  - templates/project/features/support/screens/welcome.coffee
107
- has_rdoc: true
139
+ - zucchini-ios.gemspec
108
140
  homepage: http://www.zucchiniframework.org
109
- licenses:
141
+ licenses:
110
142
  - BSD
111
143
  post_install_message:
112
144
  rdoc_options: []
113
-
114
- require_paths:
145
+ require_paths:
115
146
  - lib
116
- required_ruby_version: !ruby/object:Gem::Requirement
117
- requirements:
118
- - - ">="
119
- - !ruby/object:Gem::Version
120
- segments:
121
- - 1
122
- - 9
123
- - 2
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ none: false
149
+ requirements:
150
+ - - ! '>='
151
+ - !ruby/object:Gem::Version
124
152
  version: 1.9.2
125
- required_rubygems_version: !ruby/object:Gem::Requirement
126
- requirements:
127
- - - ">="
128
- - !ruby/object:Gem::Version
129
- segments:
130
- - 0
131
- version: "0"
153
+ required_rubygems_version: !ruby/object:Gem::Requirement
154
+ none: false
155
+ requirements:
156
+ - - ! '>='
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
132
159
  requirements: []
133
-
134
160
  rubyforge_project:
135
- rubygems_version: 1.3.6
161
+ rubygems_version: 1.8.23
136
162
  signing_key:
137
163
  specification_version: 3
138
164
  summary: Functional testing framework for iOS-powered devices
139
- test_files: []
140
-
165
+ test_files:
166
+ - spec/lib/config_spec.rb
167
+ - spec/lib/detector_spec.rb
168
+ - spec/lib/feature_spec.rb
169
+ - spec/lib/generator_spec.rb
170
+ - spec/lib/report_spec.rb
171
+ - spec/lib/screenshot_spec.rb
172
+ - spec/sample_screenshots/01_LandscapeLeft_Screenshot.png
173
+ - spec/sample_screenshots/02_LandscapeRight_Screenshot.png
174
+ - spec/sample_screenshots/03_PortraitUpsideDown_Screenshot.png
175
+ - spec/sample_setup/feature_one/feature.zucchini
176
+ - spec/sample_setup/feature_one/masks/retina_ios5/06_sign up_spinner.png
177
+ - spec/sample_setup/feature_one/reference/retina_ios5/06_sign up_spinner.png
178
+ - spec/sample_setup/feature_one/reference/retina_ios5/06_sign up_spinner_error.png
179
+ - spec/sample_setup/feature_one/run_data/Run 1/06_sign up_spinner.png
180
+ - spec/sample_setup/feature_three/feature.zucchini
181
+ - spec/sample_setup/feature_two/feature.zucchini
182
+ - spec/sample_setup/feature_two/masks/retina_ios5/06_sign up_spinner.png
183
+ - spec/sample_setup/feature_two/reference/retina_ios5/06_sign up_spinner.png
184
+ - spec/sample_setup/feature_two/reference/retina_ios5/06_sign up_spinner_error.png
185
+ - spec/sample_setup/feature_two/run_data/Run 1/06_sign up_spinner.png
186
+ - spec/sample_setup/support/config.yml
187
+ - spec/sample_setup/support/lib/helpers.coffee
188
+ - spec/sample_setup/support/masks/retina_ios5.png
189
+ - spec/sample_setup/support/screens/splash.coffee
190
+ - spec/sample_setup_2/support/config.yml
191
+ - spec/sample_setup_3/support/config.yml
192
+ - spec/spec_helper.rb
data/Gemfile.lock DELETED
@@ -1,30 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- zucchini-ios (0.5.9)
5
- clamp
6
-
7
- GEM
8
- remote: http://rubygems.org/
9
- specs:
10
- clamp (0.5.0)
11
- diff-lcs (1.1.3)
12
- rake (10.0.2)
13
- rspec (2.11.0)
14
- rspec-core (~> 2.11.0)
15
- rspec-expectations (~> 2.11.0)
16
- rspec-mocks (~> 2.11.0)
17
- rspec-core (2.11.1)
18
- rspec-expectations (2.11.2)
19
- diff-lcs (~> 1.1.3)
20
- rspec-mocks (2.11.2)
21
- watchr (0.7)
22
-
23
- PLATFORMS
24
- ruby
25
-
26
- DEPENDENCIES
27
- rake
28
- rspec
29
- watchr
30
- zucchini-ios!