sinatra-tests 0.1.5 → 0.1.6
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/README.rdoc +165 -12
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/lib/sinatra/tests.rb +4 -2
- data/lib/sinatra/tests/rspec/matchers.rb +224 -0
- data/lib/sinatra/tests/rspec/shared_specs.rb +342 -0
- data/sinatra-tests.gemspec +22 -17
- data/spec/sinatra/tests/rspec/matchers_spec.rb +274 -0
- data/spec/sinatra/tests/test_case_spec.rb +0 -15
- data/spec/sinatra/tests/tests_spec.rb +30 -0
- data/spec/spec_helper.rb +7 -9
- metadata +52 -26
- data/lib/sinatra/tests/init.rb +0 -174
- data/lib/sinatra/tests/shared_specs.rb +0 -450
data/README.rdoc
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
= Sinatra::Tests
|
2
2
|
|
3
|
-
|
3
|
+
A Sinatra extension and repository of common RSpec helpers when testing your Sinatra apps/gems.
|
4
4
|
|
5
5
|
|
6
6
|
== Installation
|
7
7
|
|
8
|
-
# Add
|
9
|
-
$ gem sources -a http://
|
8
|
+
# Add Gemcutter to your RubyGems sources
|
9
|
+
$ gem sources -a http://gemcutter.com
|
10
10
|
|
11
|
-
$ (sudo)? gem install
|
11
|
+
$ (sudo)? gem install sinatra-tests
|
12
12
|
|
13
13
|
=== Dependencies
|
14
14
|
|
15
15
|
This Gem depends upon the following:
|
16
16
|
|
17
17
|
* sinatra ( >= 0.10.1 )
|
18
|
-
* rspec (>= 1.
|
19
|
-
* rack-test (>= 0.
|
20
|
-
|
18
|
+
* rspec (>= 1.3.0 )
|
19
|
+
* rack-test (>= 0.5.3)
|
20
|
+
* rspec_hpricot_matchers (>= 0.1.0)
|
21
21
|
|
22
22
|
== Getting Started
|
23
23
|
|
@@ -45,7 +45,8 @@ Declare the following Spec block:
|
|
45
45
|
|
46
46
|
Spec::Runner.configure do |config|
|
47
47
|
config.include RspecHpricotMatchers
|
48
|
-
config.include Sinatra::Tests::
|
48
|
+
config.include Sinatra::Tests::TestCase
|
49
|
+
config.include Sinatra::Tests::RSpec::SharedSpecs
|
49
50
|
end
|
50
51
|
|
51
52
|
|
@@ -66,10 +67,7 @@ In your TestApp block, register the Sinatra::Tests extension, by adding the foll
|
|
66
67
|
And finally define the TestCase block like this:
|
67
68
|
|
68
69
|
class Test::Unit::TestCase
|
69
|
-
include Sinatra::Tests::TestCase
|
70
|
-
|
71
70
|
Sinatra::Base.set :environment, :test
|
72
|
-
|
73
71
|
end
|
74
72
|
|
75
73
|
That's all. Now onto the niceties this provides you.
|
@@ -77,7 +75,142 @@ That's all. Now onto the niceties this provides you.
|
|
77
75
|
|
78
76
|
== USAGE
|
79
77
|
|
80
|
-
|
78
|
+
|
79
|
+
=== RSpec Matchers
|
80
|
+
|
81
|
+
==== :be_even
|
82
|
+
|
83
|
+
A simple matcher that tests for an even number
|
84
|
+
|
85
|
+
1.should_not be_even
|
86
|
+
2.should be_even
|
87
|
+
|
88
|
+
|
89
|
+
==== :have_a_page_title(:title_text)
|
90
|
+
|
91
|
+
A simple matcher that tests for a <head> with a <title> tag with the given text.
|
92
|
+
|
93
|
+
body.should have_a_page_title("Home | Site Title")
|
94
|
+
|
95
|
+
body.should have_a_page_title(/Home/)
|
96
|
+
|
97
|
+
|
98
|
+
==== :have_a_page_header(:text, :tag)
|
99
|
+
|
100
|
+
A simple matcher that tests for <h(1..6)> header tag with the given text.
|
101
|
+
|
102
|
+
<b>NB!</b> Throws an Exception when there's more than one page header on the page.
|
103
|
+
|
104
|
+
|
105
|
+
body.should have_a_page_header('Page Header')
|
106
|
+
|
107
|
+
body.should have_a_page_header(/Contact Information/, 'h1')
|
108
|
+
|
109
|
+
body.should have_a_page_header(/Contact Information/, 'body > h1')
|
110
|
+
|
111
|
+
|
112
|
+
==== :have_a_ui_btn(:tag, :action, :model_name_singluar, :link_text)
|
113
|
+
|
114
|
+
A simple matcher that tests for a <tt><a href></tt> tag with class 'ui-btn :action-link'
|
115
|
+
and a number of other specific values, derived from the other arguments passed.
|
116
|
+
|
117
|
+
|
118
|
+
body.should have_a_ui_btn('div', :edit, :article, 'Edit')
|
119
|
+
|
120
|
+
=> expects <a href="/articles/:id/edit" class="ui-btn edit-link" title="edit article">Edit</a>
|
121
|
+
|
122
|
+
body.should have_a_ui_btn('div', :delete, :article) =>
|
123
|
+
|
124
|
+
=> expects <a href="/articles/:id" class="ui-btn delete-link" title="delete article">DELETE</a>
|
125
|
+
|
126
|
+
|
127
|
+
==== :have_an_edit_btn(:tag, :model_name_singluar)
|
128
|
+
|
129
|
+
A simple matcher that tests for a <tt><a href></tt> tag with class 'ui-btn edit-link'
|
130
|
+
|
131
|
+
|
132
|
+
body.should have_an_edit_btn('td.actions', :post)
|
133
|
+
|
134
|
+
body.should have_an_edit_btn('td.actions', :post, 'Custom Btn Text')
|
135
|
+
|
136
|
+
|
137
|
+
==== :have_a_delete_btn(:tag, :model_name_singluar)
|
138
|
+
|
139
|
+
A simple matcher that tests for a <tt><a href></tt> tag with class 'ui-btn delete-link'
|
140
|
+
|
141
|
+
|
142
|
+
body.should have_a_delete_btn('td.actions', :post)
|
143
|
+
|
144
|
+
body.should have_a_delete_btn('td.actions', :post, 'Custom Btn Text')
|
145
|
+
|
146
|
+
|
147
|
+
==== :have_a_show_btn(:tag, :model_name_singluar)
|
148
|
+
|
149
|
+
A simple matcher that tests for a <tt><a href></tt> tag with class 'ui-btn show-link'
|
150
|
+
|
151
|
+
|
152
|
+
body.should have_a_show_btn('td.actions', :post)
|
153
|
+
|
154
|
+
body.should have_a_show_btn('td.actions', :post, 'Custom Btn Text')
|
155
|
+
|
156
|
+
|
157
|
+
|
158
|
+
=== RSpec SharedSpecs
|
159
|
+
|
160
|
+
These are just some of the shared specs that I have been using, but they are being changed at the moment,
|
161
|
+
so no guarantees of them surviving or remaining in their current form / functionality.
|
162
|
+
|
163
|
+
|
164
|
+
==== DEBUG
|
165
|
+
|
166
|
+
|
167
|
+
Dump a list of methods for the current <tt>app</tt>
|
168
|
+
|
169
|
+
it_should_behave_like "debug => app.methods"
|
170
|
+
|
171
|
+
|
172
|
+
Tests the body output for a <tt><debug></tt> tag, ie: prints out the entire body content
|
173
|
+
|
174
|
+
it_should_behave_like "debug"
|
175
|
+
|
176
|
+
|
177
|
+
==== RESPONSE
|
178
|
+
|
179
|
+
Checks that we got a 200 status (OK), and content-type is <tt>text/html</tt>
|
180
|
+
|
181
|
+
it_should_behave_like "HTTP headers"
|
182
|
+
|
183
|
+
it_should_behave_like "HTML"
|
184
|
+
|
185
|
+
Checks that we got a 200 status (OK), and content-type is <tt>text/css</tt>
|
186
|
+
|
187
|
+
it_should_behave_like "CSS"
|
188
|
+
|
189
|
+
|
190
|
+
==== HTML OUTPUT
|
191
|
+
|
192
|
+
Checks that the page has a <tt><div id="main-content"></div></tt>
|
193
|
+
|
194
|
+
it_should_behave_like "div#main-content"
|
195
|
+
|
196
|
+
|
197
|
+
Checks that the page has an <tt><h2></tt> tag within the <tt><div id="main-content"></div></tt>
|
198
|
+
|
199
|
+
it_should_behave_like "div#main-content > h2"
|
200
|
+
|
201
|
+
|
202
|
+
More to be addded later...
|
203
|
+
|
204
|
+
|
205
|
+
==== FORMS
|
206
|
+
|
207
|
+
Checks that the page has a form with a <tt><input type="hidden"...></tt> tag.
|
208
|
+
|
209
|
+
it_should_behave_like "forms > faux method > input.hidden"
|
210
|
+
|
211
|
+
|
212
|
+
More to be addded later...
|
213
|
+
|
81
214
|
|
82
215
|
|
83
216
|
|
@@ -91,6 +224,26 @@ For a better understanding of this Gem, make sure you study the '<tt>sinatra-tes
|
|
91
224
|
If something is not behaving intuitively, it is a bug, and should be reported.
|
92
225
|
Report it here: http://github.com/kematzy/sinatra-tests/issues
|
93
226
|
|
227
|
+
== TODOs
|
228
|
+
|
229
|
+
* Add more tests to various matchers.
|
230
|
+
|
231
|
+
* Create a test suite for the Shared Specs.
|
232
|
+
|
233
|
+
* Add Test::Unit (assert*) matchers and shared tests. (Please fork and add if you want this!)
|
234
|
+
|
235
|
+
|
236
|
+
|
237
|
+
== Note on Patches/Pull Requests
|
238
|
+
|
239
|
+
* Fork the project.
|
240
|
+
* Make your feature addition or bug fix.
|
241
|
+
* Add tests for it. This is important so I don't break it in a
|
242
|
+
future version unintentionally.
|
243
|
+
* Commit, do not mess with rakefile, version, or history.
|
244
|
+
* (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
245
|
+
* Send me a pull request. Bonus points for topic branches.
|
246
|
+
|
94
247
|
== Credits
|
95
248
|
|
96
249
|
Copyright (c) 2009 Kematzy [ kematzy gmail com ]
|
data/Rakefile
CHANGED
@@ -10,9 +10,9 @@ begin
|
|
10
10
|
gem.homepage = "http://github.com/kematzy/sinatra-tests"
|
11
11
|
gem.authors = ["kematzy"]
|
12
12
|
gem.add_dependency('sinatra', '>= 0.10.1')
|
13
|
-
gem.add_dependency('rack-test', '>= 0.
|
14
|
-
gem.add_dependency('rspec', '>= 1.
|
15
|
-
gem.add_dependency('rspec_hpricot_matchers', '>= 1.0
|
13
|
+
gem.add_dependency('rack-test', '>= 0.5.3')
|
14
|
+
gem.add_dependency('rspec', '>= 1.3.0')
|
15
|
+
gem.add_dependency('rspec_hpricot_matchers', '>= 1.0')
|
16
16
|
|
17
17
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
18
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.6
|
data/lib/sinatra/tests.rb
CHANGED
@@ -7,10 +7,12 @@ require 'spec'
|
|
7
7
|
require 'spec/interop/test'
|
8
8
|
require 'rspec_hpricot_matchers'
|
9
9
|
|
10
|
+
# NB! I'm loading a private framework here,
|
11
|
+
require 'alt/rext/string' unless String.respond_to?(:plural)
|
10
12
|
|
11
13
|
module Sinatra
|
12
14
|
module Tests
|
13
|
-
VERSION = '0.1.
|
15
|
+
VERSION = '0.1.6' unless const_defined?(:VERSION)
|
14
16
|
def self.version; "Sinatra::Tests v#{VERSION}"; end
|
15
17
|
|
16
18
|
|
@@ -34,6 +36,6 @@ module Sinatra
|
|
34
36
|
end #/module Test
|
35
37
|
end #/module Sinatra
|
36
38
|
|
37
|
-
%w(test_case shared_specs).each do |f|
|
39
|
+
%w(test_case rspec/matchers rspec/shared_specs).each do |f|
|
38
40
|
require "sinatra/tests/#{f}"
|
39
41
|
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
module Tests
|
5
|
+
|
6
|
+
module RSpec
|
7
|
+
|
8
|
+
module Matchers
|
9
|
+
|
10
|
+
##
|
11
|
+
# A simple matcher that tests for an even number
|
12
|
+
#
|
13
|
+
# ==== Examples
|
14
|
+
#
|
15
|
+
# 1.should_not be_even
|
16
|
+
# 2.should be_even
|
17
|
+
#
|
18
|
+
# @api public
|
19
|
+
def be_even
|
20
|
+
simple_matcher("an even number") { |given| given % 2 == 0 }
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# A simple matcher that tests for a <head> with a <title> tag
|
25
|
+
# with the given text.
|
26
|
+
#
|
27
|
+
# ==== Examples
|
28
|
+
#
|
29
|
+
# body.should have_a_page_title("Home | Default Site Title")
|
30
|
+
#
|
31
|
+
# body.should have_a_page_title(/Home/)
|
32
|
+
#
|
33
|
+
# @api public
|
34
|
+
def have_a_page_title(expected)
|
35
|
+
simple_matcher("have a page title in the <head> element with [#{expected}]") do |given, matcher|
|
36
|
+
given.should have_tag('head > title', expected)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# A simple matcher that tests for <h(1..6)> header tag with the given text.
|
42
|
+
#
|
43
|
+
# NB! Throws an Exception when there's more than one page header on the page.
|
44
|
+
#
|
45
|
+
# ==== Examples
|
46
|
+
#
|
47
|
+
# body.should have_a_page_header('Page Header')
|
48
|
+
#
|
49
|
+
# body.should have_a_page_header(/Contact Information/, 'h1')
|
50
|
+
#
|
51
|
+
# @api public
|
52
|
+
def have_a_page_header(expected, tag = 'h2')
|
53
|
+
simple_matcher("have an '#{tag}' page header with [#{expected.inspect}]") do |given, matcher|
|
54
|
+
given.should have_tag(tag, expected, :count => 1)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# TODO: add some comments here
|
60
|
+
#
|
61
|
+
# ==== Examples
|
62
|
+
#
|
63
|
+
#
|
64
|
+
# @api private
|
65
|
+
def have_a_td_actions(model, buttons = %w(delete edit))
|
66
|
+
simple_matcher do |given, matcher|
|
67
|
+
tag = "table##{model.to_s.plural}-table > tbody > tr > td.actions"
|
68
|
+
given.should have_tag(tag) do |td|
|
69
|
+
td.attributes['id'].should match(/#{model.to_s.singular}-actions-\d+/)
|
70
|
+
end
|
71
|
+
buttons.each do |btn|
|
72
|
+
given.should have_a_ui_btn(tag, btn.to_sym, model)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# A simple matcher that tests for a <tt><a href></tt> tag with class 'ui-btn'
|
79
|
+
# and a number of other specific values.
|
80
|
+
#
|
81
|
+
#
|
82
|
+
# ==== Examples
|
83
|
+
#
|
84
|
+
# body.should have_a_ui_btn('div', :edit, :article, 'Edit') =>
|
85
|
+
#
|
86
|
+
# => returns true when there is a <a href="/articles/:id/edit" class="ui-btn edit-link" title="edit article">Edit</a>
|
87
|
+
#
|
88
|
+
#
|
89
|
+
# body.should have_a_ui_btn('div', :delete, :article) =>
|
90
|
+
#
|
91
|
+
# => returns true when there is a <a href="/articles/:id" class="ui-btn delete-link" title="delete article">DELETE</a>
|
92
|
+
#
|
93
|
+
#
|
94
|
+
# @api private
|
95
|
+
def have_a_ui_btn(tag, type, model, text=nil)
|
96
|
+
text = type.to_s.upcase if text.nil?
|
97
|
+
simple_matcher("have a #{tag} with a ui-btn as a #{type}-btn for a [#{model}] with text #{text}") do |given, matcher|
|
98
|
+
given.should have_tag(tag + ' > a.ui-btn',text) do |a|
|
99
|
+
a.attributes['class'].should match(/#{type}-link/)
|
100
|
+
a.attributes['title'].should match(/#{type} #{model.to_s.singular}/)
|
101
|
+
if type == 'edit'
|
102
|
+
a.attributes['href'].should match(/\/#{model.to_s.plural}\/\d+\/edit/)
|
103
|
+
else
|
104
|
+
a.attributes['href'].should match(/\/#{model.to_s.plural}\/\d+/)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# A simple matcher that tests for a <tt><a href></tt> tag with class 'ui-btn edit-link'
|
112
|
+
#
|
113
|
+
# ==== Examples
|
114
|
+
#
|
115
|
+
# body.should have_an_edit_btn('td.actions', :post)
|
116
|
+
#
|
117
|
+
# body.should have_an_edit_btn('td.actions', :post, 'Custom Btn Text')
|
118
|
+
#
|
119
|
+
# @api private
|
120
|
+
def have_an_edit_btn(tag, model, text="EDIT")
|
121
|
+
have_a_ui_btn(tag, :edit, model, text)
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# A simple matcher that tests for a <tt><a href></tt> tag with class 'ui-btn delete-link'
|
126
|
+
#
|
127
|
+
# ==== Examples
|
128
|
+
#
|
129
|
+
# body.should have_a_delete_btn('td.actions', :post)
|
130
|
+
#
|
131
|
+
# body.should have_a_delete_btn('td.actions', :post, 'Custom Btn Text')
|
132
|
+
#
|
133
|
+
# @api private
|
134
|
+
def have_a_delete_btn(tag, model, text="DELETE")
|
135
|
+
have_a_ui_btn(tag, :delete, model, text)
|
136
|
+
end
|
137
|
+
|
138
|
+
##
|
139
|
+
# A simple matcher that tests for a <tt><a href></tt> tag with class 'ui-btn show-link'
|
140
|
+
#
|
141
|
+
# ==== Examples
|
142
|
+
#
|
143
|
+
# body.should have_a_show_btn('td.actions', :post)
|
144
|
+
#
|
145
|
+
# body.should have_a_show_btn('td.actions', :post, 'Custom Btn Text')
|
146
|
+
#
|
147
|
+
# @api private
|
148
|
+
def have_a_show_btn(tag, model, text="SHOW")
|
149
|
+
have_a_ui_btn(tag, :show, model, text)
|
150
|
+
end
|
151
|
+
|
152
|
+
# :stopdoc:
|
153
|
+
|
154
|
+
# def have_id_attribute(tag, id)
|
155
|
+
# simple_matcher do |given, matcher|
|
156
|
+
# given.should have_tag(tag).attributes['id'].should match(id)
|
157
|
+
# end
|
158
|
+
# end
|
159
|
+
|
160
|
+
# def have_link_title(title)
|
161
|
+
# simple_matcher do |given, matcher|
|
162
|
+
# given.attributes['title'].should == title
|
163
|
+
# end
|
164
|
+
# end
|
165
|
+
|
166
|
+
##
|
167
|
+
# TODO: add some comments here
|
168
|
+
#
|
169
|
+
# ==== Examples
|
170
|
+
#
|
171
|
+
#
|
172
|
+
# @api private
|
173
|
+
def have_an_ui_form_header(model, options = {} )
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
##
|
178
|
+
# TODO: add some comments here
|
179
|
+
#
|
180
|
+
# ==== Examples
|
181
|
+
#
|
182
|
+
#
|
183
|
+
# @api private
|
184
|
+
def have_a_ui_form_message(state, msg = nil)
|
185
|
+
simple_matcher do |given, matcher|
|
186
|
+
if msg.nil?
|
187
|
+
given.should have_tag("form > div.ui-form-message.#{state} > p") #ignoring message
|
188
|
+
else
|
189
|
+
given.should have_tag("form > div.ui-form-message.#{state} > p", msg)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
##
|
195
|
+
# TODO: add some comments here
|
196
|
+
#
|
197
|
+
# ==== Examples
|
198
|
+
#
|
199
|
+
#
|
200
|
+
# @api private
|
201
|
+
def have_an_admin_header(options ={})
|
202
|
+
simple_matcher do |given, matcher|
|
203
|
+
matcher.description = "be an admin_header with [#{options.inspect}]"
|
204
|
+
matcher.failure_message = "expected #{given} to have an admin-section-header with these values #{options.inspect}"
|
205
|
+
|
206
|
+
given.should have_tag('div.admin-section-header')
|
207
|
+
if options[:model]
|
208
|
+
given.should have_tag('div.admin-section-header > div.section > h2', /#{options[:model].to_s}/i )
|
209
|
+
if options[:add_new]
|
210
|
+
given.should have_tag("div.admin-section-header > div.actions > h4 > a[@href=/#{options[:model].to_s.downcase}/new]", /ADD NEW #{options[:model].to_s.singular}:?/i )
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# :doc:
|
217
|
+
|
218
|
+
|
219
|
+
end #/module Matchers
|
220
|
+
|
221
|
+
end #/module RSpec
|
222
|
+
|
223
|
+
end #/module Tests
|
224
|
+
end #/module Sinatra
|