zucchini-ios 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://api.travis-ci.org/zucchini-src/zucchini.png)](http://travis-ci.org/zucchini-src/zucchini)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/zucchini-src/zucchini/badge.png)](https://coveralls.io/r/zucchini-src/zucchini)
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/zucchini-ios.png)](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
|
+
}
|