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.
Files changed (39) hide show
  1. data/.gitignore +17 -1
  2. data/CHANGELOG.md +28 -15
  3. data/README.md +23 -19
  4. data/Rakefile +1 -0
  5. data/bin/zucchini +4 -11
  6. data/lib/zucchini.rb +12 -0
  7. data/lib/{approver.rb → zucchini/approver.rb} +0 -0
  8. data/lib/{config.rb → zucchini/config.rb} +0 -0
  9. data/lib/{detector.rb → zucchini/detector.rb} +0 -0
  10. data/lib/{feature.rb → zucchini/feature.rb} +25 -22
  11. data/lib/{generator.rb → zucchini/generator.rb} +5 -5
  12. data/lib/{report.rb → zucchini/report.rb} +3 -4
  13. data/lib/zucchini/report/css/zucchini.report.css +241 -0
  14. data/lib/{report → zucchini/report}/js/jquery.effects.core.js +0 -0
  15. data/lib/{report → zucchini/report}/js/jquery.js +0 -0
  16. data/lib/{report → zucchini/report}/js/jquery.ui.core.js +0 -0
  17. data/lib/zucchini/report/js/zucchini.report.js +59 -0
  18. data/lib/zucchini/report/template.erb.html +47 -0
  19. data/lib/{report → zucchini/report}/view.rb +0 -0
  20. data/lib/{runner.rb → zucchini/runner.rb} +0 -0
  21. data/lib/{screenshot.rb → zucchini/screenshot.rb} +77 -30
  22. data/lib/{uia → zucchini/uia}/base.coffee +0 -1
  23. data/lib/{uia → zucchini/uia}/screen.coffee +5 -4
  24. data/lib/{version.rb → zucchini/version.rb} +1 -1
  25. data/spec/lib/{config_spec.rb → zucchini/config_spec.rb} +0 -0
  26. data/spec/lib/{detector_spec.rb → zucchini/detector_spec.rb} +0 -0
  27. data/spec/lib/{feature_spec.rb → zucchini/feature_spec.rb} +0 -0
  28. data/spec/lib/{generator_spec.rb → zucchini/generator_spec.rb} +0 -0
  29. data/spec/lib/{report_spec.rb → zucchini/report_spec.rb} +0 -0
  30. data/spec/lib/zucchini/screenshot_spec.rb +164 -0
  31. 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
  32. data/spec/sample_setup/support/masks/splash.png +0 -0
  33. data/spec/spec_helper.rb +14 -10
  34. data/zucchini-ios.gemspec +8 -9
  35. metadata +58 -36
  36. data/lib/report/css/zucchini.report.css +0 -239
  37. data/lib/report/js/zucchini.report.js +0 -59
  38. data/lib/report/template.erb +0 -47
  39. data/spec/lib/screenshot_spec.rb +0 -109
data/.gitignore CHANGED
@@ -1,3 +1,19 @@
1
- .rvmrc
2
1
  .DS_Store
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ .ruby-version
3
8
  Gemfile.lock
9
+ InstalledFiles
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
@@ -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][]-Pretorius, [#13][]
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
- Pre-requisites
4
- --------------
5
- 1. Mac OS X >= 10.6
6
- 2. XCode >= 4.2
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 strongly encourage you to run your Zucchini features on real hardware. However, you can run them on the iOS Simulator if you must.
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 '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:
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
@@ -1,3 +1,4 @@
1
+ require 'bundler/gem_tasks'
1
2
  require 'rspec/core/rake_task'
2
3
 
3
4
  desc "Run all RSpec tests"
@@ -3,20 +3,13 @@
3
3
  require 'clamp'
4
4
  require 'fileutils'
5
5
 
6
- $LOAD_PATH << File.expand_path("#{File.dirname(__FILE__)}/..")
7
- require 'lib/config'
8
- require 'lib/screenshot'
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
@@ -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
@@ -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("#{File.dirname(__FILE__)}/..")
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}/lib/uia #{@path}/../support/screens"
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
- `coffee -o #{run_data_path} -j #{run_data_path}/feature.js -c #{cs_paths}`
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__)}/../templates")
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 'lib/report/view'
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 = f.stats.map { |key, set| "#{set.length.to_s} #{key}" }.join(", ")
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
+ }