konacha 2.0.0.beta2 → 2.0.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.md +4 -2
- data/LICENSE +25 -0
- data/README.md +24 -2
- data/app/assets/javascripts/konacha/parent.js +2 -1
- data/app/assets/javascripts/konacha/runner.js +48 -23
- data/konacha.gemspec +1 -1
- data/lib/konacha.rb +2 -0
- data/lib/konacha/engine.rb +1 -0
- data/lib/konacha/formatter.rb +80 -0
- data/lib/konacha/reporter.rb +91 -0
- data/lib/konacha/reporter/example.rb +34 -0
- data/lib/konacha/reporter/example_group.rb +37 -0
- data/lib/konacha/reporter/metadata.rb +81 -0
- data/lib/konacha/runner.rb +24 -78
- data/spec/formatter_spec.rb +69 -0
- data/spec/reporter/example_group_spec.rb +64 -0
- data/spec/reporter/example_spec.rb +77 -0
- data/spec/reporter/metadata_spec.rb +68 -0
- data/spec/reporter_spec.rb +112 -0
- data/spec/runner_spec.rb +88 -19
- data/vendor/assets/javascripts/chai.js +121 -62
- data/vendor/assets/javascripts/mocha.js +64 -17
- data/vendor/assets/stylesheets/mocha.css +4 -0
- metadata +21 -3
data/History.md
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
# master
|
2
2
|
|
3
|
-
* Run tests in an iframe, with `<body id="konacha"
|
3
|
+
* Run tests in an iframe, with `<body id="konacha">`. Each test file is run in
|
4
|
+
isolation.
|
4
5
|
* Removed support for konacha_config.js and Konacha.mochaOptions in favor of
|
5
6
|
Mocha's own configuration methods. See the README for update instructions.
|
6
|
-
* Update mocha (1.
|
7
|
+
* Update mocha (1.6.0) and chai (1.3.0)
|
8
|
+
* Adopt the RSpec reporter interface
|
7
9
|
|
8
10
|
# 1.x-stable
|
9
11
|
|
data/LICENSE
CHANGED
@@ -88,3 +88,28 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
88
88
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
89
89
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
90
90
|
THE SOFTWARE.
|
91
|
+
|
92
|
+
Portions derived from RSpec (https://github.com/rspec/rspec-core)
|
93
|
+
|
94
|
+
Copyright (c) 2009 Chad Humphries, David Chelimsky
|
95
|
+
Copyright (c) 2006 David Chelimsky, The RSpec Development Team
|
96
|
+
Copyright (c) 2005 Steven Baker
|
97
|
+
|
98
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
99
|
+
a copy of this software and associated documentation files (the
|
100
|
+
"Software"), to deal in the Software without restriction, including
|
101
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
102
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
103
|
+
permit persons to whom the Software is furnished to do so, subject to
|
104
|
+
the following conditions:
|
105
|
+
|
106
|
+
The above copyright notice and this permission notice shall be
|
107
|
+
included in all copies or substantial portions of the Software.
|
108
|
+
|
109
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
110
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
111
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
112
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
113
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
114
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
115
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -112,6 +112,23 @@ $ bundle exec rake konacha:run SPEC=foo_spec
|
|
112
112
|
$ bundle exec rake konacha:run SPEC=foo_spec,bar_spec,etc_spec
|
113
113
|
```
|
114
114
|
|
115
|
+
Konacha includes a default formatter modeled upon RSpec's ProgressFormatter.
|
116
|
+
Additionally, Konacha's runner implements the same protocol as RSpec, so many
|
117
|
+
RSpec formatters also work with Konacha.
|
118
|
+
|
119
|
+
To specify one or more formatters, provide a comma separated list of class names
|
120
|
+
in the `FORMAT` environment variable. For example, you can run both Ruby and JavaScript
|
121
|
+
specs with CI integration using [ci_reporter](https://github.com/nicksieger/ci_reporter):
|
122
|
+
|
123
|
+
```
|
124
|
+
$ bundle exec rake ci:setup:rspec spec konacha:run FORMAT=CI::Reporter::RSpec
|
125
|
+
```
|
126
|
+
|
127
|
+
You will need to `require` any formatters you use. It's a good idea to do this
|
128
|
+
within a `defined?` check in your [Konacha initializer](#configuration).
|
129
|
+
|
130
|
+
To automatically trigger reruns when files change, try [guard-konacha](https://github.com/alexgb/guard-konacha).
|
131
|
+
|
115
132
|
## Spec Helper
|
116
133
|
|
117
134
|
Since Konacha integrates with the asset pipeline, using setup helpers in your specs is
|
@@ -232,8 +249,13 @@ describe("templating", function() {
|
|
232
249
|
|
233
250
|
As of Konacha 2.0, each test file is run inside an isolated iframe. For
|
234
251
|
compatibility with Konacha 1.x, the iframe's `<body>` element will have
|
235
|
-
`id="konacha"` set on it.
|
236
|
-
|
252
|
+
`id="konacha"` set on it.
|
253
|
+
|
254
|
+
Previously, all test files would run in the same environment. Thus, if only
|
255
|
+
one test file pulled in an external library, all tests would be able to use
|
256
|
+
it. Now test files are run in isolation. If you encounter an undefined
|
257
|
+
JavaScript module in your test, you may be missing an explicit `//= require`
|
258
|
+
call somewhere.
|
237
259
|
|
238
260
|
### Options
|
239
261
|
|
@@ -4,7 +4,8 @@ window.onload = function () {
|
|
4
4
|
if (!iframes[i].contentWindow.mocha) {
|
5
5
|
(function (path) {
|
6
6
|
mocha.suite.addTest(new Mocha.Test(path, function () {
|
7
|
-
throw new Error("Failed to load " + path + "
|
7
|
+
throw new Error("Failed to load " + path + ".\n" +
|
8
|
+
"Perhaps it failed to compile? Check the rake output for errors.");
|
8
9
|
}));
|
9
10
|
})(iframes[i].getAttribute("data-path"));
|
10
11
|
}
|
@@ -1,45 +1,70 @@
|
|
1
1
|
Konacha = {
|
2
|
-
|
3
|
-
|
4
|
-
return JSON.stringify(Konacha.results);
|
2
|
+
getEvents: function() {
|
3
|
+
return JSON.stringify(Konacha.events);
|
5
4
|
}
|
6
5
|
};
|
7
6
|
|
8
7
|
mocha.reporter(function(runner) {
|
8
|
+
var createTestObject = function(test, status) {
|
9
|
+
var obj = {
|
10
|
+
title:test.title,
|
11
|
+
fullTitle:test.fullTitle(),
|
12
|
+
duration:test.duration,
|
13
|
+
parentFullTitle:test.parent.fullTitle(),
|
14
|
+
status:status
|
15
|
+
};
|
16
|
+
|
17
|
+
if (status == "failed")
|
18
|
+
obj.error = test.err; // Contains message, expected, actual, operator, stack
|
19
|
+
|
20
|
+
return obj;
|
21
|
+
};
|
22
|
+
|
23
|
+
var createSuiteObject = function(suite) {
|
24
|
+
var obj = {
|
25
|
+
title:suite.title,
|
26
|
+
fullTitle:suite.fullTitle()
|
27
|
+
};
|
28
|
+
|
29
|
+
if (suite.parent)
|
30
|
+
obj.parentFullTitle = suite.parent.fullTitle();
|
31
|
+
|
32
|
+
return obj;
|
33
|
+
};
|
34
|
+
|
9
35
|
Mocha.reporters.Base.call(this, runner);
|
10
36
|
|
11
37
|
runner.on('start', function() {
|
12
|
-
Konacha.
|
38
|
+
Konacha.events = [];
|
39
|
+
});
|
40
|
+
|
41
|
+
runner.on('suite', function(suite) {
|
42
|
+
if (suite.fullTitle() && suite.fullTitle().length > 0)
|
43
|
+
Konacha.events.push({event:'suite', data:createSuiteObject(suite), type:'suite'});
|
44
|
+
});
|
45
|
+
|
46
|
+
runner.on('test', function(test) {
|
47
|
+
Konacha.events.push({event:'test', data:createTestObject(test), type:'test'});
|
13
48
|
});
|
14
49
|
|
15
50
|
runner.on('pass', function(test) {
|
16
|
-
Konacha.
|
17
|
-
Konacha.results.push({
|
18
|
-
name:test.title,
|
19
|
-
passed:true
|
20
|
-
});
|
51
|
+
Konacha.events.push({event:'pass', data:createTestObject(test, "passed"), type:'test'});
|
21
52
|
});
|
22
53
|
|
23
54
|
runner.on('fail', function(test) {
|
24
|
-
Konacha.
|
25
|
-
Konacha.results.push({
|
26
|
-
name:test.title,
|
27
|
-
passed:false,
|
28
|
-
message:test.err.message,
|
29
|
-
trace:test.err.stack
|
30
|
-
});
|
55
|
+
Konacha.events.push({event:'fail', data:createTestObject(test, "failed"), type:'test'});
|
31
56
|
});
|
32
57
|
|
33
58
|
runner.on('pending', function(test) {
|
34
|
-
Konacha.
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
59
|
+
Konacha.events.push({event:'pending', data:createTestObject(test, "pending"), type:'test'});
|
60
|
+
});
|
61
|
+
|
62
|
+
runner.on('suite end', function(suite) {
|
63
|
+
if (suite.fullTitle() && suite.fullTitle().length > 0)
|
64
|
+
Konacha.events.push({event:'suite end', data:createSuiteObject(suite), type:'suite'});
|
40
65
|
});
|
41
66
|
|
42
67
|
runner.on('end', function() {
|
43
|
-
Konacha.
|
68
|
+
Konacha.events.push({event:'end', data:{}});
|
44
69
|
});
|
45
70
|
});
|
data/konacha.gemspec
CHANGED
@@ -17,7 +17,7 @@ the asset pipeline and engines.}
|
|
17
17
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
18
|
gem.name = "konacha"
|
19
19
|
gem.require_paths = ["lib"]
|
20
|
-
gem.version = "2.0.0.
|
20
|
+
gem.version = "2.0.0.beta3"
|
21
21
|
|
22
22
|
gem.add_dependency "railties", "~> 3.1"
|
23
23
|
gem.add_dependency "actionpack", "~> 3.1"
|
data/lib/konacha.rb
CHANGED
data/lib/konacha/engine.rb
CHANGED
@@ -0,0 +1,80 @@
|
|
1
|
+
require "colorize"
|
2
|
+
|
3
|
+
module Konacha
|
4
|
+
class Formatter
|
5
|
+
attr_reader :io, :examples
|
6
|
+
|
7
|
+
def initialize(io)
|
8
|
+
@io = io
|
9
|
+
@examples = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def start(expected_example_count=nil); end
|
13
|
+
def example_group_started(group); end
|
14
|
+
def example_started(example); end
|
15
|
+
|
16
|
+
def example_passed(example)
|
17
|
+
@examples << example
|
18
|
+
io.write(".".green)
|
19
|
+
end
|
20
|
+
|
21
|
+
def example_failed(example)
|
22
|
+
@examples << example
|
23
|
+
io.write("F".red)
|
24
|
+
end
|
25
|
+
|
26
|
+
def example_pending(example)
|
27
|
+
@examples << example
|
28
|
+
io.write("P".yellow)
|
29
|
+
end
|
30
|
+
|
31
|
+
def example_group_finished(group); end
|
32
|
+
def stop; end
|
33
|
+
|
34
|
+
def start_dump
|
35
|
+
io.puts ""
|
36
|
+
end
|
37
|
+
|
38
|
+
def dump_pending
|
39
|
+
pending_examples = examples.select(&:pending?)
|
40
|
+
if pending_examples.present?
|
41
|
+
io.puts ""
|
42
|
+
io.puts(pending_examples.map {|example| pending_message(example)}.join("\n\n"))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def dump_failures
|
47
|
+
failed_examples = examples.select(&:failed?)
|
48
|
+
if failed_examples.present?
|
49
|
+
io.puts ""
|
50
|
+
io.puts(failed_examples.map {|example| failure_message(example)}.join("\n\n"))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
55
|
+
seconds = "%.2f" % duration
|
56
|
+
io.puts ""
|
57
|
+
io.puts "Finished in #{seconds} seconds"
|
58
|
+
io.puts "#{example_count} examples, #{failure_count} failed, #{pending_count} pending"
|
59
|
+
end
|
60
|
+
|
61
|
+
def seed(seed); end
|
62
|
+
|
63
|
+
def close
|
64
|
+
io.close if IO === io && io != $stdout
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def failure_message(example)
|
69
|
+
msg = []
|
70
|
+
msg << " Failed: #{example.full_description}"
|
71
|
+
msg << " #{example.exception.message}"
|
72
|
+
msg << " in #{example.exception.backtrace.first}" if example.exception.backtrace.present?
|
73
|
+
msg.join("\n").red
|
74
|
+
end
|
75
|
+
|
76
|
+
def pending_message(example)
|
77
|
+
" Pending: #{example.full_description}".yellow
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require "konacha/reporter/example"
|
2
|
+
require "konacha/reporter/example_group"
|
3
|
+
|
4
|
+
# The Konacha Reporter implements the same protocol as the RSpec Reporter.
|
5
|
+
# More details on the RSpec Reporter protocol are available in the rspec-core
|
6
|
+
# repository: https://github.com/rspec/rspec-core/blob/1852a7f4221c5731e108484cb2debfbaca60b283/lib/rspec/core/formatters/base_formatter.rb#L8-L25
|
7
|
+
|
8
|
+
module Konacha
|
9
|
+
class Reporter
|
10
|
+
EVENT_CONVERSIONS = {
|
11
|
+
'suite' => :example_group_started,
|
12
|
+
'test' => :example_started,
|
13
|
+
'pass' => :example_passed,
|
14
|
+
'fail' => :example_failed,
|
15
|
+
'pending' => :example_pending,
|
16
|
+
'suite end' => :example_group_finished,
|
17
|
+
}
|
18
|
+
|
19
|
+
attr_reader :start_time, :duration, :example_count, :failure_count, :pending_count
|
20
|
+
|
21
|
+
def initialize(*formatters)
|
22
|
+
@formatters = formatters
|
23
|
+
@example_count = @failure_count = @pending_count = 0
|
24
|
+
@duration = @start_time = nil
|
25
|
+
@examples, @groups = {}, {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def start(expected_example_count=nil)
|
29
|
+
@start_time = Time.now
|
30
|
+
process_event :start, expected_example_count
|
31
|
+
end
|
32
|
+
|
33
|
+
def finish(seed=nil)
|
34
|
+
begin
|
35
|
+
stop
|
36
|
+
process_event :start_dump
|
37
|
+
process_event :dump_pending
|
38
|
+
process_event :dump_failures
|
39
|
+
process_event :dump_summary, @duration, @example_count, @failure_count, @pending_count
|
40
|
+
process_event :seed, seed if seed
|
41
|
+
ensure
|
42
|
+
process_event :close
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def stop
|
47
|
+
@duration = Time.now - @start_time if @start_time
|
48
|
+
process_event :stop
|
49
|
+
end
|
50
|
+
|
51
|
+
def passed?
|
52
|
+
@examples.values.all? { |example| example.passed? || example.pending? }
|
53
|
+
end
|
54
|
+
|
55
|
+
def process_mocha_event(event)
|
56
|
+
if event['type']
|
57
|
+
object = update_or_create_object(event['data'], event['type'])
|
58
|
+
process_event EVENT_CONVERSIONS[event['event']], object
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def process_event(method, *args, &block)
|
63
|
+
case method
|
64
|
+
when :example_started
|
65
|
+
@example_count += 1
|
66
|
+
when :example_failed
|
67
|
+
@failure_count += 1
|
68
|
+
when :example_pending
|
69
|
+
@pending_count += 1
|
70
|
+
end
|
71
|
+
|
72
|
+
@formatters.each do |formatter|
|
73
|
+
formatter.send method, *args, &block
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def update_or_create_object(data, type)
|
78
|
+
collection = type == 'test' ? @examples : @groups
|
79
|
+
object = collection[data['fullTitle']]
|
80
|
+
if object
|
81
|
+
object.update_metadata(data)
|
82
|
+
else
|
83
|
+
klass = type == 'test' ? Example : ExampleGroup
|
84
|
+
parent = @groups[data['parentFullTitle']]
|
85
|
+
object = collection[data['fullTitle']] = klass.new(data, parent)
|
86
|
+
end
|
87
|
+
|
88
|
+
object
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "konacha/reporter/metadata"
|
2
|
+
|
3
|
+
# The Example class mimics the public interface of RSpec::Core::Example.
|
4
|
+
|
5
|
+
module Konacha
|
6
|
+
class Reporter
|
7
|
+
class Example
|
8
|
+
attr_reader :metadata, :parent
|
9
|
+
|
10
|
+
def initialize(data, parent)
|
11
|
+
@metadata = Metadata.new(data)
|
12
|
+
@parent = parent
|
13
|
+
end
|
14
|
+
|
15
|
+
delegate :full_description, :description, :location, :file_path, :line_number, :pending, :pending_message, :exception, :execution_result, :to => :metadata
|
16
|
+
|
17
|
+
alias_method :pending?, :pending
|
18
|
+
alias_method :options, :metadata
|
19
|
+
alias_method :example_group, :parent
|
20
|
+
|
21
|
+
def passed?
|
22
|
+
execution_result[:status] == "passed"
|
23
|
+
end
|
24
|
+
|
25
|
+
def failed?
|
26
|
+
execution_result[:status] == "failed"
|
27
|
+
end
|
28
|
+
|
29
|
+
def update_metadata(data)
|
30
|
+
metadata.update(data)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "konacha/reporter/metadata"
|
2
|
+
|
3
|
+
# The ExampleGroup class mimics the public interface of RSpec::Core::ExampleGroup.
|
4
|
+
|
5
|
+
module Konacha
|
6
|
+
class Reporter
|
7
|
+
class ExampleGroup
|
8
|
+
attr_reader :metadata, :parent
|
9
|
+
|
10
|
+
def initialize(data, parent)
|
11
|
+
@metadata = Metadata.new(data)
|
12
|
+
@parent = parent
|
13
|
+
end
|
14
|
+
|
15
|
+
delegate :full_description, :description, :file_path, :described_class, :to => :metadata
|
16
|
+
|
17
|
+
alias_method :display_name, :description
|
18
|
+
|
19
|
+
def parent_groups
|
20
|
+
ancestor = parent
|
21
|
+
groups = []
|
22
|
+
while ancestor
|
23
|
+
groups << ancestor
|
24
|
+
ancestor = ancestor.parent
|
25
|
+
end
|
26
|
+
|
27
|
+
groups
|
28
|
+
end
|
29
|
+
|
30
|
+
alias_method :ancestors, :parent_groups
|
31
|
+
|
32
|
+
def update_metadata(data)
|
33
|
+
metadata.update(data)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|