football_formatter 0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +4 -0
- data/LICENSE.md +20 -0
- data/README.md +13 -0
- data/Rakefile +6 -0
- data/data/nyan-cat.mp3 +0 -0
- data/demo.rb +30 -0
- data/football_formatter.gemspec +22 -0
- data/lib/nyan_cat_format/music.rb +80 -0
- data/lib/nyan_cat_format/wide.rb +20 -0
- data/lib/nyan_cat_formatter/rspec1.rb +56 -0
- data/lib/nyan_cat_formatter/rspec2.rb +39 -0
- data/lib/nyan_cat_formatter.rb +226 -0
- data/lib/nyan_cat_music_formatter.rb +7 -0
- data/lib/nyan_cat_wide_formatter.rb +7 -0
- data/lib/nyan_cat_wide_music_formatter.rb +9 -0
- data/nyan_example.gif +0 -0
- data/spec/nyan_cat_formatter_spec.rb +205 -0
- data/spec/nyan_cat_music_formatter_spec.rb +85 -0
- data/spec/nyan_cat_wide_formatter_spec.rb +44 -0
- data/spec/spec_helper.rb +3 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MGUwODhhODMxY2NmZjA2ODk2MDNhMjIzNzAxMjk5NDI2OTk0OTk4Nw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YzQxNWZlMWM0NzgzMGZjOWY3NzczZGIzNzFkNGVmYzJkMzY1MGZkNA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MjA1ZWY4OGMzYWMyOWMxOWY2NDQxMjdmNTU1Y2VmMjI0YTZiMjk4MjYwMTIz
|
10
|
+
MzRmNjZkM2Q2NDc2ZTBhMjY1NGI0ZjAxZjhjMmY3MzgyNDdiYmU4ZTdjNDJj
|
11
|
+
OWRlOWMxZDFkOTNlNTIzMGMxNmUwMGM1ZjM2ZGM0NGJhNzkwNGI=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
Njc1ZTFmMjZiYjhmM2E2N2FhNzE1MmE3OTlhNTliOTAwZDRiYWZlN2FkMmE2
|
14
|
+
ZDU2YTlkYzk3YjgwZDBkMWU1MTdjYzljMmRiNTgxNGE2OTViYWE5NjE3MTFl
|
15
|
+
M2FlZjNmZTY0MzQ0MGUwMGUyODU4MTRiNTA1MDUwOTJhZWZhMGQ=
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm 1.9.3@nyan-cat-formatter --create
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Matt Sears
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
RSpec Football Formatter
|
2
|
+
========
|
3
|
+
|
4
|
+
Initial release of a football themed rspec formatter built from Matt Sears Nyan Cat Formatter.
|
5
|
+
|
6
|
+
Next challenge:
|
7
|
+
Make the colors and quarterback names customizable for each NFL team.
|
8
|
+
|
9
|
+
|
10
|
+
Author
|
11
|
+
----------
|
12
|
+
[Matt Sears](http://www.mattsears.com) :: @mattsears
|
13
|
+
Ben Cutrell :: @bcutrell
|
data/Rakefile
ADDED
data/data/nyan-cat.mp3
ADDED
Binary file
|
data/demo.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'spec/spec_helper'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
describe NyanCatFormatter do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@output = StringIO.new
|
8
|
+
@formatter = NyanCatFormatter.new(@output)
|
9
|
+
@formatter.start(2)
|
10
|
+
@example = RSpec::Core::ExampleGroup.describe.example
|
11
|
+
|
12
|
+
@samples = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
|
13
|
+
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
14
|
+
|
15
|
+
sleep(0.1) # Just to slow it down a little :-)
|
16
|
+
end
|
17
|
+
|
18
|
+
100.times do |index|
|
19
|
+
it "should perform passing specs" do
|
20
|
+
@formatter.current.should == @samples.sample
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should perform pending specs" do
|
24
|
+
if @samples.sample == 1
|
25
|
+
pending
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "football_formatter"
|
5
|
+
s.version = "0"
|
6
|
+
s.authors = ["Matt Sears", "Ben Cutrell"]
|
7
|
+
s.email = ["matt@mattsears.com", "bcutrell13@gmail.com"]
|
8
|
+
s.homepage = "https://github.com/bcutrell/football_formatter"
|
9
|
+
s.summary = %q{football themed rspec formatter, built from nyan-cat-formatter}
|
10
|
+
s.description = s.summary
|
11
|
+
|
12
|
+
s.rubyforge_project = "football_formatter"
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_dependency "rspec", ">= 2.13"
|
20
|
+
|
21
|
+
s.add_development_dependency "rake"
|
22
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module NyanCatFormat
|
2
|
+
module Music
|
3
|
+
|
4
|
+
MUSIC_LENGTH = 27.06 # seconds
|
5
|
+
|
6
|
+
def osx?
|
7
|
+
platform.downcase.include?("darwin")
|
8
|
+
end
|
9
|
+
|
10
|
+
def linux?
|
11
|
+
platform.downcase.include?('linux')
|
12
|
+
end
|
13
|
+
|
14
|
+
def kernel=(kernel)
|
15
|
+
@kernel = kernel
|
16
|
+
end
|
17
|
+
|
18
|
+
def kernel
|
19
|
+
@kernel ||= Kernel
|
20
|
+
end
|
21
|
+
|
22
|
+
def platform=(platform)
|
23
|
+
@platform = platform
|
24
|
+
end
|
25
|
+
|
26
|
+
def platform
|
27
|
+
@platform ||= RUBY_PLATFORM
|
28
|
+
end
|
29
|
+
|
30
|
+
def nyan_mp3
|
31
|
+
File.expand_path('../../../data/nyan-cat.mp3', __FILE__)
|
32
|
+
end
|
33
|
+
|
34
|
+
def start input
|
35
|
+
super
|
36
|
+
t = Thread.new do
|
37
|
+
loop do
|
38
|
+
if osx?
|
39
|
+
kernel.system("afplay #{nyan_mp3} &")
|
40
|
+
elsif linux?
|
41
|
+
play_on_linux
|
42
|
+
end
|
43
|
+
Thread.current["started_playing"] ||= true
|
44
|
+
sleep MUSIC_LENGTH
|
45
|
+
end
|
46
|
+
end
|
47
|
+
until t["started_playing"]
|
48
|
+
sleep 0.001
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def kill_music
|
53
|
+
if File.exists? nyan_mp3
|
54
|
+
if osx?
|
55
|
+
system("killall -9 afplay &>/dev/null")
|
56
|
+
elsif linux?
|
57
|
+
kill_music_on_linux
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
63
|
+
kill_music
|
64
|
+
super
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def play_on_linux
|
70
|
+
kernel.system("[ -e #{nyan_mp3} ] && type mpg321 &>/dev/null && mpg321 #{nyan_mp3} &>/dev/null &") if kernel.system('which mpg321 &>/dev/null && type mpg321 &>/dev/null')
|
71
|
+
kernel.system("[ -e #{nyan_mp3} ] && type mpg123 &>/dev/null && mpg123 #{nyan_mp3} &>/dev/null &") if kernel.system('which mpg123 &>/dev/null && type mpg123 &>/dev/null')
|
72
|
+
end
|
73
|
+
|
74
|
+
def kill_music_on_linux
|
75
|
+
system("killall -9 mpg321 &>/dev/null") if kernel.system("which mpg321 &>/dev/null && type mpg321 &>/dev/null")
|
76
|
+
system("killall -9 mpg123 &>/dev/null") if kernel.system("which mpg123 &>/dev/null && type mpg123 &>/dev/null")
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module NyanCatFormat
|
2
|
+
module Wide
|
3
|
+
|
4
|
+
def example_width(example = current)
|
5
|
+
net_width_for(example) - net_width_for(example - 1)
|
6
|
+
end
|
7
|
+
|
8
|
+
def net_width_for(example)
|
9
|
+
@net_width ||= {}
|
10
|
+
|
11
|
+
@net_width[example] ||= begin
|
12
|
+
return 0 if example < 0
|
13
|
+
net_width = terminal_width - padding_width - cat_length
|
14
|
+
rough_example_width = (net_width * example.to_f / @example_count.to_f)
|
15
|
+
rough_example_width.round
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module RSpec1
|
2
|
+
|
3
|
+
def start(example_count)
|
4
|
+
super(example_count)
|
5
|
+
@example_count = example_count
|
6
|
+
@current = @color_index = @passing_count = @failure_count = @pending_count = 0
|
7
|
+
@example_results = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def example_passed(example)
|
11
|
+
super
|
12
|
+
@passing_count += 1
|
13
|
+
tick PASS
|
14
|
+
end
|
15
|
+
|
16
|
+
def example_pending(example, message = nil)
|
17
|
+
super
|
18
|
+
@pending_count =+1
|
19
|
+
tick PENDING
|
20
|
+
end
|
21
|
+
|
22
|
+
def example_failed(example, counter = nil, failure = nil)
|
23
|
+
super
|
24
|
+
@failure_count =+1
|
25
|
+
tick FAIL
|
26
|
+
end
|
27
|
+
|
28
|
+
def start_dump
|
29
|
+
@current = @example_count
|
30
|
+
end
|
31
|
+
|
32
|
+
def dump_pending
|
33
|
+
output.puts "\e[0;33m"
|
34
|
+
super
|
35
|
+
end
|
36
|
+
|
37
|
+
def dump_failure(*args)
|
38
|
+
output.puts "\e[0;31m"
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
43
|
+
@output.puts "\nYou've Nyaned for #{format_duration(duration)}\n".each_char.map {|c| rainbowify(c)}.join
|
44
|
+
summary = "#{example_count} Wins #{'s' unless example_count == 1}, #{failure_count} Loses #{'s' unless failure_count == 1}"
|
45
|
+
summary << ", #{pending_count} pending" if pending_count > 0
|
46
|
+
|
47
|
+
if failure_count == 0
|
48
|
+
@output.puts failure_color(summary)
|
49
|
+
elsif pending_count > 0
|
50
|
+
@output.puts pending_color(summary)
|
51
|
+
else
|
52
|
+
@output.puts success_color(summary)
|
53
|
+
end
|
54
|
+
@output.flush
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module RSpec2
|
2
|
+
|
3
|
+
def start(example_count)
|
4
|
+
super(example_count)
|
5
|
+
@current = @color_index = @passing_count = 0
|
6
|
+
@example_results = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def example_passed(example)
|
10
|
+
super(example)
|
11
|
+
tick PASS
|
12
|
+
end
|
13
|
+
|
14
|
+
def example_pending(example)
|
15
|
+
super(example)
|
16
|
+
@pending_count +=1
|
17
|
+
tick PENDING
|
18
|
+
end
|
19
|
+
|
20
|
+
def example_failed(example)
|
21
|
+
super(example)
|
22
|
+
@failure_count +=1
|
23
|
+
tick FAIL
|
24
|
+
end
|
25
|
+
|
26
|
+
def start_dump
|
27
|
+
@current = @example_count
|
28
|
+
end
|
29
|
+
|
30
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
31
|
+
dump_profile if profile_examples? && failure_count == 0
|
32
|
+
summary = "\nTom Brady has been throwing footballs for #{format_duration(duration)}\n".split(//).map { |c| rainbowify(c) }
|
33
|
+
output.puts summary.join
|
34
|
+
output.puts colorise_summary(summary_line(example_count, failure_count, pending_count))
|
35
|
+
if respond_to?(:dump_commands_to_rerun_failed_examples)
|
36
|
+
dump_commands_to_rerun_failed_examples
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,226 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
rspec_bin = $0.split('/').last
|
4
|
+
if rspec_bin == 'spec'
|
5
|
+
['spec', 'nyan_cat_formatter/rspec1', 'spec/runner/formatter/base_text_formatter'].each {|f| require f}
|
6
|
+
parent_class = Spec::Runner::Formatter::BaseTextFormatter
|
7
|
+
rspec_module = RSpec1
|
8
|
+
else
|
9
|
+
['nyan_cat_formatter/rspec2', 'rspec/core/formatters/base_text_formatter'].each {|f| require f}
|
10
|
+
parent_class = RSpec::Core::Formatters::BaseTextFormatter
|
11
|
+
rspec_module = RSpec2
|
12
|
+
end
|
13
|
+
|
14
|
+
NyanCatFormatter = Class.new(parent_class) do
|
15
|
+
|
16
|
+
ESC = "\e["
|
17
|
+
NND = "#{ESC}0m"
|
18
|
+
PASS = '='
|
19
|
+
PASS_ARY = ['-', '_']
|
20
|
+
FAIL = '*'
|
21
|
+
ERROR = '!'
|
22
|
+
PENDING = '+'
|
23
|
+
|
24
|
+
include rspec_module
|
25
|
+
|
26
|
+
attr_reader :current, :example_results, :color_index, :pending_count,
|
27
|
+
:failure_count, :example_count
|
28
|
+
|
29
|
+
# Increments the example count and displays the current progress
|
30
|
+
#
|
31
|
+
# @returns nothing
|
32
|
+
def tick(mark = PASS)
|
33
|
+
@example_results << mark
|
34
|
+
@current = (@current > @example_count) ? @example_count : @current + 1
|
35
|
+
dump_progress
|
36
|
+
end
|
37
|
+
|
38
|
+
# Determine which Ascii Nyan Cat to display. If tests are complete,
|
39
|
+
# Nyan Cat goes to sleep. If there are failing or pending examples,
|
40
|
+
# Nyan Cat is concerned.
|
41
|
+
#
|
42
|
+
# @return [String] Nyan Cat
|
43
|
+
def nyan_cat
|
44
|
+
if self.failed_or_pending? && self.finished?
|
45
|
+
ascii_cat('x')[@color_index%2].join("\n") #'~|_(x.x)'
|
46
|
+
elsif self.failed_or_pending?
|
47
|
+
ascii_cat('o')[@color_index%2].join("\n") #'~|_(o.o)'
|
48
|
+
elsif self.finished?
|
49
|
+
ascii_cat('-')[@color_index%2].join("\n") # '~|_(-.-)'
|
50
|
+
else
|
51
|
+
ascii_cat('^')[@color_index%2].join("\n") # '~|_(^.^)'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Displays the current progress in all Nyan Cat glory
|
56
|
+
#
|
57
|
+
# @return nothing
|
58
|
+
def dump_progress
|
59
|
+
padding = @example_count.to_s.length * 2 + 2
|
60
|
+
line = nyan_trail.split("\n").each_with_index.inject([]) do |result, (trail, index)|
|
61
|
+
value = "#{scoreboard[index]}/#{@example_count}:"
|
62
|
+
result << format("%s %s", value, trail)
|
63
|
+
end.join("\n")
|
64
|
+
output.print line + eol
|
65
|
+
end
|
66
|
+
|
67
|
+
# Determines how we end the trail line. If complete, return a newline etc.
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
def eol
|
71
|
+
return "\n" if @current == @example_count
|
72
|
+
length = (nyan_cat.split("\n").length - 1)
|
73
|
+
length > 0 ? format("\e[1A" * length + "\r") : "\r"
|
74
|
+
end
|
75
|
+
|
76
|
+
# Calculates the current flight length
|
77
|
+
#
|
78
|
+
# @return [Fixnum]
|
79
|
+
def current_width
|
80
|
+
padding_width + example_width + cat_length
|
81
|
+
end
|
82
|
+
|
83
|
+
# Gets the padding for the current example count
|
84
|
+
#
|
85
|
+
# @return [Fixnum]
|
86
|
+
def padding_width
|
87
|
+
@example_count.to_s.length * 2 + 6
|
88
|
+
end
|
89
|
+
|
90
|
+
# A Unix trick using stty to get the console columns
|
91
|
+
#
|
92
|
+
# @return [Fixnum]
|
93
|
+
def terminal_width
|
94
|
+
if defined? JRUBY_VERSION
|
95
|
+
default_width = 80
|
96
|
+
else
|
97
|
+
default_width = `stty size`.split.map { |x| x.to_i }.reverse.first - 1
|
98
|
+
end
|
99
|
+
@terminal_width ||= default_width
|
100
|
+
end
|
101
|
+
|
102
|
+
# Creates a data store of pass, failed, and pending example results
|
103
|
+
# We have to pad the results here because sprintf can't properly pad color
|
104
|
+
#
|
105
|
+
# @return [Array]
|
106
|
+
def scoreboard
|
107
|
+
@pending_examples ||= []
|
108
|
+
@failed_examples ||= []
|
109
|
+
padding = @example_count.to_s.length
|
110
|
+
[ @current.to_s.rjust(padding),
|
111
|
+
success_color((@current - @pending_examples.size - @failed_examples.size).to_s.rjust(padding)),
|
112
|
+
pending_color(@pending_examples.size.to_s.rjust(padding)),
|
113
|
+
failure_color(@failed_examples.size.to_s.rjust(padding)) ]
|
114
|
+
end
|
115
|
+
|
116
|
+
# Creates a rainbow trail
|
117
|
+
#
|
118
|
+
# @return [String] the sprintf format of the Nyan cat
|
119
|
+
def nyan_trail
|
120
|
+
marks = @example_results.each_with_index.map{ |mark, i| highlight(mark) * example_width(i) }
|
121
|
+
marks.shift(current_width - terminal_width) if current_width >= terminal_width
|
122
|
+
nyan_cat_lines = nyan_cat.split("\n").each_with_index.map do |line, index|
|
123
|
+
format("%s#{line}", marks.join)
|
124
|
+
end.join("\n")
|
125
|
+
end
|
126
|
+
|
127
|
+
# Times a mark has to be repeated
|
128
|
+
def example_width(item = 1)
|
129
|
+
1
|
130
|
+
end
|
131
|
+
|
132
|
+
# Ascii version of Nyan cat. Two cats in the array allow Nyan to animate running.
|
133
|
+
#
|
134
|
+
# @param o [String] Nyan's eye
|
135
|
+
# @return [Array] Nyan cats
|
136
|
+
def ascii_cat(o = '^')
|
137
|
+
[[ " _.-=""=-._ ",
|
138
|
+
" .'\\\\-++++-//'.",
|
139
|
+
" ( || || )",
|
140
|
+
" '.// \\\\.'",
|
141
|
+
" `'-=..=-'`"
|
142
|
+
],
|
143
|
+
[ " _.-=""=-._ ",
|
144
|
+
" .'\\\\-++++-//'.",
|
145
|
+
" ( || || )",
|
146
|
+
" '.// \\\\.'",
|
147
|
+
" `'-=..=-'`"
|
148
|
+
]
|
149
|
+
]
|
150
|
+
end
|
151
|
+
|
152
|
+
# Colorizes the string with raindow colors of the rainbow
|
153
|
+
#
|
154
|
+
# @params string [String]
|
155
|
+
# @return [String]
|
156
|
+
def rainbowify(string)
|
157
|
+
c = colors[@color_index % colors.size]
|
158
|
+
@color_index += 1
|
159
|
+
"#{ESC}38;5;#{c}m#{string}#{NND}"
|
160
|
+
end
|
161
|
+
|
162
|
+
# Calculates the colors of the rainbow
|
163
|
+
#
|
164
|
+
# @return [Array]
|
165
|
+
def colors
|
166
|
+
@colors ||= (0...(6 * 7)).map do |n|
|
167
|
+
pi_3 = Math::PI / 3
|
168
|
+
n *= 1.0 / 6
|
169
|
+
r = (3 * Math.sin(n ) + 3).to_i
|
170
|
+
g = (3 * Math.sin(n + 2 * pi_3) + 3).to_i
|
171
|
+
b = (3 * Math.sin(n + 4 * pi_3) + 3).to_i
|
172
|
+
36 * r + 6 * g + b + 16
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Determines how to color the example. If pass, it is rainbowified, otherwise
|
177
|
+
# we assign red if failed or yellow if an error occurred.
|
178
|
+
#
|
179
|
+
# @return [String]
|
180
|
+
def highlight(mark = PASS)
|
181
|
+
case mark
|
182
|
+
when PASS; rainbowify PASS_ARY[@color_index%2]
|
183
|
+
when FAIL; "\e[31m#{mark}\e[0m"
|
184
|
+
when ERROR; "\e[33m#{mark}\e[0m"
|
185
|
+
when PENDING; "\e[33m#{mark}\e[0m"
|
186
|
+
else mark
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# Converts a float of seconds into a minutes/seconds string
|
191
|
+
#
|
192
|
+
# @return [String]
|
193
|
+
def format_duration(duration)
|
194
|
+
seconds = ((duration % 60) * 100.0).round / 100.0 # 1.8.7 safe .round(2)
|
195
|
+
seconds = seconds.to_i if seconds.to_i == seconds # drop that zero if it's not needed
|
196
|
+
|
197
|
+
message = "#{seconds} second#{seconds == 1 ? "" : "s"}"
|
198
|
+
message = "#{(duration / 60).to_i} minute#{(duration / 60).to_i == 1 ? "" : "s"} and " + message if duration >= 60
|
199
|
+
|
200
|
+
message
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
# Determines if the specs have completed
|
205
|
+
#
|
206
|
+
# @returns [Boolean] true if finished; false otherwise
|
207
|
+
def finished?
|
208
|
+
(@current == @example_count)
|
209
|
+
end
|
210
|
+
|
211
|
+
# Determines if the any specs failed or are in pending state
|
212
|
+
#
|
213
|
+
# @returns [Boolean] true if failed or pending; false otherwise
|
214
|
+
def failed_or_pending?
|
215
|
+
(@failure_count.to_i > 0 || @pending_count.to_i > 0)
|
216
|
+
end
|
217
|
+
|
218
|
+
# Returns the cat length
|
219
|
+
#
|
220
|
+
# @returns [Fixnum]
|
221
|
+
def cat_length
|
222
|
+
nyan_cat.split("\n").group_by(&:size).max.first
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
226
|
+
|
data/nyan_example.gif
ADDED
Binary file
|
@@ -0,0 +1,205 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
describe NyanCatFormatter do
|
5
|
+
|
6
|
+
before do
|
7
|
+
rspec_bin = $0.split('/').last
|
8
|
+
@output = StringIO.new
|
9
|
+
if rspec_bin == 'rspec'
|
10
|
+
@formatter = NyanCatFormatter.new(@output)
|
11
|
+
@example = RSpec::Core::ExampleGroup.describe.example
|
12
|
+
else
|
13
|
+
formatter_options = OpenStruct.new(:colour => true, :dry_run => false, :autospec => nil)
|
14
|
+
@formatter = NyanCatFormatter.new(formatter_options, @output)
|
15
|
+
@example = Spec::Example::ExampleProxy.new("should pass")
|
16
|
+
@formatter.instance_variable_set(:@example_group, OpenStruct.new(:description => "group"))
|
17
|
+
end
|
18
|
+
@formatter.start(2)
|
19
|
+
sleep(0.1) # Just to slow it down a little :-)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'passed, pending and failed' do
|
23
|
+
|
24
|
+
before do
|
25
|
+
@formatter.stub!(:tick)
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'example_passed' do
|
29
|
+
|
30
|
+
it 'should call the increment method' do
|
31
|
+
@formatter.should_receive :tick
|
32
|
+
@formatter.example_passed(@example)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should relax Nyan Cat' do
|
36
|
+
@formatter.example_passed(@example)
|
37
|
+
@formatter.nyan_cat.should == [
|
38
|
+
'_,------, ',
|
39
|
+
'_| /\_/\ ',
|
40
|
+
'~|_( ^ .^) ',
|
41
|
+
' "" "" '
|
42
|
+
].join("\n")
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should update the scoreboard' do
|
46
|
+
@formatter.scoreboard.size.should == 4
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'example_pending' do
|
52
|
+
|
53
|
+
it 'should call the tick method' do
|
54
|
+
@formatter.should_receive :tick
|
55
|
+
@formatter.example_pending(@example)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should increment the pending count' do
|
59
|
+
lambda { @formatter.example_pending(@example)}.
|
60
|
+
should change(@formatter, :pending_count).by(1)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should alert Nyan Cat' do
|
64
|
+
@formatter.example_pending(@example)
|
65
|
+
@formatter.nyan_cat.should == [
|
66
|
+
'_,------, ',
|
67
|
+
'_| /\_/\ ',
|
68
|
+
'~|_( o .o) ',
|
69
|
+
' "" "" '
|
70
|
+
].join("\n")
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'example_failed' do
|
76
|
+
|
77
|
+
it 'should call the increment method' do
|
78
|
+
@formatter.should_receive :tick
|
79
|
+
@formatter.example_failed(@example)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should increment the failure count' do
|
83
|
+
lambda { @formatter.example_failed(@example)}.
|
84
|
+
should change(@formatter, :failure_count).by(1)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should alert Nyan Cat' do
|
88
|
+
@formatter.example_failed(@example)
|
89
|
+
@formatter.nyan_cat.should == [
|
90
|
+
'_,------, ',
|
91
|
+
'_| /\_/\ ',
|
92
|
+
'~|_( o .o) ',
|
93
|
+
' "" "" '
|
94
|
+
].join("\n")
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should kill nyan if the specs are finished' do
|
98
|
+
@formatter.example_failed(@example)
|
99
|
+
@formatter.stub(:finished?).and_return(true)
|
100
|
+
@formatter.nyan_cat.should == [
|
101
|
+
'_,------, ',
|
102
|
+
'_| /\_/\ ',
|
103
|
+
'~|_( x .x) ',
|
104
|
+
' "" "" '
|
105
|
+
].join("\n")
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe 'tick' do
|
112
|
+
|
113
|
+
before do
|
114
|
+
@formatter.stub!(:current).and_return(1)
|
115
|
+
@formatter.stub!(:example_count).and_return(2)
|
116
|
+
@formatter.tick
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should increment the current' do
|
120
|
+
@formatter.current.should == 1
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should store the marks in an array' do
|
124
|
+
@formatter.example_results.should include('=')
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
describe 'rainbowify' do
|
130
|
+
|
131
|
+
it 'should increment the color index count' do
|
132
|
+
lambda { @formatter.rainbowify('=') }.should change(@formatter, :color_index).by(1)
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
describe 'highlight' do
|
138
|
+
|
139
|
+
it 'should rainbowify passing examples' do
|
140
|
+
@formatter.highlight('=').should == "\e[38;5;154m-\e[0m"
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should mark failing examples as red' do
|
144
|
+
@formatter.highlight('*').should == "\e[31m*\e[0m"
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should mark pending examples as yellow' do
|
148
|
+
@formatter.highlight('!').should == "\e[33m!\e[0m"
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
describe 'start' do
|
154
|
+
|
155
|
+
it 'should set the total amount of specs' do
|
156
|
+
@formatter.example_count.should == 2
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should set the current to 0' do
|
160
|
+
@formatter.current.should == 0
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
describe "#format_duration" do
|
166
|
+
it "should return just seconds for sub 60 seconds" do
|
167
|
+
@formatter.format_duration(5.3).should eq("5.3 seconds")
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should remove that extra zero if it is not needed" do
|
171
|
+
@formatter.format_duration(1.0).should eq("1 second")
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should plurlaize seconds" do
|
175
|
+
@formatter.format_duration(1.1).should eq("1.1 seconds")
|
176
|
+
end
|
177
|
+
|
178
|
+
it "add a minute if it is just over 60 seconds" do
|
179
|
+
@formatter.format_duration(63.2543456456).should eq("1 minute and 3.25 seconds")
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should pluralize minutes" do
|
183
|
+
@formatter.format_duration(987.34).should eq("16 minutes and 27.34 seconds")
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe "example width" do
|
188
|
+
[15, 36, 60].each do |n|
|
189
|
+
context "for #{n} examples" do
|
190
|
+
before { @formatter.start(n) }
|
191
|
+
|
192
|
+
[0.25, 0.5, 0.75].each do |p|
|
193
|
+
i = (n * p).to_i
|
194
|
+
before { i.times { @formatter.tick } }
|
195
|
+
|
196
|
+
context "when in example #{i}" do
|
197
|
+
it "should return 1 as the example width" do
|
198
|
+
@formatter.example_width.should == 1
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stringio'
|
3
|
+
require 'nyan_cat_music_formatter'
|
4
|
+
|
5
|
+
class MockKernel
|
6
|
+
def system(string)
|
7
|
+
seen << string
|
8
|
+
end
|
9
|
+
|
10
|
+
def seen
|
11
|
+
@seen ||= []
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe NyanCatMusicFormatter do
|
16
|
+
let(:path_to_mp3) { NyanCatMusicFormatter.new(NyanCatFormatter).nyan_mp3 }
|
17
|
+
let(:stdout) { StringIO.new }
|
18
|
+
let(:formatter) { described_class.new stdout }
|
19
|
+
let(:mock_kernel) { MockKernel.new }
|
20
|
+
|
21
|
+
before { formatter.kernel = mock_kernel }
|
22
|
+
|
23
|
+
describe 'kernel' do
|
24
|
+
it 'defaults to Kernel' do
|
25
|
+
described_class.new(stdout).kernel.should == Kernel
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'can be set' do
|
29
|
+
formatter = described_class.new stdout
|
30
|
+
formatter.kernel = 'something else'
|
31
|
+
formatter.kernel.should == 'something else'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'platform' do
|
36
|
+
it 'defaults to RUBY_PLATFORM' do
|
37
|
+
described_class.new(stdout).platform.should eq RUBY_PLATFORM
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'can be set' do
|
41
|
+
formatter = described_class.new stdout
|
42
|
+
formatter.platform = 'something else'
|
43
|
+
formatter.platform.should == 'something else'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'start' do
|
48
|
+
it 'sets the total amount of specs' do
|
49
|
+
formatter.start 3
|
50
|
+
formatter.example_count.should == 3
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'sets the current to 0' do
|
54
|
+
formatter.start 3
|
55
|
+
formatter.current.should == 0
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when on OS X' do
|
59
|
+
before { formatter.platform = 'darwin' }
|
60
|
+
|
61
|
+
it 'plays the song in the background' do
|
62
|
+
formatter.start 3
|
63
|
+
mock_kernel.seen.should include "afplay #{path_to_mp3} &"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'when on linux' do
|
68
|
+
before { formatter.platform = 'linux'}
|
69
|
+
it 'plays the song for linux too' do
|
70
|
+
formatter.start 10
|
71
|
+
mock_kernel.seen.any? { |entry| entry. end_with? "mpg321 #{path_to_mp3} &>/dev/null &" }.should be
|
72
|
+
mock_kernel.seen.any? { |entry| entry. end_with? "mpg123 #{path_to_mp3} &>/dev/null &" }.should be
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when not on OS X' do
|
77
|
+
before { formatter.platform = 'windows' }
|
78
|
+
|
79
|
+
it 'does not play the song' do
|
80
|
+
formatter.start 4
|
81
|
+
mock_kernel.seen.should be_empty
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stringio'
|
3
|
+
require 'nyan_cat_wide_formatter'
|
4
|
+
|
5
|
+
describe NyanCatWideFormatter do
|
6
|
+
before do
|
7
|
+
@output = StringIO.new
|
8
|
+
@formatter = NyanCatWideFormatter.new(@output)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "cat situation" do
|
12
|
+
before do
|
13
|
+
@formatter.stub!(:terminal_width).and_return(100)
|
14
|
+
@formatter.stub!(:cat_length).and_return(11)
|
15
|
+
@whole_net_width = 100 - 2*2 - 6 - 11
|
16
|
+
end
|
17
|
+
|
18
|
+
context "for 35 examples" do
|
19
|
+
before do
|
20
|
+
@formatter.start(35)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should calculate the net width for example 3" do
|
24
|
+
@formatter.net_width_for(3).should == (@whole_net_width * 3.0 / 35.0).round
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should calculate the net width for example 30" do
|
28
|
+
@formatter.net_width_for(5).should == (@whole_net_width * 5.0 / 35.0).round
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "for 50 examples" do
|
33
|
+
before { @formatter.start(50) }
|
34
|
+
|
35
|
+
it "should calculate the net width for example 1" do
|
36
|
+
@formatter.net_width_for(1).should == (@whole_net_width * 1.0 / 50.0).round
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should calculate the net width for example 25" do
|
40
|
+
@formatter.net_width_for(25).should == (@whole_net_width * 25.0 / 50.0).round
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: football_formatter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matt Sears
|
8
|
+
- Ben Cutrell
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-09-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ! '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '2.13'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ! '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '2.13'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ! '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
description: football themed rspec formatter, built from nyan-cat-formatter
|
43
|
+
email:
|
44
|
+
- matt@mattsears.com
|
45
|
+
- bcutrell13@gmail.com
|
46
|
+
executables: []
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- .gitignore
|
51
|
+
- .rspec
|
52
|
+
- .rvmrc
|
53
|
+
- .travis.yml
|
54
|
+
- CHANGELOG.md
|
55
|
+
- Gemfile
|
56
|
+
- LICENSE.md
|
57
|
+
- README.md
|
58
|
+
- Rakefile
|
59
|
+
- data/nyan-cat.mp3
|
60
|
+
- demo.rb
|
61
|
+
- football_formatter.gemspec
|
62
|
+
- lib/nyan_cat_format/music.rb
|
63
|
+
- lib/nyan_cat_format/wide.rb
|
64
|
+
- lib/nyan_cat_formatter.rb
|
65
|
+
- lib/nyan_cat_formatter/rspec1.rb
|
66
|
+
- lib/nyan_cat_formatter/rspec2.rb
|
67
|
+
- lib/nyan_cat_music_formatter.rb
|
68
|
+
- lib/nyan_cat_wide_formatter.rb
|
69
|
+
- lib/nyan_cat_wide_music_formatter.rb
|
70
|
+
- nyan_example.gif
|
71
|
+
- spec/nyan_cat_formatter_spec.rb
|
72
|
+
- spec/nyan_cat_music_formatter_spec.rb
|
73
|
+
- spec/nyan_cat_wide_formatter_spec.rb
|
74
|
+
- spec/spec_helper.rb
|
75
|
+
homepage: https://github.com/bcutrell/football_formatter
|
76
|
+
licenses: []
|
77
|
+
metadata: {}
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
requirements: []
|
93
|
+
rubyforge_project: football_formatter
|
94
|
+
rubygems_version: 2.1.3
|
95
|
+
signing_key:
|
96
|
+
specification_version: 4
|
97
|
+
summary: football themed rspec formatter, built from nyan-cat-formatter
|
98
|
+
test_files:
|
99
|
+
- spec/nyan_cat_formatter_spec.rb
|
100
|
+
- spec/nyan_cat_music_formatter_spec.rb
|
101
|
+
- spec/nyan_cat_wide_formatter_spec.rb
|
102
|
+
- spec/spec_helper.rb
|