coco 0.13.0 → 0.14.0

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 (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
+ }