coco 0.13.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTORS +9 -0
  3. data/Changelog.markdown +42 -0
  4. data/Gemfile.lock +36 -55
  5. data/LICENSE +7 -0
  6. data/README.markdown +124 -73
  7. data/Rakefile +10 -37
  8. data/VERSION +1 -1
  9. data/lib/coco.rb +9 -21
  10. data/lib/coco/configuration.rb +59 -20
  11. data/lib/coco/cover.rb +1 -0
  12. data/lib/coco/cover/coverage_result.rb +72 -16
  13. data/lib/coco/cover/coverage_stat.rb +20 -8
  14. data/lib/coco/cover/summary.rb +50 -0
  15. data/lib/coco/deprecated_message.rb +31 -0
  16. data/lib/coco/formatter.rb +2 -2
  17. data/lib/coco/formatter/colored_string.rb +1 -1
  18. data/lib/coco/formatter/console_formatter.rb +24 -19
  19. data/lib/coco/formatter/context.rb +10 -39
  20. data/lib/coco/formatter/html_formatter.rb +7 -13
  21. data/lib/coco/formatter/html_index_formatter.rb +20 -16
  22. data/lib/coco/formatter/index_context.rb +37 -0
  23. data/lib/coco/formatter/index_line.rb +21 -0
  24. data/lib/coco/formatter/template.rb +2 -3
  25. data/lib/coco/helpers.rb +88 -68
  26. data/lib/coco/lister/source_lister.rb +23 -26
  27. data/lib/coco/lister/uncovered_lister.rb +6 -9
  28. data/lib/coco/project.rb +65 -0
  29. data/lib/coco/theme.rb +15 -0
  30. data/lib/coco/writer/file_writer.rb +5 -5
  31. data/lib/coco/writer/html_directory.rb +16 -8
  32. data/lib/coco/writer/html_files_writer.rb +9 -6
  33. data/lib/coco/writer/html_index_writer.rb +6 -3
  34. data/template/css/dark.css +178 -0
  35. data/template/css/{coco.css → light.css} +22 -9
  36. data/template/file.erb +3 -3
  37. data/template/index.erb +35 -33
  38. data/template/js/coco.js +18 -0
  39. metadata +34 -58
  40. data/COPYING +0 -674
  41. data/lib/coco/formatter/formatter.rb +0 -23
  42. data/template/img/coconut16.png +0 -0
  43. data/template/img/licenses +0 -19
@@ -2,16 +2,12 @@ module Coco
2
2
 
3
3
  # I retrieve the .rb files from a list of directories.
4
4
  class SourceLister
5
-
5
+
6
6
  # config - Hash.
7
7
  def initialize(config)
8
- @exclude_files = config[:excludes]
9
- dirs = config[:directories]
10
- unless dirs.is_a? Array
11
- @folders = [dirs]
12
- else
13
- @folders = dirs
14
- end
8
+ @exclude_files = config[:exclude]
9
+ dirs = config[:include]
10
+ @folders = [*dirs]
15
11
  @folders.each do |folder|
16
12
  unless File.directory?(folder)
17
13
  raise ArgumentError, "Not a folder: #{folder}"
@@ -19,41 +15,42 @@ module Coco
19
15
  end
20
16
  @list = []
21
17
  end
22
-
18
+
23
19
  # Returns Array of String, that is a list of all `.rb` files from
24
20
  # the directories found in configuration.
25
21
  def list
26
22
  look_for_sources
27
- @list.map! {|file| File.expand_path(file) }
28
- exclude_files_user_dont_want
23
+ @list.map! { |file| File.expand_path(file) }
24
+ exclude_files_user_dont_want if @exclude_files
29
25
  @list
30
26
  end
31
-
27
+
32
28
  private
33
-
29
+
34
30
  def look_for_sources
35
- @folders.each {|folder| @list += Helpers.rb_files_from folder }
31
+ @folders.each do |folder|
32
+ @list += Helpers.rb_files_from folder
33
+ end
36
34
  end
37
-
35
+
38
36
  def exclude_files_user_dont_want
39
- return if @exclude_files.nil?
40
-
41
37
  @exclude_files.each do |filename|
