butternut 0.2.2-java
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/.document +5 -0
- data/.gitignore +22 -0
- data/LICENSE +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +63 -0
- data/VERSION +1 -0
- data/butternut.gemspec +82 -0
- data/lib/butternut/cucumber.css +112 -0
- data/lib/butternut/cucumber.sass +152 -0
- data/lib/butternut/formatter.rb +144 -0
- data/lib/butternut/helpers.rb +103 -0
- data/lib/butternut/scenario_extensions.rb +7 -0
- data/lib/butternut.rb +27 -0
- data/spec/butternut/formatter_spec.rb +146 -0
- data/spec/butternut/helpers_spec.rb +132 -0
- data/spec/butternut_spec.rb +53 -0
- data/spec/fixtures/blargh.html +9 -0
- data/spec/fixtures/css/bar.css +3 -0
- data/spec/fixtures/facepalm.jpg +0 -0
- data/spec/fixtures/foo.css +9 -0
- data/spec/fixtures/foo.html +27 -0
- data/spec/fixtures/foo.js +3 -0
- data/spec/fixtures/picard.jpg +0 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +97 -0
- data/tmp/.gitignore +2 -0
- metadata +123 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
module Butternut
|
2
|
+
module Helpers
|
3
|
+
def browser
|
4
|
+
@browser ||= Celerity::Browser.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def visit(url)
|
8
|
+
browser.goto(url)
|
9
|
+
@page_changed = true
|
10
|
+
end
|
11
|
+
|
12
|
+
def current_url
|
13
|
+
browser.page.web_response.request_url.to_string
|
14
|
+
end
|
15
|
+
|
16
|
+
def current_page_source
|
17
|
+
return nil unless browser.page
|
18
|
+
|
19
|
+
string_writer = java.io.StringWriter.new
|
20
|
+
print_writer = java.io.PrintWriter.new(string_writer)
|
21
|
+
|
22
|
+
root = browser.page.document_element
|
23
|
+
node_to_xml(root, print_writer)
|
24
|
+
print_writer.close
|
25
|
+
string_writer.to_string
|
26
|
+
end
|
27
|
+
|
28
|
+
# Fill in a text field with a value
|
29
|
+
def fill_in(label_or_name, options = {})
|
30
|
+
elt = find_element_by_label_or_name(:text_field, label_or_name)
|
31
|
+
if elt.exist?
|
32
|
+
elt.value = options[:with]
|
33
|
+
@page_changed = true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def select(option_text, options = {})
|
38
|
+
elt = find_element_by_label_or_name(:select_list, options[:from])
|
39
|
+
if elt.exist?
|
40
|
+
elt.select(option_text)
|
41
|
+
@page_changed = true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def click_button(button_value)
|
46
|
+
browser.button(button_value).click
|
47
|
+
@page_changed = true
|
48
|
+
end
|
49
|
+
|
50
|
+
def page_changed?
|
51
|
+
@page_changed
|
52
|
+
end
|
53
|
+
|
54
|
+
def find_element_by_label_or_name(type, label_or_name)
|
55
|
+
elt = browser.send(type, :label, label_or_name)
|
56
|
+
elt.exist? ? elt : browser.send(type, :name, label_or_name)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
# NOTE: I have to do this because HtmlUnit's asXml likes to put spaces
|
61
|
+
# and newlines in the middle of whitespace-sensitive tags (like
|
62
|
+
# <a> and <textarea>). Fail.
|
63
|
+
def node_to_xml(node, print_writer)
|
64
|
+
closing_tag = false
|
65
|
+
|
66
|
+
case node
|
67
|
+
when HtmlUnit::Html::DomText
|
68
|
+
# just print out the text
|
69
|
+
print_writer.write(HtmlUnit::Util::StringUtils.escape_xml_chars(node.data))
|
70
|
+
when HtmlUnit::Html::DomCDataSection, HtmlUnit::Html::DomProcessingInstruction
|
71
|
+
# use default printXml here
|
72
|
+
node.print_xml("", print_writer)
|
73
|
+
when HtmlUnit::Html::DomComment
|
74
|
+
print_writer.write("<!-- #{node.data} -->")
|
75
|
+
when HtmlUnit::Html::HtmlTextArea
|
76
|
+
node_print_opening_tag(node, print_writer)
|
77
|
+
print_writer.write(node.text)
|
78
|
+
closing_tag = true
|
79
|
+
else
|
80
|
+
node_print_opening_tag(node, print_writer)
|
81
|
+
closing_tag = true
|
82
|
+
end
|
83
|
+
|
84
|
+
child = node.first_child
|
85
|
+
while child
|
86
|
+
node_to_xml(child, print_writer)
|
87
|
+
child = child.next_sibling
|
88
|
+
end
|
89
|
+
|
90
|
+
node_print_closing_tag(node, print_writer) if closing_tag
|
91
|
+
end
|
92
|
+
|
93
|
+
def node_print_opening_tag(node, print_writer)
|
94
|
+
print_writer.write("<")
|
95
|
+
node.print_opening_tag_content_as_xml(print_writer)
|
96
|
+
print_writer.write(">")
|
97
|
+
end
|
98
|
+
|
99
|
+
def node_print_closing_tag(node, print_writer)
|
100
|
+
print_writer.write("</#{node.tag_name}>")
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/butternut.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'cucumber'
|
3
|
+
require 'celerity'
|
4
|
+
|
5
|
+
module Butternut
|
6
|
+
def self.setup_hooks(obj)
|
7
|
+
obj.instance_exec do
|
8
|
+
AfterStep do |object|
|
9
|
+
if object.is_a?(Cucumber::Ast::Scenario)
|
10
|
+
if page_changed?
|
11
|
+
object.last_page_source = current_page_source
|
12
|
+
object.last_page_url = current_url
|
13
|
+
else
|
14
|
+
object.last_page_source = nil
|
15
|
+
object.last_page_url = nil
|
16
|
+
end
|
17
|
+
@page_changed = false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require File.dirname(__FILE__) + "/butternut/scenario_extensions"
|
25
|
+
require File.dirname(__FILE__) + "/butternut/helpers"
|
26
|
+
require File.dirname(__FILE__) + "/butternut/formatter"
|
27
|
+
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
module Butternut
|
4
|
+
describe Formatter do
|
5
|
+
extend SpecHelperDsl
|
6
|
+
include SpecHelper
|
7
|
+
|
8
|
+
def setup_formatter(options = {})
|
9
|
+
@out = StringIO.new
|
10
|
+
@formatter = Butternut::Formatter.new(step_mother, @out, options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def most_recent_html_file(dir)
|
14
|
+
path = Pathname.new(dir)
|
15
|
+
files = path.entries.collect { |file|
|
16
|
+
path+file
|
17
|
+
}.sort { |file1,file2|
|
18
|
+
file2.mtime <=> file1.mtime
|
19
|
+
}
|
20
|
+
files.detect { |f| f.to_s =~ /\.html$/ }
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be a subclass of the html formatter" do
|
24
|
+
Butternut::Formatter.superclass.should == Cucumber::Formatter::Html
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "running without the --out option" do
|
28
|
+
define_steps do
|
29
|
+
Given(/foo/) do
|
30
|
+
visit("file://" + File.expand_path(File.dirname(__FILE__) + "/../fixtures/foo.html"))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
define_feature(<<-FEATURE)
|
35
|
+
Scenario: Monkey goes to the zoo
|
36
|
+
Given foo
|
37
|
+
FEATURE
|
38
|
+
|
39
|
+
it "should raise an error" do
|
40
|
+
lambda {
|
41
|
+
setup_formatter
|
42
|
+
run_defined_feature
|
43
|
+
}.should raise_error
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "running with the --out option" do
|
48
|
+
before(:each) do
|
49
|
+
dir = File.join(File.dirname(__FILE__), "..", "..", "tmp")
|
50
|
+
@tmp_dir = File.join(dir, "#{Time.now.to_i}-#{rand(1000)}")
|
51
|
+
FileUtils.mkdir(@tmp_dir)
|
52
|
+
|
53
|
+
#@tmp_dir = File.join(dir, "features", Date.today.to_s)
|
54
|
+
#file = most_recent_html_file(@tmp_dir)
|
55
|
+
#@page_doc = Nokogiri.HTML(open(file).read)
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "with a filename specified" do
|
59
|
+
define_steps do
|
60
|
+
Given(/foo/) do
|
61
|
+
visit("file://" + File.join(FIXTURE_DIR, "foo.html"))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
define_feature(<<-FEATURE)
|
66
|
+
Scenario: Monkey goes to the zoo
|
67
|
+
Given foo
|
68
|
+
Then bar
|
69
|
+
FEATURE
|
70
|
+
|
71
|
+
before(:each) do
|
72
|
+
setup_formatter({
|
73
|
+
:formats => [
|
74
|
+
['Butternut::Formatter', File.join(@tmp_dir, "output.html")]
|
75
|
+
]
|
76
|
+
})
|
77
|
+
run_defined_feature
|
78
|
+
@doc = Nokogiri.HTML(@out.string)
|
79
|
+
|
80
|
+
file = most_recent_html_file(File.join(@tmp_dir, "output"))
|
81
|
+
@page_doc = Nokogiri.HTML(open(file).read)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "creates assets directory" do
|
85
|
+
File.join(@tmp_dir, "output").should be_an_existing_directory
|
86
|
+
end
|
87
|
+
|
88
|
+
it "links to the page source" do
|
89
|
+
step = @doc.at('.feature .scenario .step.passed')
|
90
|
+
link = step.at("a")
|
91
|
+
link.should_not be_nil
|
92
|
+
file = link['href']
|
93
|
+
file.should match(%r{^output/butternut.+\.html})
|
94
|
+
end
|
95
|
+
|
96
|
+
it "saves images and stylesheets and rewrites urls in page source" do
|
97
|
+
@page_doc.at('img:nth(1)')['src'].should == "picard.jpg"
|
98
|
+
File.join(@tmp_dir, "output", "picard.jpg").should be_an_existing_file
|
99
|
+
|
100
|
+
@page_doc.at('link:nth(1)[rel="stylesheet"]')['href'].should == "foo.css"
|
101
|
+
File.join(@tmp_dir, "output", "foo.css").should be_an_existing_file
|
102
|
+
|
103
|
+
@page_doc.at('link:nth(2)[rel="stylesheet"]')['href'].should == "bar.css"
|
104
|
+
File.join(@tmp_dir, "output", "bar.css").should be_an_existing_file
|
105
|
+
end
|
106
|
+
|
107
|
+
it "saves assets and rewrites urls referred to by stylesheets" do
|
108
|
+
foo = open(File.join(@tmp_dir, "output", "foo.css")).read
|
109
|
+
foo.should include("url(facepalm.jpg)")
|
110
|
+
File.join(@tmp_dir, "output", "facepalm.jpg").should be_an_existing_file
|
111
|
+
end
|
112
|
+
|
113
|
+
it "turns off links" do
|
114
|
+
link = @page_doc.at('a')
|
115
|
+
link['href'].should == "#"
|
116
|
+
link.inner_html.should == "Picard song"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "turns off scripts" do
|
120
|
+
@page_doc.css('script').length.should == 0
|
121
|
+
end
|
122
|
+
|
123
|
+
it "disables form elements" do
|
124
|
+
@page_doc.css('input, select, textarea').each do |elt|
|
125
|
+
elt['disabled'].should == "disabled"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
it "handles Errno::ENOENT" do
|
130
|
+
@page_doc.at('img:nth(2)')['src'].should == "/roflpwnage/missing_file_omg.gif"
|
131
|
+
end
|
132
|
+
|
133
|
+
it "handles OpenURI::HTTPError" do
|
134
|
+
@page_doc.at('img:nth(3)')['src'].should == "http://google.com/missing_file_omg.gif"
|
135
|
+
end
|
136
|
+
|
137
|
+
it "handles Net::FTPPermError" do
|
138
|
+
@page_doc.at('img:nth(4)')['src'].should == "ftp://mirror.anl.gov/missing_file_omg.gif"
|
139
|
+
end
|
140
|
+
|
141
|
+
it "handles badly formed URI's" do
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
module Butternut
|
4
|
+
describe Helpers do
|
5
|
+
include Helpers
|
6
|
+
|
7
|
+
def define_stub_chain
|
8
|
+
# This is what I hate about RSpec.
|
9
|
+
@stub_request_url = stub("fake request url", :to_string => "http://example.com")
|
10
|
+
@stub_response = stub("fake web response", :request_url => @stub_request_url)
|
11
|
+
@stub_page = stub("fake html page", {
|
12
|
+
:as_xml => "<cheese>pepperjack</cheese>",
|
13
|
+
:web_response => @stub_response
|
14
|
+
})
|
15
|
+
@stub_element = stub("fake element", :value= => nil, :select => nil, :click => nil, :exist? => true)
|
16
|
+
@stub_empty = stub("fake empty element", :exist? => false)
|
17
|
+
|
18
|
+
@stub_browser = stub("fake celerity browser", {
|
19
|
+
:goto => @stub_page, :page => @stub_page,
|
20
|
+
:text_field => @stub_element, :select_list => @stub_element,
|
21
|
+
:button => @stub_element
|
22
|
+
})
|
23
|
+
stub!(:browser).and_return(@stub_browser)
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#browser" do
|
27
|
+
it { browser.should be_a(Celerity::Browser) }
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#page_changed?" do
|
31
|
+
it { page_changed?.should_not be_true }
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#visit" do
|
35
|
+
before(:each) { define_stub_chain }
|
36
|
+
|
37
|
+
it "should go to the page" do
|
38
|
+
@stub_browser.should_receive(:goto).with("http://google.com")
|
39
|
+
visit("http://google.com")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should flag page as changed" do
|
43
|
+
visit("http://google.com")
|
44
|
+
page_changed?.should be_true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#current_url" do
|
49
|
+
before(:each) { define_stub_chain }
|
50
|
+
it do
|
51
|
+
@stub_request_url.should_receive(:to_string).and_return("http://google.com")
|
52
|
+
current_url.should == "http://google.com"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#current_page_source" do
|
57
|
+
before(:each) do
|
58
|
+
@browser = browser
|
59
|
+
visit("file://" + File.expand_path(File.dirname(__FILE__) + "/../fixtures/blargh.html"))
|
60
|
+
end
|
61
|
+
|
62
|
+
it "constructs the current page's source" do
|
63
|
+
# HtmlUnit's text node parsing it a little strange
|
64
|
+
expected = "<html><head>\n <title>Blargh</title>\n </head><body>\n <p>Foo</p>\n <p>Bar</p>\n \n</body></html>"
|
65
|
+
current_page_source.should == expected
|
66
|
+
end
|
67
|
+
|
68
|
+
it "returns nil if page is nil" do
|
69
|
+
@browser.stub!(:page).and_return(nil)
|
70
|
+
current_page_source.should be_nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#fill_in" do
|
75
|
+
before(:each) { define_stub_chain }
|
76
|
+
|
77
|
+
it "should find by label" do
|
78
|
+
@stub_browser.should_receive(:text_field).with(:label, "pants").and_return(@stub_element)
|
79
|
+
@stub_element.should_receive(:value=).with("khakis")
|
80
|
+
fill_in("pants", :with => "khakis")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should find by name" do
|
84
|
+
@stub_browser.should_receive(:text_field).with(:label, "pants").and_return(@stub_empty)
|
85
|
+
@stub_browser.should_receive(:text_field).with(:name, "pants").and_return(@stub_element)
|
86
|
+
@stub_element.should_receive(:value=).with("khakis")
|
87
|
+
fill_in("pants", :with => "khakis")
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should flag page as changed" do
|
91
|
+
fill_in("pants", :with => "khakis")
|
92
|
+
page_changed?.should be_true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#select" do
|
97
|
+
before(:each) { define_stub_chain }
|
98
|
+
|
99
|
+
it "should find by label" do
|
100
|
+
@stub_browser.should_receive(:select_list).with(:label, "pants").and_return(@stub_element)
|
101
|
+
@stub_element.should_receive(:select).with("khakis")
|
102
|
+
select("khakis", :from => "pants")
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should find by name" do
|
106
|
+
@stub_browser.should_receive(:select_list).with(:label, "pants").and_return(@stub_empty)
|
107
|
+
@stub_browser.should_receive(:select_list).with(:name, "pants").and_return(@stub_element)
|
108
|
+
@stub_element.should_receive(:select).with("khakis")
|
109
|
+
select("khakis", :from => "pants")
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should flag page as changed" do
|
113
|
+
select("khakis", :from => "pants")
|
114
|
+
page_changed?.should be_true
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "#click_button" do
|
119
|
+
before(:each) { define_stub_chain }
|
120
|
+
it do
|
121
|
+
@stub_browser.should_receive(:button).with("pants").and_return(@stub_element)
|
122
|
+
@stub_element.should_receive(:click)
|
123
|
+
click_button("pants")
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should flag page as changed" do
|
127
|
+
click_button("pants")
|
128
|
+
page_changed?.should be_true
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Butternut do
|
4
|
+
describe "running a scenario" do
|
5
|
+
extend SpecHelperDsl
|
6
|
+
include SpecHelper
|
7
|
+
|
8
|
+
describe "saving last page info" do
|
9
|
+
define_steps do
|
10
|
+
Given('waffles') do
|
11
|
+
visit("file://" + File.expand_path(File.dirname(__FILE__) + "/fixtures/foo.html"))
|
12
|
+
end
|
13
|
+
AfterStep do |scenario|
|
14
|
+
begin
|
15
|
+
scenario.last_page_source.should match(/Foo/)
|
16
|
+
scenario.last_page_url.should match(/foo\.html/)
|
17
|
+
rescue Exception => e
|
18
|
+
p e
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
define_feature <<-FEATURE
|
24
|
+
Scenario: Roffle waffles
|
25
|
+
Given waffles
|
26
|
+
FEATURE
|
27
|
+
|
28
|
+
it { run_defined_feature }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "resetting page_changed" do
|
32
|
+
define_steps do
|
33
|
+
Given('waffles') do
|
34
|
+
visit("file://" + File.expand_path(File.dirname(__FILE__) + "/fixtures/foo.txt"))
|
35
|
+
end
|
36
|
+
AfterStep do |scenario|
|
37
|
+
begin
|
38
|
+
page_changed?.should be_false
|
39
|
+
rescue Exception => e
|
40
|
+
p e
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
define_feature <<-FEATURE
|
46
|
+
Scenario: Roffle waffles
|
47
|
+
Given waffles
|
48
|
+
FEATURE
|
49
|
+
|
50
|
+
it { run_defined_feature }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
Binary file
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Foo</title>
|
4
|
+
<link rel="stylesheet" href="foo.css" type="text/css"/>
|
5
|
+
<link rel="stylesheet" href="css/bar.css" type="text/css"/>
|
6
|
+
<script type="text/javascript" src="foo.js"></script>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
Foo
|
10
|
+
<img src="picard.jpg"/>
|
11
|
+
<a href="http://picard.ytmnd.com/">Picard song</a>
|
12
|
+
<form action="foo.html" method="post">
|
13
|
+
<input type="text" name="foo" />
|
14
|
+
<select name="bar">
|
15
|
+
<option>pants</option>
|
16
|
+
</select>
|
17
|
+
<textarea name="yar"></textarea>
|
18
|
+
<input type="submit" value="Submit" />
|
19
|
+
</form>
|
20
|
+
<img src="/roflpwnage/missing_file_omg.gif"/>
|
21
|
+
<img src="http://google.com/missing_file_omg.gif"/>
|
22
|
+
<img src="ftp://mirror.anl.gov/missing_file_omg.gif"/>
|
23
|
+
<img src="//baduri/pants.png"/>
|
24
|
+
|
25
|
+
<div class="facepalm"> </div>
|
26
|
+
</body>
|
27
|
+
</html>
|
Binary file
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'rspec'
|
3
|
+
require 'spec'
|
4
|
+
require 'spec/autorun'
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
9
|
+
require 'butternut'
|
10
|
+
|
11
|
+
require 'cucumber/rb_support/rb_language'
|
12
|
+
require 'nokogiri'
|
13
|
+
|
14
|
+
module SpecHelperDsl
|
15
|
+
attr_reader :feature_content, :step_defs
|
16
|
+
|
17
|
+
def define_feature(string)
|
18
|
+
@feature_content = string
|
19
|
+
end
|
20
|
+
|
21
|
+
def define_steps(&block)
|
22
|
+
@step_defs = block
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module SpecHelper
|
27
|
+
def run_defined_feature
|
28
|
+
setup_world
|
29
|
+
define_steps
|
30
|
+
features = load_features(self.class.feature_content || raise("No feature content defined!"))
|
31
|
+
run(features)
|
32
|
+
end
|
33
|
+
|
34
|
+
def step_mother
|
35
|
+
@step_mother ||= Cucumber::StepMother.new
|
36
|
+
end
|
37
|
+
|
38
|
+
def load_features(content)
|
39
|
+
feature_file = Cucumber::FeatureFile.new('spec.feature', content)
|
40
|
+
features = Cucumber::Ast::Features.new
|
41
|
+
features.add_feature feature_file.parse(step_mother, {})
|
42
|
+
features
|
43
|
+
end
|
44
|
+
|
45
|
+
def run(features)
|
46
|
+
# options = { :verbose => true }
|
47
|
+
options = {}
|
48
|
+
tree_walker = Cucumber::Ast::TreeWalker.new(step_mother, @formatter ? [@formatter] : [], options, STDOUT)
|
49
|
+
tree_walker.visit_features(features)
|
50
|
+
end
|
51
|
+
|
52
|
+
def dsl
|
53
|
+
unless @dsl
|
54
|
+
rb = step_mother.load_programming_language('rb')
|
55
|
+
@dsl = Object.new
|
56
|
+
@dsl.extend Cucumber::RbSupport::RbDsl
|
57
|
+
end
|
58
|
+
@dsl
|
59
|
+
end
|
60
|
+
|
61
|
+
def define_steps
|
62
|
+
return unless step_defs = self.class.step_defs
|
63
|
+
dsl.instance_exec &step_defs
|
64
|
+
end
|
65
|
+
|
66
|
+
def setup_world
|
67
|
+
dsl.instance_exec do
|
68
|
+
Butternut.setup_hooks(self)
|
69
|
+
World(Butternut::Helpers)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
FIXTURE_DIR = File.expand_path(File.join(File.dirname(__FILE__), "fixtures"))
|
75
|
+
|
76
|
+
Spec::Matchers.define :be_an_existing_file do
|
77
|
+
match { |filename| File.exist?(filename) }
|
78
|
+
end
|
79
|
+
|
80
|
+
Spec::Matchers.define :be_an_existing_directory do
|
81
|
+
match { |filename| File.directory?(filename) }
|
82
|
+
end
|
83
|
+
|
84
|
+
Spec::Matchers.define :match_content_of do |expected|
|
85
|
+
match do |actual|
|
86
|
+
raise "expected file doesn't exist" unless File.exist?(expected)
|
87
|
+
raise "actual file doesn't exist" unless File.exist?(actual)
|
88
|
+
open(expected).read == open(actual).read
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
Spec::Runner.configure do |config|
|
94
|
+
config.before(:each) do
|
95
|
+
Cucumber::Parser::NaturalLanguage.instance_variable_set(:@languages, nil)
|
96
|
+
end
|
97
|
+
end
|
data/tmp/.gitignore
ADDED