zucchini-ios 0.6.1 → 0.6.2
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/.gitignore +17 -1
- data/CHANGELOG.md +28 -15
- data/README.md +23 -19
- data/Rakefile +1 -0
- data/bin/zucchini +4 -11
- data/lib/zucchini.rb +12 -0
- data/lib/{approver.rb → zucchini/approver.rb} +0 -0
- data/lib/{config.rb → zucchini/config.rb} +0 -0
- data/lib/{detector.rb → zucchini/detector.rb} +0 -0
- data/lib/{feature.rb → zucchini/feature.rb} +25 -22
- data/lib/{generator.rb → zucchini/generator.rb} +5 -5
- data/lib/{report.rb → zucchini/report.rb} +3 -4
- data/lib/zucchini/report/css/zucchini.report.css +241 -0
- data/lib/{report → zucchini/report}/js/jquery.effects.core.js +0 -0
- data/lib/{report → zucchini/report}/js/jquery.js +0 -0
- data/lib/{report → zucchini/report}/js/jquery.ui.core.js +0 -0
- data/lib/zucchini/report/js/zucchini.report.js +59 -0
- data/lib/zucchini/report/template.erb.html +47 -0
- data/lib/{report → zucchini/report}/view.rb +0 -0
- data/lib/{runner.rb → zucchini/runner.rb} +0 -0
- data/lib/{screenshot.rb → zucchini/screenshot.rb} +77 -30
- data/lib/{uia → zucchini/uia}/base.coffee +0 -1
- data/lib/{uia → zucchini/uia}/screen.coffee +5 -4
- data/lib/{version.rb → zucchini/version.rb} +1 -1
- data/spec/lib/{config_spec.rb → zucchini/config_spec.rb} +0 -0
- data/spec/lib/{detector_spec.rb → zucchini/detector_spec.rb} +0 -0
- data/spec/lib/{feature_spec.rb → zucchini/feature_spec.rb} +0 -0
- data/spec/lib/{generator_spec.rb → zucchini/generator_spec.rb} +0 -0
- data/spec/lib/{report_spec.rb → zucchini/report_spec.rb} +0 -0
- data/spec/lib/zucchini/screenshot_spec.rb +164 -0
- data/spec/sample_setup/feature_one/run_data/Run 1/06_sign up_spinner.png b/data/spec/sample_setup/feature_one/run_data/Run 1/06_splash-screen_sign → up_spinner.png +0 -0
- data/spec/sample_setup/support/masks/splash.png +0 -0
- data/spec/spec_helper.rb +14 -10
- data/zucchini-ios.gemspec +8 -9
- metadata +58 -36
- data/lib/report/css/zucchini.report.css +0 -239
- data/lib/report/js/zucchini.report.js +0 -59
- data/lib/report/template.erb +0 -47
- data/spec/lib/screenshot_spec.rb +0 -109
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
|
+
## 0.6.2 / 2013-08-07
|
|
2
|
+
* Implement screen specific masks - [@phatmann][], [#24][]
|
|
3
|
+
* Rearrange source files in a more conventional gem way - [@vaskas][], [#25][]
|
|
4
|
+
* Fix report UI in Firefox - [@vaskas][], [#26][]
|
|
5
|
+
* Do not squash landscape screenshots in the report - [@phatmann][]
|
|
6
|
+
* Remove 1 second delay after screen is loaded - [@phatmann][], [#23][]
|
|
7
|
+
|
|
1
8
|
## 0.6.1 / 2013-07-28
|
|
2
|
-
* Add Rotate device screen action - [@phatmann][], [#19][]
|
|
9
|
+
* Add `Rotate device` screen action - [@phatmann][], [#19][]
|
|
3
10
|
* Fix screenshot code to work with the latest version of ImageMagick - [@phatmann][], [#17][]
|
|
4
11
|
* Raise error if screen anchor is not found - [@phatmann][], [#16][]
|
|
5
12
|
|
|
6
13
|
## 0.6.0 / 2013-03-30
|
|
7
14
|
* Add a mask for retina iPad - [@phatmann][], [#8][]
|
|
8
|
-
* Fix alert Confirm / Cancel actions so that they match to end of line - [@phatmann][], [#9][]
|
|
15
|
+
* Fix alert `Confirm` / `Cancel` actions so that they match to end of line - [@phatmann][], [#9][]
|
|
9
16
|
* Allow app path to be set via an environment variable - [@phatmann][], [#10][]
|
|
10
|
-
* Screenshot orientation matching device orientation - [@Jaco][]
|
|
17
|
+
* Screenshot orientation matching device orientation - [@Jaco-Pretorius][], [#13][]
|
|
11
18
|
|
|
12
19
|
## 0.5.9 / 2013-02-04
|
|
13
20
|
* Add default device flag - [@insanehunter][], [#6][]
|
|
@@ -29,22 +36,28 @@
|
|
|
29
36
|
* Fix Instruments template detection for Xcode 4.5 - [@vaskas][]
|
|
30
37
|
* Fixed config to take relative paths to the app - [@coomans][]
|
|
31
38
|
* Quote path params in call to instruments - [@kconnor][]
|
|
39
|
+
|
|
32
40
|
<!--- 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
|
|
41
|
+
[#1]: https://github.com/zucchini-src/zucchini/issues/1
|
|
42
|
+
[#3]: https://github.com/zucchini-src/zucchini/issues/3
|
|
43
|
+
[#5]: https://github.com/zucchini-src/zucchini/issues/5
|
|
44
|
+
[#6]: https://github.com/zucchini-src/zucchini/issues/6
|
|
45
|
+
[#8]: https://github.com/zucchini-src/zucchini/issues/8
|
|
46
|
+
[#9]: https://github.com/zucchini-src/zucchini/issues/9
|
|
47
|
+
[#10]: https://github.com/zucchini-src/zucchini/issues/10
|
|
48
|
+
[#13]: https://github.com/zucchini-src/zucchini/issues/13
|
|
49
|
+
[#16]: https://github.com/zucchini-src/zucchini/issues/16
|
|
50
|
+
[#17]: https://github.com/zucchini-src/zucchini/issues/17
|
|
51
|
+
[#19]: https://github.com/zucchini-src/zucchini/issues/19
|
|
52
|
+
[#23]: https://github.com/zucchini-src/zucchini/issues/23
|
|
53
|
+
[#24]: https://github.com/zucchini-src/zucchini/issues/24
|
|
54
|
+
[#25]: https://github.com/zucchini-src/zucchini/issues/25
|
|
55
|
+
[#26]: https://github.com/zucchini-src/zucchini/issues/26
|
|
56
|
+
|
|
44
57
|
[@Jaco-Pretorius]: https://github.com/Jaco-Pretorius
|
|
45
58
|
[@NathanSudell]: https://github.com/NathanSudell
|
|
46
59
|
[@coomans]: https://github.com/coomans
|
|
47
60
|
[@insanehunter]: https://github.com/insanehunter
|
|
48
61
|
[@kconnor]: https://github.com/kconnor
|
|
49
62
|
[@phatmann]: https://github.com/phatmann
|
|
50
|
-
[@vaskas]: https://github.com/vaskas
|
|
63
|
+
[@vaskas]: https://github.com/vaskas
|
data/README.md
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
|
+
# Zucchini
|
|
2
|
+
|
|
1
3
|
[](http://travis-ci.org/zucchini-src/zucchini)
|
|
4
|
+
[](https://coveralls.io/r/zucchini-src/zucchini)
|
|
5
|
+
[](http://badge.fury.io/rb/zucchini-ios)
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
2
8
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
3. Ruby >= 1.9.2
|
|
8
|
-
4. A few command line tools:
|
|
9
|
+
1. Mac OS X 10.6 or newer
|
|
10
|
+
2. XCode 4.2 or newer
|
|
11
|
+
3. Ruby 1.9.3 or newer
|
|
12
|
+
4. A few command line tools which can be installed with [homebrew](http://brew.sh/):
|
|
9
13
|
|
|
10
14
|
```
|
|
11
15
|
brew update && brew install imagemagick node
|
|
12
16
|
npm install -g coffee-script
|
|
13
17
|
```
|
|
14
18
|
|
|
15
|
-
Start using Zucchini
|
|
16
|
-
|
|
19
|
+
## Start using Zucchini
|
|
20
|
+
|
|
17
21
|
```
|
|
18
22
|
gem install zucchini-ios
|
|
19
23
|
```
|
|
@@ -33,13 +37,13 @@ Create a feature scaffold for your first feature:
|
|
|
33
37
|
zucchini generate --feature /path/to/my_project/features/my_feature
|
|
34
38
|
```
|
|
35
39
|
|
|
36
|
-
Start hacking by modifying features/my_feature/feature.zucchini and features/support/screens/welcome.coffee
|
|
40
|
+
Start hacking by modifying `features/my_feature/feature.zucchini` and `features/support/screens/welcome.coffee`.
|
|
37
41
|
|
|
38
42
|
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
43
|
|
|
40
|
-
Running on the device
|
|
41
|
-
|
|
42
|
-
Add your device to features/support/config.yml
|
|
44
|
+
## Running on the device
|
|
45
|
+
|
|
46
|
+
Add your device to `features/support/config.yml`.
|
|
43
47
|
|
|
44
48
|
The [udidetect](https://github.com/vaskas/udidetect) utility comes in handy if you plan to add devices from time to time: `udidetect -z`.
|
|
45
49
|
|
|
@@ -47,17 +51,17 @@ The [udidetect](https://github.com/vaskas/udidetect) utility comes in handy if y
|
|
|
47
51
|
ZUCCHINI_DEVICE="My Device" zucchini run /path/to/my_feature
|
|
48
52
|
```
|
|
49
53
|
|
|
50
|
-
Running on the iOS Simulator
|
|
51
|
-
|
|
52
|
-
We
|
|
54
|
+
## Running on the iOS Simulator
|
|
55
|
+
|
|
56
|
+
We encourage you to run your Zucchini features on real hardware. However you can also run them on the iOS Simulator.
|
|
53
57
|
|
|
54
|
-
First off, modify your features/support/config.yml to include the path to your compiled app, e.g.
|
|
58
|
+
First off, modify your `features/support/config.yml` to include the path to your compiled app, e.g.
|
|
55
59
|
|
|
56
60
|
```
|
|
57
61
|
app: ./Build/Products/Debug-iphonesimulator/CoreDataBooks.app
|
|
58
62
|
```
|
|
59
63
|
|
|
60
|
-
Secondly, add an
|
|
64
|
+
Secondly, add an `iOS Simulator` entry to the devices section (no UDID needed) and make sure you provide the actual value for 'screen' based on your iOS Simulator settings:
|
|
61
65
|
|
|
62
66
|
```
|
|
63
67
|
devices:
|
|
@@ -89,8 +93,8 @@ Run Zucchini and watch the simulator go!
|
|
|
89
93
|
ZUCCHINI_DEVICE="iOS Simulator" zucchini run /path/to/my_feature
|
|
90
94
|
```
|
|
91
95
|
|
|
92
|
-
See also
|
|
93
|
-
|
|
96
|
+
## See also
|
|
97
|
+
|
|
94
98
|
```
|
|
95
99
|
zucchini --help
|
|
96
100
|
zucchini run --help
|
data/Rakefile
CHANGED
data/bin/zucchini
CHANGED
|
@@ -3,20 +3,13 @@
|
|
|
3
3
|
require 'clamp'
|
|
4
4
|
require 'fileutils'
|
|
5
5
|
|
|
6
|
-
$LOAD_PATH << File.expand_path("
|
|
7
|
-
require 'lib/
|
|
8
|
-
|
|
9
|
-
require 'lib/report'
|
|
10
|
-
require 'lib/feature'
|
|
11
|
-
require 'lib/detector'
|
|
12
|
-
require 'lib/runner'
|
|
13
|
-
require 'lib/generator'
|
|
14
|
-
require 'lib/approver'
|
|
15
|
-
|
|
6
|
+
$LOAD_PATH << File.expand_path("../..", __FILE__)
|
|
7
|
+
require 'lib/zucchini'
|
|
8
|
+
|
|
16
9
|
class Zucchini::App < Clamp::Command
|
|
17
10
|
subcommand "generate", "Generate a project scaffold", Zucchini::Generator
|
|
18
11
|
subcommand "run", "Run zucchini", Zucchini::Runner
|
|
19
12
|
subcommand "approve", "Update reference screenshots", Zucchini::Approver
|
|
20
13
|
end
|
|
21
14
|
|
|
22
|
-
Zucchini::App.run
|
|
15
|
+
Zucchini::App.run
|
data/lib/zucchini.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__))
|
|
2
|
+
|
|
3
|
+
module Zucchini
|
|
4
|
+
require 'zucchini/config'
|
|
5
|
+
require 'zucchini/screenshot'
|
|
6
|
+
require 'zucchini/report'
|
|
7
|
+
require 'zucchini/feature'
|
|
8
|
+
require 'zucchini/detector'
|
|
9
|
+
require 'zucchini/runner'
|
|
10
|
+
require 'zucchini/generator'
|
|
11
|
+
require 'zucchini/approver'
|
|
12
|
+
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -3,20 +3,20 @@ class Zucchini::Feature
|
|
|
3
3
|
attr_accessor :device
|
|
4
4
|
attr_accessor :template
|
|
5
5
|
attr_accessor :stats
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
attr_reader :succeeded
|
|
8
|
-
attr_reader :name
|
|
9
|
-
|
|
8
|
+
attr_reader :name
|
|
9
|
+
|
|
10
10
|
def initialize(path)
|
|
11
11
|
@path = path
|
|
12
12
|
@device = nil
|
|
13
13
|
@succeeded = false
|
|
14
14
|
@name = File.basename(path)
|
|
15
15
|
end
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
def run_data_path
|
|
18
|
-
"#{@path}/run_data"
|
|
19
|
-
end
|
|
18
|
+
"#{@path}/run_data"
|
|
19
|
+
end
|
|
20
20
|
|
|
21
21
|
def unmatched_pending_screenshots
|
|
22
22
|
Dir.glob("#{@path}/pending/#{@device[:screen]}/[^0-9]*.png").map do |file|
|
|
@@ -26,53 +26,56 @@ class Zucchini::Feature
|
|
|
26
26
|
screenshot
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
def screenshots(process = true)
|
|
31
31
|
@screenshots ||= Dir.glob("#{run_data_path}/Run\ 1/*.png").map do |file|
|
|
32
32
|
screenshot = Zucchini::Screenshot.new(file, @device)
|
|
33
33
|
if process
|
|
34
|
-
screenshot.rotate
|
|
35
34
|
screenshot.mask
|
|
36
35
|
screenshot.compare
|
|
37
36
|
end
|
|
38
37
|
screenshot
|
|
39
38
|
end + unmatched_pending_screenshots
|
|
40
39
|
end
|
|
41
|
-
|
|
40
|
+
|
|
42
41
|
def stats
|
|
43
42
|
@stats ||= screenshots.inject({:passed => [], :failed => [], :pending => []}) do |stats, s|
|
|
44
43
|
stats[s.diff[0]] << s
|
|
45
44
|
stats
|
|
46
45
|
end
|
|
47
|
-
end
|
|
48
|
-
|
|
46
|
+
end
|
|
47
|
+
|
|
49
48
|
def compile_js
|
|
50
|
-
zucchini_base_path = File.expand_path(
|
|
51
|
-
|
|
49
|
+
zucchini_base_path = File.expand_path(File.dirname(__FILE__))
|
|
50
|
+
|
|
52
51
|
feature_text = File.open("#{@path}/feature.zucchini").read.gsub(/\#.+[\z\n]?/,"").gsub(/\n/, "\\n")
|
|
53
52
|
File.open("#{run_data_path}/feature.coffee", "w+") { |f| f.write("Zucchini.run('#{feature_text}')") }
|
|
54
53
|
|
|
55
|
-
cs_paths = "#{zucchini_base_path}/
|
|
54
|
+
cs_paths = "#{zucchini_base_path}/uia #{@path}/../support/screens"
|
|
56
55
|
cs_paths += " #{@path}/../support/lib" if File.exists?("#{@path}/../support/lib")
|
|
57
56
|
cs_paths += " #{run_data_path}/feature.coffee"
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
|
|
58
|
+
compile_cmd = "coffee -o #{run_data_path} -j #{run_data_path}/feature.js -c #{cs_paths}"
|
|
59
|
+
system compile_cmd
|
|
60
|
+
unless $?.exitstatus == 0
|
|
61
|
+
raise "Error compiling a feature file: #{compile_cmd}"
|
|
62
|
+
end
|
|
60
63
|
end
|
|
61
64
|
|
|
62
65
|
def collect
|
|
63
|
-
with_setup do
|
|
66
|
+
with_setup do
|
|
64
67
|
`rm -rf #{run_data_path}/*`
|
|
65
68
|
compile_js
|
|
66
|
-
|
|
69
|
+
|
|
67
70
|
device_params = (@device[:name] == "iOS Simulator") ? "" : "-w #{@device[:udid]}"
|
|
68
|
-
|
|
71
|
+
|
|
69
72
|
begin
|
|
70
73
|
out = `instruments #{device_params} -t "#{@template}" "#{Zucchini::Config.app}" -e UIASCRIPT "#{run_data_path}/feature.js" -e UIARESULTSPATH "#{run_data_path}" 2>&1`
|
|
71
74
|
puts out
|
|
72
75
|
# Hack. Instruments don't issue error return codes when JS exceptions occur
|
|
73
76
|
raise "Instruments run error" if (out.match /JavaScript error/) || (out.match /Instruments\ .{0,5}\ Error\ :/ )
|
|
74
77
|
ensure
|
|
75
|
-
`rm -rf instrumentscli*.trace`
|
|
78
|
+
`rm -rf instrumentscli*.trace`
|
|
76
79
|
end
|
|
77
80
|
end
|
|
78
81
|
end
|
|
@@ -84,8 +87,8 @@ class Zucchini::Feature
|
|
|
84
87
|
|
|
85
88
|
def with_setup
|
|
86
89
|
setup = "#{@path}/setup.rb"
|
|
87
|
-
if File.exists?(setup)
|
|
88
|
-
require setup
|
|
90
|
+
if File.exists?(setup)
|
|
91
|
+
require setup
|
|
89
92
|
begin
|
|
90
93
|
Setup.before { yield }
|
|
91
94
|
ensure
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
class Zucchini::Generator < Clamp::Command
|
|
2
2
|
option %W(-p --project), :flag, "Generate a project"
|
|
3
3
|
option %W(-f --feature), :flag, "Generate a feature"
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
parameter "PATH", "Path"
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
def templates_path
|
|
8
|
-
File.expand_path("#{File.dirname(__FILE__)}
|
|
8
|
+
File.expand_path("#{File.dirname(__FILE__)}/../../templates")
|
|
9
9
|
end
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
def execute
|
|
12
12
|
if project?
|
|
13
13
|
FileUtils.mkdir_p(path)
|
|
@@ -15,4 +15,4 @@ class Zucchini::Generator < Clamp::Command
|
|
|
15
15
|
elsif feature? then FileUtils.cp_r("#{templates_path}/feature", path)
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
|
-
end
|
|
18
|
+
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require 'erb'
|
|
2
|
-
require '
|
|
2
|
+
require 'zucchini/report/view'
|
|
3
3
|
|
|
4
4
|
class Zucchini::Report
|
|
5
5
|
|
|
@@ -11,7 +11,7 @@ class Zucchini::Report
|
|
|
11
11
|
def text
|
|
12
12
|
@features.map do |f|
|
|
13
13
|
failed_list = f.stats[:failed].empty? ? "" : "\n\nFailed:\n" + f.stats[:failed].map { |s| " #{s.file_name}: #{s.diff[1]}" }.join
|
|
14
|
-
summary
|
|
14
|
+
summary = f.stats.map { |key, set| "#{set.length.to_s} #{key}" }.join(", ")
|
|
15
15
|
|
|
16
16
|
"#{f.name}:\n#{summary}#{failed_list}"
|
|
17
17
|
end.join("\n\n")
|
|
@@ -19,7 +19,7 @@ class Zucchini::Report
|
|
|
19
19
|
|
|
20
20
|
def html
|
|
21
21
|
@html ||= begin
|
|
22
|
-
template_path = File.expand_path("#{File.dirname(__FILE__)}/report/template.erb")
|
|
22
|
+
template_path = File.expand_path("#{File.dirname(__FILE__)}/report/template.erb.html")
|
|
23
23
|
|
|
24
24
|
view = Zucchini::ReportView.new(@features, @ci)
|
|
25
25
|
compiled = (ERB.new(File.open(template_path).read)).result(view.get_binding)
|
|
@@ -37,5 +37,4 @@ class Zucchini::Report
|
|
|
37
37
|
def open; system "open #{@html_path}"; end
|
|
38
38
|
|
|
39
39
|
def log(buf); puts buf; end
|
|
40
|
-
|
|
41
40
|
end
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
html {
|
|
2
|
+
font-family: Myriad Pro, sans-serif;
|
|
3
|
+
}
|
|
4
|
+
body {
|
|
5
|
+
margin: 0;
|
|
6
|
+
}
|
|
7
|
+
tr {
|
|
8
|
+
text-align: center;
|
|
9
|
+
}
|
|
10
|
+
td {
|
|
11
|
+
padding: 2px;
|
|
12
|
+
}
|
|
13
|
+
dl {
|
|
14
|
+
-webkit-margin-before: 0;
|
|
15
|
+
}
|
|
16
|
+
dd {
|
|
17
|
+
-webkit-margin-start: 0;
|
|
18
|
+
}
|
|
19
|
+
h1 {
|
|
20
|
+
margin: 16px;
|
|
21
|
+
font-weight: normal;
|
|
22
|
+
font-size: 24px;
|
|
23
|
+
}
|
|
24
|
+
h1 .time {
|
|
25
|
+
margin-left: 10px;
|
|
26
|
+
opacity: 0.5;
|
|
27
|
+
}
|
|
28
|
+
h3 {
|
|
29
|
+
margin: 0 0 6px 4px;
|
|
30
|
+
font-size: 24px;
|
|
31
|
+
width: 763px;
|
|
32
|
+
padding: 0;
|
|
33
|
+
float: left;
|
|
34
|
+
text-shadow: 1px 1px 1px white;
|
|
35
|
+
}
|
|
36
|
+
.indicators {
|
|
37
|
+
font-size: 12px;
|
|
38
|
+
width: 92px;
|
|
39
|
+
float: left;
|
|
40
|
+
margin: 5px 28px 5px 0;
|
|
41
|
+
-webkit-transition: all 0.1s ease-in-out;
|
|
42
|
+
}
|
|
43
|
+
.indicators div {
|
|
44
|
+
border-radius: 8px;
|
|
45
|
+
padding: 3px 8px;
|
|
46
|
+
margin-right: 5px;
|
|
47
|
+
float: right;
|
|
48
|
+
color: #FFF;
|
|
49
|
+
opacity: 0.8;
|
|
50
|
+
height: 11px;
|
|
51
|
+
line-height: 11px;
|
|
52
|
+
font-weight: bold;
|
|
53
|
+
}
|
|
54
|
+
.indicators div:hover {
|
|
55
|
+
-webkit-transition:opacity 0.3s ease-in-out;
|
|
56
|
+
}
|
|
57
|
+
.indicators .passed {
|
|
58
|
+
background: #65C400;
|
|
59
|
+
}
|
|
60
|
+
.indicators .failed {
|
|
61
|
+
background: #C20000;
|
|
62
|
+
}
|
|
63
|
+
.indicators .pending {
|
|
64
|
+
background: #F9E934;
|
|
65
|
+
color: #000;
|
|
66
|
+
}
|
|
67
|
+
.feature {
|
|
68
|
+
padding: 10px 9px 4px 9px;
|
|
69
|
+
border-radius: 5px;
|
|
70
|
+
width: 1012px;
|
|
71
|
+
margin: 15px 15px 24px 15px;
|
|
72
|
+
box-shadow: 0 0 4px rgba(0,0,0,0.2);
|
|
73
|
+
}
|
|
74
|
+
.ci .feature {
|
|
75
|
+
display: none;
|
|
76
|
+
}
|
|
77
|
+
.ci .first.feature {
|
|
78
|
+
display: block;
|
|
79
|
+
}
|
|
80
|
+
.buttons {
|
|
81
|
+
float: left;
|
|
82
|
+
width: 125px;
|
|
83
|
+
display: block;
|
|
84
|
+
}
|
|
85
|
+
.ci .buttons {
|
|
86
|
+
display: none;
|
|
87
|
+
}
|
|
88
|
+
.buttons a {
|
|
89
|
+
text-align: center;
|
|
90
|
+
width: 70px;
|
|
91
|
+
color: #484848;
|
|
92
|
+
text-decoration: none;
|
|
93
|
+
text-shadow: 0 1px 0 white;
|
|
94
|
+
font: bold 12px Helvetica, Arial, sans-serif;
|
|
95
|
+
margin-bottom: 6px;
|
|
96
|
+
line-height: 26px;
|
|
97
|
+
height: 25px;
|
|
98
|
+
display: block;
|
|
99
|
+
float: left;
|
|
100
|
+
padding: 0 5px;
|
|
101
|
+
background: -webkit-linear-gradient(top, #F4F4F4, #ECECEC);
|
|
102
|
+
border: solid 1px #D4D4D4;
|
|
103
|
+
border-radius: 5px;
|
|
104
|
+
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
|
105
|
+
-webkit-transition: border-color .218s;
|
|
106
|
+
cursor: pointer;
|
|
107
|
+
}
|
|
108
|
+
.buttons a.left {
|
|
109
|
+
border-radius: 5px 0 0 5px;
|
|
110
|
+
width: 50px;
|
|
111
|
+
float: left;
|
|
112
|
+
margin: 0;
|
|
113
|
+
}
|
|
114
|
+
.buttons a.right {
|
|
115
|
+
border-radius: 0 5px 5px 0;
|
|
116
|
+
width: 50px;
|
|
117
|
+
float: left;
|
|
118
|
+
position: relative;
|
|
119
|
+
left: -1px;
|
|
120
|
+
margin: 0;
|
|
121
|
+
}
|
|
122
|
+
.buttons a:hover {
|
|
123
|
+
border: solid 1px #7f7f7f;
|
|
124
|
+
color: #282828;
|
|
125
|
+
background: -webkit-linear-gradient(top, #ffffff, #dfdfdf);
|
|
126
|
+
}
|
|
127
|
+
.buttons a:active {
|
|
128
|
+
border: solid 1px #7f7f7f;
|
|
129
|
+
background: #d0d0d0;
|
|
130
|
+
background: -webkit-gradient(linear, left top, left bottom, from(#a8a8a8), color-stop(0.15, #c6c6c6), to(#d8d8d8));
|
|
131
|
+
background: -webkit-linear-gradient(top, #a8a8a8, #c6c6c6 15%, #d8d8d8);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.screen {
|
|
135
|
+
-webkit-transition:all 0.2s ease-in-out;
|
|
136
|
+
width: 990px;
|
|
137
|
+
height: 15px;
|
|
138
|
+
padding: 5px 0 5px 9px;
|
|
139
|
+
margin-bottom: 6px;
|
|
140
|
+
border-radius: 5px;
|
|
141
|
+
cursor: pointer;
|
|
142
|
+
overflow: hidden;
|
|
143
|
+
}
|
|
144
|
+
.screen.passed {
|
|
145
|
+
color: #65C400;
|
|
146
|
+
background-color: #DBFFB4;
|
|
147
|
+
border: 1px #65C400 solid;
|
|
148
|
+
border-left: 10px #65C400 solid;
|
|
149
|
+
}
|
|
150
|
+
.screen.passed img {
|
|
151
|
+
box-shadow: 0px 0px 4px #65C400;
|
|
152
|
+
}
|
|
153
|
+
.screen.failed {
|
|
154
|
+
color: #C20000;
|
|
155
|
+
background-color: #FFD6D6;
|
|
156
|
+
border: 1px #C20000 solid;
|
|
157
|
+
border-left: 10px #C20000 solid;
|
|
158
|
+
}
|
|
159
|
+
.screen.failed img {
|
|
160
|
+
box-shadow: 0px 0px 4px #C20000;
|
|
161
|
+
}
|
|
162
|
+
.screen.pending {
|
|
163
|
+
color: #F2CF32;
|
|
164
|
+
background-color: #FFFDBC;
|
|
165
|
+
border: 1px solid #F9E934;
|
|
166
|
+
border-left: 10px solid #F9E934;
|
|
167
|
+
}
|
|
168
|
+
.screen.pending img {
|
|
169
|
+
box-shadow: 0px 0px 4px #F9E934;
|
|
170
|
+
}
|
|
171
|
+
.screen dt {
|
|
172
|
+
color: #000;
|
|
173
|
+
font-size: 13px;
|
|
174
|
+
line-height: 17px;
|
|
175
|
+
margin: 0;
|
|
176
|
+
font-weight: normal;
|
|
177
|
+
}
|
|
178
|
+
.ci .screen dt {
|
|
179
|
+
position: relative;
|
|
180
|
+
z-index: 2;
|
|
181
|
+
}
|
|
182
|
+
.screen dd {
|
|
183
|
+
float: left;
|
|
184
|
+
margin: 0 10px 0 0;
|
|
185
|
+
-webkit-transition:all 0.3s ease-in-out;
|
|
186
|
+
opacity: 0;
|
|
187
|
+
position: relative;
|
|
188
|
+
top: -30px;
|
|
189
|
+
}
|
|
190
|
+
.screen dd.hidden {
|
|
191
|
+
visibility: hidden;
|
|
192
|
+
}
|
|
193
|
+
.screen.expanded, .ci .screen {
|
|
194
|
+
-webkit-transition:all 0.2s ease-in-out;
|
|
195
|
+
height: 510px;
|
|
196
|
+
}
|
|
197
|
+
.screen.expanded dd, .ci .screen dd {
|
|
198
|
+
opacity: 1.0;
|
|
199
|
+
-webkit-transition:all 0.3s ease-in-out;
|
|
200
|
+
}
|
|
201
|
+
.screen p {
|
|
202
|
+
margin-bottom: -3px;
|
|
203
|
+
padding: 5px;
|
|
204
|
+
font-size: 13px;
|
|
205
|
+
text-align: center;
|
|
206
|
+
font-weight: bold;
|
|
207
|
+
background-color: rgba(255, 255, 255, 0.5);;
|
|
208
|
+
border-radius: 5px;
|
|
209
|
+
opacity: 0.0;
|
|
210
|
+
position: relative;
|
|
211
|
+
z-index: 0;
|
|
212
|
+
}
|
|
213
|
+
.screen dd:hover p {
|
|
214
|
+
opacity: 1.0;
|
|
215
|
+
}
|
|
216
|
+
.ci .screen dd p {
|
|
217
|
+
opacity: 1.0;
|
|
218
|
+
background: transparent;
|
|
219
|
+
}
|
|
220
|
+
.screen img {
|
|
221
|
+
width: 320px;
|
|
222
|
+
position: relative;
|
|
223
|
+
}
|
|
224
|
+
.viewport {
|
|
225
|
+
clear: both;
|
|
226
|
+
}
|
|
227
|
+
.ci .viewport {
|
|
228
|
+
width: 1018px;
|
|
229
|
+
height: 530px;
|
|
230
|
+
overflow: scroll;
|
|
231
|
+
}
|
|
232
|
+
.ci .surface {
|
|
233
|
+
height: 530px;
|
|
234
|
+
width: 100000px;
|
|
235
|
+
position: relative;
|
|
236
|
+
}
|
|
237
|
+
.ci .surface .screen {
|
|
238
|
+
float: left;
|
|
239
|
+
margin-right: 10px;
|
|
240
|
+
position: relative;
|
|
241
|
+
}
|