zucchini-ios 0.6.0 → 0.6.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 (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!