coco 0.4.1

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.
@@ -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>