effective_test_bot 0.4.13 → 0.4.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +26 -22
- data/app/helpers/effective_test_bot_controller_helper.rb +0 -6
- data/lib/effective_test_bot.rb +1 -0
- data/lib/effective_test_bot/engine.rb +32 -31
- data/lib/effective_test_bot/middleware.rb +40 -0
- data/lib/effective_test_bot/version.rb +1 -1
- data/lib/generators/templates/test_helper.rb +1 -1
- data/test/concerns/test_botable/devise_dsl.rb +2 -0
- data/test/concerns/test_botable/wizard_dsl.rb +6 -1
- data/test/support/effective_test_bot_assertions.rb +23 -12
- data/test/support/effective_test_bot_form_filler.rb +7 -0
- data/test/support/effective_test_bot_form_helper.rb +1 -0
- data/test/support/effective_test_bot_login_helper.rb +7 -3
- data/test/support/effective_test_bot_test_helper.rb +5 -0
- data/test/test_bot/integration/application_test.rb +41 -11
- data/test/test_bot/integration/environment_test.rb +20 -68
- data/test/test_botable/base_test.rb +3 -3
- data/test/test_botable/crud_test.rb +20 -18
- data/test/test_botable/devise_test.rb +25 -13
- data/test/test_botable/wizard_test.rb +2 -1
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c57de4dc4b6c0cf80fe3cefea43adb80d683bde
|
4
|
+
data.tar.gz: a2f0200f1fb20a3df4272adf99e9858103630fe8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca5a005d6ecf7d17b699f615bd1b953f4607718a2f4ee6f5349d6f55506a73f974826287033927292aef55dd5875d0baae5a2bc29aaaf58be87f426346d0c2e0
|
7
|
+
data.tar.gz: bc67e5f134111162842ef992a4451e3dfd49ce235fee9d2505b355a8aef54a0858ab6c88a21aa03003f760b43c961f85779ecc1bc6a2e12138031a5d8173afed
|
data/README.md
CHANGED
@@ -99,22 +99,24 @@ Effective TestBot provides 4 areas of support in writing [minitest](https://gith
|
|
99
99
|
|
100
100
|
The following assertions are added for use in any integration test:
|
101
101
|
|
102
|
-
- `
|
103
|
-
- `
|
104
|
-
- `
|
105
|
-
- `assert_submit_input` makes sure there is an `input[type='submit']` present.
|
106
|
-
- `assert_page_status` checks for a given http status, default 200.
|
102
|
+
- `assert_assigns` asserts a given rails view_assigns object is present.
|
103
|
+
- `assert_assigns_errors` use after an intentionally invalid form submit to make sure your assigned rails object has errors, or a specific error.
|
104
|
+
- `assert_no_assigns_errors` should be used after any form submit to make sure your assigned rails object has no errors. Prints out any errors if they exist.
|
107
105
|
- `assert_current_path(path)` asserts the current page path.
|
108
|
-
- `
|
109
|
-
- `
|
110
|
-
- `assert_no_unpermitted_params` makes sure the last submitted form did not include any unpermitted params and prints out any unpermitted params that do exist.
|
106
|
+
- `assert_flash`, optionally with the desired `:success`, `:error` key and/or message, makes sure the flash is set.
|
107
|
+
- `assert_jquery_ujs_disable_with` makes sure all `input[type=submit]` elements on the page have the `data-disable-with` property set.
|
111
108
|
- `assert_no_exceptions` checks for any exceptions in the last page request and gives a stacktrace if there was.
|
112
109
|
- `assert_no_html_form_validation_errors` checks for frontend html5 errors.
|
113
|
-
- `
|
114
|
-
- `
|
115
|
-
- `
|
116
|
-
- `
|
117
|
-
- `
|
110
|
+
- `assert_no_js_errors` - checks for any javascript errors on the page.
|
111
|
+
- `assert_no_unpermitted_params` makes sure the last submitted form did not include any unpermitted params and prints out any unpermitted params that do exist.
|
112
|
+
- `assert_page_content(content)` checks that the given content is present without waiting the capybara default wait time.
|
113
|
+
- `assert_no_page_content(content)` checks that the given content is blank without waiting the capybara default wait time.
|
114
|
+
- `assert_page_status` checks for a given http status, default 200.
|
115
|
+
- `assert_page_title` makes sure there is an html `<title></title>` present.
|
116
|
+
- `assert_redirect(from_path)` optionally with to_path, makes sure the current page path is not from_path.
|
117
|
+
- `assert_signed_in` checks that the assigned `@current_user` is present.
|
118
|
+
- `assert_signed_out` checks that the assigned `@current_user` is blank.
|
119
|
+
- `assert_submit_input` makes sure there is an `input[type='submit']` present.
|
118
120
|
|
119
121
|
As well,
|
120
122
|
|
@@ -181,15 +183,17 @@ end
|
|
181
183
|
|
182
184
|
### other helpers
|
183
185
|
|
184
|
-
- `
|
186
|
+
- `as_user(user) do .. end` yields a block between `sign_in`, and `logout`.
|
185
187
|
- `clear_form` clears all form fields, probably used before `submit_novalidate_form` to test invalid form submissions.
|
188
|
+
- `click_first(label)` clicks the first link matching the given label
|
189
|
+
- `submit_novalidate_form` submits the form without client side validation, ignoring any required field requirements.
|
186
190
|
- `sign_in(user)` optionally with user, signs in via `Warden::Test::Helpers` hacky login skipping method.
|
187
191
|
- `sign_in_manually(user, password)` visits the devise `new_user_session_path` and signs in via the form.
|
188
192
|
- `sign_up` visits the devise `new_user_registration_path` and signs up as a new user.
|
189
|
-
- `as_user(user) do .. end` yields a block between `sign_in`, and `logout`.
|
190
193
|
- `synchronize!` should fix any timing issues waiting for page elements.
|
191
194
|
- `was_redirect?` returns true/false if the last time we changed pages was a 304 redirect.
|
192
195
|
- `was_download?` if clicking a link returned a file of any type rather than a page change.
|
196
|
+
- `within_if(selector, boolean) do .. end` runs the block inside capybara's `within do .. end` if boolean is true, otherwise runs the same block skipping the `within`.
|
193
197
|
|
194
198
|
## Capybara Super Extras
|
195
199
|
|
@@ -269,14 +273,14 @@ The individual test suites may also be used as part of a larger test:
|
|
269
273
|
class PostsTest < ActionDispatch::IntegrationTest
|
270
274
|
test 'user may only update a post once' do
|
271
275
|
crud_action_test(:create_valid, Post, User.first)
|
272
|
-
|
276
|
+
assert_text 'successfully created post. You may only update it once.'
|
273
277
|
|
274
278
|
crud_action_test(:update_valid, Post.last, User.first)
|
275
|
-
|
279
|
+
assert_text 'successfully updated post.'
|
276
280
|
|
277
281
|
crud_action_test(:update_valid, Post.last, User.first, skip: [:no_assigns_errors, :updated_at])
|
278
282
|
assert_assigns_errors(:post, 'you may no longer update this post.')
|
279
|
-
|
283
|
+
assert_text 'you may no longer update this post.'
|
280
284
|
end
|
281
285
|
end
|
282
286
|
```
|
@@ -305,7 +309,7 @@ Or each individually in part of a regular test:
|
|
305
309
|
class MyApplicationTest < ActionDispatch::IntegrationTest
|
306
310
|
test 'user receives 10 tokens after signing up' do
|
307
311
|
devise_action_test(:sign_up)
|
308
|
-
|
312
|
+
assert_text 'Tokens: 10'
|
309
313
|
assert_equals 10, User.last.tokens
|
310
314
|
assert_equals 10, assigns(:current_user).tokens
|
311
315
|
end
|
@@ -372,7 +376,7 @@ class PostsTest < ActionDispatch::IntegrationTest
|
|
372
376
|
page_action_test(:posts_path, User.first)
|
373
377
|
|
374
378
|
assert page.current_path, '/posts'
|
375
|
-
|
379
|
+
assert_text 'first post'
|
376
380
|
end
|
377
381
|
end
|
378
382
|
```
|
@@ -397,7 +401,7 @@ class PostsTest < ActionDispatch::IntegrationTest
|
|
397
401
|
test 'visiting blog redirects to posts' do
|
398
402
|
Post.create(title: 'first post')
|
399
403
|
redirect_action_test('/blog', '/posts', User.first)
|
400
|
-
|
404
|
+
assert_text 'first post'
|
401
405
|
end
|
402
406
|
end
|
403
407
|
```
|
@@ -425,7 +429,7 @@ class PostsTest < ActionDispatch::IntegrationTest
|
|
425
429
|
test 'building a post in 5 steps' do
|
426
430
|
wizard_action_test('/build_post/step1', '/build_post/step5', User.first) do
|
427
431
|
if page.current_path.end_with?('step4')
|
428
|
-
|
432
|
+
assert_text 'your post is ready but must first be approved by an admin.'
|
429
433
|
end
|
430
434
|
end
|
431
435
|
end
|
@@ -30,10 +30,4 @@ module EffectiveTestBotControllerHelper
|
|
30
30
|
response.headers['Test-Bot-Unpermitted-Params'] = Base64.encode64(exception.params.to_json)
|
31
31
|
end
|
32
32
|
end
|
33
|
-
|
34
|
-
def assign_test_bot_exceptions_header(exception)
|
35
|
-
info = [exception.message] + exception.backtrace.first(8)
|
36
|
-
response.headers['Test-Bot-Exceptions'] = Base64.encode64(info.to_json)
|
37
|
-
end
|
38
|
-
|
39
33
|
end
|
data/lib/effective_test_bot.rb
CHANGED
@@ -13,32 +13,40 @@ module EffectiveTestBot
|
|
13
13
|
end
|
14
14
|
|
15
15
|
initializer 'effective_test_bot.test_suite' do |app|
|
16
|
-
Rails.
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
if Rails.env.test?
|
17
|
+
Rails.application.config.to_prepare do
|
18
|
+
# test/support/
|
19
|
+
ActionDispatch::IntegrationTest.include EffectiveTestBotAssertions
|
20
|
+
ActionDispatch::IntegrationTest.include EffectiveTestBotFormHelper
|
21
|
+
ActionDispatch::IntegrationTest.include EffectiveTestBotFormFiller
|
22
|
+
ActionDispatch::IntegrationTest.include EffectiveTestBotLoginHelper
|
23
|
+
ActionDispatch::IntegrationTest.include EffectiveTestBotScreenshotsHelper
|
24
|
+
ActionDispatch::IntegrationTest.include EffectiveTestBotTestHelper
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
# test/test_botable/
|
27
|
+
ActionDispatch::IntegrationTest.include BaseTest
|
28
|
+
ActionDispatch::IntegrationTest.include CrudTest
|
29
|
+
ActionDispatch::IntegrationTest.include DeviseTest
|
30
|
+
ActionDispatch::IntegrationTest.include MemberTest
|
31
|
+
ActionDispatch::IntegrationTest.include PageTest
|
32
|
+
ActionDispatch::IntegrationTest.include RedirectTest
|
33
|
+
ActionDispatch::IntegrationTest.include WizardTest
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
# test/concerns/test_botable/
|
36
|
+
ActionDispatch::IntegrationTest.include TestBotable::BaseDsl
|
37
|
+
ActionDispatch::IntegrationTest.include TestBotable::CrudDsl
|
38
|
+
ActionDispatch::IntegrationTest.include TestBotable::DeviseDsl
|
39
|
+
ActionDispatch::IntegrationTest.include TestBotable::MemberDsl
|
40
|
+
ActionDispatch::IntegrationTest.include TestBotable::PageDsl
|
41
|
+
ActionDispatch::IntegrationTest.include TestBotable::RedirectDsl
|
42
|
+
ActionDispatch::IntegrationTest.include TestBotable::WizardDsl
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
initializer 'effective_test_bot.middleware' do |app|
|
48
|
+
if Rails.env.test?
|
49
|
+
Rails.application.config.middleware.use EffectiveTestBot::Middleware
|
42
50
|
end
|
43
51
|
end
|
44
52
|
|
@@ -54,14 +62,7 @@ module EffectiveTestBot
|
|
54
62
|
rescue_from ActionController::UnpermittedParameters do |exception|
|
55
63
|
assign_test_bot_unpermitted_params_header(exception)
|
56
64
|
end
|
57
|
-
|
58
|
-
# This isn't working properly. TODO: Fix this
|
59
|
-
# rescue_from StandardError do |exception|
|
60
|
-
# assign_test_bot_exceptions_header(exception)
|
61
|
-
# render status: 500, text: "<html><body><h1>Uncaught Exception</h1><p>#{exception.message}</p><p>#{exception.backtrace.first(20).join('<br>')}</p></body></html>"
|
62
|
-
# end
|
63
65
|
end
|
64
|
-
|
65
66
|
end
|
66
67
|
end
|
67
68
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Watch for any rails server exceptions and write the stacktrace to ./tmp/test_bot/exception.txt
|
2
|
+
# This file is checked for by assert_no_exceptions
|
3
|
+
|
4
|
+
module EffectiveTestBot
|
5
|
+
class Middleware
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
begin
|
12
|
+
@app.call(env)
|
13
|
+
rescue Exception => exception
|
14
|
+
begin
|
15
|
+
save(exception)
|
16
|
+
rescue => e
|
17
|
+
puts "TestBotError: An error occurred while attempting to save a rails server exception: #{e.message}"
|
18
|
+
end
|
19
|
+
|
20
|
+
raise exception
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def save(exception)
|
25
|
+
lines = [exception.message] + exception.backtrace.first(8)
|
26
|
+
|
27
|
+
dir = File.join(Dir.pwd, 'tmp', 'test_bot')
|
28
|
+
file = File.join(dir, 'exception.txt')
|
29
|
+
|
30
|
+
Dir.mkdir(dir) unless File.exists?(dir)
|
31
|
+
File.delete(file) if File.exists?(file)
|
32
|
+
|
33
|
+
File.open(file, 'w') do |file|
|
34
|
+
file.write "================== Start server exception ==================\n"
|
35
|
+
lines.each { |line| file.write(line); file.write("\n") }
|
36
|
+
file.write "=================== End server exception ===================\n"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -30,7 +30,7 @@ class ActionDispatch::IntegrationTest
|
|
30
30
|
# def setup # Called before every test
|
31
31
|
# end
|
32
32
|
|
33
|
-
# def teardown # Called after every
|
33
|
+
# def teardown # Called after every test
|
34
34
|
# end
|
35
35
|
|
36
36
|
def after_teardown # I reset sessions here so capybara-screenshot can still make screenshots when tests fail
|
@@ -35,6 +35,8 @@ module TestBotable
|
|
35
35
|
def devise_action_test(test, options = {})
|
36
36
|
options[:email] ||= "unique-#{Time.zone.now.to_i}@example.com"
|
37
37
|
options[:password] ||= '!Password123'
|
38
|
+
options[:username] ||= 'unique-username'
|
39
|
+
options[:login] ||= 'unique-login'
|
38
40
|
options[:user] ||= User.new
|
39
41
|
|
40
42
|
begin
|
@@ -20,7 +20,12 @@ module TestBotable
|
|
20
20
|
module ClassMethods
|
21
21
|
|
22
22
|
def wizard_test(from_path, to_path, user, options = {})
|
23
|
-
|
23
|
+
if to_path.present?
|
24
|
+
options[:current_test] = options.delete(:label) || "#{from_path} to #{to_path}"
|
25
|
+
else
|
26
|
+
options[:current_test] = options.delete(:label) || "#{from_path}"
|
27
|
+
end
|
28
|
+
|
24
29
|
return if EffectiveTestBot.skip?(options[:current_test])
|
25
30
|
|
26
31
|
method_name = test_bot_method_name('wizard_test', options[:current_test])
|
@@ -1,14 +1,20 @@
|
|
1
1
|
module EffectiveTestBotAssertions
|
2
|
+
def assert_page_content(content, message = "(page_content) Expected page content :content: to be present")
|
3
|
+
assert page.has_text?(content, wait: 0), message.sub(':content:', content)
|
4
|
+
end
|
5
|
+
|
6
|
+
def assert_no_page_content(content, message = "(page_content) Expected page content :content: to be blank")
|
7
|
+
assert page.has_no_text?(content, wait: 0), message.sub(':content:', content)
|
8
|
+
end
|
9
|
+
|
2
10
|
def assert_signed_in(message = nil)
|
3
|
-
visit
|
4
|
-
|
5
|
-
assert page.has_no_selector?('form#new_user'), message || '(signed_in) Expected new_user form to be blank'
|
11
|
+
visit(root_path) if page.current_path.blank?
|
12
|
+
assert assigns['current_user'].present?, message || 'Expected @current_user to be present when signed in'
|
6
13
|
end
|
7
14
|
|
8
15
|
def assert_signed_out(message = nil)
|
9
|
-
visit
|
10
|
-
|
11
|
-
assert page.has_selector?('form#new_user'), message || '(signed_out) Expected new_user form to be present'
|
16
|
+
visit(root_path) if page.current_path.blank? || assigns['current_user'].present?
|
17
|
+
assert assigns['current_user'].blank?, message || 'Expected @current_user to be blank when signed out'
|
12
18
|
end
|
13
19
|
|
14
20
|
def assert_capybara_can_execute_javascript(message = "Expected capybara-webkit page.evaluate_script() to be successful")
|
@@ -32,8 +38,6 @@ module EffectiveTestBotAssertions
|
|
32
38
|
end
|
33
39
|
|
34
40
|
def assert_page_title(title = :any, message = '(page_title) Expected page title to be present')
|
35
|
-
return if was_download? # If this was a download, it correctly won't have a page title
|
36
|
-
|
37
41
|
if title.present? && title != :any
|
38
42
|
assert_title(title) # Capybara TitleQuery, match this text
|
39
43
|
else
|
@@ -43,7 +47,7 @@ module EffectiveTestBotAssertions
|
|
43
47
|
end
|
44
48
|
|
45
49
|
def assert_form(selector, message = "(form) Expected visible form with selector :selector: to be present")
|
46
|
-
assert all(selector).present?, message.sub(':selector', selector)
|
50
|
+
assert all(selector).present?, message.sub(':selector:', selector)
|
47
51
|
end
|
48
52
|
|
49
53
|
def assert_submit_input(message = "(submit_input) Expected one or more visible input[type='submit'] to be present")
|
@@ -56,7 +60,7 @@ module EffectiveTestBotAssertions
|
|
56
60
|
|
57
61
|
def assert_current_path(path, message = '(current_path) Expected current_path to be :path:')
|
58
62
|
path = public_send(path) if path.kind_of?(Symbol)
|
59
|
-
assert_equal path, page.current_path, message.sub(':path', path.to_s)
|
63
|
+
assert_equal path, page.current_path, message.sub(':path:', path.to_s)
|
60
64
|
end
|
61
65
|
|
62
66
|
# assert_redirect '/about'
|
@@ -78,8 +82,15 @@ module EffectiveTestBotAssertions
|
|
78
82
|
assert_equal [], unpermitted_params, message
|
79
83
|
end
|
80
84
|
|
81
|
-
def assert_no_exceptions(message =
|
82
|
-
|
85
|
+
def assert_no_exceptions(message = "(no_exceptions) Unexpected rails server exception:\n:exception:")
|
86
|
+
# this file is created by EffectiveTestBot::Middleware when an exception is encountered in the rails app
|
87
|
+
file = File.join(Dir.pwd, 'tmp', 'test_bot', 'exception.txt')
|
88
|
+
return unless File.exists?(file)
|
89
|
+
|
90
|
+
exception = File.read(file)
|
91
|
+
File.delete(file)
|
92
|
+
|
93
|
+
assert false, message.sub(':exception:', exception)
|
83
94
|
end
|
84
95
|
|
85
96
|
# This must be run after submit_form()
|
@@ -65,6 +65,7 @@ module EffectiveTestBotFormFiller
|
|
65
65
|
case [field.tag_name, field['type']].compact.join('_')
|
66
66
|
when 'input_text', 'input_email', 'input_password', 'input_tel', 'input_number', 'input_checkbox', 'input_radio', 'textarea'
|
67
67
|
field.set(value_for_field(field, fills))
|
68
|
+
close_effective_date_time_picker(field) if field['class'].to_s.include?('effective_date')
|
68
69
|
when 'select'
|
69
70
|
if EffectiveTestBot.tour_mode_extreme? && field['class'].to_s.include?('select2') # select2
|
70
71
|
page.execute_script("try { $('select##{field['id']}').select2('open'); } catch(e) {};")
|
@@ -165,6 +166,8 @@ module EffectiveTestBotFormFiller
|
|
165
166
|
LETTERS.sample + DIGITS.sample + LETTERS.sample + ' ' + DIGITS.sample + LETTERS.sample + DIGITS.sample
|
166
167
|
elsif attribute.include?('zip') && attribute.include?('code') # Make a US zip code
|
167
168
|
DIGITS.sample + DIGITS.sample + DIGITS.sample + DIGITS.sample + DIGITS.sample
|
169
|
+
elsif attribute.include?('slug')
|
170
|
+
Faker::Lorem.words(3).join(' ').parameterize
|
168
171
|
else
|
169
172
|
Faker::Lorem.words(3).join(' ').capitalize
|
170
173
|
end
|
@@ -319,6 +322,10 @@ module EffectiveTestBotFormFiller
|
|
319
322
|
end
|
320
323
|
end
|
321
324
|
|
325
|
+
def close_effective_date_time_picker(field)
|
326
|
+
page.execute_script("try { $('input##{field['id']}').data('DateTimePicker').hide(); } catch(e) {};")
|
327
|
+
end
|
328
|
+
|
322
329
|
private
|
323
330
|
|
324
331
|
def fill_value_for_field(fills, attributes)
|
@@ -2,13 +2,15 @@
|
|
2
2
|
|
3
3
|
module EffectiveTestBotLoginHelper
|
4
4
|
def as_user(user)
|
5
|
-
sign_in(user); yield;
|
5
|
+
sign_in(user); yield; sign_out
|
6
6
|
end
|
7
7
|
|
8
|
-
|
8
|
+
# This is currently hardcoded to use the warden login_as test helper
|
9
|
+
def sign_in(user)
|
9
10
|
user.kind_of?(String) ? login_as(User.find_by_email!(user)) : login_as(user)
|
10
11
|
end
|
11
12
|
|
13
|
+
# This is currently hardcoded to use the warden logout test helper
|
12
14
|
def sign_out
|
13
15
|
logout
|
14
16
|
end
|
@@ -17,9 +19,11 @@ module EffectiveTestBotLoginHelper
|
|
17
19
|
visit new_user_session_path
|
18
20
|
|
19
21
|
email = (user_or_email.respond_to?(:email) ? user_or_email.email : user_or_email)
|
22
|
+
username = (user_or_email.respond_to?(:username) ? user_or_email.username : user_or_email)
|
23
|
+
login = (user_or_email.respond_to?(:login) ? user_or_email.login : user_or_email)
|
20
24
|
|
21
25
|
within('form#new_user') do
|
22
|
-
fill_form(email: email, password: password)
|
26
|
+
fill_form(email: email, password: password, username: username, login: login)
|
23
27
|
submit_novalidate_form
|
24
28
|
end
|
25
29
|
end
|
@@ -29,6 +29,11 @@ module EffectiveTestBotTestHelper
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
# Calls capybara within do .. end if selector is present and bool is true
|
33
|
+
def within_if(selector, bool = true, &block)
|
34
|
+
(selector.present? && bool) ? within(selector) { yield } : yield
|
35
|
+
end
|
36
|
+
|
32
37
|
def click_first(label)
|
33
38
|
click_link(label, match: :first)
|
34
39
|
end
|
@@ -52,12 +52,17 @@ module TestBot
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
# Wizard Test
|
56
|
+
elsif is_wicked_controller?(route)
|
57
|
+
first_step_path = "/#{controller}/#{controller_instance(route).wizard_steps.first}"
|
58
|
+
wizard_test(first_step_path, nil, User.first)
|
59
|
+
|
55
60
|
# Member Test
|
56
61
|
elsif route.verb.to_s.include?('GET') && route.path.required_names == ['id']
|
57
62
|
member_test(controller, action, User.first)
|
58
63
|
|
59
64
|
# Page Test
|
60
|
-
elsif route.verb.to_s.include?('GET') && route.name.present?
|
65
|
+
elsif route.verb.to_s.include?('GET') && route.name.present? && Array(route.path.required_names).blank? # This could eventually be removed to supported nested routes
|
61
66
|
page_test("#{route.name}_path".to_sym, User.first, route: route, label: "#{route.name}_path")
|
62
67
|
|
63
68
|
else
|
@@ -67,22 +72,47 @@ module TestBot
|
|
67
72
|
end
|
68
73
|
end
|
69
74
|
|
70
|
-
|
75
|
+
protected
|
71
76
|
|
72
77
|
def is_crud_controller?(route)
|
73
78
|
return false unless CRUD_ACTIONS.include?(route.defaults[:action])
|
74
|
-
return false unless route.defaults[:controller].present? && route.app.respond_to?(:controller)
|
75
79
|
|
76
|
-
|
77
|
-
|
78
|
-
|
80
|
+
controller = controller_instance(route)
|
81
|
+
controller.respond_to?(:new) && controller.respond_to?(:create)
|
82
|
+
end
|
79
83
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
84
|
+
# https://github.com/schneems/wicked/
|
85
|
+
def is_wicked_controller?(route)
|
86
|
+
return false unless defined?(Wicked::Wizard)
|
87
|
+
|
88
|
+
controller = controller_instance(route)
|
89
|
+
return false unless controller.kind_of?(Wicked::Wizard)
|
90
|
+
|
91
|
+
# So this is a Wicked::Wizard controller, we have to trick it into running an action to make the steps available
|
92
|
+
controller.params = {}
|
93
|
+
(controller.run_callbacks(:process_action) rescue false)
|
94
|
+
|
95
|
+
controller.wizard_steps.present?
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def controller_instance(route)
|
101
|
+
return :none unless route.defaults[:controller] && route.defaults[:action]
|
102
|
+
|
103
|
+
@_controller_instances ||= {}
|
104
|
+
@_controller_instances[route.defaults[:controller]] ||= build_controller_instance(route)
|
105
|
+
end
|
106
|
+
|
107
|
+
def build_controller_instance(route)
|
108
|
+
# Find the correct route.app that links to the controller
|
109
|
+
# If there is a routing constraint, we have to traverse the route.app linked list to find the route with a controller
|
110
|
+
route_app = route
|
111
|
+
route_app = route_app.app while (route_app.respond_to?(:app) && route_app != route_app.app)
|
112
|
+
|
113
|
+
return :none unless route_app.respond_to?(:controller)
|
85
114
|
|
115
|
+
(route_app.controller(route.defaults).new() rescue :none)
|
86
116
|
end
|
87
117
|
|
88
118
|
end
|
@@ -5,16 +5,13 @@ module TestBot
|
|
5
5
|
@@original_users_count = User.count
|
6
6
|
let(:original_users_count) { @@original_users_count }
|
7
7
|
|
8
|
-
let(:email) { 'unique@testbot.com' }
|
9
|
-
let(:password) { '!Password123' }
|
10
|
-
let(:username) { 'test_bot_user' }
|
11
|
-
|
12
8
|
def self.test_order
|
13
9
|
:alpha
|
14
10
|
end
|
15
11
|
|
16
|
-
test '01:
|
17
|
-
|
12
|
+
test '01: can visit root_path' do
|
13
|
+
visit root_path
|
14
|
+
assert_page_status
|
18
15
|
end
|
19
16
|
|
20
17
|
test '02: all fixtures and seeds valid' do
|
@@ -29,86 +26,41 @@ module TestBot
|
|
29
26
|
end
|
30
27
|
end
|
31
28
|
|
32
|
-
|
33
|
-
|
34
|
-
assert (User.count > 0), 'please create at least 1 seed or fixture user for effective_test_bot to function'
|
29
|
+
test '03: at least one user is present' do
|
30
|
+
assert (User.count > 0), 'please fixture or seed at least 1 user for effective_test_bot to function'
|
35
31
|
end
|
36
32
|
|
37
|
-
test '04: activerecord can
|
38
|
-
|
33
|
+
test '04: activerecord can save a resource' do
|
34
|
+
User.new(email: 'unique@testbot.com', password: '!Password123', password_confirmation: '!Password123').save(validate: false)
|
39
35
|
assert_equal (original_users_count + 1), User.count
|
40
36
|
end
|
41
37
|
|
42
|
-
test '05:
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
test '06: capybara can execute javascript' do
|
47
|
-
visit root_path
|
48
|
-
assert_capybara_can_execute_javascript
|
49
|
-
end
|
50
|
-
|
51
|
-
test '07: jquery is present' do
|
52
|
-
visit root_path
|
53
|
-
assert_jquery_present
|
38
|
+
test '05: database has rolled back' do
|
39
|
+
assert_equal original_users_count, User.count, 'the activerecord resource created in a previous test is still present'
|
54
40
|
end
|
55
41
|
|
56
|
-
test '
|
57
|
-
|
58
|
-
assert_jquery_ujs_present
|
59
|
-
end
|
60
|
-
|
61
|
-
test '09: capybara can sign up a user' do
|
62
|
-
user = sign_up()
|
63
|
-
assert user.kind_of?(User), "expected to create a new user after submitting sign up form at #{new_user_registration_path}"
|
64
|
-
|
65
|
-
assert_equal (original_users_count + 1), User.count
|
42
|
+
test '06: capybara can sign_in' do
|
43
|
+
sign_in(User.first)
|
66
44
|
assert_signed_in
|
67
45
|
end
|
68
46
|
|
69
|
-
test '
|
47
|
+
test '07: capybara session has reset' do
|
70
48
|
assert_signed_out
|
71
|
-
assert_environment_normal
|
72
49
|
end
|
73
50
|
|
74
|
-
test '
|
75
|
-
|
76
|
-
|
77
|
-
assert_signed_in
|
78
|
-
end
|
79
|
-
|
80
|
-
test '12: database and session have reset' do
|
81
|
-
assert_signed_out
|
82
|
-
assert_environment_normal
|
83
|
-
end
|
84
|
-
|
85
|
-
test '13: capybara can sign in manually' do
|
86
|
-
create_user!
|
87
|
-
sign_in_manually(email, password)
|
88
|
-
assert_signed_in
|
89
|
-
end
|
90
|
-
|
91
|
-
test '14: database and session have reset' do
|
92
|
-
assert_signed_out
|
93
|
-
assert_environment_normal
|
51
|
+
test '08: capybara can execute javascript' do
|
52
|
+
visit root_path
|
53
|
+
assert_capybara_can_execute_javascript
|
94
54
|
end
|
95
55
|
|
96
|
-
|
97
|
-
|
98
|
-
# This is all about seeing if the cookies, session, and database are rolling back properly in between tests
|
99
|
-
def assert_environment_normal
|
56
|
+
test '09: jquery is present' do
|
100
57
|
visit root_path
|
101
|
-
|
102
|
-
assert_equal original_users_count, User.count, 'Expected User.count to be back to original'
|
103
|
-
assert assigns[:current_user].blank?, 'Expected current_user to be blank'
|
58
|
+
assert_jquery_present
|
104
59
|
end
|
105
60
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
user.login = username if user.respond_to?('login=')
|
110
|
-
|
111
|
-
user.valid? ? user.save : user.save(validate: false)
|
61
|
+
test '10: rails jquery_ujs is present' do
|
62
|
+
visit root_path
|
63
|
+
assert_jquery_ujs_present
|
112
64
|
end
|
113
65
|
|
114
66
|
end
|
@@ -10,7 +10,7 @@ module BaseTest
|
|
10
10
|
assert_no_exceptions unless test_bot_skip?(:exceptions)
|
11
11
|
assert_page_status unless test_bot_skip?(:page_status)
|
12
12
|
assert_no_js_errors unless test_bot_skip?(:no_js_errors)
|
13
|
-
assert_page_title unless test_bot_skip?(:page_title)
|
13
|
+
assert_page_title unless (test_bot_skip?(:page_title) || all('head').blank? || was_download?)
|
14
14
|
end
|
15
15
|
|
16
16
|
private
|
@@ -44,9 +44,9 @@ module BaseTest
|
|
44
44
|
|
45
45
|
visit(new_resource_path)
|
46
46
|
|
47
|
-
assert_form
|
47
|
+
assert_form("form#new_#{resource_name}", "TestBotError: Failed to find form#new_#{resource_name}. #{hint}") unless test_bot_skip?(:form)
|
48
48
|
|
49
|
-
|
49
|
+
within_if("form#new_#{resource_name}", !test_bot_skip?(:form)) do
|
50
50
|
fill_form(resource_attributes)
|
51
51
|
|
52
52
|
assert_submit_input "TestBotError: Failed to find a visible input[type='submit'] on #{page.current_path}. #{hint}"
|
@@ -37,15 +37,12 @@ module CrudTest
|
|
37
37
|
assert_page_normal
|
38
38
|
assert_assigns(resource_name) # unskippable
|
39
39
|
|
40
|
-
#
|
41
|
-
form_selector = "form#new_#{resource_name}"
|
42
|
-
assert_selector form_selector, "Expected form with selector #{form_selector}"
|
40
|
+
assert_form("form#new_#{resource_name}") unless test_bot_skip?(:form)
|
43
41
|
|
44
|
-
|
42
|
+
within_if("form#new_#{resource_name}", !test_bot_skip?(:form)) do
|
45
43
|
assert_submit_input unless test_bot_skip?(:submit_input)
|
46
44
|
assert_jquery_ujs_disable_with unless test_bot_skip?(:jquery_ujs_disable_with)
|
47
45
|
end
|
48
|
-
|
49
46
|
end
|
50
47
|
|
51
48
|
def test_bot_create_invalid_test
|
@@ -53,7 +50,9 @@ module CrudTest
|
|
53
50
|
|
54
51
|
before = { count: resource_class.count }
|
55
52
|
|
56
|
-
|
53
|
+
assert_form("form#new_#{resource_name}") unless test_bot_skip?(:form)
|
54
|
+
|
55
|
+
within_if("form#new_#{resource_name}", !test_bot_skip?(:form)) do
|
57
56
|
without_screenshots { clear_form }
|
58
57
|
submit_novalidate_form
|
59
58
|
end
|
@@ -79,7 +78,9 @@ module CrudTest
|
|
79
78
|
|
80
79
|
before = { count: resource_class.count, path: page.current_path }
|
81
80
|
|
82
|
-
|
81
|
+
assert_form("form#new_#{resource_name}") unless test_bot_skip?(:form)
|
82
|
+
|
83
|
+
within_if("form#new_#{resource_name}", !test_bot_skip?(:form)) do
|
83
84
|
fill_form(resource_attributes)
|
84
85
|
submit_form
|
85
86
|
end
|
@@ -117,12 +118,9 @@ module CrudTest
|
|
117
118
|
|
118
119
|
assert_page_normal
|
119
120
|
assert_assigns(resource_name) # unskippable
|
121
|
+
assert_form("form#edit_#{resource_name}_#{resource.id}") unless test_bot_skip?(:form)
|
120
122
|
|
121
|
-
#
|
122
|
-
form_selector = "form#edit_#{resource_name}_#{resource.id}"
|
123
|
-
assert_selector form_selector, "Expected form with selector #{form_selector}"
|
124
|
-
|
125
|
-
within(form_selector) do
|
123
|
+
within_if("form#edit_#{resource_name}_#{resource.id}", !test_bot_skip?(:form)) do
|
126
124
|
assert_submit_input unless test_bot_skip?(:submit_input)
|
127
125
|
assert_jquery_ujs_disable_with unless test_bot_skip?(:jquery_ujs_disable_with)
|
128
126
|
end
|
@@ -136,14 +134,16 @@ module CrudTest
|
|
136
134
|
|
137
135
|
before = { count: resource_class.count, updated_at: (resource.updated_at rescue nil) }
|
138
136
|
|
139
|
-
|
137
|
+
assert_form("form#edit_#{resource_name}_#{resource.id}") unless test_bot_skip?(:form)
|
138
|
+
|
139
|
+
within_if("form#edit_#{resource_name}_#{resource.id}", !test_bot_skip?(:form)) do
|
140
140
|
clear_form
|
141
141
|
submit_novalidate_form
|
142
142
|
end
|
143
143
|
|
144
144
|
save_test_bot_screenshot
|
145
145
|
|
146
|
-
resource = resource_class.
|
146
|
+
resource = resource_class.where(id: resource.id).first
|
147
147
|
|
148
148
|
after = { count: resource_class.count, updated_at: (resource.updated_at rescue nil) }
|
149
149
|
|
@@ -169,14 +169,16 @@ module CrudTest
|
|
169
169
|
|
170
170
|
before = { count: resource_class.count, updated_at: (resource.updated_at rescue nil) }
|
171
171
|
|
172
|
-
|
172
|
+
assert_form("form#edit_#{resource_name}_#{resource.id}") unless test_bot_skip?(:form)
|
173
|
+
|
174
|
+
within_if("form#edit_#{resource_name}_#{resource.id}", !test_bot_skip?(:form)) do
|
173
175
|
fill_form(resource_attributes)
|
174
176
|
submit_form
|
175
177
|
end
|
176
178
|
|
177
179
|
save_test_bot_screenshot
|
178
180
|
|
179
|
-
resource = resource_class.
|
181
|
+
resource = resource_class.where(id: resource.id).first
|
180
182
|
|
181
183
|
after = { count: resource_class.count, updated_at: (resource.updated_at rescue nil) }
|
182
184
|
|
@@ -224,10 +226,10 @@ module CrudTest
|
|
224
226
|
assert((@visit_delete_page.find(:xpath, '//title', visible: false) rescue nil).present?, '(page_title) Expected page title to be present') unless test_bot_skip?(:page_title)
|
225
227
|
end
|
226
228
|
|
227
|
-
after = { count: resource_class.count, archived: (resource_class.
|
229
|
+
after = { count: resource_class.count, archived: (resource_class.where(id: resource.id).first.try(:archived) rescue nil) }
|
228
230
|
|
229
231
|
if resource.respond_to?(:archived)
|
230
|
-
assert_equal(true, after[:archived], "Expected
|
232
|
+
assert_equal(true, after[:archived], "Expected @#{resource_name}.archived? to be true")
|
231
233
|
else
|
232
234
|
assert_equal before[:count]-1, after[:count], "Expected: #{resource_class}.count to decrement by 1"
|
233
235
|
end
|
@@ -7,33 +7,43 @@ module DeviseTest
|
|
7
7
|
def test_bot_devise_sign_up_test
|
8
8
|
visit new_user_registration_path
|
9
9
|
|
10
|
-
|
10
|
+
assert_form('form#new_user') unless test_bot_skip?(:form)
|
11
|
+
|
12
|
+
within_if('form#new_user', !test_bot_skip?(:form)) do
|
11
13
|
fill_form(email: email, password: password, password_confirmation: password)
|
12
14
|
submit_form
|
13
15
|
end
|
14
16
|
|
15
17
|
assert_page_normal
|
16
18
|
|
17
|
-
|
18
|
-
assert User.
|
19
|
-
|
19
|
+
assert_signed_in('Expected @current_user to be present after sign up')
|
20
|
+
assert User.where(email: email).first.present?, "Expected user to be present after submitting sign up form at #{new_user_registration_path}"
|
21
|
+
assert_page_content(I18n.t('devise.registrations.signed_up')) unless test_bot_skip?(:page_content)
|
20
22
|
end
|
21
23
|
|
22
24
|
def test_bot_devise_sign_in_valid_test
|
23
|
-
User.new(email: email, password: password, password_confirmation: password)
|
25
|
+
user = User.new(email: email, password: password, password_confirmation: password)
|
26
|
+
user.username = username if user.respond_to?(:username)
|
27
|
+
user.login = login if user.respond_to?(:login)
|
28
|
+
user.save(validate: false)
|
24
29
|
|
25
30
|
visit new_user_session_path
|
26
31
|
|
27
|
-
|
28
|
-
|
32
|
+
assert_form('form#new_user') unless test_bot_skip?(:form)
|
33
|
+
|
34
|
+
within_if('form#new_user', !test_bot_skip?(:form)) do
|
35
|
+
fill_form(email: email, password: password, username: username, login: login)
|
29
36
|
submit_form
|
30
37
|
end
|
31
38
|
|
32
39
|
assert_page_normal
|
33
40
|
|
34
|
-
|
35
|
-
|
36
|
-
|
41
|
+
assert_signed_in
|
42
|
+
assert_page_content(I18n.t('devise.sessions.signed_in')) unless test_bot_skip?(:page_content)
|
43
|
+
|
44
|
+
if User.new().respond_to?(:sign_in_count)
|
45
|
+
assert_equal 1, User.where(email: email).first.try(:sign_in_count), "Expected user sign in count to be incremented after signing in"
|
46
|
+
end
|
37
47
|
end
|
38
48
|
|
39
49
|
def test_bot_devise_sign_in_invalid_test
|
@@ -41,15 +51,17 @@ module DeviseTest
|
|
41
51
|
|
42
52
|
visit new_user_session_path
|
43
53
|
|
44
|
-
|
54
|
+
assert_form('form#new_user') unless test_bot_skip?(:form)
|
55
|
+
|
56
|
+
within_if('form#new_user', !test_bot_skip?(:form)) do
|
45
57
|
fill_form(email: email, password: 'not-correct-password')
|
46
58
|
submit_form
|
47
59
|
end
|
48
60
|
|
49
61
|
assert_page_normal
|
50
62
|
|
51
|
-
|
52
|
-
|
63
|
+
assert_signed_out
|
64
|
+
assert_page_content(I18n.t('devise.failure.invalid', authentication_keys: Devise.authentication_keys.join(', '))) unless test_bot_skip?(:page_content)
|
53
65
|
end
|
54
66
|
|
55
67
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_test_bot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -214,11 +214,15 @@ executables: []
|
|
214
214
|
extensions: []
|
215
215
|
extra_rdoc_files: []
|
216
216
|
files:
|
217
|
+
- MIT-LICENSE
|
218
|
+
- README.md
|
219
|
+
- Rakefile
|
217
220
|
- app/helpers/effective_test_bot_controller_helper.rb
|
218
221
|
- lib/effective_profile_bot/heap_analyzer.rb
|
222
|
+
- lib/effective_test_bot.rb
|
219
223
|
- lib/effective_test_bot/engine.rb
|
224
|
+
- lib/effective_test_bot/middleware.rb
|
220
225
|
- lib/effective_test_bot/version.rb
|
221
|
-
- lib/effective_test_bot.rb
|
222
226
|
- lib/generators/effective_test_bot/install_generator.rb
|
223
227
|
- lib/generators/templates/effective_test_bot.rb
|
224
228
|
- lib/generators/templates/test_helper.rb
|
@@ -247,9 +251,6 @@ files:
|
|
247
251
|
- test/test_botable/page_test.rb
|
248
252
|
- test/test_botable/redirect_test.rb
|
249
253
|
- test/test_botable/wizard_test.rb
|
250
|
-
- MIT-LICENSE
|
251
|
-
- Rakefile
|
252
|
-
- README.md
|
253
254
|
homepage: https://github.com/code-and-effect/effective_test_bot
|
254
255
|
licenses:
|
255
256
|
- MIT
|
@@ -270,7 +271,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
270
271
|
version: '0'
|
271
272
|
requirements: []
|
272
273
|
rubyforge_project:
|
273
|
-
rubygems_version: 2.
|
274
|
+
rubygems_version: 2.4.6
|
274
275
|
signing_key:
|
275
276
|
specification_version: 4
|
276
277
|
summary: A shared library of rails model & capybara-based feature tests that should
|