bbq-core 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4a48e0d7e2b08e20b007adafe0ead84e77bb54cc68bd4c8cdf7e5d68a1ae1fde
4
+ data.tar.gz: d8a944e766fb21bc119d771d28fcdee6e27a393e78ae4fded7bd403b420e613f
5
+ SHA512:
6
+ metadata.gz: 69a88b57acf34e2ec33f347a86d82f8c45f275f2ed25852e4a313fa4196ba9f6fc2fab33758f9059b67fa7b318a18ba2efd87ef4cc88bbb7114df4a84a47f6a6
7
+ data.tar.gz: f90be21ff429c510175e37d08fa438734053b97260b9979bb04b53e2caf3bc8edcd17d4b2458cd4cb7e50be74ff7efcccba963e28b1553dc526c1d9afa29261c
@@ -0,0 +1,14 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ bin/*
6
+ tmp/*
7
+ test/dummy/db/*.sqlite3
8
+ test/dummy/log/*.log
9
+ test/dummy/tmp/
10
+ test/dummy/test/acceptance/*
11
+ test/dummy/spec/acceptance/*
12
+ test/dope/test/acceptance/*
13
+ test/dope/spec/acceptance/*
14
+ nbproject/
@@ -0,0 +1,4 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 2.0.0
4
+ - 2.1.0
@@ -0,0 +1,47 @@
1
+ 0.2.1 / 2013-08-22
2
+ ==================
3
+
4
+ * bugfix: Bbq::TestClient propagates NoMethodErrors from the controller of
5
+ tested app instead of rising unsupported method errors.
6
+
7
+ 0.2.0 / 2013-01-06
8
+ ==================
9
+
10
+ * Dropped support for Ruby 1.8.7
11
+ * Capybara 2.0 support
12
+
13
+ 0.1.0 / 2013-01-06
14
+ ==================
15
+
16
+ * Extracted Rails' URL helpers inclusion to separate module
17
+ * Include only Capybara::Session::DSL_METHODS in TestUser, not the whole Capybara::DSL
18
+ * Added Capybara sessions pool
19
+ * Moved Test::User default options to separate method
20
+ * Added Test::Client for testing REST APIs
21
+ * Renamed bbq/test.rb to bbq/test_unit.rb. You may want to fix your test_helper.
22
+ * Moved require bbq/test_user to generated test_user.rb. You may want to update your existing test_user.rb.
23
+ * Fixed Capybara 'within' scope for RSpec flavour
24
+
25
+ 0.0.4 / 2011-10-19
26
+ ==================
27
+
28
+ * Make Bbq work with Capybara 1.0 and 1.1
29
+ * Rails is development dependency
30
+
31
+ 0.0.3 / 2011-07-14
32
+ ==================
33
+
34
+ * Added support and tests for Sinatra
35
+ * Added Bbq.app and Bbq.app=
36
+
37
+ 0.0.2 / 2011-07-01
38
+ ==================
39
+
40
+ * Extracted Bbq::TestUser::Eyes module
41
+ * Added :within option to TestUser methods
42
+ * Fix tests for ree and ruby187
43
+
44
+ 0.0.1 / 2011-04-20
45
+ ==================
46
+
47
+ * Bbq introduced to the wild world!
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "jruby-openssl", :platforms => :jruby
@@ -0,0 +1,20 @@
1
+ Copyright 2011 DRUG, Dolnośląska Grupa Użytkowników Ruby
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,318 @@
1
+ # BBQ
2
+
3
+ [![Build Status](https://secure.travis-ci.org/drugpl/bbq-core.png)](http://travis-ci.org/drugpl/bbq-core) [![Dependency Status](https://gemnasium.com/drugpl/bbq-core.png)](https://gemnasium.com/drugpl/bbq-core) [![Code Climate](https://codeclimate.com/github/drugpl/bbq-core.png)](https://codeclimate.com/github/drugpl/bbq-core) [![Gem Version](https://badge.fury.io/rb/bbq-core.png)](http://badge.fury.io/rb/bbq-core)
4
+
5
+ Object oriented acceptance testing using personas.
6
+
7
+ * Ruby (no Gherkin)
8
+ * Objects and methods instead of steps
9
+ * Test framework independent (RSpec and Test::Unit support)
10
+ * Thins based on Capybara.
11
+ * DCI (Data Context Interaction) for roles/personas
12
+ * Opinionated
13
+
14
+ ## Setup
15
+
16
+ First, add BBQ to your apps `Gemfile`:
17
+
18
+ ```ruby
19
+ gem "bbq", "0.2.1"
20
+ ```
21
+
22
+ Run install generator:
23
+
24
+ ```
25
+ bundle exec rails generate bbq:install
26
+ ```
27
+
28
+ Require BBQ in test/test_helper.rb (in case of Test::Unit):
29
+
30
+ ```ruby
31
+ require "bbq/test_unit"
32
+ ```
33
+
34
+ Require BBQ in spec/spec_helper.rb (in case of RSpec):
35
+
36
+ ```ruby
37
+ require "bbq/rspec"
38
+ ```
39
+
40
+ ## Feature generator
41
+
42
+ ```
43
+ bundle exec rails g bbq:test MyFeatureName
44
+ ```
45
+
46
+ ## Running features
47
+
48
+ For Test::Unit flavour:
49
+
50
+ ```
51
+ bundle exec rake test:acceptance
52
+ ```
53
+
54
+ For RSpec flavour:
55
+
56
+ ```
57
+ bundle exec rake spec:acceptance
58
+ ```
59
+
60
+ ## Examples
61
+
62
+ ### Roles and Devise integration
63
+
64
+ ```ruby
65
+ class TestUser < Bbq::TestUser
66
+ include Bbq::Devise
67
+
68
+ def update_ticket(summary, comment)
69
+ show_ticket(summary)
70
+ fill_in "Comment", :with => comment
71
+ click_on "Add update"
72
+ end
73
+
74
+ def open_application
75
+ visit '/'
76
+ end
77
+
78
+ module TicketReporter
79
+ def open_tickets_listing
80
+ open_application
81
+ click_link 'Tickets'
82
+ end
83
+
84
+ def open_ticket(summary, description)
85
+ open_tickets_listing
86
+ click_on "Open a new ticket"
87
+ fill_in "Summary", :with => summary
88
+ fill_in "Description", :with => description
89
+ click_on "Open ticket"
90
+ end
91
+
92
+ def show_ticket(summary)
93
+ open_tickets_listing
94
+ click_on summary
95
+ end
96
+ end
97
+
98
+ module TicketManager
99
+ def open_administration
100
+ visit '/admin'
101
+ end
102
+
103
+ def open_tickets_listing
104
+ open_administration
105
+ click_link 'Tickets'
106
+ end
107
+
108
+ def close_ticket(summary, comment = nil)
109
+ open_tickets_listing
110
+ click_on summary
111
+ fill_in "Comment", :with => comment if comment
112
+ click_on "Close ticket"
113
+ end
114
+
115
+ def show_ticket(summary)
116
+ open_tickets_listing
117
+ click_on summary
118
+ end
119
+ end
120
+ end
121
+ ```
122
+
123
+ ```ruby
124
+ class AdminTicketsTest < Bbq::TestCase
125
+ background do
126
+ admin = Factory(:admin)
127
+ @email, @password = admin.email, admin.password
128
+ end
129
+
130
+ scenario "admin can browse all user tickets" do
131
+ summaries = ["Forgot my password", "Page is not displayed correctly"]
132
+ descriptions = ["I lost my yellow note with password under the table!",
133
+ "My IE renders crap instead of crispy fonts!"]
134
+
135
+ alice = TestUser.new
136
+ alice.roles(:ticket_reporter)
137
+ alice.register_and_login
138
+ alice.open_ticket(summaries.first, descriptions.first)
139
+
140
+ bob = TestUser.new
141
+ bob.roles(:ticket_reporter)
142
+ bob.register_and_login
143
+ bob.open_ticket(summaries.second, descriptions.second)
144
+
145
+ charlie = TestUser.new(:email => @email, :password => @password)
146
+ charlie.login # charlie was already "registered" in factory as admin
147
+ charlie.roles(:ticket_manager)
148
+ charlie.open_tickets_listing
149
+ charlie.see!(*summaries)
150
+
151
+ charlie.click_on(summaries.second)
152
+ charlie.see!(summaries.second, descriptions.second)
153
+ charlie.not_see!(summaries.first, descriptions.first)
154
+ end
155
+ end
156
+ ```
157
+
158
+ ### RSpec integration
159
+
160
+ ```ruby
161
+ class TestUser < Bbq::TestUser
162
+ def email
163
+ @options[:email] || "buyer@example.com"
164
+ end
165
+
166
+ module Buyer
167
+ def ask_question(question)
168
+ fill_in "question", :with => question
169
+ fill_in "email", :with => email
170
+ click_on("Ask")
171
+ end
172
+
173
+ def go_to_page_and_open_widget(page_url, &block)
174
+ go_to_page(page_url)
175
+ open_widget &block
176
+ end
177
+
178
+ def go_to_page(page_url)
179
+ visit page_url
180
+ wait_until { page.find("iframe") }
181
+ end
182
+
183
+ def open_widget
184
+ within_widget do
185
+ page.find("#widget h3").click
186
+ yield if block_given?
187
+ end
188
+ end
189
+
190
+ ef within_widget(&block)
191
+ within_frame(widget_frame, &block)
192
+ end
193
+
194
+ def widget_frame
195
+ page.evaluate_script("document.getElementsByTagName('iframe')[0].id")
196
+ end
197
+ end
198
+ end
199
+ ```
200
+
201
+ ```ruby
202
+ feature "ask question widget" do
203
+ let(:user) {
204
+ user = TestUser.new(:driver => :webkit)
205
+ user.roles('buyer')
206
+ user
207
+ }
208
+
209
+ scenario "as a guest user, I should be able to ask a question" do
210
+ user.go_to_page_and_open_widget("/widget") do
211
+ user.ask_question "my question"
212
+ user.see!("Thanks!")
213
+ end
214
+ end
215
+ end
216
+ ```
217
+
218
+ ## Testing REST APIs
219
+
220
+ Bbq provides `Bbq::TestClient`, similar to `Bbq::TestUser`, but intended for testing APIs.
221
+ It's a thin wrapper around `Rack::Test` which allows you to send requests and run assertions
222
+ against responses.
223
+
224
+ ```ruby
225
+ class ApiTest < Bbq::TestCase
226
+ background do
227
+ headers = {'HTTP_ACCEPT' => 'application/json'}
228
+ @client = TestClient.new(:headers => headers)
229
+ end
230
+
231
+ scenario "admin can browse all user tickets" do
232
+ @client.get "/unicorn" do |response|
233
+ assert_equal 200, response.status
234
+ assert_equal "pink", response.body["unicorn"]["color"]
235
+ end
236
+ @client.post "/ponies", { :name => "Miracle" } do |response|
237
+ assert_equal 200, response.status
238
+ end
239
+ end
240
+ end
241
+ ```
242
+
243
+ ## Rails URL Helpers
244
+
245
+ Using url helpers from Rails in integration tests is not recommended.
246
+ Testing routes is part of integration test, so you should actually use only
247
+
248
+ ```ruby
249
+ visit '/'
250
+ ```
251
+
252
+ in your integration test. Use links and buttons in order to get to other pages in your app.
253
+
254
+ If you really need url helpers in your test user, just include them in your TestUser class:
255
+
256
+ ```ruby
257
+ require 'bbq/rails/routes'
258
+
259
+ class TestUser < Bbq::TestUser
260
+ include Bbq::Rails::Routes
261
+ end
262
+ ```
263
+ or just
264
+
265
+ ```ruby
266
+ class TestUser < Bbq::TestUser
267
+ include ::ActionDispatch::Routing::UrlFor
268
+ include ::Rails.application.routes.url_helpers
269
+ include ::ActionDispatch::Routing::RouteSet::MountedHelpers unless ::Rails.version < "3.1"
270
+ end
271
+ ```
272
+
273
+ ## Devise support
274
+
275
+ ```ruby
276
+ require "bbq/test_user"
277
+ require "bbq/devise"
278
+
279
+ class TestUser < Bbq::TestUser
280
+ include Bbq::Devise
281
+ end
282
+ ```
283
+
284
+ After that TestUser have *login*, *logout*, *register*, *register_and_login* methods.
285
+
286
+ ```ruby
287
+ test "user register with devise" do
288
+ user = TestUser.new # or TestUser.new(:email => "email@example.com", :password => "secret")
289
+ user.register_and_login
290
+ user.see!("Stuff after auth")
291
+ end
292
+ ```
293
+
294
+ ## Caveats
295
+
296
+ ### Timeout::Error
297
+
298
+ If you simulate multiple users in your tests and spawn multiple browsers with selenium it might
299
+ be a good idea to use Thin instead of Webrick to create application server.
300
+ We have experienced some problems with Webrick that lead to `Timeout::Error` exception
301
+ when user/browser that was inactive for some time (due to other users/browsers
302
+ activities) was requested to execute an action.
303
+
304
+ Capybara will use Thin instead of Webrick when it's available, so you only need to add Thin to you Gemfile:
305
+
306
+ ```ruby
307
+ # In test group if you want it to
308
+ # be used only in tests and not in your development mode
309
+ # ex. when running 'rails s'
310
+
311
+ gem 'thin', :require => false
312
+ ```
313
+
314
+ ## Additional information
315
+
316
+ * [2 problems with Cucumber](http://andrzejonsoftware.blogspot.com/2011/03/2-problems-with-cucumber.html)
317
+ * [Object oriented acceptance testing](http://andrzejonsoftware.blogspot.com/2011/04/object-oriented-acceptance-testing.html)
318
+
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ t.test_files = FileList['test/*_test.rb']
7
+ t.verbose = true
8
+ end
9
+
10
+ task default: :test
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "bbq/core/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "bbq-core"
7
+ s.version = Bbq::Core::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["DRUG - Dolnośląska Grupa Użytkowników Ruby"]
10
+ s.email = ["bbq@drug.org.pl"]
11
+ s.homepage = ""
12
+ s.description = %q{Objected oriented acceptance testing for Rails, using personas.}
13
+ s.summary = %q{Objected oriented acceptance testing for Rails, using personas.}
14
+
15
+ s.rubyforge_project = "bbq-core"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "capybara", ">= 2.0"
23
+ s.add_dependency "activesupport", ">= 2.0"
24
+
25
+ s.add_development_dependency "rake"
26
+ s.add_development_dependency "rdoc", "~> 3.7"
27
+ s.add_development_dependency "minitest", "~> 5.0"
28
+ end
@@ -0,0 +1,7 @@
1
+ module Bbq
2
+ module Core
3
+ class << self
4
+ attr_accessor :app
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,14 @@
1
+ require 'bbq/core/util'
2
+
3
+ module Bbq
4
+ module Core
5
+ module Roles
6
+ def roles(*names)
7
+ names.each do |name|
8
+ module_obj = Bbq::Core::Util.find_module(name, self)
9
+ self.extend(module_obj)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,64 @@
1
+ require 'bbq/core'
2
+
3
+ module Bbq
4
+ module Core
5
+ module Session
6
+ extend self
7
+
8
+ def next(options = {})
9
+ driver = options.delete(:driver)
10
+ pool = options.delete(:pool)
11
+
12
+ if pool
13
+ pool.next(driver)
14
+ else
15
+ create(driver)
16
+ end
17
+ end
18
+
19
+ def create(driver)
20
+ Capybara::Session.new(driver, Bbq::Core.app)
21
+ end
22
+
23
+ def pool
24
+ @pool ||= Pool.new
25
+ end
26
+
27
+ class Pool
28
+ attr_accessor :idle, :taken
29
+
30
+ def initialize
31
+ @idle = []
32
+ @taken = []
33
+ end
34
+
35
+ def next(driver)
36
+ take_idle(driver) || create(driver)
37
+ end
38
+
39
+ def release
40
+ taken.each(&:reset!)
41
+ idle.concat(taken)
42
+ taken.clear
43
+ end
44
+
45
+ private
46
+
47
+ def take_idle(driver)
48
+ idle.find { |s| s.mode == driver }.tap do |session|
49
+ if session
50
+ idle.delete(session)
51
+ taken.push(session)
52
+ end
53
+ end
54
+ end
55
+
56
+ def create(driver)
57
+ Bbq::Core::Session.create(driver).tap do |session|
58
+ taken.push(session)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,97 @@
1
+ require 'bbq/core/roles'
2
+
3
+ module Bbq
4
+ module Core
5
+ class TestClient
6
+ class UnsupportedMethodError < StandardError; end
7
+
8
+ include Bbq::Core::Roles
9
+
10
+ def initialize(options = {})
11
+ @options = options
12
+ end
13
+
14
+ HTTP_METHODS = %w(get post put delete head options patch)
15
+
16
+ HTTP_METHODS.each do |method|
17
+ class_eval <<-RUBY
18
+ def #{method}(path, params = {}, headers = {})
19
+ unless driver.respond_to? :#{method}
20
+ raise UnsupportedMethodError, "Your driver does not support #{method.upcase} method"
21
+ end
22
+
23
+ response = driver.#{method}(path, params, default_headers.merge(headers))
24
+ parsed_response = parse_response(response)
25
+ yield parsed_response if block_given?
26
+ parsed_response
27
+ end
28
+ RUBY
29
+ end
30
+
31
+ protected
32
+ def app
33
+ @options[:app] || Bbq::Core.app
34
+ end
35
+
36
+ def default_headers
37
+ @options[:headers] || {}
38
+ end
39
+
40
+ def driver
41
+ @driver ||= RackTest.new(app)
42
+ end
43
+
44
+ def parse_response(response)
45
+ case response.headers["Content-Type"]
46
+ when /^application\/(.*\+)?json/
47
+ response.extend(JsonBody)
48
+ when /^application\/(.*\+)?x-yaml/
49
+ response.extend(YamlBody)
50
+ else
51
+ response
52
+ end
53
+ end
54
+
55
+ class RackTest
56
+ attr_accessor :app
57
+
58
+ def initialize(app)
59
+ self.app = app
60
+ end
61
+
62
+ module ConvertHeaders
63
+ HTTP_METHODS.each do |method|
64
+ class_eval <<-RUBY
65
+ def #{method}(path, params = {}, headers = {})
66
+ super(path, params, to_env_headers(headers))
67
+ end
68
+ RUBY
69
+ end
70
+
71
+ def to_env_headers(http_headers)
72
+ http_headers.map do |k, v|
73
+ k = k.upcase.gsub("-", "_")
74
+ k = "HTTP_#{k}" unless ["CONTENT_TYPE", "CONTENT_LENGTH"].include?(k)
75
+ { k => v }
76
+ end.inject({}, :merge)
77
+ end
78
+ end
79
+
80
+ include Rack::Test::Methods
81
+ include ConvertHeaders
82
+ end
83
+
84
+ module JsonBody
85
+ def body
86
+ @parsed_body ||= super.empty?? super : JSON.parse(super)
87
+ end
88
+ end
89
+
90
+ module YamlBody
91
+ def body
92
+ @parsed_body ||= YAML.load(super)
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,33 @@
1
+ require 'bbq/core/session'
2
+ require 'bbq/core/roles'
3
+ require 'bbq/core/test_user/capybara_dsl'
4
+ require 'bbq/core/test_user/eyes'
5
+ require 'bbq/core/test_user/within'
6
+
7
+ module Bbq
8
+ module Core
9
+ class TestUser
10
+ include Bbq::Core::TestUser::CapybaraDsl
11
+ include Bbq::Core::TestUser::Eyes
12
+ include Bbq::Core::TestUser::Within
13
+ include Bbq::Core::Roles
14
+
15
+ attr_reader :options
16
+
17
+ def initialize(options = {})
18
+ @options = default_options.merge(options)
19
+ end
20
+
21
+ def default_options
22
+ {
23
+ :pool => Bbq::Core::Session.pool,
24
+ :driver => ::Capybara.default_driver
25
+ }
26
+ end
27
+
28
+ def page
29
+ @page ||= options[:session] || Bbq::Core::Session.next(:driver => options[:driver], :pool => options[:pool])
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ require 'capybara/dsl'
2
+
3
+ module Bbq
4
+ module Core
5
+ class TestUser
6
+ module CapybaraDsl
7
+ ::Capybara::Session::DSL_METHODS.each do |method|
8
+ class_eval <<-RUBY, __FILE__, __LINE__+1
9
+ def #{method}(*args, &block)
10
+ page.#{method}(*args, &block)
11
+ end
12
+ RUBY
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ module Bbq
2
+ module Core
3
+ class TestUser
4
+ module Eyes
5
+ def see?(*args)
6
+ args.all? { |arg| has_content?(arg) }
7
+ end
8
+
9
+ def not_see?(*args)
10
+ args.all? { |arg| has_no_content?(arg) }
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ require 'active_support/core_ext/array/extract_options'
2
+
3
+ module Bbq
4
+ module Core
5
+ class TestUser
6
+ module Within
7
+ METHODS_USING_WITHIN = [
8
+ :see?, :not_see?,
9
+ :attach_file, :check, :choose, :click_link_or_button, :click_button,
10
+ :click_link, :click_on, :fill_in, :select, :uncheck, :unselect
11
+ ]
12
+
13
+ METHODS_USING_WITHIN.each do |method_name|
14
+ class_eval <<-RUBY
15
+ def #{method_name}(*args)
16
+ using_within(args) { super }
17
+ end
18
+ RUBY
19
+ end
20
+
21
+ def using_within(args)
22
+ options = args.extract_options!
23
+ locator = options.delete(:within)
24
+ args.push(options) unless options.empty?
25
+
26
+ if locator
27
+ within(locator) { yield }
28
+ else
29
+ yield
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,21 @@
1
+ require 'active_support/core_ext/string/inflections'
2
+
3
+ module Bbq
4
+ module Core
5
+ class Util
6
+ def self.find_module(name, scope = nil)
7
+ namespace = case scope
8
+ when String, Symbol
9
+ "::#{scope.to_s.camelize}"
10
+ when Class
11
+ "::#{scope.name}"
12
+ when NilClass
13
+ nil
14
+ else
15
+ "::#{scope.class.name}"
16
+ end
17
+ "#{namespace}::#{name.to_s.camelize}".constantize
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ module Bbq
2
+ module Core
3
+ VERSION = '0.3.0'
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new("test:acceptance") do |t|
4
+ t.libs << 'test'
5
+ t.pattern = 'test/acceptance/**/*_test.rb'
6
+ t.verbose = false
7
+ end if File.exists?('test/acceptance')
8
+
9
+ begin
10
+ require 'rspec/core/rake_task'
11
+ RSpec::Core::RakeTask.new('spec:acceptance') do |spec|
12
+ spec.pattern = FileList['spec/acceptance/**/*_spec.rb']
13
+ end if File.exists?('spec/acceptance')
14
+ rescue LoadError
15
+ end
@@ -0,0 +1,44 @@
1
+ require 'test_helper'
2
+ require 'bbq/core/test_user'
3
+
4
+ class SessionPoolTest < Minitest::Test
5
+
6
+ def setup
7
+ Bbq::Core::Session.instance_variable_set(:@pool, nil)
8
+ end
9
+
10
+ def test_reuses_sessions
11
+ pool = Bbq::Core::Session::Pool.new
12
+ user1 = Bbq::Core::TestUser.new(:pool => pool).tap { |u| u.page }
13
+ pool.release
14
+ user2 = Bbq::Core::TestUser.new(:pool => pool).tap { |u| u.page }
15
+
16
+ assert_same user1.page, user2.page
17
+ end
18
+
19
+ def test_has_default_pool
20
+ user1 = Bbq::Core::TestUser.new.tap { |u| u.page }
21
+ Bbq::Core::Session::pool.release
22
+ user2 = Bbq::Core::TestUser.new.tap { |u| u.page }
23
+
24
+ assert_same user1.page, user2.page
25
+ end
26
+
27
+ def test_without_pool
28
+ user1 = Bbq::Core::TestUser.new(:pool => false).tap { |u| u.page }
29
+ Bbq::Core::Session::pool.release
30
+ user2 = Bbq::Core::TestUser.new(:pool => false).tap { |u| u.page }
31
+
32
+ refute_same user1.page, user2.page
33
+ end
34
+
35
+ def test_pool_returns_correct_driver
36
+ pool = Bbq::Core::Session::Pool.new
37
+ pool.next(:rack_test)
38
+ pool.next(:rack_test_the_other)
39
+ pool.release
40
+
41
+ assert_equal :rack_test, pool.next(:rack_test).mode
42
+ end
43
+
44
+ end
@@ -0,0 +1,30 @@
1
+ require 'test_helper'
2
+ require 'bbq/core/test_client'
3
+
4
+ class TestClientTest < Minitest::Test
5
+
6
+ def test_rack_test_to_env_headers_for_empty_hash
7
+ test_client = Bbq::Core::TestClient::RackTest.new(:app)
8
+ assert_equal({}, test_client.to_env_headers({}))
9
+ end
10
+
11
+ def test_rack_test_to_env_headers_for_content_type_or_content_length
12
+ test_client = Bbq::Core::TestClient::RackTest.new(:app)
13
+ result = test_client.to_env_headers({
14
+ "content-type" => "text/plain",
15
+ "content-length" => "40"
16
+ })
17
+ assert_includes(result.keys, "CONTENT_TYPE")
18
+ assert_includes(result.keys, "CONTENT_LENGTH")
19
+ end
20
+
21
+ def test_rack_test_to_env_headers_for_other_headers
22
+ test_client = Bbq::Core::TestClient::RackTest.new(:app)
23
+ result = test_client.to_env_headers({
24
+ "silly-header" => "silly-value"
25
+ })
26
+ assert_includes(result.keys, "HTTP_SILLY_HEADER")
27
+ end
28
+
29
+ end
30
+
@@ -0,0 +1,8 @@
1
+ require 'minitest/autorun'
2
+ require 'capybara'
3
+
4
+ Capybara.register_driver :rack_test_the_other do |app|
5
+ Capybara::RackTest::Driver.new(app)
6
+ end
7
+
8
+
@@ -0,0 +1,112 @@
1
+ require 'test_helper'
2
+ require 'bbq/core/test_user'
3
+
4
+
5
+ def text(output)
6
+ end
7
+
8
+ def html(output)
9
+ ->{ ['200', {'Content-Type' => 'text/html'}, [output]] }
10
+ end
11
+
12
+ TestApp = Rack::Builder.new do
13
+ map '/' do
14
+ run ->(env) { ['200', {'Content-Type' => 'text/plain'}, ['BBQ']] }
15
+ end
16
+
17
+ map '/miracle' do
18
+ run ->(env) { ['200', {'Content-Type' => 'text/plain'}, ['MIRACLE']] }
19
+ end
20
+
21
+ map '/ponycorns' do
22
+ run ->(env) { ['200', {'Content-Type' => 'text/html'}, [<<HTML
23
+ <ul id="unicorns">
24
+ <li>Pink</li>
25
+ </ul>
26
+ <ul id="ponies">
27
+ <li>Violet</li>
28
+ </ul>
29
+ <div id="new_pony">
30
+ <input type="text" name="color" value="" />
31
+ </div>
32
+ <a href="#">More ponycorns</a>
33
+ HTML
34
+ ]] }
35
+ end
36
+ end
37
+
38
+
39
+ class TestUser < Bbq::Core::TestUser
40
+ module Commenter
41
+ def comment
42
+ end
43
+ end
44
+
45
+ module VideoUploader
46
+ def upload
47
+ end
48
+ end
49
+
50
+ module CommentModerator
51
+ def moderate
52
+ end
53
+ end
54
+ end
55
+
56
+ class TestUserTest < Minitest::Test
57
+
58
+ def setup
59
+ Bbq::Core.app = TestApp
60
+ end
61
+
62
+ def teardown
63
+ Bbq::Core.app = nil
64
+ end
65
+
66
+ def test_capybara_dsl_methods
67
+ user = TestUser.new
68
+ Capybara::Session::DSL_METHODS.each do |m|
69
+ assert user.respond_to?(m)
70
+ end
71
+ end
72
+
73
+ def test_driver_option
74
+ user = TestUser.new(:driver => :rack_test_the_other)
75
+ assert_equal :rack_test_the_other, user.page.mode
76
+ end
77
+
78
+ def test_roles
79
+ user = TestUser.new
80
+ %w(comment upload moderate).each { |m| assert !user.respond_to?(m) }
81
+
82
+ user.roles(:commenter, "comment_moderator")
83
+ %w(comment moderate).each { |m| assert user.respond_to?(m) }
84
+ assert !user.respond_to?(:upload)
85
+
86
+ user.roles(:video_uploader)
87
+ %w(comment upload moderate).each { |m| assert user.respond_to?(m) }
88
+ end
89
+
90
+ def test_explicit_user_eyes
91
+ @user = TestUser.new
92
+ @user.visit "/miracle"
93
+ assert @user.not_see?("BBQ")
94
+ assert @user.see?("MIRACLE")
95
+ end
96
+
97
+ def test_user_eyes_within_scope
98
+ @user = TestUser.new
99
+ @user.visit "/ponycorns"
100
+ assert @user.see?("Pink", :within => "#unicorns")
101
+ assert ! @user.see?("Violet", :within => "#unicorns")
102
+ assert @user.not_see?("Violet", :within => "#unicorns")
103
+ assert ! @user.not_see?("Pink", :within => "#unicorns")
104
+
105
+ @user.fill_in "color", :with => "red", :within => "#new_pony"
106
+ assert_raises Capybara::ElementNotFound do
107
+ @user.fill_in "color", :with => "red", :within => "#new_unicorn"
108
+ end
109
+ @user.click_link "More ponycorns"
110
+ end
111
+
112
+ end
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+ require 'bbq/core/util'
3
+
4
+ class User
5
+ module Commenter
6
+ end
7
+ end
8
+
9
+ module Commenter
10
+ end
11
+
12
+ class UtilTest < Minitest::Test
13
+
14
+ def test_find_module_in_object_namespace
15
+ assert_commenter(User.new, User::Commenter)
16
+ end
17
+
18
+ def test_find_module_in_class_namespace
19
+ assert_commenter(User, User::Commenter)
20
+ end
21
+
22
+ def test_find_module_in_string_namespace
23
+ assert_commenter("User", User::Commenter)
24
+ end
25
+
26
+ def test_find_global_module
27
+ assert_commenter(nil, ::Commenter)
28
+ end
29
+
30
+ def assert_commenter(namespace, result)
31
+ [:commenter, "commenter"].each do |name|
32
+ assert_equal Bbq::Core::Util.find_module(name, namespace), result
33
+ end
34
+ end
35
+
36
+ end
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bbq-core
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - DRUG - Dolnośląska Grupa Użytkowników Ruby
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-03-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: capybara
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rdoc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.7'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.0'
83
+ description: Objected oriented acceptance testing for Rails, using personas.
84
+ email:
85
+ - bbq@drug.org.pl
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".travis.yml"
92
+ - CHANGELOG
93
+ - Gemfile
94
+ - MIT-LICENSE
95
+ - README.md
96
+ - Rakefile
97
+ - bbq-core.gemspec
98
+ - lib/bbq/core.rb
99
+ - lib/bbq/core/roles.rb
100
+ - lib/bbq/core/session.rb
101
+ - lib/bbq/core/test_client.rb
102
+ - lib/bbq/core/test_user.rb
103
+ - lib/bbq/core/test_user/capybara_dsl.rb
104
+ - lib/bbq/core/test_user/eyes.rb
105
+ - lib/bbq/core/test_user/within.rb
106
+ - lib/bbq/core/util.rb
107
+ - lib/bbq/core/version.rb
108
+ - lib/tasks/bbq.rake
109
+ - test/session_pool_test.rb
110
+ - test/test_client_test.rb
111
+ - test/test_helper.rb
112
+ - test/test_user_test.rb
113
+ - test/util_test.rb
114
+ homepage: ''
115
+ licenses: []
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubygems_version: 3.0.3
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: Objected oriented acceptance testing for Rails, using personas.
136
+ test_files:
137
+ - test/session_pool_test.rb
138
+ - test/test_client_test.rb
139
+ - test/test_helper.rb
140
+ - test/test_user_test.rb
141
+ - test/util_test.rb