sinatra-tests 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,23 +1,23 @@
1
1
  = Sinatra::Tests
2
2
 
3
- Commonly used bits when testing Sinatra apps/gems.
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 GitHub to your RubyGems sources
9
- $ gem sources -a http://gems.github.com
8
+ # Add Gemcutter to your RubyGems sources
9
+ $ gem sources -a http://gemcutter.com
10
10
 
11
- $ (sudo)? gem install kematzy-sinatra-tests
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.2.7 )
19
- * rack-test (>= 0.4.1)
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::SharedSpecs
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
- TODO:: write more documentation here
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.4.1')
14
- gem.add_dependency('rspec', '>= 1.2.8')
15
- gem.add_dependency('rspec_hpricot_matchers', '>= 1.0.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.5
1
+ 0.1.6
@@ -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.5' unless const_defined?(:VERSION)
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