zucchini-ios 0.5.9 → 0.6.0
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.
- data/lib/config.rb +1 -1
- data/lib/feature.rb +1 -0
- data/lib/screenshot.rb +36 -14
- data/lib/uia/screen.coffee +15 -4
- data/lib/version.rb +1 -1
- data/templates/project/features/support/masks/ipad_retina_ios6.png +0 -0
- metadata +73 -116
- data/spec/lib/config_spec.rb +0 -36
- data/spec/lib/detector_spec.rb +0 -52
- data/spec/lib/feature_spec.rb +0 -69
- data/spec/lib/generator_spec.rb +0 -27
- data/spec/lib/report_spec.rb +0 -31
- data/spec/lib/screenshot_spec.rb +0 -73
- data/spec/sample_setup/feature_one/feature.zucchini +0 -1
- data/spec/sample_setup/feature_one/masks/retina_ios5/06_sign up_spinner.png +0 -0
- data/spec/sample_setup/feature_one/reference/retina_ios5/06_sign up_spinner.png +0 -0
- data/spec/sample_setup/feature_one/reference/retina_ios5/06_sign up_spinner_error.png +0 -0
- data/spec/sample_setup/feature_one/run_data/Run 1/06_sign up_spinner.png +0 -0
- data/spec/sample_setup/feature_three/feature.zucchini +0 -1
- data/spec/sample_setup/feature_two/feature.zucchini +0 -1
- data/spec/sample_setup/feature_two/masks/retina_ios5/06_sign up_spinner.png +0 -0
- data/spec/sample_setup/feature_two/reference/retina_ios5/06_sign up_spinner.png +0 -0
- data/spec/sample_setup/feature_two/reference/retina_ios5/06_sign up_spinner_error.png +0 -0
- data/spec/sample_setup/feature_two/run_data/Run 1/06_sign up_spinner.png +0 -0
- data/spec/sample_setup/support/config.yml +0 -16
- data/spec/sample_setup/support/lib/helpers.coffee +0 -3
- data/spec/sample_setup/support/masks/retina_ios5.png +0 -0
- data/spec/sample_setup/support/screens/splash.coffee +0 -8
- data/spec/sample_setup_2/support/config.yml +0 -15
- data/spec/spec_helper.rb +0 -18
- data/zucchini-ios.gemspec +0 -27
data/lib/config.rb
CHANGED
@@ -21,7 +21,7 @@ module Zucchini
|
|
21
21
|
|
22
22
|
def self.app
|
23
23
|
device_name = ENV['ZUCCHINI_DEVICE'] || @@default_device_name
|
24
|
-
app_path = File.absolute_path(devices[device_name]['app'] || @@config['app'])
|
24
|
+
app_path = File.absolute_path(devices[device_name]['app'] || @@config['app'] || ENV['ZUCCHINI_APP'])
|
25
25
|
|
26
26
|
if device_name == 'iOS Simulator' && !File.exists?(app_path)
|
27
27
|
raise "Can't find application at path #{app_path}"
|
data/lib/feature.rb
CHANGED
data/lib/screenshot.rb
CHANGED
@@ -1,29 +1,49 @@
|
|
1
1
|
class Zucchini::Screenshot
|
2
|
+
ORIENTATION = /^\d\d_(?<orientation>(Unknown|Portrait|PortraitUpsideDown|LandscapeLeft|LandscapeRight|FaceUp|FaceDown))_.*$/
|
3
|
+
|
2
4
|
attr_reader :file_path, :file_name
|
3
|
-
attr_accessor :diff, :masks_paths, :masked_paths, :test_path, :diff_path
|
5
|
+
attr_accessor :diff, :masks_paths, :masked_paths, :test_path, :diff_path
|
4
6
|
|
5
7
|
def initialize(file_path, device, unmatched_pending = false)
|
6
|
-
|
7
|
-
@
|
8
|
+
file_name = File.basename(file_path)
|
9
|
+
@original_file_path = file_path
|
8
10
|
@device = device
|
9
11
|
|
10
|
-
@
|
12
|
+
@orientation = (match = ORIENTATION.match(file_name)) ? match[:orientation] : nil
|
13
|
+
if @orientation
|
14
|
+
@file_name = file_name.gsub("_#{@orientation}", '')
|
15
|
+
@file_path = File.join(File.dirname(file_path),@file_name)
|
16
|
+
else
|
17
|
+
@file_name = file_name
|
18
|
+
@file_path = file_path
|
19
|
+
end
|
11
20
|
|
12
21
|
unless unmatched_pending
|
13
|
-
|
22
|
+
file_base_path = File.dirname(@file_path)
|
14
23
|
|
15
24
|
@masks_paths = {
|
16
|
-
:global => "#{
|
17
|
-
:specific => "#{
|
25
|
+
:global => "#{file_base_path}/../../../support/masks/#{@device[:screen]}.png",
|
26
|
+
:specific => "#{file_base_path}/../../masks/#{@device[:screen]}/#{@file_name}"
|
18
27
|
}
|
19
28
|
|
20
|
-
masked_path = "#{
|
29
|
+
masked_path = "#{file_base_path}/../Masked/actual/#{@file_name}"
|
21
30
|
@masked_paths = { :globally => masked_path, :specifically => masked_path }
|
22
31
|
|
23
|
-
@
|
24
|
-
|
25
|
-
|
32
|
+
@diff_path = "#{file_base_path}/../Diff/#{@file_name}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def rotate
|
37
|
+
return unless @orientation
|
38
|
+
degrees = case @orientation
|
39
|
+
when 'LandscapeRight' then 90
|
40
|
+
when 'LandscapeLeft' then 270
|
41
|
+
when 'PortraitUpsideDown' then 180
|
42
|
+
else
|
43
|
+
0
|
26
44
|
end
|
45
|
+
`convert \"#{@original_file_path}\" -rotate \"#{degrees}\" \"#{@file_path}\"`
|
46
|
+
FileUtils.rm @original_file_path
|
27
47
|
end
|
28
48
|
|
29
49
|
def mask
|
@@ -41,7 +61,8 @@ class Zucchini::Screenshot
|
|
41
61
|
if @test_path
|
42
62
|
FileUtils.mkdir_p(File.dirname(@diff_path))
|
43
63
|
|
44
|
-
|
64
|
+
compare_command = "compare -metric AE -fuzz 2% -dissimilarity-threshold 1 -subimage-search"
|
65
|
+
out = `#{compare_command} \"#{@masked_paths[:specifically]}\" \"#{@test_path}\" \"#{@diff_path}\" 2>&1`
|
45
66
|
@diff = (out == "0\n") ? [:passed, nil] : [:failed, out]
|
46
67
|
@diff = [:pending, @diff[1]] if @pending
|
47
68
|
else
|
@@ -58,9 +79,10 @@ class Zucchini::Screenshot
|
|
58
79
|
end
|
59
80
|
|
60
81
|
def mask_reference
|
82
|
+
file_base_path = File.dirname(@file_path)
|
61
83
|
%W(reference pending).each do |reference_type|
|
62
|
-
reference_file_path = "#{
|
63
|
-
output_path = "#{
|
84
|
+
reference_file_path = "#{file_base_path}/../../#{reference_type}/#{@device[:screen]}/#{@file_name}"
|
85
|
+
output_path = "#{file_base_path}/../Masked/#{reference_type}/#{@file_name}"
|
64
86
|
|
65
87
|
if File.exists?(reference_file_path)
|
66
88
|
@test_path = output_path
|
data/lib/uia/screen.coffee
CHANGED
@@ -1,14 +1,25 @@
|
|
1
1
|
class Screen
|
2
|
+
takeScreenshot: (name) ->
|
3
|
+
orientation = switch app.interfaceOrientation()
|
4
|
+
when 0 then 'Unknown'
|
5
|
+
when 1 then 'Portrait'
|
6
|
+
when 2 then 'PortraitUpsideDown'
|
7
|
+
when 3 then 'LandscapeLeft'
|
8
|
+
when 4 then 'LandscapeRight'
|
9
|
+
when 5 then 'FaceUp'
|
10
|
+
when 6 then 'FaceDown'
|
11
|
+
target.captureScreenWithName("#{orientation}_#{name}")
|
12
|
+
|
2
13
|
constructor: (@name) ->
|
3
14
|
if @anchor then target.waitForElement @anchor()
|
4
15
|
|
5
16
|
elements: {}
|
6
17
|
actions :
|
7
18
|
'Take a screenshot$' : ->
|
8
|
-
|
19
|
+
@takeScreenshot(@name)
|
9
20
|
|
10
21
|
'Take a screenshot named "([^"]*)"$' : (name) ->
|
11
|
-
|
22
|
+
@takeScreenshot(name)
|
12
23
|
|
13
24
|
'Tap "([^"]*)"$' : (element) ->
|
14
25
|
raise "Element '#{element}' not defined for the screen '#{@name}'" unless @elements[element]
|
@@ -29,12 +40,12 @@ class Screen
|
|
29
40
|
raise "Element '#{element}' not defined for the screen '#{@name}'" unless @elements[element]
|
30
41
|
@elements[element]().setValue ""
|
31
42
|
|
32
|
-
'Cancel the alert' : ->
|
43
|
+
'Cancel the alert$' : ->
|
33
44
|
alert = app.alert()
|
34
45
|
raise "No alert found to dismiss on screen '#{@name}'" if isNullElement alert
|
35
46
|
alert.cancelButton().tap()
|
36
47
|
|
37
|
-
'Confirm the alert' : ->
|
48
|
+
'Confirm the alert$' : ->
|
38
49
|
alert = app.alert()
|
39
50
|
raise "No alert found to dismiss on screen '#{@name}'" if isNullElement alert
|
40
51
|
alert.defaultButton().tap()
|
data/lib/version.rb
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,75 +1,70 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: zucchini-ios
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 6
|
8
|
+
- 0
|
9
|
+
version: 0.6.0
|
6
10
|
platform: ruby
|
7
|
-
authors:
|
11
|
+
authors:
|
8
12
|
- Vasily Mikhaylichenko
|
9
13
|
- Rajesh Kumar
|
10
14
|
- Kevin O'Neill
|
11
15
|
autorequire:
|
12
16
|
bindir: bin
|
13
17
|
cert_chain: []
|
14
|
-
|
15
|
-
|
16
|
-
|
18
|
+
|
19
|
+
date: 2013-03-31 00:00:00 +11:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
17
23
|
name: clamp
|
18
|
-
requirement: !ruby/object:Gem::Requirement
|
19
|
-
none: false
|
20
|
-
requirements:
|
21
|
-
- - ! '>='
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: '0'
|
24
|
-
type: :runtime
|
25
24
|
prerelease: false
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
33
35
|
name: rspec
|
34
|
-
requirement: !ruby/object:Gem::Requirement
|
35
|
-
none: false
|
36
|
-
requirements:
|
37
|
-
- - ! '>='
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '0'
|
40
|
-
type: :development
|
41
36
|
prerelease: false
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
name: watchr
|
50
|
-
requirement: !ruby/object:Gem::Requirement
|
51
|
-
none: false
|
52
|
-
requirements:
|
53
|
-
- - ! '>='
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version: '0'
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
56
44
|
type: :development
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: watchr
|
57
48
|
prerelease: false
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
version: "0"
|
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:
|
67
60
|
- vaskas@zucchiniframework.org
|
68
|
-
executables:
|
61
|
+
executables:
|
69
62
|
- zucchini
|
70
63
|
extensions: []
|
64
|
+
|
71
65
|
extra_rdoc_files: []
|
72
|
-
|
66
|
+
|
67
|
+
files:
|
73
68
|
- .gitignore
|
74
69
|
- .travis.yml
|
75
70
|
- Gemfile
|
@@ -96,29 +91,6 @@ files:
|
|
96
91
|
- lib/uia/base.coffee
|
97
92
|
- lib/uia/screen.coffee
|
98
93
|
- 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_setup/feature_one/feature.zucchini
|
106
|
-
- spec/sample_setup/feature_one/masks/retina_ios5/06_sign up_spinner.png
|
107
|
-
- spec/sample_setup/feature_one/reference/retina_ios5/06_sign up_spinner.png
|
108
|
-
- spec/sample_setup/feature_one/reference/retina_ios5/06_sign up_spinner_error.png
|
109
|
-
- spec/sample_setup/feature_one/run_data/Run 1/06_sign up_spinner.png
|
110
|
-
- spec/sample_setup/feature_three/feature.zucchini
|
111
|
-
- spec/sample_setup/feature_two/feature.zucchini
|
112
|
-
- spec/sample_setup/feature_two/masks/retina_ios5/06_sign up_spinner.png
|
113
|
-
- spec/sample_setup/feature_two/reference/retina_ios5/06_sign up_spinner.png
|
114
|
-
- spec/sample_setup/feature_two/reference/retina_ios5/06_sign up_spinner_error.png
|
115
|
-
- spec/sample_setup/feature_two/run_data/Run 1/06_sign up_spinner.png
|
116
|
-
- spec/sample_setup/support/config.yml
|
117
|
-
- spec/sample_setup/support/lib/helpers.coffee
|
118
|
-
- spec/sample_setup/support/masks/retina_ios5.png
|
119
|
-
- spec/sample_setup/support/screens/splash.coffee
|
120
|
-
- spec/sample_setup_2/support/config.yml
|
121
|
-
- spec/spec_helper.rb
|
122
94
|
- templates/feature/feature.zucchini
|
123
95
|
- templates/feature/masks/retina_ios5/.gitkeep
|
124
96
|
- templates/feature/pending/retina_ios5/.gitkeep
|
@@ -128,56 +100,41 @@ files:
|
|
128
100
|
- templates/project/features/support/config.yml
|
129
101
|
- templates/project/features/support/lib/helpers.coffee
|
130
102
|
- templates/project/features/support/masks/ipad_ios5.png
|
103
|
+
- templates/project/features/support/masks/ipad_retina_ios6.png
|
131
104
|
- templates/project/features/support/masks/low_ios4.png
|
132
105
|
- templates/project/features/support/masks/retina_ios5.png
|
133
106
|
- templates/project/features/support/screens/welcome.coffee
|
134
|
-
|
107
|
+
has_rdoc: true
|
135
108
|
homepage: http://www.zucchiniframework.org
|
136
|
-
licenses:
|
109
|
+
licenses:
|
137
110
|
- BSD
|
138
111
|
post_install_message:
|
139
112
|
rdoc_options: []
|
140
|
-
|
113
|
+
|
114
|
+
require_paths:
|
141
115
|
- lib
|
142
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
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
124
|
version: 1.9.2
|
148
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
125
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
version: "0"
|
154
132
|
requirements: []
|
133
|
+
|
155
134
|
rubyforge_project:
|
156
|
-
rubygems_version: 1.
|
135
|
+
rubygems_version: 1.3.6
|
157
136
|
signing_key:
|
158
137
|
specification_version: 3
|
159
138
|
summary: Functional testing framework for iOS-powered devices
|
160
|
-
test_files:
|
161
|
-
|
162
|
-
- spec/lib/detector_spec.rb
|
163
|
-
- spec/lib/feature_spec.rb
|
164
|
-
- spec/lib/generator_spec.rb
|
165
|
-
- spec/lib/report_spec.rb
|
166
|
-
- spec/lib/screenshot_spec.rb
|
167
|
-
- spec/sample_setup/feature_one/feature.zucchini
|
168
|
-
- spec/sample_setup/feature_one/masks/retina_ios5/06_sign up_spinner.png
|
169
|
-
- spec/sample_setup/feature_one/reference/retina_ios5/06_sign up_spinner.png
|
170
|
-
- spec/sample_setup/feature_one/reference/retina_ios5/06_sign up_spinner_error.png
|
171
|
-
- spec/sample_setup/feature_one/run_data/Run 1/06_sign up_spinner.png
|
172
|
-
- spec/sample_setup/feature_three/feature.zucchini
|
173
|
-
- spec/sample_setup/feature_two/feature.zucchini
|
174
|
-
- spec/sample_setup/feature_two/masks/retina_ios5/06_sign up_spinner.png
|
175
|
-
- spec/sample_setup/feature_two/reference/retina_ios5/06_sign up_spinner.png
|
176
|
-
- spec/sample_setup/feature_two/reference/retina_ios5/06_sign up_spinner_error.png
|
177
|
-
- spec/sample_setup/feature_two/run_data/Run 1/06_sign up_spinner.png
|
178
|
-
- spec/sample_setup/support/config.yml
|
179
|
-
- spec/sample_setup/support/lib/helpers.coffee
|
180
|
-
- spec/sample_setup/support/masks/retina_ios5.png
|
181
|
-
- spec/sample_setup/support/screens/splash.coffee
|
182
|
-
- spec/sample_setup_2/support/config.yml
|
183
|
-
- spec/spec_helper.rb
|
139
|
+
test_files: []
|
140
|
+
|
data/spec/lib/config_spec.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Zucchini::Config do
|
4
|
-
before(:all) { Zucchini::Config.base_path = "spec/sample_setup" }
|
5
|
-
|
6
|
-
describe "device" do
|
7
|
-
context "device present in config.yml" do
|
8
|
-
it "should return the device hash" do
|
9
|
-
Zucchini::Config.device("My iDevice").should eq({:name =>"My iDevice", :udid =>"lolffb28d74a6fraj2156090784avasc50725dd0", :screen =>"ipad_ios5"})
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
context "device not present in config.yml" do
|
14
|
-
it "should raise an error" do
|
15
|
-
expect { Zucchini::Config.device("My Android Phone")}.to raise_error "Device not listed in config.yml"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
context "default device" do
|
20
|
-
it "should use default device if device name argument is nil" do
|
21
|
-
Zucchini::Config.device(nil).should eq({:name =>"Default Device", :screen =>"low_ios5", :udid => nil})
|
22
|
-
end
|
23
|
-
|
24
|
-
it "should raise error if no default device provided" do
|
25
|
-
Zucchini::Config.base_path = "spec/sample_setup_2"
|
26
|
-
expect { Zucchini::Config.device(nil) }.to raise_error "Neither default device nor ZUCCHINI_DEVICE environment variable was set"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe "url" do
|
32
|
-
it "should return a full URL string for a given server name" do
|
33
|
-
Zucchini::Config.url('backend', '/api').should eq "http://192.168.1.2:8080/api"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/spec/lib/detector_spec.rb
DELETED
@@ -1,52 +0,0 @@
|
|
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
|
data/spec/lib/feature_spec.rb
DELETED
@@ -1,69 +0,0 @@
|
|
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
|
data/spec/lib/generator_spec.rb
DELETED
@@ -1,27 +0,0 @@
|
|
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
|
data/spec/lib/report_spec.rb
DELETED
@@ -1,31 +0,0 @@
|
|
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
|
data/spec/lib/screenshot_spec.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'digest/md5'
|
3
|
-
|
4
|
-
def md5(blob)
|
5
|
-
Digest::MD5.hexdigest(blob)
|
6
|
-
end
|
7
|
-
|
8
|
-
describe Zucchini::Screenshot do
|
9
|
-
let (:device) { { :name => "iPhone 4S", :screen => "retina_ios5", :udid => "rspec987654" } }
|
10
|
-
let (:base_path) { "spec/sample_setup/feature_one" }
|
11
|
-
let (:original_path) { "#{base_path}/run_data/Run\ 1/06_sign\ up_spinner.png" }
|
12
|
-
|
13
|
-
let (:screenshot) do
|
14
|
-
screenshot = Zucchini::Screenshot.new(original_path, device)
|
15
|
-
screenshot.masked_paths = { :globally => "#{base_path}/globally_masked.png", :specifically => "#{base_path}/specifically_masked.png" }
|
16
|
-
screenshot.mask
|
17
|
-
screenshot
|
18
|
-
end
|
19
|
-
|
20
|
-
after(:all) do
|
21
|
-
screenshot.masked_paths.each { |k, path| FileUtils.rm(path) }
|
22
|
-
FileUtils.rm_rf("#{base_path}/run_data/Masked")
|
23
|
-
FileUtils.rm_rf(screenshot.diff_path)
|
24
|
-
end
|
25
|
-
|
26
|
-
describe "mask" do
|
27
|
-
before(:all) do
|
28
|
-
@md5 = {
|
29
|
-
:original => md5(File.read(original_path)),
|
30
|
-
:globally_masked => md5(File.read(screenshot.masked_paths[:globally])),
|
31
|
-
:specifically_masked => md5(File.read(screenshot.masked_paths[:specifically]))
|
32
|
-
}
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should apply a standard global mask based on the screen" do
|
36
|
-
File.exists?(screenshot.masked_paths[:globally]).should be true
|
37
|
-
@md5[:globally_masked].should_not be_equal @md5[:original]
|
38
|
-
end
|
39
|
-
|
40
|
-
it "should apply a screenshot-specific mask if it exists" do
|
41
|
-
File.exists?(screenshot.masked_paths[:specifically]).should be true
|
42
|
-
@md5[:specifically_masked].should_not be_equal @md5[:original]
|
43
|
-
@md5[:specifically_masked].should_not be_equal @md5[:globally_masked]
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe "compare" do
|
48
|
-
context "images are identical" do
|
49
|
-
it "should have a passed indicator in the diff" do
|
50
|
-
screenshot.compare
|
51
|
-
screenshot.diff.should eq [:passed, nil]
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
context "images are different" do
|
56
|
-
it "should have a failed indicator in the diff" do
|
57
|
-
screenshot.stub!(:mask_reference)
|
58
|
-
screenshot.test_path = "#{base_path}/reference/#{device[:screen]}/06_sign\ up_spinner_error.png"
|
59
|
-
screenshot.compare
|
60
|
-
screenshot.diff.should eq [:failed, "3017\n"]
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
describe "mask reference" do
|
66
|
-
it "should create masked versions of reference screenshots" do
|
67
|
-
screenshot.mask_reference
|
68
|
-
|
69
|
-
File.exists?(screenshot.test_path).should be_true
|
70
|
-
md5(File.read(screenshot.test_path)).should_not be_equal md5(File.read("#{base_path}/reference/#{device[:screen]}/06_sign\ up_spinner.png"))
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
# Start on the "Splash" screen
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -1 +0,0 @@
|
|
1
|
-
# Start on the "Menu" screen
|
@@ -1 +0,0 @@
|
|
1
|
-
# Start on the "Menu" screen
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/spec/spec_helper.rb
DELETED
@@ -1,18 +0,0 @@
|
|
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
|
data/zucchini-ios.gemspec
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require 'version'
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "zucchini-ios"
|
7
|
-
s.version = Zucchini::VERSION
|
8
|
-
s.date = Date.today.to_s
|
9
|
-
s.platform = Gem::Platform::RUBY
|
10
|
-
s.authors = ["Vasily Mikhaylichenko", "Rajesh Kumar", "Kevin O'Neill"]
|
11
|
-
s.license = "BSD"
|
12
|
-
s.email = ["vaskas@zucchiniframework.org"]
|
13
|
-
s.homepage = "http://www.zucchiniframework.org"
|
14
|
-
s.summary = %q{Functional testing framework for iOS-powered devices}
|
15
|
-
s.description = %q{Zucchini follows simple walkthrough scenarios for your iOS app, takes screenshots and compares them to the reference ones.}
|
16
|
-
|
17
|
-
s.add_runtime_dependency "clamp"
|
18
|
-
s.add_development_dependency "rspec"
|
19
|
-
s.add_development_dependency "watchr"
|
20
|
-
|
21
|
-
s.files = `git ls-files | grep -vE '(web|.watchr)'`.split("\n")
|
22
|
-
s.test_files = `git ls-files -- spec/*`.split("\n")
|
23
|
-
s.executables = %w(zucchini)
|
24
|
-
s.require_paths = ["lib"]
|
25
|
-
|
26
|
-
s.required_ruby_version = '>= 1.9.2'
|
27
|
-
end
|