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.
@@ -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