specdown 0.3.0 → 0.4.0.beta.1
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/CHANGELOG.markdown +7 -0
- data/README.markdown +84 -8
- data/VERSION +1 -1
- data/features/command.feature +3 -1
- data/features/config.feature +3 -3
- data/features/fixtures/codeblocks_and_implicits.markdown +7 -0
- data/features/implicit_parser.feature +113 -0
- data/features/implicit_specs.feature +135 -0
- data/features/parser.feature +69 -1
- data/features/pending_specs.feature +49 -0
- data/features/report_summary.feature +1 -1
- data/features/specdown_examples/complete_implicit/specdown/implicit.specdown +4 -0
- data/features/specdown_examples/complete_implicit/specdown/test.markdown +3 -0
- data/features/specdown_examples/no_implicit/specdown/test.markdown +3 -0
- data/features/specdown_examples/pending_implicit/specdown/implicit.specdown +4 -0
- data/features/specdown_examples/pending_implicit/specdown/test.markdown +3 -0
- data/features/specdown_examples/pending_specs/specdown/test.markdown +7 -0
- data/features/step_definitions/command.rb +7 -3
- data/features/step_definitions/implicit_parser.rb +19 -0
- data/features/step_definitions/implicit_specs.rb +18 -0
- data/features/step_definitions/parser.rb +24 -0
- data/features/step_definitions/pending_specs.rb +7 -0
- data/features/support/env.rb +6 -0
- data/lib/specdown.rb +6 -0
- data/lib/specdown/config.rb +12 -1
- data/lib/specdown/event_handlers/test_pending.rb +3 -0
- data/lib/specdown/event_handlers/test_undefined.rb +3 -0
- data/lib/specdown/implicit_parser.rb +47 -0
- data/lib/specdown/node.rb +2 -1
- data/lib/specdown/parser.rb +40 -6
- data/lib/specdown/pending.rb +7 -0
- data/lib/specdown/pending_exception.rb +4 -0
- data/lib/specdown/reporter.rb +8 -0
- data/lib/specdown/reporters/color_terminal_reporter.rb +12 -0
- data/lib/specdown/reporters/terminal_reporter.rb +16 -0
- data/lib/specdown/reporters/text_reporter.rb +8 -0
- data/lib/specdown/runner.rb +25 -16
- data/lib/specdown/runner/report_summary.rb +8 -0
- data/lib/specdown/runner/stats.rb +13 -2
- data/lib/specdown/sandbox_decorators/pending.rb +3 -0
- data/lib/specdown/templates/color_summary.erb +20 -4
- data/lib/specdown/templates/summary.erb +17 -0
- metadata +45 -9
data/features/parser.feature
CHANGED
@@ -171,7 +171,6 @@ Feature: Specdown Parser
|
|
171
171
|
"""
|
172
172
|
|
173
173
|
|
174
|
-
@focus
|
175
174
|
Scenario: Multiple code blocks in a section should join together with newlines
|
176
175
|
|
177
176
|
Given the following specdown example file containing multiple executable codeblocks in a single section:
|
@@ -198,3 +197,72 @@ Feature: Specdown Parser
|
|
198
197
|
"""
|
199
198
|
@tree.root.code.should == "hi = 'hello'\nputs hi"
|
200
199
|
"""
|
200
|
+
|
201
|
+
@focus
|
202
|
+
Scenario: Code blocks + Undefined Implicit Specs
|
203
|
+
|
204
|
+
Given the following README:
|
205
|
+
"""
|
206
|
+
@readme = <<-README.undent
|
207
|
+
# Specdown Example
|
208
|
+
|
209
|
+
**This is an implicit spec.**
|
210
|
+
|
211
|
+
This text has two implicit specs: **one** and **two**.
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
hi = "explicit spec"
|
215
|
+
```
|
216
|
+
README
|
217
|
+
"""
|
218
|
+
|
219
|
+
When I parse it into a tree:
|
220
|
+
"""
|
221
|
+
@tree = Specdown::Parser.parse @readme
|
222
|
+
"""
|
223
|
+
|
224
|
+
Then the root node should include the explicit code:
|
225
|
+
"""
|
226
|
+
@tree.root.code.should == %{hi = "explicit spec"}
|
227
|
+
"""
|
228
|
+
|
229
|
+
And the root node should include the undefined implicit specs:
|
230
|
+
"""
|
231
|
+
@tree.root.undefined_implicits.should == ["This is an implicit spec.", "one", "two"]
|
232
|
+
"""
|
233
|
+
|
234
|
+
@focus
|
235
|
+
Scenario: Code blocks + Defined Implicit Specs
|
236
|
+
|
237
|
+
Given the following README:
|
238
|
+
"""
|
239
|
+
@readme = <<-README.undent
|
240
|
+
# Specdown Example
|
241
|
+
|
242
|
+
**This is an implicit spec.**
|
243
|
+
|
244
|
+
```ruby
|
245
|
+
hi = "explicit spec"
|
246
|
+
```
|
247
|
+
README
|
248
|
+
"""
|
249
|
+
|
250
|
+
And the following implicit specs:
|
251
|
+
"""
|
252
|
+
@implicits = <<-SPECDOWN.undent
|
253
|
+
This is an implicit spec.
|
254
|
+
-----------------------------
|
255
|
+
|
256
|
+
puts "howdy"
|
257
|
+
SPECDOWN
|
258
|
+
"""
|
259
|
+
|
260
|
+
When I parse it into a tree:
|
261
|
+
"""
|
262
|
+
@tree = Specdown::Parser.parse @readme, Specdown::ImplicitParser.parse(@implicits)
|
263
|
+
"""
|
264
|
+
|
265
|
+
Then the code block and the implicit spec should be joined together:
|
266
|
+
"""
|
267
|
+
@tree.root.code.should == %{puts "howdy"\nhi = "explicit spec"}
|
268
|
+
"""
|
@@ -0,0 +1,49 @@
|
|
1
|
+
Feature: Pending specs
|
2
|
+
|
3
|
+
You can mark a spec as pending by using the "pending" method.
|
4
|
+
|
5
|
+
For example, consider the following markdown file:
|
6
|
+
|
7
|
+
Example of Pending Specification
|
8
|
+
-----------------------------------
|
9
|
+
|
10
|
+
This spec is pending.
|
11
|
+
|
12
|
+
pending
|
13
|
+
|
14
|
+
|
15
|
+
If you ran this with specdown, you'd receive the following output:
|
16
|
+
|
17
|
+
|
18
|
+
P
|
19
|
+
|
20
|
+
1 markdown
|
21
|
+
1 test
|
22
|
+
1 pending
|
23
|
+
0 successes
|
24
|
+
0 failures
|
25
|
+
|
26
|
+
|
27
|
+
Scenario: Pending specification
|
28
|
+
|
29
|
+
Given the following markdown with a pending spec:
|
30
|
+
"""
|
31
|
+
# Example of Pending Specification
|
32
|
+
|
33
|
+
This spec is pending.
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
pending
|
37
|
+
```
|
38
|
+
"""
|
39
|
+
|
40
|
+
Then the `specdown` command should return the following output:
|
41
|
+
"""
|
42
|
+
P
|
43
|
+
|
44
|
+
1 markdown
|
45
|
+
1 test
|
46
|
+
1 pending
|
47
|
+
0 successes
|
48
|
+
0 failures
|
49
|
+
"""
|
@@ -12,7 +12,7 @@ Feature: Specdown::ReportSummary
|
|
12
12
|
|
13
13
|
Scenario: A Specdown::Reporter instantiated with a single stats object
|
14
14
|
|
15
|
-
Given the following specdown example file
|
15
|
+
Given the following specdown example file:
|
16
16
|
"""
|
17
17
|
# Specdown Example
|
18
18
|
|
@@ -3,9 +3,7 @@ When /^I run `specdown` from the command line in a directory that contains no 's
|
|
3
3
|
end
|
4
4
|
|
5
5
|
Then /^I should see the following output:$/ do |string|
|
6
|
-
string
|
7
|
-
@output.should include(line.strip)
|
8
|
-
end
|
6
|
+
ensure_included! string, @output
|
9
7
|
end
|
10
8
|
|
11
9
|
Given /^I have a specdown directory containing a (?:single )?markdown file:$/ do |string|
|
@@ -106,6 +104,12 @@ Given /^`specdown \-\-format=condensed`$/ do
|
|
106
104
|
ensure_condensed! bundle_exec!("specdown --format=condensed")
|
107
105
|
end
|
108
106
|
|
107
|
+
def ensure_included!(desired, actual)
|
108
|
+
desired.split("\n").each do |line|
|
109
|
+
actual.should include(line.strip)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
109
113
|
def ensure_condensed!(output)
|
110
114
|
output.strip.should_not be_empty
|
111
115
|
output.should match(/^[^\. ]+\.markdown: .*$/)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Given /^the following implicit specification:$/ do |string|
|
2
|
+
eval string
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I parse it with the implicit parser:$/ do |string|
|
6
|
+
eval string
|
7
|
+
end
|
8
|
+
|
9
|
+
Then /^I should receive a hash lookup of implicit definitions:$/ do |string|
|
10
|
+
eval string
|
11
|
+
end
|
12
|
+
|
13
|
+
Given /^two implicit specification strings:$/ do |string|
|
14
|
+
eval string
|
15
|
+
end
|
16
|
+
|
17
|
+
When /^I pass both off to the Specdown::ImplicitParser:$/ do |string|
|
18
|
+
eval string
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Given /^a markdown file with an implicit spec:$/ do |string|
|
2
|
+
end
|
3
|
+
|
4
|
+
Given /^no implicit specification$/ do
|
5
|
+
@directory = "features/specdown_examples/no_implicit/"
|
6
|
+
end
|
7
|
+
|
8
|
+
When /^I run the `specdown` command$/ do
|
9
|
+
@output = bundle_exec! "specdown"
|
10
|
+
end
|
11
|
+
|
12
|
+
Given /^a specdown file with a pending specification:$/ do |string|
|
13
|
+
@directory = "features/specdown_examples/pending_implicit/"
|
14
|
+
end
|
15
|
+
|
16
|
+
Given /^a specdown file with a complete specification:$/ do |string|
|
17
|
+
@directory = "features/specdown_examples/complete_implicit/"
|
18
|
+
end
|
@@ -10,6 +10,30 @@ Given /^the following specdown example file containing multiple executable codeb
|
|
10
10
|
@readme = File.read "features/fixtures/multiple_codeblocks_per_section_example.markdown"
|
11
11
|
end
|
12
12
|
|
13
|
+
Given /^the following specdown example file containing both codeblocks and implicit specs:$/ do |string|
|
14
|
+
@readme = File.read "features/fixtures/codeblocks_and_implicits.markdown"
|
15
|
+
end
|
16
|
+
|
17
|
+
Given /^the following README:$/ do |string|
|
18
|
+
eval string
|
19
|
+
end
|
20
|
+
|
21
|
+
Then /^the root node should include the explicit code:$/ do |string|
|
22
|
+
eval string
|
23
|
+
end
|
24
|
+
|
25
|
+
Then /^the root node should include the undefined implicit specs:$/ do |string|
|
26
|
+
eval string
|
27
|
+
end
|
28
|
+
|
29
|
+
Given /^the following implicit specs:$/ do |string|
|
30
|
+
eval string
|
31
|
+
end
|
32
|
+
|
33
|
+
Then /^the code block and the implicit spec should be joined together:$/ do |string|
|
34
|
+
eval string
|
35
|
+
end
|
36
|
+
|
13
37
|
When /^I parse it into a tree:$/ do |string|
|
14
38
|
eval string
|
15
39
|
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
Given /^the following markdown with a pending spec:$/ do |string|
|
2
|
+
@directory = "features/specdown_examples/pending_specs/"
|
3
|
+
end
|
4
|
+
|
5
|
+
Then /^the `specdown` command should return the following output:$/ do |string|
|
6
|
+
ensure_included! string, bundle_exec!("specdown")
|
7
|
+
end
|
data/features/support/env.rb
CHANGED
data/lib/specdown.rb
CHANGED
@@ -3,6 +3,7 @@ require 'term/ansicolor'
|
|
3
3
|
require 'erb'
|
4
4
|
require 'optparse'
|
5
5
|
require 'specdown/parser'
|
6
|
+
require 'specdown/implicit_parser'
|
6
7
|
require 'specdown/node'
|
7
8
|
require 'specdown/tree'
|
8
9
|
require 'specdown/runner'
|
@@ -17,6 +18,10 @@ require 'specdown/event_handlers/run_complete'
|
|
17
18
|
require 'specdown/event_handlers/run_started'
|
18
19
|
require 'specdown/event_handlers/test_failed'
|
19
20
|
require 'specdown/event_handlers/test_passed'
|
21
|
+
require 'specdown/event_handlers/test_pending'
|
22
|
+
require 'specdown/event_handlers/test_undefined'
|
23
|
+
require 'specdown/pending'
|
24
|
+
require 'specdown/pending_exception'
|
20
25
|
require 'specdown/config'
|
21
26
|
require 'specdown/specdown'
|
22
27
|
require 'specdown/sandbox_factory'
|
@@ -31,3 +36,4 @@ require 'specdown/reporters/text_reporter'
|
|
31
36
|
require 'specdown/sandbox_decorators/default_assertion_library'
|
32
37
|
require 'specdown/sandbox_decorators/rspec_expectations'
|
33
38
|
require 'specdown/sandbox_decorators/test_unit_assertions'
|
39
|
+
require 'specdown/sandbox_decorators/pending'
|
data/lib/specdown/config.rb
CHANGED
@@ -9,7 +9,7 @@ module Specdown
|
|
9
9
|
attr_accessor :format
|
10
10
|
|
11
11
|
def format
|
12
|
-
@format ||= :
|
12
|
+
@format ||= :condensed
|
13
13
|
end
|
14
14
|
|
15
15
|
def reporter
|
@@ -35,6 +35,12 @@ module Specdown
|
|
35
35
|
@tests ||= find_tests_in root
|
36
36
|
end
|
37
37
|
|
38
|
+
def implicit_specs
|
39
|
+
return @implicit_specs if @implicit_specs
|
40
|
+
implicit_spec_files = find_implicit_specs_in(root).map {|file| File.read(file)}
|
41
|
+
@implicit_specs = Specdown::ImplicitParser.parse *implicit_spec_files
|
42
|
+
end
|
43
|
+
|
38
44
|
def tests=(test_files)
|
39
45
|
unless test_files.empty?
|
40
46
|
@tests = test_files
|
@@ -66,6 +72,11 @@ module Specdown
|
|
66
72
|
Dir["#{directory}/**/*.markdown"] + Dir["#{directory}/**/*.md"]
|
67
73
|
end
|
68
74
|
|
75
|
+
def find_implicit_specs_in(directory)
|
76
|
+
directory = strip_trailing_slash directory
|
77
|
+
Dir["#{directory}/**/*.specdown"]
|
78
|
+
end
|
79
|
+
|
69
80
|
def strip_trailing_slash(string)
|
70
81
|
if string[-1..-1] == "/"
|
71
82
|
string[0...-1]
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Specdown
|
2
|
+
class ImplicitParser
|
3
|
+
def self.parse(*implicit_specifications)
|
4
|
+
self.new(*implicit_specifications).parse
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(*implicit_specifications)
|
8
|
+
@specs = implicit_specifications
|
9
|
+
@lookups = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse
|
13
|
+
@specs.each do |spec|
|
14
|
+
kramdown = Kramdown::Document.new spec, :input => "GithubMarkdown"
|
15
|
+
build_lookup kramdown.root.children
|
16
|
+
end
|
17
|
+
|
18
|
+
@lookups
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def build_lookup(parsed_elements)
|
23
|
+
scan_for_header parsed_elements
|
24
|
+
consume_section parsed_elements until parsed_elements.empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
def consume_section(parsed_elements)
|
28
|
+
key = parsed_elements.shift.options[:raw_text]
|
29
|
+
value = ""
|
30
|
+
|
31
|
+
while !parsed_elements.empty? && parsed_elements.first.type != :header
|
32
|
+
element = parsed_elements.shift
|
33
|
+
value += "\n" + element.value.to_s.strip if element.type == :codeblock && ([nil, "ruby", ""].include? element.options["language"])
|
34
|
+
end
|
35
|
+
|
36
|
+
@lookups[key] = value.strip
|
37
|
+
end
|
38
|
+
|
39
|
+
def scan_for_header(parsed_elements)
|
40
|
+
until parsed_elements.empty? || (
|
41
|
+
parsed_elements.first.type == :header
|
42
|
+
)
|
43
|
+
parsed_elements.shift
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/specdown/node.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
module Specdown
|
2
2
|
class Node
|
3
|
-
attr_accessor :name, :code, :contents, :children, :parent
|
3
|
+
attr_accessor :name, :code, :undefined_implicits, :contents, :children, :parent
|
4
4
|
|
5
5
|
def initialize
|
6
6
|
@code = ''
|
7
7
|
@contents = ''
|
8
8
|
@children = []
|
9
|
+
@undefined_implicits = []
|
9
10
|
end
|
10
11
|
|
11
12
|
def code
|
data/lib/specdown/parser.rb
CHANGED
@@ -1,15 +1,22 @@
|
|
1
1
|
module Specdown
|
2
|
-
|
3
|
-
|
2
|
+
class Parser
|
3
|
+
def self.parse(readme, lookups={})
|
4
|
+
self.new(readme, lookups).parse
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(readme, lookups={})
|
8
|
+
@readme = readme
|
9
|
+
@lookups = lookups
|
10
|
+
end
|
4
11
|
|
5
|
-
def parse
|
6
|
-
kramdown = Kramdown::Document.new readme, :input => "GithubMarkdown"
|
12
|
+
def parse
|
13
|
+
kramdown = Kramdown::Document.new @readme, :input => "GithubMarkdown"
|
7
14
|
build_tree kramdown.root.children
|
8
15
|
end
|
9
16
|
|
10
17
|
private
|
11
18
|
def build_tree(parsed_elements)
|
12
|
-
tree = Tree.new
|
19
|
+
tree = Specdown::Tree.new
|
13
20
|
scan_for_root_node parsed_elements
|
14
21
|
tree.root = consume_section parsed_elements unless parsed_elements.empty?
|
15
22
|
consume_children parsed_elements, tree.root unless parsed_elements.empty?
|
@@ -43,7 +50,22 @@ module Specdown
|
|
43
50
|
|
44
51
|
while !parsed_elements.empty? && parsed_elements.first.type != :header
|
45
52
|
element = parsed_elements.shift
|
46
|
-
|
53
|
+
|
54
|
+
if element.type == :codeblock && element.options["language"] == "ruby"
|
55
|
+
node.code += "\n" + element.value.to_s.strip
|
56
|
+
|
57
|
+
elsif has_implicits?(element)
|
58
|
+
gather_implicit_keys(element).each do |key|
|
59
|
+
value = @lookups[key]
|
60
|
+
|
61
|
+
if value
|
62
|
+
node.code += "\n" + value
|
63
|
+
else
|
64
|
+
node.undefined_implicits << key
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
47
69
|
node.contents += element.value.to_s + element.children.map(&:value).join
|
48
70
|
end
|
49
71
|
node
|
@@ -56,5 +78,17 @@ module Specdown
|
|
56
78
|
parsed_elements.shift
|
57
79
|
end
|
58
80
|
end
|
81
|
+
|
82
|
+
def has_implicits?(element)
|
83
|
+
element.type == :strong || element.children.map {|child| has_implicits?(child) }.any?
|
84
|
+
end
|
85
|
+
|
86
|
+
def gather_implicit_keys(element)
|
87
|
+
if element.type == :strong
|
88
|
+
[element.children.map(&:value).compact.join(" ")]
|
89
|
+
else
|
90
|
+
element.children.map {|child| gather_implicit_keys(child)}.flatten
|
91
|
+
end
|
92
|
+
end
|
59
93
|
end
|
60
94
|
end
|