42
- full_path = File.expand_path(filename)
43
- if File.file?(full_path)
44
- @list.delete full_path
45
- elsif File.directory?(full_path)
46
- exclude_all_from_dir full_path
47
- end
38
+ exclude_path(File.expand_path(filename))
48
39
  end
49
40
  end
50
-
41
+
42
+ def exclude_path(full_path)
43
+ if File.file?(full_path)
44
+ @list.delete full_path
45
+ elsif File.directory?(full_path)
46
+ exclude_all_from_dir full_path
47
+ end
48
+ end
49
+
51
50
  def exclude_all_from_dir(full_path)
52
51
  Helpers.rb_files_from(full_path).each do |file|
53
52
  @list.delete File.expand_path(file)
54
53
  end
55
54
  end
56
-
57
55
  end
58
-
59
56
  end
@@ -1,24 +1,21 @@
1
1
  module Coco
2
2
 
3
3
  # I retrieve the list of uncovered (0%) .rb files.
4
+ #
4
5
  class UncoveredLister
5
-
6
+
6
7
  # sources - Array of String list of filenames.
7
8
  # covered - Hash raw coverage from the domain.
9
+ #
8
10
  def initialize(sources, covered)
9
11
  @source_files = Helpers.expand(sources)
10
12
  @covered_files = Helpers.expand(covered.keys)
11
13
  end
12
-
14
+
13
15
  # Returns Array of String list of uncovered filenames.
16
+ #
14
17
  def list
15
- list = []
16
- @source_files.each do |elem|
17
- list << elem unless @covered_files.include?(elem)
18
- end
19
- list
18
+ @source_files.select { |elem| !@covered_files.include?(elem) }
20
19
  end
21
-
22
20
  end
23
-
24
21
  end
@@ -0,0 +1,65 @@
1
+ module Coco
2
+
3
+ # A project reports statistics about the code coverage.
4
+ #
5
+ class Project
6
+
7
+ # raw_result - The hash obtain by the call to `Coverage.result`.
8
+ # out - The output where results will be displayed, by
9
+ # default this is stdout.
10
+ #
11
+ def self.run(raw_result, out = STDOUT)
12
+ new(raw_result, out).run
13
+ end
14
+
15
+ def initialize(raw_result, out)
16
+ @raw_result = raw_result
17
+ @out = out
18
+ @config = Configuration.new
19
+ end
20
+
21
+ def run
22
+ return unless @config.run_this_time?
23
+
24
+ report_on_console
25
+ report_in_html
26
+ end
27
+
28
+ private
29
+
30
+ def report_on_console
31
+ formatter = ConsoleFormatter.new(uncovered, @config[:threshold],
32
+ result, @config)
33
+ @out.puts formatter.format
34
+ @out.puts formatter.link if @config[:show_link_in_terminal]
35
+ end
36
+
37
+ def report_in_html
38
+ report_code_files
39
+ report_index
40
+ end
41
+
42
+ def report_code_files
43
+ files = HtmlFormatter.new(result.coverable_files).format
44
+ HtmlFilesWriter.new(files, @config[:theme]).write
45
+ end
46
+
47
+ def report_index
48
+ index = HtmlIndexFormatter.new(uncovered, result,
49
+ @config[:threshold]).format
50
+ HtmlIndexWriter.new(index).write
51
+ end
52
+
53
+ def result
54
+ @result ||= CoverageResult.new(@config, @raw_result)
55
+ end
56
+
57
+ def uncovered
58
+ @uncovered ||= UncoveredLister.new(sources, result.coverable_files).list
59
+ end
60
+
61
+ def sources
62
+ SourceLister.new(@config).list
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,15 @@
1
+ module Coco
2
+
3
+ # A CSS theme for the report.
4
+ #
5
+ class Theme
6
+
7
+ def initialize(name)
8
+ @name = "#{name}.css"
9
+ end
10
+
11
+ def filename
12
+ File.join(Coco::ROOT, 'template/css', @name)
13
+ end
14
+ end
15
+ end
@@ -1,8 +1,8 @@
1
1
  module Coco
2
-
2
+
3
3
  # Public: I write a single file.
4
+ #
4
5
  module FileWriter
5
- extend self
6
6
 
7
7
  # Public: Write a file.
8
8
  #
@@ -10,9 +10,9 @@ module Coco
10
10
  # content - String content to put in the file.
