peck-on-rails 0.1.0

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.
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: []