konacha 2.0.0.beta2 → 2.0.0.beta3
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.
- 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
|