11
11
  #
12
12
  # Returns nothing.
13
- def write(filename, content)
14
- File.open(filename, 'w') {|file| file.write(content) }
13
+ #
14
+ def self.write(filename, content)
15
+ File.open(filename, 'w') { |file| file.write(content) }
15
16
  end
16
17
  end
17
-
18
18
  end
@@ -1,13 +1,17 @@
1
1
  module Coco
2
2
 
3
3
  # Public: I prepare the coverage/ directory for html files.
4
+ #
4
5
  class HtmlDirectory
5
- COVERAGE_DIR = 'coverage'
6
+ COVERAGE_DIR = 'coverage'.freeze
6
7
 
7
8
  # Public: Initialize a new HtmlDirectory object.
8
- def initialize
9
- css = File.join(Coco::ROOT, 'template/css')
10
- @css_files = Dir.glob(css + '/*')
9
+ #
10
+ # theme - The String name of the theme. There is 2 builtin themes :
11
+ # light & dark. The default one is light.
12
+ #
13
+ def initialize(theme = 'light')
14
+ @theme = Theme.new(theme)
11
15
  img = File.join(Coco::ROOT, 'template/img')
12
16
  @img_files = Dir.glob(img + '/*')
13
17
  end
@@ -32,10 +36,10 @@ module Coco
32
36
  #
33
37
  # Returns nothing.
34
38
  def setup
35
- FileUtils.makedirs(css_dir)
36
- FileUtils.makedirs(image_dir)
37
- FileUtils.cp(@css_files, css_dir)
39
+ FileUtils.makedirs([css_dir, image_dir, js_dir])
40
+ FileUtils.cp(@theme.filename, File.join(css_dir, 'coco.css'))
38
41
  FileUtils.cp(@img_files, image_dir)
42
+ FileUtils.cp(File.join(Coco::ROOT, 'template/js/coco.js'), js_dir)
39
43
  end
40
44
 
41
45
  # Public: I list the html files from the directory where the HTML
@@ -44,7 +48,7 @@ module Coco
44
48
  # Returns nothing.
45
49
  def list
46
50
  files = Dir.glob("#{coverage_dir}/*.html")
47
- files.map {|file| File.basename(file) }
51
+ files.map { |file| File.basename(file) }
48
52
  end
49
53
 
50
54
  private
@@ -56,5 +60,9 @@ module Coco
56
60
  def image_dir
57
61
  "#{COVERAGE_DIR}/img"
58
62
  end
63
+
64
+ def js_dir
65
+ "#{COVERAGE_DIR}/js"
66
+ end
59
67
  end
60
68
  end
@@ -6,20 +6,23 @@ module Coco
6
6
  # Public: Initialize a new HtmlFilesWriter.
7
7
  #
8
8
  # html_files - Hash, key is filename, value is html content.
9
- def initialize(html_files)
9
+ # theme - The String name of the theme. Default is light.
10
+ #
11
+ def initialize(html_files, theme = 'light')
10
12
  @html_files = html_files
11
- @html_dir = HtmlDirectory.new
13
+ @html_dir = HtmlDirectory.new(theme)
12
14
  end
13
15
 
14
16
  # Public: Write HTML files in the right place.
15
17
  #
16
18
  # Returns nothing.
19
+ #
17
20
  def write
18
21
  @html_dir.clean
19
- if @html_files.size > 0
20
- @html_dir.setup
21
- write_each_file
22
- end
22
+ return if @html_files.empty?
23
+
24
+ @html_dir.setup
25
+ write_each_file
23
26
  end
24
27
 
25
28
  private
@@ -1,19 +1,22 @@
1
1
  module Coco
2
-
2
+
3
3
  # Public: I write the index.html
4
+ #
4
5
  class HtmlIndexWriter
5
-
6
+
6
7
  # Public: Initialize a new HtmlIndexWriter object.
7
8
  #
8
9
  # index - A String HTML document.
10
+ #
9
11
  def initialize(index)
10
12
  @index = index
11
13
  @dir = HtmlDirectory.new.coverage_dir
12
14
  end
13
-
15
+
14
16
  # Public: Write the index file in the right place.
15
17
  #
16
18
  # Returns nothing.
19
+ #
17
20
  def write
