effective_test_bot 0.4.2 → 0.4.3
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.
- checksums.yaml +4 -4
- data/README.md +55 -0
- data/app/helpers/effective_test_bot_controller_helper.rb +6 -1
- data/lib/effective_test_bot.rb +25 -9
- data/lib/effective_test_bot/engine.rb +8 -1
- data/lib/effective_test_bot/version.rb +1 -1
- data/lib/generators/templates/test_helper.rb +9 -5
- data/lib/tasks/effective_test_bot_tasks.rake +15 -1
- data/test/concerns/test_botable/base_dsl.rb +4 -3
- data/test/concerns/test_botable/crud_dsl.rb +2 -1
- data/test/concerns/test_botable/devise_dsl.rb +50 -0
- data/test/concerns/test_botable/member_dsl.rb +4 -2
- data/test/concerns/test_botable/page_dsl.rb +5 -3
- data/test/concerns/test_botable/redirect_dsl.rb +4 -2
- data/test/concerns/test_botable/wizard_dsl.rb +4 -2
- data/test/support/effective_test_bot_assertions.rb +7 -2
- data/test/support/effective_test_bot_form_helper.rb +14 -3
- data/test/support/effective_test_bot_test_helper.rb +16 -0
- data/test/test_bot/integration/application_test.rb +2 -6
- data/test/test_bot/integration/{minitest_test.rb → environment_test.rb} +1 -1
- data/test/test_botable/base_test.rb +4 -2
- data/test/test_botable/crud_test.rb +13 -16
- data/test/test_botable/devise_test.rb +55 -0
- data/test/test_botable/member_test.rb +0 -2
- data/test/test_botable/page_test.rb +0 -2
- data/test/test_botable/redirect_test.rb +0 -2
- data/test/test_botable/wizard_test.rb +0 -2
- metadata +5 -5
- data/test/test_bot/integration/devise_test.rb +0 -54
- data/test/test_bot/models/user_test.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 836a02fd7342588742c06d55d4f64d06382b5db5
|
4
|
+
data.tar.gz: a136f7e711237d2038d86b64273f9d2d54248183
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a81518d383fabca6561057e0262c33487f8c377b90f7b0569ec18da26cae2910546a983af8afe2614dfa217a7206c95f2e952539d77a0345086a172226483364
|
7
|
+
data.tar.gz: fe6980136e37b6881cf11ea673340d69af4d3c766c6932e0adb40b8c7db87a978bf27488371d768cfff4b5dada780972a5447241bf3f2c2d320dec4a95166e8e
|
data/README.md
CHANGED
@@ -35,14 +35,69 @@ Run the test suite with:
|
|
35
35
|
|
36
36
|
```ruby
|
37
37
|
bundle exec rake test:bot
|
38
|
+
bundle exec rake test:bot:environment
|
38
39
|
```
|
39
40
|
|
40
41
|
You should now see multiple -- hopefully passing -- tests that you didn't write!
|
41
42
|
|
43
|
+
## TODO
|
42
44
|
|
45
|
+
Document this gem
|
46
|
+
|
47
|
+
Minitest:
|
43
48
|
|
44
49
|
rake test TEST=test/integration/clinic_assets_test.rb
|
45
50
|
|
51
|
+
TestBot:
|
52
|
+
|
53
|
+
rake test:bot TEST=posts
|
54
|
+
rake test:bot TEST=posts#index
|
55
|
+
rake test:bot TEST=
|
56
|
+
|
57
|
+
Excepts will always work and be accounted for in test:bot
|
58
|
+
Definign TEST= works with test names 'documents#new' or 'documents' or 'something_path' but not with 'flash' assertions
|
59
|
+
|
60
|
+
|
61
|
+
# config.except = [
|
62
|
+
# 'flash',
|
63
|
+
# 'users#show',
|
64
|
+
# 'users#create_invalid' => ['path', 'page_title'],
|
65
|
+
# 'users#create_invalid' => 'no_unpermitted_params',
|
66
|
+
# 'report_total_allocation_index_path'
|
67
|
+
# 'documents#destroy flash'
|
68
|
+
# ]
|
69
|
+
|
70
|
+
|
71
|
+
require 'test_helper'
|
72
|
+
|
73
|
+
class UsersTest < ActionDispatch::IntegrationTest
|
74
|
+
# The Create and Update action return to /members/12345 instead of /users/12345 when failing validation
|
75
|
+
# This is a side effect of working in the same namespace as devise
|
76
|
+
crud_test(User, User.find_by_email('admin@agilestyle.com'), except: :show, skip: {create_invalid: :path, update_invalid: :path})
|
77
|
+
end
|
78
|
+
|
79
|
+
require 'test_helper'
|
80
|
+
|
81
|
+
class SettingTest < ActionDispatch::IntegrationTest
|
82
|
+
crud_test(Setting, User.first, only: [:new, :create])
|
83
|
+
end
|
84
|
+
|
85
|
+
require 'test_helper'
|
86
|
+
|
87
|
+
class PhysiciansTest < ActionDispatch::IntegrationTest
|
88
|
+
page_test(:user_settings_path, User.first)
|
89
|
+
page_test(:user_settings_path, User.first)
|
90
|
+
page_test(:user_settings_path, User.first)
|
91
|
+
crud_test(Physician, User.first, except: :show)
|
92
|
+
crud_test('physicians', User.first, except: :show)
|
93
|
+
|
94
|
+
test 'another action' do
|
95
|
+
crud_action_test(:new, Physician, User.first)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
|
46
101
|
|
47
102
|
## Fixtures
|
48
103
|
|
@@ -25,10 +25,15 @@ module EffectiveTestBotControllerHelper
|
|
25
25
|
end
|
26
26
|
|
27
27
|
# We get here if ApplicationController raised a ActionController::UnpermittedParameters error
|
28
|
-
def
|
28
|
+
def assign_test_bot_unpermitted_params_header(exception)
|
29
29
|
if exception.kind_of?(ActionController::UnpermittedParameters)
|
30
30
|
response.headers['Test-Bot-Unpermitted-Params'] = Base64.encode64(exception.params.to_json)
|
31
31
|
end
|
32
32
|
end
|
33
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
|
+
|
34
39
|
end
|
data/lib/effective_test_bot.rb
CHANGED
@@ -9,17 +9,33 @@ module EffectiveTestBot
|
|
9
9
|
yield self
|
10
10
|
end
|
11
11
|
|
12
|
+
# Test could be something like "crud_test", "crud_test (documents#new)", "documents", documents#new"
|
13
|
+
# Assertion will be page_title, or flash
|
14
|
+
|
12
15
|
def self.skip?(test, assertion = nil)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
return false if (test || assertion).blank?
|
17
|
+
|
18
|
+
test = test.to_s
|
19
|
+
assertion = assertion.to_s
|
20
|
+
|
21
|
+
# If I get passed a method_name, "crud_test: (posts#create_invalid)" extract the inner test name from it
|
22
|
+
# I dunno why this is needed really, but it might help someone one day.
|
23
|
+
if test.include?('_test: (') # This is how the BaseDsl test_bot_method_name formats the test names.
|
24
|
+
left = test.index('(') || -1
|
25
|
+
right = test.rindex(')') || (test.length+1)
|
26
|
+
test = test[(left+1)..(right-1)]
|
22
27
|
end
|
28
|
+
|
29
|
+
value = "#{test} #{assertion}".strip # This is the format config.excepts is flattened into
|
30
|
+
|
31
|
+
# Excepts are defined in the app's config/initializers/effective_test_bot.rb file
|
32
|
+
return true if excepts.any? { |except| [test, assertion, value].include?(except) }
|
33
|
+
|
34
|
+
# Onlies are defined in the same config file, or on the command like rake test:bot TEST=posts#new
|
35
|
+
# It doesn't match just 'flash' or 'page_title' assertions
|
36
|
+
return true if onlies.present? && onlies.find { |only| test.start_with?(only) }.blank?
|
37
|
+
|
38
|
+
false # Don't skip this test
|
23
39
|
end
|
24
40
|
|
25
41
|
private
|
@@ -17,6 +17,7 @@ module EffectiveTestBot
|
|
17
17
|
# test/test_botable/
|
18
18
|
ActionDispatch::IntegrationTest.include BaseTest
|
19
19
|
ActionDispatch::IntegrationTest.include CrudTest
|
20
|
+
ActionDispatch::IntegrationTest.include DeviseTest
|
20
21
|
ActionDispatch::IntegrationTest.include MemberTest
|
21
22
|
ActionDispatch::IntegrationTest.include PageTest
|
22
23
|
ActionDispatch::IntegrationTest.include RedirectTest
|
@@ -25,6 +26,7 @@ module EffectiveTestBot
|
|
25
26
|
# test/concerns/test_botable/
|
26
27
|
ActionDispatch::IntegrationTest.include TestBotable::BaseDsl
|
27
28
|
ActionDispatch::IntegrationTest.include TestBotable::CrudDsl
|
29
|
+
ActionDispatch::IntegrationTest.include TestBotable::DeviseDsl
|
28
30
|
ActionDispatch::IntegrationTest.include TestBotable::MemberDsl
|
29
31
|
ActionDispatch::IntegrationTest.include TestBotable::PageDsl
|
30
32
|
ActionDispatch::IntegrationTest.include TestBotable::RedirectDsl
|
@@ -48,7 +50,12 @@ module EffectiveTestBot
|
|
48
50
|
|
49
51
|
ApplicationController.instance_exec do
|
50
52
|
rescue_from ActionController::UnpermittedParameters do |exception|
|
51
|
-
|
53
|
+
assign_test_bot_unpermitted_params_header(exception)
|
54
|
+
end
|
55
|
+
|
56
|
+
rescue_from Exception do |exception| # Not sure if I should rescue Exception or StandardError
|
57
|
+
assign_test_bot_exceptions_header(exception)
|
58
|
+
render status: 500, text: "<html><body><h1>Uncaught Exception</h1><p>#{exception.message}</p><p>#{exception.backtrace.first(20).join('<br>')}</p></body></html>"
|
52
59
|
end
|
53
60
|
end
|
54
61
|
|
@@ -36,7 +36,6 @@ class ActionDispatch::IntegrationTest
|
|
36
36
|
def after_teardown # I reset sessions here so capybara-screenshot can still make screenshots when tests fail
|
37
37
|
super(); Capybara.reset_sessions!
|
38
38
|
end
|
39
|
-
|
40
39
|
end
|
41
40
|
|
42
41
|
|
@@ -53,14 +52,19 @@ Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
|
|
53
52
|
### That gets run just once before the whole test suite loads
|
54
53
|
|
55
54
|
# So the very first thing I do is set up a consistent database
|
56
|
-
|
55
|
+
silence_stream(STDOUT) do
|
56
|
+
Rake::Task['db:schema:load'].invoke
|
57
|
+
end
|
58
|
+
|
57
59
|
ActiveRecord::Migration.maintain_test_schema!
|
58
60
|
|
59
61
|
# or the following 3:
|
60
62
|
|
61
|
-
#
|
62
|
-
#Rake::Task['db:
|
63
|
-
#Rake::Task['db:
|
63
|
+
# silence_stream(STDOUT) do
|
64
|
+
# Rake::Task['db:drop'].invoke
|
65
|
+
# Rake::Task['db:create'].invoke
|
66
|
+
# Rake::Task['db:migrate'].invoke
|
67
|
+
# end
|
64
68
|
|
65
69
|
Rake::Task['db:fixtures:load'].invoke # There's just no way to get the seeds first, as this has to delete everything
|
66
70
|
Rake::Task['db:seed'].invoke
|
@@ -6,6 +6,8 @@ require 'rails/test_unit/sub_test_task'
|
|
6
6
|
# rake test:bot TEST=documents#new,documents#show
|
7
7
|
# rake test:bot TEST=documents#new path,documents#show,documents#update_valid no_unpermitted_params
|
8
8
|
|
9
|
+
# rake test:bot:environment
|
10
|
+
|
9
11
|
namespace :test do
|
10
12
|
desc 'Runs Effective Test Bot'
|
11
13
|
task :bot do
|
@@ -17,9 +19,21 @@ namespace :test do
|
|
17
19
|
Rake::Task["test:effective_test_bot"].invoke
|
18
20
|
end
|
19
21
|
|
22
|
+
namespace :bot do
|
23
|
+
desc 'Runs Effective Test Bot environment test'
|
24
|
+
task :environment do
|
25
|
+
Rake::Task["test:effective_test_bot_environment"].invoke
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
20
29
|
Rails::TestTask.new('effective_test_bot' => 'test:prepare') do |t|
|
21
30
|
t.libs << 'test'
|
22
|
-
t.test_files = FileList["#{File.dirname(__FILE__)}/../../test/test_bot
|
31
|
+
t.test_files = FileList["#{File.dirname(__FILE__)}/../../test/test_bot/integration/application_test.rb"]
|
32
|
+
end
|
33
|
+
|
34
|
+
Rails::TestTask.new('effective_test_bot_environment' => 'test:prepare') do |t|
|
35
|
+
t.libs << 'test'
|
36
|
+
t.test_files = FileList["#{File.dirname(__FILE__)}/../../test/test_bot/integration/environment_test.rb"]
|
23
37
|
end
|
24
38
|
|
25
39
|
desc 'loads test/fixtures/seeds.rb'
|
@@ -3,7 +3,7 @@ module TestBotable
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
module ClassMethods
|
6
|
-
TEST_BOT_TEST_PREFIXES = ['crud_test', 'member_test', 'page_test', 'redirect_test', 'wizard_test']
|
6
|
+
TEST_BOT_TEST_PREFIXES = ['crud_test', 'devise_test', 'member_test', 'page_test', 'redirect_test', 'wizard_test']
|
7
7
|
|
8
8
|
# Parses and validates lots of options
|
9
9
|
# This is a big manual merge wherein we translate some DSL methods into one consistent Hash here
|
@@ -80,10 +80,10 @@ module TestBotable
|
|
80
80
|
options[:resource_class] = resource_class
|
81
81
|
options[:resource_name] = resource_class.name.underscore
|
82
82
|
options[:resource_attributes] = resource_attributes
|
83
|
-
|
84
|
-
options[:normalized] = true
|
85
83
|
end
|
86
84
|
|
85
|
+
options[:normalized] = true
|
86
|
+
|
87
87
|
options
|
88
88
|
end
|
89
89
|
|
@@ -106,6 +106,7 @@ module TestBotable
|
|
106
106
|
@num_defined_test_bot_tests[test_family] = (@num_defined_test_bot_tests[test_family] || 0) + 1
|
107
107
|
end
|
108
108
|
|
109
|
+
# If we change the format here, also update effective_test_bot.skip? method
|
109
110
|
if current_test.present?
|
110
111
|
"#{test_family}: (#{current_test})"
|
111
112
|
elsif number_of_tests > 1
|
@@ -46,6 +46,7 @@ module TestBotable
|
|
46
46
|
].compact.join('/') + '#' + test.to_s
|
47
47
|
|
48
48
|
method_name = test_bot_method_name('crud_test', label || options_for_method[:current_test])
|
49
|
+
next if EffectiveTestBot.skip?(label || options_for_method[:current_test])
|
49
50
|
|
50
51
|
define_method(method_name) { crud_action_test(test, resource, user, options_for_method) }
|
51
52
|
end
|
@@ -83,7 +84,7 @@ module TestBotable
|
|
83
84
|
begin
|
84
85
|
assign_test_bot_lets!(options.reverse_merge!(user: user, resource: resource))
|
85
86
|
rescue => e
|
86
|
-
raise "Error: #{e.message}. Expected usage: crud_action_test(:new, Post || Post.new, User.first
|
87
|
+
raise "Error: #{e.message}. Expected usage: crud_action_test(:new, Post || Post.new, User.first)"
|
87
88
|
end
|
88
89
|
|
89
90
|
self.send("test_bot_#{test}_test")
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# This DSL gives a class level and an instance level way of calling specific test suite
|
2
|
+
#
|
3
|
+
# class DeviseTest < ActionDispatch::IntegrationTest
|
4
|
+
# devise_test()
|
5
|
+
#
|
6
|
+
# test 'a one-off action' do
|
7
|
+
# devise_action_test(:sign_up)
|
8
|
+
# devise_action_test(:sign_in_valid)
|
9
|
+
# devise_action_test(:sign_in_invalid)
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
|
13
|
+
module TestBotable
|
14
|
+
module DeviseDsl
|
15
|
+
extend ActiveSupport::Concern
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
|
19
|
+
def devise_test(options = {})
|
20
|
+
label = options.delete(:label).presence
|
21
|
+
|
22
|
+
[:sign_up, :sign_in_valid, :sign_in_invalid].each do |test|
|
23
|
+
options[:current_test] = label || test
|
24
|
+
|
25
|
+
method_name = test_bot_method_name('devise_test', options[:current_test])
|
26
|
+
next if EffectiveTestBot.skip?(options[:current_test])
|
27
|
+
|
28
|
+
define_method(method_name) { devise_action_test(test, options) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
# Instance Methods - Call me from within a test
|
35
|
+
def devise_action_test(test, options = {})
|
36
|
+
options[:email] ||= "unique-#{Time.zone.now.to_i}@example.com"
|
37
|
+
options[:password] ||= '!Password123'
|
38
|
+
options[:user] ||= User.new
|
39
|
+
|
40
|
+
begin
|
41
|
+
assign_test_bot_lets!(options)
|
42
|
+
rescue => e
|
43
|
+
raise "Error: #{e.message}. Expected usage: devise_action_test(:sign_up)"
|
44
|
+
end
|
45
|
+
|
46
|
+
self.send("test_bot_devise_#{test}_test")
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -18,8 +18,10 @@ module TestBotable
|
|
18
18
|
module ClassMethods
|
19
19
|
|
20
20
|
def member_test(controller, action, user, obj_to_param = nil, options = {})
|
21
|
-
options[:current_test] = "#{controller}##{action}"
|
22
|
-
|
21
|
+
options[:current_test] = options.delete(:label) || "#{controller}##{action}"
|
22
|
+
|
23
|
+
method_name = test_bot_method_name('member_test', options[:current_test])
|
24
|
+
return if EffectiveTestBot.skip?(options[:current_test])
|
23
25
|
|
24
26
|
define_method(method_name) { member_action_test(controller, action, user, obj_to_param, options) }
|
25
27
|
end
|
@@ -16,8 +16,10 @@ module TestBotable
|
|
16
16
|
module ClassMethods
|
17
17
|
|
18
18
|
def page_test(path, user, options = {})
|
19
|
-
options[:current_test] = path.to_s
|
20
|
-
|
19
|
+
options[:current_test] = options.delete(:label) || path.to_s
|
20
|
+
|
21
|
+
method_name = test_bot_method_name('page_test', options[:current_test])
|
22
|
+
return if EffectiveTestBot.skip?(options[:current_test])
|
21
23
|
|
22
24
|
define_method(method_name) { page_action_test(path, user, options) }
|
23
25
|
end
|
@@ -29,7 +31,7 @@ module TestBotable
|
|
29
31
|
begin
|
30
32
|
assign_test_bot_lets!(options.reverse_merge!(user: user, page_path: path))
|
31
33
|
rescue => e
|
32
|
-
raise "Error: #{e.message}. Expected usage:
|
34
|
+
raise "Error: #{e.message}. Expected usage: page_action_test(root_path, User.first)"
|
33
35
|
end
|
34
36
|
|
35
37
|
self.send(:test_bot_page_test)
|
@@ -15,8 +15,10 @@ module TestBotable
|
|
15
15
|
module ClassMethods
|
16
16
|
|
17
17
|
def redirect_test(from_path, to_path, user, options = {})
|
18
|
-
options[:current_test] = "#{from_path} to #{to_path}"
|
19
|
-
|
18
|
+
options[:current_test] = options.delete(:label) || "#{from_path} to #{to_path}"
|
19
|
+
|
20
|
+
method_name = test_bot_method_name('redirect_test', options[:current_test])
|
21
|
+
return if EffectiveTestBot.skip?(options[:current_test])
|
20
22
|
|
21
23
|
define_method(method_name) { redirect_action_test(from_path, to_path, user, options) }
|
22
24
|
end
|
@@ -18,8 +18,10 @@ module TestBotable
|
|
18
18
|
module ClassMethods
|
19
19
|
|
20
20
|
def wizard_test(from_path, to_path, user, options = {})
|
21
|
-
options[:current_test] = "#{from_path} to #{to_path}"
|
22
|
-
|
21
|
+
options[:current_test] = options.delete(:label) || "#{from_path} to #{to_path}"
|
22
|
+
|
23
|
+
method_name = test_bot_method_name('wizard_test', options[:current_test])
|
24
|
+
return if EffectiveTestBot.skip?(options[:current_test])
|
23
25
|
|
24
26
|
define_method(method_name) { wizard_action_test(from_path, to_path, user, options) }
|
25
27
|
end
|
@@ -12,6 +12,8 @@ module EffectiveTestBotAssertions
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def assert_page_title(title = :any, message = '(page_title) Expected page title to be present')
|
15
|
+
return if was_download? # If this was a download, it correctly won't have a page title
|
16
|
+
|
15
17
|
if title.present? && title != :any
|
16
18
|
assert_title(title) # Capybara TitleQuery, match this text
|
17
19
|
else
|
@@ -39,16 +41,19 @@ module EffectiveTestBotAssertions
|
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
42
|
-
|
43
44
|
def assert_no_js_errors(message = nil)
|
44
45
|
errors = page.driver.error_messages
|
45
|
-
|
46
|
+
assert errors.blank?, message || "(no_js_errors) Unexpected javascript error:\n#{errors.first.to_s}"
|
46
47
|
end
|
47
48
|
|
48
49
|
def assert_no_unpermitted_params(message = '(no_unpermitted_params) Expected no unpermitted params')
|
49
50
|
assert_equal [], unpermitted_params, message
|
50
51
|
end
|
51
52
|
|
53
|
+
def assert_no_exceptions(message = nil)
|
54
|
+
assert exceptions.blank?, message || "(no_exceptions) Unexpected exception:\n#{exceptions.join("\n")}\n========== End Exception ==========\n"
|
55
|
+
end
|
56
|
+
|
52
57
|
# assert_flash
|
53
58
|
# assert_flash :success
|
54
59
|
# assert_flash :error, 'there was a specific error'
|
@@ -10,6 +10,7 @@ module EffectiveTestBotFormHelper
|
|
10
10
|
|
11
11
|
# Support for the cocoon gem
|
12
12
|
all('a.add_fields[data-association-insertion-template]').each do |cocoon_add_field|
|
13
|
+
next unless cocoon_add_field.visible?
|
13
14
|
[1,2].sample.times { cocoon_add_field.click() }
|
14
15
|
end
|
15
16
|
|
@@ -65,7 +66,10 @@ module EffectiveTestBotFormHelper
|
|
65
66
|
when 'input_email'
|
66
67
|
Faker::Internet.email
|
67
68
|
when 'input_number'
|
68
|
-
|
69
|
+
min = (Float(field['min']) rescue 1)
|
70
|
+
max = (Float(field['max']) rescue 1000)
|
71
|
+
number = Random.new.rand(min..max)
|
72
|
+
number.kind_of?(Float) ? number.round(2) : number
|
69
73
|
when 'input_password'
|
70
74
|
@test_bot_password ||= Faker::Internet.password # Use the same password throughout a single test. Allows passwords and password_confirmations to match.
|
71
75
|
when 'input_tel'
|
@@ -75,9 +79,16 @@ module EffectiveTestBotFormHelper
|
|
75
79
|
classes = field['class'].to_s.split(' ')
|
76
80
|
|
77
81
|
if classes.include?('date') # Let's assume this is a date input.
|
78
|
-
Faker::Date.backward(365).strftime('%
|
82
|
+
Faker::Date.backward(365).strftime('%Y-%m-%d')
|
79
83
|
elsif classes.include?('datetime')
|
80
|
-
Faker::Date.backward(365).strftime('%
|
84
|
+
Faker::Date.backward(365).strftime('%Y-%m-%d %H:%m')
|
85
|
+
elsif classes.include?('price')
|
86
|
+
4.times.map { DIGITS.sample }.join('') + '.00'
|
87
|
+
elsif classes.include?('numeric')
|
88
|
+
min = (Float(field['min']) rescue 1)
|
89
|
+
max = (Float(field['max']) rescue 1000)
|
90
|
+
number = Random.new.rand(min..max)
|
91
|
+
number.kind_of?(Float) ? number.round(2) : number
|
81
92
|
elsif attributes.last.to_s.include?('first_name')
|
82
93
|
Faker::Name.first_name
|
83
94
|
elsif attributes.last.to_s.include?('last_name')
|
@@ -17,12 +17,23 @@ module EffectiveTestBotTestHelper
|
|
17
17
|
@flash = (JSON.parse(Base64.decode64(session.driver.response_headers['Test-Bot-Flash'])) rescue {})
|
18
18
|
@assigns = (JSON.parse(Base64.decode64(session.driver.response_headers['Test-Bot-Assigns'])) rescue {})
|
19
19
|
@unpermitted_params = (JSON.parse(Base64.decode64(session.driver.response_headers['Test-Bot-Unpermitted-Params'])) rescue [])
|
20
|
+
|
21
|
+
@visit_delete_page = session
|
20
22
|
end
|
21
23
|
|
22
24
|
def was_redirect?(from_path, to_path = nil)
|
23
25
|
from_path != (to_path || page.current_path)
|
24
26
|
end
|
25
27
|
|
28
|
+
def was_download?(filename = nil)
|
29
|
+
if filename.present?
|
30
|
+
page.response_headers['Content-Disposition'].to_s.include?('filename=') &&
|
31
|
+
page.response_headers['Content-Disposition'].to_s.include?(filename)
|
32
|
+
else
|
33
|
+
page.response_headers['Content-Disposition'].to_s.include?('filename=')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
26
37
|
# EffectiveTestBot includes an after_filter on ApplicationController to set an http header
|
27
38
|
# that encodes the flash message, and some of the assigns
|
28
39
|
def flash
|
@@ -36,4 +47,9 @@ module EffectiveTestBotTestHelper
|
|
36
47
|
def unpermitted_params
|
37
48
|
@unpermitted_params ||= (JSON.parse(Base64.decode64(page.response_headers['Test-Bot-Unpermitted-Params'])) rescue [])
|
38
49
|
end
|
50
|
+
|
51
|
+
def exceptions
|
52
|
+
@exceptions ||= (JSON.parse(Base64.decode64(page.response_headers['Test-Bot-Exceptions'])) rescue [])
|
53
|
+
end
|
54
|
+
|
39
55
|
end
|
@@ -13,10 +13,6 @@ module TestBot
|
|
13
13
|
routes = Rails.application.routes.routes.to_a
|
14
14
|
seen_actions = Hash.new([]) # {posts: ['new', 'edit'], events: ['new', 'edit', 'show']}
|
15
15
|
|
16
|
-
#Rails.application.routes.recognize_path('/your/path/here')
|
17
|
-
#Rails.application.routes.recognize_path('/admin/jobs/3/unarchive')
|
18
|
-
# => {:action=>"unarchive", :controller=>"admin/jobs", :id=>"3"}
|
19
|
-
|
20
16
|
routes.each_with_index do |route, index|
|
21
17
|
controller = route.defaults[:controller]
|
22
18
|
action = route.defaults[:action]
|
@@ -24,10 +20,10 @@ module TestBot
|
|
24
20
|
# Devise Test
|
25
21
|
if (controller || '').include?('devise')
|
26
22
|
next if seen_actions['devise'].present?
|
27
|
-
|
28
|
-
puts 'define devise test!!'
|
29
23
|
seen_actions['devise'] = true # So we don't repeat it
|
30
24
|
|
25
|
+
devise_test()
|
26
|
+
|
31
27
|
# Redirect Test
|
32
28
|
elsif route.app.kind_of?(ActionDispatch::Routing::PathRedirect) && route.path.required_names.blank?
|
33
29
|
path = route.path.spec.to_s
|
@@ -6,6 +6,7 @@ module BaseTest
|
|
6
6
|
|
7
7
|
def assert_page_normal(message = nil)
|
8
8
|
unless test_bot_skip?(:normal)
|
9
|
+
assert_no_exceptions unless test_bot_skip?(:exceptions)
|
9
10
|
assert_page_status unless test_bot_skip?(:page_status)
|
10
11
|
assert_page_title unless test_bot_skip?(:page_title)
|
11
12
|
assert_no_js_errors unless test_bot_skip?(:no_js_errors)
|
@@ -21,11 +22,12 @@ module BaseTest
|
|
21
22
|
# if you use the action_test_ instance methods, current_test is nil, and test skips won't apply
|
22
23
|
# Any global assertion skips will tho
|
23
24
|
def test_bot_skip?(assertion = nil)
|
24
|
-
# Skip the whole test
|
25
|
+
# Skip the whole test 'documents#new'
|
25
26
|
# this will put SKIP into the minitest output
|
26
27
|
skip if (defined?(current_test) && EffectiveTestBot.skip?(current_test))
|
27
28
|
|
28
|
-
#
|
29
|
+
# Skip just this assertion sub test 'flash'
|
30
|
+
# this will not print anything to the minitest output
|
29
31
|
EffectiveTestBot.skip?((current_test if defined?(current_test)), assertion)
|
30
32
|
end
|
31
33
|
|
@@ -5,7 +5,6 @@ module CrudTest
|
|
5
5
|
protected
|
6
6
|
|
7
7
|
def test_bot_new_test
|
8
|
-
test_bot_skip?
|
9
8
|
sign_in(user) and visit(new_resource_path)
|
10
9
|
|
11
10
|
assert_page_normal
|
@@ -21,7 +20,6 @@ module CrudTest
|
|
21
20
|
end
|
22
21
|
|
23
22
|
def test_bot_create_valid_test
|
24
|
-
test_bot_skip?
|
25
23
|
sign_in(user) and visit(new_resource_path)
|
26
24
|
|
27
25
|
before = { count: resource_class.count, path: page.current_path }
|
@@ -46,7 +44,6 @@ module CrudTest
|
|
46
44
|
end
|
47
45
|
|
48
46
|
def test_bot_create_invalid_test
|
49
|
-
test_bot_skip?
|
50
47
|
sign_in(user) and visit(new_resource_path)
|
51
48
|
|
52
49
|
before = { count: resource_class.count }
|
@@ -58,11 +55,11 @@ module CrudTest
|
|
58
55
|
|
59
56
|
after = { count: resource_class.count }
|
60
57
|
|
61
|
-
|
62
|
-
assert_page_title(:any, '(page_title) Expected page title to be present after failed validation') unless test_bot_skip?(:page_title)
|
58
|
+
assert_page_normal
|
63
59
|
|
64
|
-
|
60
|
+
assert_equal before[:count], after[:count], "Expected #{resource_class}.count to be unchanged"
|
65
61
|
assert_flash(:danger) unless test_bot_skip?(:flash)
|
62
|
+
|
66
63
|
assert_assigns(resource_name) unless test_bot_skip?(:assigns)
|
67
64
|
assert_assigns_errors(resource_name) unless test_bot_skip?(:assigns_errors)
|
68
65
|
|
@@ -70,7 +67,6 @@ module CrudTest
|
|
70
67
|
end
|
71
68
|
|
72
69
|
def test_bot_edit_test
|
73
|
-
test_bot_skip?
|
74
70
|
sign_in(user) and (resource = find_or_create_resource!)
|
75
71
|
|
76
72
|
visit(edit_resource_path(resource))
|
@@ -88,7 +84,6 @@ module CrudTest
|
|
88
84
|
end
|
89
85
|
|
90
86
|
def test_bot_update_valid_test
|
91
|
-
test_bot_skip?
|
92
87
|
sign_in(user) and (resource = find_or_create_resource!)
|
93
88
|
|
94
89
|
visit(edit_resource_path(resource))
|
@@ -103,8 +98,7 @@ module CrudTest
|
|
103
98
|
|
104
99
|
after = { count: resource_class.count, updated_at: (resource.updated_at rescue nil) }
|
105
100
|
|
106
|
-
|
107
|
-
assert_no_unpermitted_params unless test_bot_skip?(:unpermitted_params)
|
101
|
+
assert_page_normal
|
108
102
|
|
109
103
|
assert_equal before[:count], after[:count], "Expected #{resource_class}.count to be unchanged"
|
110
104
|
refute_equal(before[:updated_at], after[:updated_at], "(updated_at_changed) Expected @#{resource_name}.updated_at to have changed") if (resource.respond_to?(:updated_at) && !test_bot_skip?(:updated_at_changed))
|
@@ -118,7 +112,6 @@ module CrudTest
|
|
118
112
|
end
|
119
113
|
|
120
114
|
def test_bot_update_invalid_test
|
121
|
-
test_bot_skip?
|
122
115
|
sign_in(user) and (resource = find_or_create_resource!)
|
123
116
|
|
124
117
|
visit(edit_resource_path(resource))
|
@@ -133,12 +126,13 @@ module CrudTest
|
|
133
126
|
|
134
127
|
after = { count: resource_class.count, updated_at: (resource.updated_at rescue nil) }
|
135
128
|
|
136
|
-
|
129
|
+
assert_page_normal
|
130
|
+
|
137
131
|
assert_equal before[:count], after[:count], "Expected: #{resource_class}.count to be unchanged"
|
138
132
|
assert_equal(before[:updated_at], after[:updated_at], "Expected @#{resource_name}.updated_at to be unchanged") if resource.respond_to?(:updated_at)
|
139
|
-
assert_page_title(:any, '(page_title) Expected page title to be present after failed validation') unless test_bot_skip?(:page_title)
|
140
133
|
|
141
134
|
assert_flash(:danger) unless test_bot_skip?(:flash)
|
135
|
+
|
142
136
|
assert_assigns(resource_name) unless test_bot_skip?(:assigns)
|
143
137
|
assert_assigns_errors(resource_name) unless test_bot_skip?(:assigns_errors)
|
144
138
|
|
@@ -146,7 +140,6 @@ module CrudTest
|
|
146
140
|
end
|
147
141
|
|
148
142
|
def test_bot_index_test
|
149
|
-
test_bot_skip?
|
150
143
|
sign_in(user) and (resource = (find_or_create_resource! rescue nil))
|
151
144
|
|
152
145
|
visit resources_path
|
@@ -160,7 +153,6 @@ module CrudTest
|
|
160
153
|
end
|
161
154
|
|
162
155
|
def test_bot_show_test
|
163
|
-
test_bot_skip?
|
164
156
|
sign_in(user) and (resource = find_or_create_resource!)
|
165
157
|
|
166
158
|
visit resource_path(resource)
|
@@ -170,7 +162,6 @@ module CrudTest
|
|
170
162
|
end
|
171
163
|
|
172
164
|
def test_bot_destroy_test
|
173
|
-
test_bot_skip?
|
174
165
|
sign_in(user) and (resource = find_or_create_resource!)
|
175
166
|
|
176
167
|
before = { count: resource_class.count, archived: (resource.archived rescue nil) }
|
@@ -179,6 +170,12 @@ module CrudTest
|
|
179
170
|
|
180
171
|
after = { count: resource_class.count, archived: (resource_class.find(resource.id).archived rescue nil) }
|
181
172
|
|
173
|
+
# Because of the way delete works, we can't use assert_page_normal()
|
174
|
+
# So we just assert the 200 status code, and page title present manually
|
175
|
+
# Javascript errors cannot be detected
|
176
|
+
assert_equal(200, @visit_delete_page.try(:status_code), '(page_status) Expected 200 HTTP status code') unless test_bot_skip?(:page_status)
|
177
|
+
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)
|
178
|
+
|
182
179
|
assert_flash(:success) unless test_bot_skip?(:flash)
|
183
180
|
|
184
181
|
if resource.respond_to?(:archived)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# All the methods in this file should not be called from the outside world
|
2
|
+
# See the DSL files in concerns/test_botable/ for how to call these tests
|
3
|
+
|
4
|
+
module DeviseTest
|
5
|
+
protected
|
6
|
+
|
7
|
+
def test_bot_devise_sign_up_test
|
8
|
+
visit new_user_registration_path
|
9
|
+
|
10
|
+
within('form#new_user') do
|
11
|
+
fill_form(email: email, password: password, password_confirmation: password)
|
12
|
+
submit_form
|
13
|
+
end
|
14
|
+
|
15
|
+
assert_page_normal
|
16
|
+
|
17
|
+
assert_content I18n.t('devise.registrations.signed_up')
|
18
|
+
assert User.find_by_email(email).present?
|
19
|
+
assert_assigns :current_user
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_bot_devise_sign_in_valid_test
|
23
|
+
User.new(email: email, password: password, password_confirmation: password).save(validate: false)
|
24
|
+
|
25
|
+
visit new_user_session_path
|
26
|
+
|
27
|
+
within('form#new_user') do
|
28
|
+
fill_form(email: email, password: password)
|
29
|
+
submit_form
|
30
|
+
end
|
31
|
+
|
32
|
+
assert_page_normal
|
33
|
+
|
34
|
+
assert_content I18n.t('devise.sessions.signed_in')
|
35
|
+
assert_equal 1, User.find_by_email(email).sign_in_count
|
36
|
+
assert_assigns :current_user
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_bot_devise_sign_in_invalid_test
|
40
|
+
User.new(email: email, password: password, password_confirmation: password).save(validate: false)
|
41
|
+
|
42
|
+
visit new_user_session_path
|
43
|
+
|
44
|
+
within('form#new_user') do
|
45
|
+
fill_form(email: email, password: 'not-correct-password')
|
46
|
+
submit_form
|
47
|
+
end
|
48
|
+
|
49
|
+
assert_page_normal
|
50
|
+
|
51
|
+
assert_content I18n.t('devise.failure.invalid', authentication_keys: Devise.authentication_keys.join(', '))
|
52
|
+
assert assigns[:current_user].blank?
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -5,7 +5,6 @@ module MemberTest
|
|
5
5
|
protected
|
6
6
|
|
7
7
|
def test_bot_member_test
|
8
|
-
test_bot_skip?
|
9
8
|
sign_in(user) and (resource = find_or_create_resource!)
|
10
9
|
|
11
10
|
path = url_for(controller: controller, action: action, id: resource.id, only_path: true)
|
@@ -13,7 +12,6 @@ module MemberTest
|
|
13
12
|
visit(path)
|
14
13
|
|
15
14
|
assert_page_normal
|
16
|
-
assert_flash unless test_bot_skip?(:flash)
|
17
15
|
assert_assigns(resource_name) unless (was_redirect?(path) || test_bot_skip?(:assigns))
|
18
16
|
end
|
19
17
|
|
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.3
|
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: 2015-
|
11
|
+
date: 2015-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -213,6 +213,7 @@ files:
|
|
213
213
|
- lib/tasks/effective_test_bot_tasks.rake
|
214
214
|
- test/concerns/test_botable/base_dsl.rb
|
215
215
|
- test/concerns/test_botable/crud_dsl.rb
|
216
|
+
- test/concerns/test_botable/devise_dsl.rb
|
216
217
|
- test/concerns/test_botable/member_dsl.rb
|
217
218
|
- test/concerns/test_botable/page_dsl.rb
|
218
219
|
- test/concerns/test_botable/redirect_dsl.rb
|
@@ -223,11 +224,10 @@ files:
|
|
223
224
|
- test/support/effective_test_bot_login_helper.rb
|
224
225
|
- test/support/effective_test_bot_test_helper.rb
|
225
226
|
- test/test_bot/integration/application_test.rb
|
226
|
-
- test/test_bot/integration/
|
227
|
-
- test/test_bot/integration/minitest_test.rb
|
228
|
-
- test/test_bot/models/user_test.rb
|
227
|
+
- test/test_bot/integration/environment_test.rb
|
229
228
|
- test/test_botable/base_test.rb
|
230
229
|
- test/test_botable/crud_test.rb
|
230
|
+
- test/test_botable/devise_test.rb
|
231
231
|
- test/test_botable/member_test.rb
|
232
232
|
- test/test_botable/page_test.rb
|
233
233
|
- test/test_botable/redirect_test.rb
|
@@ -1,54 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
if defined?(Devise) && defined?(User)
|
4
|
-
module TestBot
|
5
|
-
class DeviseTest < ActionDispatch::IntegrationTest
|
6
|
-
let(:email) { 'unique@testbot.com'}
|
7
|
-
let(:password) { '!Password123' }
|
8
|
-
let(:create_user!) { User.new(email: email, password: password, password_confirmation: password).save(validate: false) }
|
9
|
-
|
10
|
-
test 'sign up' do
|
11
|
-
visit new_user_registration_path
|
12
|
-
|
13
|
-
within('form#new_user') do
|
14
|
-
fill_form(email: email, password: password, password_confirmation: password)
|
15
|
-
submit_form
|
16
|
-
end
|
17
|
-
|
18
|
-
assert_equal page.status_code, 200
|
19
|
-
assert_content I18n.t('devise.registrations.signed_up')
|
20
|
-
assert User.find_by_email(email).present?
|
21
|
-
assert_assigns :current_user
|
22
|
-
end
|
23
|
-
|
24
|
-
test 'sign in' do
|
25
|
-
create_user!
|
26
|
-
visit new_user_session_path
|
27
|
-
|
28
|
-
within('form#new_user') do
|
29
|
-
fill_form(email: email, password: password)
|
30
|
-
submit_form
|
31
|
-
end
|
32
|
-
|
33
|
-
assert_equal 200, page.status_code
|
34
|
-
assert_content I18n.t('devise.sessions.signed_in')
|
35
|
-
assert_equal 1, User.find_by_email(email).sign_in_count
|
36
|
-
assert_assigns :current_user
|
37
|
-
end
|
38
|
-
|
39
|
-
test 'invalid sign in' do
|
40
|
-
create_user!
|
41
|
-
visit new_user_session_path
|
42
|
-
|
43
|
-
within('form#new_user') do
|
44
|
-
fill_form(email: email, password: 'not-correct-password')
|
45
|
-
submit_form
|
46
|
-
end
|
47
|
-
|
48
|
-
assert_equal 200, page.status_code
|
49
|
-
assert_content I18n.t('devise.failure.invalid', authentication_keys: Devise.authentication_keys.join(', '))
|
50
|
-
assert assigns[:current_user].blank?
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
if defined?(Devise) && defined?(User)
|
4
|
-
module TestBot
|
5
|
-
class UserTest < ActiveSupport::TestCase
|
6
|
-
let(:user) { User.new() }
|
7
|
-
|
8
|
-
# These are mostly here as an example of using shoulda
|
9
|
-
# I don't find that I use the gem, but I see it's value
|
10
|
-
should validate_presence_of(:email)
|
11
|
-
should validate_presence_of(:password)
|
12
|
-
should validate_presence_of(:encrypted_password)
|
13
|
-
|
14
|
-
test "user invalid when password and confirmation mismatch" do
|
15
|
-
user.password = '123456789'
|
16
|
-
user.password_confirmation = '987654321'
|
17
|
-
|
18
|
-
refute user.valid?, 'user should be invalid with mismatched passwords'
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|