coco 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'erb'
4
+
5
+ module Coco
6
+
7
+ # I format the index.html
8
+ # @todo document
9
+ class HtmlIndexFormatter < Formatter
10
+
11
+ def initialize raw_coverages, uncovered
12
+ super(raw_coverages, uncovered)
13
+ @context = nil
14
+ @template = Template.open File.join($COCO_PATH,'template/index.erb')
15
+ @lines = []
16
+ build_lines_for_context
17
+ end
18
+
19
+ def format
20
+ @context = IndexContext.new Helpers.index_title, @lines, @uncovered
21
+ @template.result(@context.get_binding)
22
+ end
23
+
24
+ private
25
+
26
+ def build_lines_for_context
27
+ @raw_coverages.each do |filename, coverage|
28
+ filename = File.expand_path(filename)
29
+ percentage = CoverageStat.coverage_percent(coverage)
30
+ @lines << [percentage, filename, Helpers.rb2html(filename)]
31
+ end
32
+ @lines.sort!
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'erb'
4
+
5
+ module Coco
6
+
7
+ # From me, you can obtain ERB templates.
8
+ class Template
9
+ # @param [String] filename An ERB template
10
+ # @return [ERB]
11
+ def self.open filename
12
+ io = IO.readlines(filename, nil)
13
+ ERB.new(io[0], nil, '><')
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Coco
4
+
5
+ # @todo The app is full of <tt>Dir.pwd</tt>. This is the root project directory
6
+ # and must be in Configuration class (or Coco module ?).
7
+ module Helpers
8
+
9
+ # Get html filename (from a ruby filename) suitable for the coverage
10
+ # directory.
11
+ #
12
+ # @example
13
+ # ruby = '/home/user/my_project/lib/source.rb'
14
+ # html = Helpers.rb2html(ruby)
15
+ # => '_lib_source.rb.html'
16
+ #
17
+ # @param [String] name Ruby filename
18
+ # @return [String] Html filename
19
+ def Helpers.rb2html name
20
+ name.sub(Dir.pwd, '').tr('/\\', '_') + '.html'
21
+ end
22
+
23
+ # @return [String] The title of the index.html file
24
+ def Helpers.index_title
25
+ "Coco #{File.read(File.join($COCO_PATH, 'VERSION')).strip}, code coverage for #{File.basename(Dir.pwd)}"
26
+ end
27
+
28
+ # @param [Array<String>] files List of filenames
29
+ # @return [Array<String>]
30
+ def Helpers.expand files
31
+ files.map {|file| File.expand_path file}
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,4 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'coco/lister/source_lister'
4
+ require 'coco/lister/uncovered_lister'
@@ -0,0 +1,47 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Coco
4
+
5
+ # I retrieve the .rb files from a list of directories.
6
+ class SourceLister
7
+
8
+ # @param [Hash] config
9
+ def initialize config
10
+ @exclude_files = config[:excludes]
11
+ dirs = config[:directories]
12
+ unless dirs.is_a? Array
13
+ @folders = [dirs]
14
+ else
15
+ @folders = dirs
16
+ end
17
+ @folders.each {|folder| raise ArgumentError unless File.directory?(folder)}
18
+ @list = []
19
+ end
20
+
21
+ # @return [Array<String>] A list of all .rb files from the directories found in configuration
22
+ def list
23
+ look_for_sources
24
+ @list.map! {|file| File.expand_path(file)}
25
+ exclude_files_user_dont_want
26
+ @list
27
+ end
28
+
29
+ private
30
+
31
+ def look_for_sources
32
+ @folders.each do |folder|
33
+ rb_files = File.join(folder, "**", "*.rb")
34
+ @list += Dir.glob(rb_files)
35
+ end
36
+ end
37
+
38
+ def exclude_files_user_dont_want
39
+ return if @exclude_files.nil?
40
+ @exclude_files.each do |filename|
41
+ @list.delete File.expand_path(filename)
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Coco
4
+
5
+ # I retrieve the list of uncovered (0%) .rb files.
6
+ class UncoveredLister
7
+
8
+ # @param [Array<String>] sources List of filenames
9
+ # @param [Hash] covered Raw coverage from the domain
10
+ def initialize sources, covered
11
+ @source_files = Helpers.expand(sources)
12
+ @covered_files = Helpers.expand(covered.keys)
13
+ end
14
+
15
+ # @return [Array<String>] List of uncovered filenames
16
+ def list
17
+ list = []
18
+ @source_files.each do |elem|
19
+ list << elem unless @covered_files.include?(elem)
20
+ end
21
+ list
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,6 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'coco/writer/file_writer'
4
+ require 'coco/writer/html_directory'
5
+ require 'coco/writer/html_files_writer'
6
+ require 'coco/writer/html_index_writer'
@@ -0,0 +1,14 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Coco
4
+
5
+ # I write one file.
6
+ class FileWriter
7
+ def FileWriter.write filename, content
8
+ file = File.new(filename, "w")
9
+ file.write content
10
+ file.close
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,39 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Coco
4
+
5
+ # I prepare the coverage/ directory for html files.
6
+ class HtmlDirectory
7
+ attr_reader :coverage_dir
8
+
9
+ def initialize
10
+ @coverage_dir = 'coverage'
11
+ @css_dir = 'coverage/css'
12
+ @img_dir = 'coverage/img'
13
+ css = File.join($COCO_PATH, 'template/css')
14
+ @css_files = Dir.glob(css + '/*')
15
+ img = File.join($COCO_PATH, 'template/img')
16
+ @img_files = Dir.glob(img + '/*')
17
+ end
18
+
19
+ # Delete the coverage/ directory
20
+ def clean
21
+ FileUtils.remove_dir @coverage_dir if File.exist? @coverage_dir
22
+ end
23
+
24
+ def setup
25
+ FileUtils.makedirs @css_dir
26
+ FileUtils.makedirs @img_dir
27
+ FileUtils.cp @css_files, @css_dir
28
+ FileUtils.cp @img_files, @img_dir
29
+ end
30
+
31
+ # I list the html files from the coverage directory
32
+ def list
33
+ files = Dir.glob("#{@coverage_dir}/*.html")
34
+ files.map {|file| File.basename(file)}
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Coco
4
+
5
+ # I populate the coverage/ directory with files, if any.
6
+ class HtmlFilesWriter
7
+
8
+ # @param [Hash] html_files Key is filename, value is html content
9
+ def initialize html_files
10
+ @html_files = html_files
11
+ @html_dir = HtmlDirectory.new
12
+ end
13
+
14
+ def write
15
+ @html_dir.clean
16
+ if @html_files.size > 0
17
+ @html_dir.setup
18
+ write_each_file
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def write_each_file
25
+ @html_files.each do |filename, html|
26
+ FileWriter.write File.join('coverage', Helpers.rb2html(filename)), html
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Coco
4
+
5
+ # I write the index.html
6
+ class HtmlIndexWriter
7
+
8
+ def initialize index
9
+ @index = index
10
+ @dir = HtmlDirectory.new.coverage_dir
11
+ end
12
+
13
+ def write
14
+ if File.exist?(@dir)
15
+ FileWriter.write File.join(@dir, 'index.html'), @index
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,5 @@
1
+ base-min.css, fonts-min.css and reset-min.css: BSD licence.
2
+ Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3
+ Code licensed under the BSD License:
4
+ http://developer.yahoo.com/yui/license.html
5
+ version: 2.8.2r1
@@ -0,0 +1 @@
1
+ body{margin:10px;}h1{font-size:138.5%;}h2{font-size:123.1%;}h3{font-size:108%;}h1,h2,h3{margin:1em 0;}h1,h2,h3,h4,h5,h6,strong,dt{font-weight:bold;}optgroup{font-weight:normal;}abbr,acronym{border-bottom:1px dotted #000;cursor:help;}em{font-style:italic;}del{text-decoration:line-through;}blockquote,ul,ol,dl{margin:1em;}ol,ul,dl{margin-left:2em;}ol li{list-style:decimal outside;}ul li{list-style:disc outside;}dl dd{margin-left:1em;}th,td{border:1px solid #000;padding:.5em;}th{font-weight:bold;text-align:center;}caption{margin-bottom:.5em;text-align:center;}sup{vertical-align:super;}sub{vertical-align:sub;}p,fieldset,table,pre{margin-bottom:1em;}button,input[type="checkbox"],input[type="radio"],input[type="reset"],input[type="submit"]{padding:1px;}
@@ -0,0 +1,96 @@
1
+ @charset "UTF-8";
2
+ @import url("reset-min.css");
3
+ @import url("base-min.css");
4
+ @import url("font-min.css");
5
+ @import url("ext.css");
6
+
7
+ html
8
+ {
9
+ background-color: #fcfcff;
10
+ }
11
+
12
+ h2
13
+ {
14
+ padding: 10px;
15
+ background-color: #668;
16
+ color: #fcfcff;
17
+ }
18
+
19
+ a
20
+ {
21
+ color:#446;
22
+ text-decoration: none;
23
+ }
24
+
25
+ p.menu a
26
+ {
27
+ font-weight: bold;
28
+ }
29
+
30
+ p.license
31
+ {
32
+ color: #888;
33
+ margin-top: 20px;
34
+ padding-top: 5px;
35
+ border-top: 1px solid #888;
36
+ font-size: 80%;
37
+ }
38
+
39
+ p.date
40
+ {
41
+ font-size: 80%;
42
+ }
43
+
44
+ table td
45
+ {
46
+ border-width: 0;
47
+ }
48
+
49
+ table.source td
50
+ {
51
+ padding: 0;
52
+ }
53
+
54
+ tr.never
55
+ {
56
+ background-color: #eee;
57
+ }
58
+
59
+ tr.hit
60
+ {
61
+ background-color: #efe;
62
+ }
63
+
64
+ tr.miss
65
+ {
66
+ background-color: #fbb;
67
+ }
68
+
69
+ td.yellow
70
+ {
71
+ background-color: #fffead;
72
+ }
73
+
74
+ td.orange
75
+ {
76
+ background-color: #ffcd84;
77
+ }
78
+
79
+ td.pink
80
+ {
81
+ background-color: #ffcd84;
82
+ }
83
+
84
+ td.red
85
+ {
86
+ background-color: #ff4747;
87
+ color: #fff;
88
+ font-weight: bold;
89
+ }
90
+
91
+ td.black
92
+ {
93
+ background-color: #002;
94
+ color: #fff;
95
+ font-weight: bold;
96
+ }
@@ -0,0 +1,5 @@
1
+ td, h2
2
+ {
3
+ -moz-border-radius: 10px 0;
4
+ border-radius: 10px 0;
5
+ }
@@ -0,0 +1 @@
1
+ body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}
@@ -0,0 +1 @@
1
+ html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}
data/template/file.erb ADDED
@@ -0,0 +1,35 @@
1
+ <html>
2
+ <head>
3
+ <meta charset='utf-8'>
4
+ <title><%= @filename %></title>
5
+ <link rel="stylesheet" href="css/coco.css" type="text/css" />
6
+ </head>
7
+ <body>
8
+ <p class="menu">
9
+ <a href="index.html">Index</a> <img src="img/coconut16.png" width="16" height="16" />
10
+ <a href="https://github.com/lkdjiin/coco/wiki">Wiki</a> <img src="img/coconut16.png" width="16" height="16" />
11
+ <a href="https://github.com/lkdjiin/coco">Source</a> <img src="img/coconut16.png" width="16" height="16" />
12
+ <a href="#">Web site</a>
13
+ </p>
14
+ <h2><%= @filename %></h2>
15
+ <p class="date"><%= "#{Time.now}" %></p>
16
+
17
+ <table class="source">
18
+
19
+ <% @lines.each do |num, text, hit|%>
20
+ <% if hit.nil? %>
21
+ <tr class="never">
22
+ <% elsif hit.zero? %>
23
+ <tr class="miss">
24
+ <% elsif hit > 0 %>
25
+ <tr class="hit" %>
26
+ <% end %>
27
+
28
+ <%= "<td><pre>#{num} </pre></td><td><pre>#{text}</pre></td>" %>
29
+
30
+ </tr>
31
+ <% end%>
32
+
33
+ </table>
34
+ </body>
35
+ </html>