18
21
  if File.exist?(@dir)
19
22
  FileWriter.write File.join(@dir, 'index.html'), @index
@@ -0,0 +1,178 @@
1
+ @charset "UTF-8";
2
+
3
+ /*
4
+ * Dark theme for Coco.
5
+ */
6
+
7
+ table.source {
8
+ border-collapse:collapse;
9
+ border-spacing: 0;
10
+ }
11
+
12
+ table.index tr {
13
+ height: 1.8em;
14
+ }
15
+
16
+ table.index td {
17
+ padding-left: 0.5em;
18
+ }
19
+
20
+ html {
21
+ background-color: #505050;
22
+ color: #F5F5F5;
23
+ }
24
+
25
+ body {
26
+ margin: 0;
27
+ }
28
+
29
+ h2 {
30
+ padding: 10px;
31
+ background-color: #6A9FB5;
32
+ color: #F5F5F5;
33
+ font-size: 1.1em;
34
+ }
35
+
36
+ a {
37
+ color: #F5F5F5;
38
+ text-decoration: none;
39
+ }
40
+
41
+ p {
42
+ margin: 1em;
43
+ }
44
+
45
+ p.menu a {
46
+ font-weight: bold;
47
+ }
48
+
49
+ p.date {
50
+ font-size: 80%;
51
+ }
52
+
53
+ table {
54
+ width: 100%;
55
+ }
56
+
57
+ table td {
58
+ border-width: 0;
59
+ }
60
+
61
+ table.source td {
62
+ padding-top: 0;
63
+ padding-bottom: 0;
64
+ padding-left: 0;
65
+ }
66
+
67
+ thead {
68
+ font-weight: bold;
69
+ background-color: #404040;
70
+ text-align: center;
71
+ }
72
+
73
+ td,
74
+ td a {
75
+ color: #B0B0B0;
76
+ }
77
+
78
+ td b,
79
+ td a b {
80
+ color: #F5F5F5;
81
+ }
82
+
83
+ tr.never {
84
+ background-color: #505050;
85
+ }
86
+
87
+ tr.hit {
88
+ background-color: #506939;
89
+ }
90
+
91
+ tr.hit:hover {
92
+ background-color: #90A959;
93
+ }
94
+
95
+ tr.miss {
96
+ background-color: #AC4142;
97
+ }
98
+
99
+ tr.miss:hover {
100
+ background-color: #E65758;
101
+ }
102
+
103
+ td.yellow, td.red, td.black, td.green {
104
+ width: 45px;
105
+ }
106
+
107
+ td.yellow {
108
+ background-color: #F4BF75;
109
+ color: #202020;
110
+ }
111
+
112
+ td.red {
113
+ background-color: #AC4142;
114
+ color: #F5F5F5;
115
+ }
116
+
117
+ td.black {
118
+ background-color: #404040;
119
+ color: #F5F5F5;
120
+ }
121
+
122
+ td.green {
123
+ background-color: #90A959;
124
+ color: #F5F5F5;
125
+ }
126
+
127
+ td.percentage {
128
+ text-align: right;
129
+ padding-right: 20px;
130
+ }
131
+
132
+ td.line-num,
133
+ td.line-hits,
134
+ td.line-source {
135
+ color: #F5F5F5;
136
+ }
137
+
138
+ td.line-num,
139
+ td.line-hits {
140
+ width: 10%;
141
+ text-align: right;
142
+ }
143
+
144
+ td.line-source {
145
+ padding-right: 0;
146
+ }
147
+
148
+ td.line-num {
149
+ padding-right: 5px;
150
+ }
151
+
152
+ td.line-hits {
153
+ padding-right: 20px;
154
+ }
155
+
156
+ th {
157
+ padding-bottom: 5px;
158
+ padding-top: 5px;
159
+ }
160
+
161
+ pre {
162
+ margin: 6px 0;
163
+ }
164
+
165
+ .summary {
166
+ font-size: 150%;
167
+ color: #F5F5F5;
168
+ }
169
+
170
+ .summary-rate, .summary-uncovered, .summary-files {
171
+ background-color: #6A9FB5;
172
+ padding: 5px 10px;
173
+ margin-right: 20px;
174
+ }
175
+
176
+ #bis {
177
+ display: none;
178
+ }