peck-on-rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/COPYING +18 -0
  2. data/README.md +11 -0
  3. data/lib/peck_on_rails.rb +354 -0
  4. metadata +84 -0
data/COPYING ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) Manfred Stienstra, Fingertips <manfred@fngtps.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # Peck On Rails
2
+
3
+ Peck-On-Rails is an extension for Peck to make testing Rails easier.
4
+
5
+ [![Build Status](https://secure.travis-ci.org/Fingertips/Peck-On-Rails.png?branch=master)](http://travis-ci.org/Fingertips/Peck)
6
+
7
+ ## Getting Started
8
+
9
+ You can install Peck On Rails as a gem.
10
+
11
+ $ gem install peck-on-rails
@@ -0,0 +1,354 @@
1
+ # encoding: utf-8
2
+
3
+ require 'active_support/testing/assertions'
4
+ require 'active_support/testing/deprecation'
5
+ require 'active_support/testing/isolation'
6
+ require 'active_support/core_ext/kernel/reporting'
7
+ require 'active_support/deprecation'
8
+ require 'rails/backtrace_cleaner'
9
+
10
+ class Peck
11
+ class Rails
12
+ module BacktraceCleaning
13
+ protected
14
+
15
+ def clean_backtrace(backtrace)
16
+ super Peck::Rails::BacktraceCleaning.backtrace_cleaner.clean(backtrace)
17
+ end
18
+
19
+ def self.backtrace_cleaner
20
+ @backtrace_cleaner ||= ::Rails::BacktraceCleaner.new
21
+ end
22
+ end
23
+
24
+ class Context
25
+ def self.init(context, context_type, subject)
26
+ Peck.log("Peck::Rails::Context.init")
27
+ end
28
+ end
29
+
30
+ class Helper
31
+ def self.init(context, context_type, subject)
32
+ if [:helper].include?(context_type)
33
+ Peck.log("Peck::Rails::Helper.init")
34
+ context.class_eval do
35
+ include subject
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ class Model
42
+ def self.init(context, context_type, subject)
43
+ if [:model, :controller, :helper].include?(context_type)
44
+ Peck.log("Peck::Rails::Model.init")
45
+ context.class_eval do
46
+ include ::ActiveRecord::TestFixtures
47
+ self.fixture_path = File.join(::Rails.root, 'test', 'fixtures')
48
+ fixtures :all
49
+ define_method(:method_name) { self.class.label }
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ class Controller
56
+ def self.init(context, context_type, subject)
57
+ if context_type == :controller
58
+ Peck.log("Peck::Rails::Controller.init")
59
+ context.class_eval do
60
+ attr_accessor :controller
61
+
62
+ before do
63
+ @routes = ::Rails.application.routes
64
+ end
65
+
66
+ def self.determine_default_controller_class(name)
67
+ self._controller_class = Peck::Rails.subject(self)
68
+ end
69
+
70
+ include ::ActionController::TestCase::Behavior
71
+ include ::Peck::Rails::Controller::Helpers
72
+ extend ::Peck::Rails::Controller::Fixtures
73
+ end
74
+ end
75
+ end
76
+
77
+ # Stores expression to be evaluated later in the correct context
78
+ class LazyValue
79
+ def initialize(expression)
80
+ @expression = expression
81
+ end
82
+
83
+ def to_param(spec)
84
+ spec.instance_eval(@expression)
85
+ end
86
+
87
+ def inspect
88
+ @expression
89
+ end
90
+ end
91
+
92
+ module Fixtures
93
+ # Returns true when the passed name is a known table, we assume known tables also have fixtures
94
+ def known_fixture?(name)
95
+ respond_to?(:fixture_table_names) && fixture_table_names.include?(name.to_s)
96
+ end
97
+
98
+ # Filter calls to fixture methods so we can use them in the context definition
99
+ def method_missing(method, *arguments, &block)
100
+ if known_fixture?(method)
101
+ arguments = arguments.map { |a| a.inspect }
102
+ ::Peck::Rails::Controller::LazyValue.new("#{method}(#{arguments.join(', ')})")
103
+ else
104
+ super
105
+ end
106
+ end
107
+ end
108
+
109
+ module Helpers
110
+ def status
111
+ Peck::Rails::Controller::Status.new(@response)
112
+ end
113
+
114
+ def templates
115
+ # Force body to be read in case the template is being streamed
116
+ response.body
117
+ @templates.keys
118
+ end
119
+
120
+ def body
121
+ Peck::Rails::Controller::Body.new(@response)
122
+ end
123
+
124
+ # Interpret the non-immediate values in params and replace them
125
+ def immediate_values(params)
126
+ result = {}
127
+ params.each do |key, value|
128
+ result[key] = case value
129
+ when Hash
130
+ immediate_values(value)
131
+ when ::Peck::Rails::Controller::LazyValue
132
+ value.to_param(self)
133
+ when Proc
134
+ value.call
135
+ else
136
+ value
137
+ end
138
+ end
139
+ result
140
+ end
141
+ end
142
+
143
+ class Status
144
+ def initialize(response)
145
+ @response = response
146
+ end
147
+
148
+ def ==(other)
149
+ case other
150
+ when Numeric
151
+ @response.status == other
152
+ else
153
+ code = Rack::Utils::SYMBOL_TO_STATUS_CODE[other]
154
+ @response.status === code
155
+ end
156
+ end
157
+
158
+ def inspect
159
+ "#<Peck::Rails::Controller::Status:#{@response.status}>"
160
+ end
161
+ end
162
+
163
+ class Body
164
+ def initialize(response)
165
+ @response = response
166
+ end
167
+
168
+ def document
169
+ if defined?(:Nokogiri)
170
+ @document ||= Nokogiri::HTML.parse(@response.body)
171
+ else
172
+ raise RuntimeError, "Please install Nokogiri to use the CSS or Xpath matchers (gem install nokogiri)"
173
+ end
174
+ end
175
+
176
+ def json
177
+ if defined?(:JSON)
178
+ @json ||= JSON.parse(@response.body)
179
+ else
180
+ raise RuntimeError, "Please install a JSON gem to use the json accessor (gem install json)"
181
+ end
182
+ end
183
+
184
+ def match_css?(query)
185
+ !document.css(query).empty?
186
+ end
187
+
188
+ def match_xpath?(query)
189
+ !document.xpath(query).empty?
190
+ end
191
+
192
+ def blank?
193
+ @response.body.blank?
194
+ end
195
+
196
+ def inspect
197
+ "#<html body=\"#{@response.body}\">"
198
+ end
199
+ end
200
+ end
201
+
202
+ def self.subject(context)
203
+ context.description.find { |a| a.is_a?(Module) }
204
+ end
205
+
206
+ def self.context_type_for_description(context, subject)
207
+ context.description.find do |subject|
208
+ subject.is_a?(Symbol)
209
+ end
210
+ end
211
+
212
+ HELPER_RE = /Helper$/
213
+
214
+ def self.context_type_for_subject(context, subject)
215
+ if subject < ActionController::Base
216
+ :controller
217
+ elsif subject < ActiveRecord::Base
218
+ :model
219
+ elsif subject.name =~ HELPER_RE
220
+ :helper
221
+ else
222
+ :plain
223
+ end
224
+ end
225
+
226
+ def self.context_type(context, subject)
227
+ context_type =
228
+ context_type_for_description(context, subject) ||
229
+ context_type_for_subject(context, subject)
230
+ Peck.log("Using `#{context_type}' as context type for `#{subject.name}'")
231
+ context_type
232
+ end
233
+
234
+ def self.init
235
+ Peck.log("Setting up Peck::Rails")
236
+ proc do |context|
237
+ subject = Peck::Rails.subject(context)
238
+ context_type = Peck::Rails.context_type(context, subject)
239
+ [
240
+ Peck::Rails::Context,
241
+ Peck::Rails::Helper,
242
+ Peck::Rails::Model,
243
+ Peck::Rails::Controller
244
+ ].each do |klass|
245
+ klass.send(:init, context, context_type, subject)
246
+ end
247
+ end
248
+ end
249
+ end
250
+ end
251
+
252
+ class Peck
253
+ class Should
254
+ class ResponseRequirement < Peck::Should::Proxy
255
+ SUPPORTED_VERBS = [:get, :post, :put, :delete, :options]
256
+
257
+ attr_accessor :method, :expected
258
+
259
+ def define_specification(verb, action, params={})
260
+ _method = self.method
261
+ _expected = self.expected
262
+ context.it(description(verb, action, params)) do
263
+ send(verb, action, immediate_values(params))
264
+ send(_method).should == _expected
265
+ end
266
+ end
267
+
268
+ def method_missing(method, *attributes, &block)
269
+ verb = method.to_sym
270
+ if self.class.supported_verbs.include?(verb)
271
+ define_specification(verb, *attributes)
272
+ else
273
+ super
274
+ end
275
+ end
276
+
277
+ def self.supported_verbs
278
+ SUPPORTED_VERBS
279
+ end
280
+ end
281
+
282
+ class RequireLogin < ResponseRequirement
283
+ def description(verb, action, params={})
284
+ description = []
285
+ description << "should not" if (negated == false)
286
+ description << "#{verb.upcase}s `#{action}' without logging in"
287
+ description << "#{params.inspect}" unless params.blank?
288
+ description.join(' ')
289
+ end
290
+ end
291
+
292
+ class Disallow < ResponseRequirement
293
+ def description(verb, action, params={})
294
+ description = ["should"]
295
+ description << "not" if (negated == false)
296
+ description << "be allowed to #{verb.upcase}s `#{action}'"
297
+ description << "#{params.inspect}" unless params.blank?
298
+ description.join(' ')
299
+ end
300
+ end
301
+
302
+ class Specification
303
+ def require_login
304
+ requirement = RequireLogin.new(context)
305
+ requirement.negated = @negated
306
+ requirement.method = :login_required?
307
+ requirement.expected = true
308
+ requirement
309
+ end
310
+
311
+ def disallow
312
+ requirement = Disallow.new(context)
313
+ requirement.negated = @negated
314
+ requirement.method = :disallowed?
315
+ requirement.expected = true
316
+ requirement
317
+ end
318
+
319
+ def allow
320
+ requirement = Disallow.new(context)
321
+ requirement.negated = !@negated
322
+ requirement.method = :allowed?
323
+ requirement.expected = true
324
+ requirement
325
+ end
326
+ end
327
+ end
328
+ end
329
+
330
+ class Peck
331
+ class Notifiers
332
+ class Base
333
+ include Peck::Rails::BacktraceCleaning
334
+ end
335
+ end
336
+ end
337
+
338
+ class Peck
339
+ class Should
340
+ def validate_with(attribute, value)
341
+ message = "Expected #{!@negated ? 'no' : ''}errors on #{attribute.inspect} with value `#{value.inspect}' after validation"
342
+
343
+ @this.send("#{attribute}=", value)
344
+ @this.valid?
345
+ if @this.errors[attribute].kind_of?(Array)
346
+ satisfy(message) { @this.errors[attribute].empty? }
347
+ else
348
+ satisfy(message) { @this.errors[attribute].nil? }
349
+ end
350
+ end
351
+ end
352
+ end
353
+
354
+ Peck::Context.once(&Peck::Rails.init)
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: peck-on-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Manfred Stienstra
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: peck
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rails
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 3.2.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 3.2.0
46
+ description: ! ' Peck-On-Rails is an extension for Peck to make testing Rails easier.
47
+
48
+ '
49
+ email: manfred@fngtps.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files:
53
+ - COPYING
54
+ files:
55
+ - lib/peck_on_rails.rb
56
+ - COPYING
57
+ - README.md
58
+ homepage:
59
+ licenses: []
60
+ post_install_message:
61
+ rdoc_options:
62
+ - --charset=utf-8
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 1.8.23
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: Peck-On-Rails adds useful helpers and context extensions to make testing
83
+ Ruby on Rails apps easier.
84
+ test_files: []