beyond_the_api_test_helpers 0.0.1
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 +7 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +60 -0
- data/.ruby-version +1 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/beyond_the_api_test_helpers.gemspec +27 -0
- data/config.reek +63 -0
- data/lib/beyond_the_api_test_helpers.rb +43 -0
- data/lib/beyond_the_api_test_helpers/i18n_test_helpers.rb +13 -0
- data/lib/beyond_the_api_test_helpers/request/common_assertions.rb +51 -0
- data/lib/beyond_the_api_test_helpers/request/create_assertions.rb +82 -0
- data/lib/beyond_the_api_test_helpers/request/destroy_assertions.rb +67 -0
- data/lib/beyond_the_api_test_helpers/request/helpers.rb +45 -0
- data/lib/beyond_the_api_test_helpers/request/index_assertions.rb +103 -0
- data/lib/beyond_the_api_test_helpers/request/restore_assertions.rb +53 -0
- data/lib/beyond_the_api_test_helpers/request/show_assertions.rb +36 -0
- data/lib/beyond_the_api_test_helpers/request/update_assertions.rb +91 -0
- data/lib/beyond_the_api_test_helpers/shoulda/have_foreign_key.rb +59 -0
- data/lib/beyond_the_api_test_helpers/shoulda/have_model_translations.rb +80 -0
- data/lib/beyond_the_api_test_helpers/shoulda/have_valid_association.rb +51 -0
- data/lib/beyond_the_api_test_helpers/shoulda/have_valid_enum.rb +60 -0
- data/lib/beyond_the_api_test_helpers/shoulda/require_association.rb +51 -0
- data/lib/beyond_the_api_test_helpers/shoulda/validate_timeliness.rb +179 -0
- data/lib/beyond_the_api_test_helpers/version.rb +3 -0
- metadata +138 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
module BeyondTheApiTestHelpers
|
2
|
+
module Request
|
3
|
+
module DestroyAssertions
|
4
|
+
def assert_request_destroy_valid(url, options = {})
|
5
|
+
request_instance_variables_set options
|
6
|
+
if required_login
|
7
|
+
assert_request_needs_to_be_logged(url, :delete)
|
8
|
+
@headers.merge!(logged_in_headers)
|
9
|
+
end
|
10
|
+
|
11
|
+
assert_i18n_for_all_locales do
|
12
|
+
do_destroy_request_with_transaction(url)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def assert_request_destroy_not_found(urls_not_found, options = {})
|
17
|
+
request_instance_variables_set options
|
18
|
+
@headers.merge!(logged_in_headers) if required_login
|
19
|
+
|
20
|
+
urls_not_found.each do |url_not_found|
|
21
|
+
assert_request_destroy_not_found_i18n_all(url_not_found)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def do_destroy_request_with_transaction(url)
|
28
|
+
ActiveRecord::Base.transaction do
|
29
|
+
do_destroy_request_and_assert(url)
|
30
|
+
Redis.current.flushdb if @flush_redis_db_between_i18n_tests
|
31
|
+
raise ActiveRecord::Rollback
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# :reek:DuplicateMethodCall: { max_calls: 2 }
|
36
|
+
def do_destroy_request_and_assert(url)
|
37
|
+
subject_id = subject.id unless @skip_destroyed_validate
|
38
|
+
delete(url, params: @params, headers: @headers)
|
39
|
+
response_assertions(status: 200)
|
40
|
+
assert_destroyed(subject_id) unless @skip_destroyed_validate
|
41
|
+
assert_equal I18n.t(*@message), json['success']
|
42
|
+
end
|
43
|
+
|
44
|
+
def assert_destroyed(subject_id)
|
45
|
+
if subject.respond_to? :deleted_at
|
46
|
+
assert_not_nil subject.reload.deleted_at
|
47
|
+
elsif subject.respond_to? :active
|
48
|
+
assert_active_destroyed
|
49
|
+
else
|
50
|
+
klass = @klass || subject.class
|
51
|
+
assert_equal false, klass.exists?(subject_id)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def assert_active_destroyed
|
56
|
+
assert_equal false, subject.reload.active?
|
57
|
+
end
|
58
|
+
|
59
|
+
def assert_request_destroy_not_found_i18n_all(url_not_found)
|
60
|
+
assert_i18n_for_all_locales do
|
61
|
+
delete(url_not_found, params: @params, headers: @headers)
|
62
|
+
assert_not_found_request
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module BeyondTheApiTestHelpers
|
2
|
+
module Request
|
3
|
+
module Helpers
|
4
|
+
|
5
|
+
def api_url
|
6
|
+
'/'
|
7
|
+
end
|
8
|
+
|
9
|
+
def json
|
10
|
+
@json = JSON.parse(response.body)
|
11
|
+
end
|
12
|
+
|
13
|
+
def logged_in_headers
|
14
|
+
{
|
15
|
+
client: 'client_id_test',
|
16
|
+
'access-token': 'token_test',
|
17
|
+
uid: user_authorizations(:logged).uid,
|
18
|
+
'HTTP_USER_AGENT': 'Rails Testing'
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def not_logged_in_headers
|
23
|
+
{ 'HTTP_USER_AGENT': 'Rails Testing' }
|
24
|
+
end
|
25
|
+
|
26
|
+
def response_assertions(options)
|
27
|
+
assert_equal response.content_type, Mime[:json]
|
28
|
+
assert_meta_now
|
29
|
+
assert_meta_version
|
30
|
+
assert_response options[:status]
|
31
|
+
end
|
32
|
+
|
33
|
+
# rubocop:disable Rails/Date
|
34
|
+
def assert_meta_now
|
35
|
+
assert_kind_of Time, json['meta']['now'].to_time
|
36
|
+
end
|
37
|
+
# rubocop:enable Rails/Date
|
38
|
+
|
39
|
+
def assert_meta_version
|
40
|
+
assert_equal json['meta']['version'], api_version
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module BeyondTheApiTestHelpers
|
2
|
+
module Request
|
3
|
+
module IndexAssertions
|
4
|
+
def assert_request_index_valid(url, options = {})
|
5
|
+
request_instance_variables_set_pluralize options
|
6
|
+
|
7
|
+
if required_login
|
8
|
+
assert_request_needs_to_be_logged(url, :get)
|
9
|
+
@headers.merge!(logged_in_headers)
|
10
|
+
end
|
11
|
+
|
12
|
+
get(url, params: @params, headers: @headers)
|
13
|
+
response_assertions(status: 200)
|
14
|
+
assert_kind_of Array, json_response_name
|
15
|
+
assert_request_index_should_include if @should_include || @should_not_include
|
16
|
+
end
|
17
|
+
|
18
|
+
def assert_request_index_total_count(url, options = {})
|
19
|
+
request_instance_variables_set_pluralize options
|
20
|
+
@headers.merge!(logged_in_headers) if required_login
|
21
|
+
get(url, params: @params.merge(total_count: true), headers: @headers)
|
22
|
+
assert_kind_of Integer, meta['total_count']
|
23
|
+
end
|
24
|
+
|
25
|
+
def assert_request_index_paginated(url, params = {})
|
26
|
+
request_instance_variables_set_pluralize params
|
27
|
+
@headers.merge!(logged_in_headers) if required_login
|
28
|
+
|
29
|
+
get(url, params: @params.merge(page: 1, per_page: 1, total_pages: true), headers: @headers)
|
30
|
+
assert_equal 1, json_response_name.size
|
31
|
+
assert_kind_of Integer, meta['total_pages']
|
32
|
+
end
|
33
|
+
|
34
|
+
def assert_request_index_with_filters(url, filters, params = {})
|
35
|
+
request_instance_variables_set_pluralize params
|
36
|
+
@headers.merge!(logged_in_headers) if required_login
|
37
|
+
|
38
|
+
filters.each do |key, options|
|
39
|
+
assert_request_index_filter(url, key, options)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def assert_request_index_not_found(urls_not_found, options = {})
|
44
|
+
request_instance_variables_set options
|
45
|
+
@headers.merge!(logged_in_headers) if required_login
|
46
|
+
|
47
|
+
urls_not_found.each do |url_not_found|
|
48
|
+
assert_request_index_not_found_i18n_all(url_not_found)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def assert_request_index_should_include
|
55
|
+
@should_include&.each do |object|
|
56
|
+
assert_request_includes_should_include(object)
|
57
|
+
end
|
58
|
+
@should_not_include&.each do |object|
|
59
|
+
assert_request_not_includes_should_not_include(object)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def assert_request_includes_should_include(object)
|
64
|
+
serialized = object.serialize_to_json(current_user: users(:logged))
|
65
|
+
assert_includes json_response_name, serialized
|
66
|
+
end
|
67
|
+
|
68
|
+
def assert_request_not_includes_should_not_include(object)
|
69
|
+
serialized = object.serialize_to_json(current_user: users(:logged))
|
70
|
+
assert_not_includes json_response_name, serialized
|
71
|
+
end
|
72
|
+
|
73
|
+
def assert_request_index_filter(url, key, options)
|
74
|
+
options.each do |option|
|
75
|
+
get(url, params: { key => option[:value] }, headers: @headers)
|
76
|
+
assert_request_include_filter(option[:include])
|
77
|
+
assert_request_exclude_filter(option[:exclude])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def assert_request_include_filter(objects)
|
82
|
+
objects.each do |object|
|
83
|
+
serialized = object.serialize_to_json(current_user: users(:logged))
|
84
|
+
assert_includes json_response_name, serialized
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def assert_request_exclude_filter(objects)
|
89
|
+
objects.each do |object|
|
90
|
+
serialized = object.serialize_to_json(current_user: users(:logged))
|
91
|
+
assert_not_includes json_response_name, serialized
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def assert_request_index_not_found_i18n_all(url_not_found)
|
96
|
+
assert_i18n_for_all_locales do
|
97
|
+
get(url_not_found, params: @params, headers: @headers)
|
98
|
+
assert_not_found_request
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module BeyondTheApiTestHelpers
|
2
|
+
module Request
|
3
|
+
module RestoreAssertions
|
4
|
+
def assert_request_restore_valid(url, options = {})
|
5
|
+
request_instance_variables_set options
|
6
|
+
if required_login
|
7
|
+
assert_request_needs_to_be_logged(url, :patch)
|
8
|
+
assert_request_needs_to_be_logged(url, :put)
|
9
|
+
@headers.merge!(logged_in_headers)
|
10
|
+
end
|
11
|
+
|
12
|
+
assert_i18n_for_all_locales do
|
13
|
+
do_restore_request_with_transaction(url)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def assert_request_restore_not_found(urls_not_found, options = {})
|
18
|
+
request_instance_variables_set options
|
19
|
+
@headers.merge!(logged_in_headers) if required_login
|
20
|
+
|
21
|
+
urls_not_found.each do |url_not_found|
|
22
|
+
assert_request_restore_not_found_i18n_all(url_not_found)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def do_restore_request_with_transaction(url)
|
29
|
+
ActiveRecord::Base.transaction do
|
30
|
+
do_restore_request_and_assert(url)
|
31
|
+
raise ActiveRecord::Rollback
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# :reek:DuplicateMethodCall: { max_calls: 2 }
|
36
|
+
def do_restore_request_and_assert(url)
|
37
|
+
patch(url, params: @params, headers: @headers)
|
38
|
+
assert_nil subject.reload.deleted_at
|
39
|
+
response_assertions(status: 200)
|
40
|
+
assert_equal I18n.t(@message), json['success']
|
41
|
+
end
|
42
|
+
|
43
|
+
def assert_request_restore_not_found_i18n_all(url_not_found)
|
44
|
+
assert_i18n_for_all_locales do
|
45
|
+
patch(url_not_found, params: @params, headers: @headers)
|
46
|
+
assert_not_found_request
|
47
|
+
put(url_not_found, params: @params, headers: @headers)
|
48
|
+
assert_not_found_request
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module BeyondTheApiTestHelpers
|
2
|
+
module Request
|
3
|
+
module ShowAssertions
|
4
|
+
def assert_request_show_valid(url, options = {})
|
5
|
+
request_instance_variables_set options
|
6
|
+
|
7
|
+
if required_login
|
8
|
+
assert_request_needs_to_be_logged(url, :get)
|
9
|
+
@headers.merge!(logged_in_headers)
|
10
|
+
end
|
11
|
+
|
12
|
+
get(url, params: @params, headers: @headers)
|
13
|
+
response_assertions(status: 200)
|
14
|
+
assert_kind_of Hash, json_response_name
|
15
|
+
end
|
16
|
+
|
17
|
+
def assert_request_show_not_found(urls_not_found, options = {})
|
18
|
+
request_instance_variables_set options
|
19
|
+
@headers.merge!(logged_in_headers) if required_login
|
20
|
+
|
21
|
+
urls_not_found.each do |url_not_found|
|
22
|
+
assert_request_show_not_found_i18n_all(url_not_found)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def assert_request_show_not_found_i18n_all(url_not_found)
|
29
|
+
assert_i18n_for_all_locales do
|
30
|
+
get(url_not_found, params: @params, headers: @headers)
|
31
|
+
assert_not_found_request
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module BeyondTheApiTestHelpers
|
2
|
+
module Request
|
3
|
+
module UpdateAssertions
|
4
|
+
def assert_request_update_valid(url, options = {})
|
5
|
+
request_instance_variables_set options
|
6
|
+
if required_login
|
7
|
+
assert_request_needs_to_be_logged(url, :put)
|
8
|
+
assert_request_needs_to_be_logged(url, :patch)
|
9
|
+
@headers.merge!(logged_in_headers)
|
10
|
+
end
|
11
|
+
|
12
|
+
assert_i18n_for_all_locales do
|
13
|
+
do_update_request_with_transaction(url)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def assert_request_update_missing_param(url, options = {})
|
18
|
+
request_instance_variables_set options
|
19
|
+
@headers.merge!(logged_in_headers) if required_login
|
20
|
+
patch(url, params: {}, headers: @headers)
|
21
|
+
assert_parameter_missing_request
|
22
|
+
put(url, params: {}, headers: @headers)
|
23
|
+
assert_parameter_missing_request
|
24
|
+
end
|
25
|
+
|
26
|
+
def assert_request_update_with_errors(url, invalid_params, params = {})
|
27
|
+
request_instance_variables_set params
|
28
|
+
# pp @headers
|
29
|
+
# pp user_authorizations(:logged)
|
30
|
+
# abort
|
31
|
+
@headers.merge!(logged_in_headers) if required_login
|
32
|
+
|
33
|
+
ActiveRecord::Base.transaction do
|
34
|
+
do_update_request_and_assert_invalid(url, invalid_params)
|
35
|
+
raise ActiveRecord::Rollback
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def assert_request_update_not_found(urls_not_found, options = {})
|
40
|
+
request_instance_variables_set options
|
41
|
+
@headers.merge!(logged_in_headers) if required_login
|
42
|
+
|
43
|
+
urls_not_found.each do |url_not_found|
|
44
|
+
assert_request_update_not_found_i18n_all(url_not_found)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def do_update_request_with_transaction(url)
|
51
|
+
ActiveRecord::Base.transaction do
|
52
|
+
do_update_request_and_assert(url)
|
53
|
+
raise ActiveRecord::Rollback
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def do_update_request_and_assert(url)
|
58
|
+
patch(url, params: @params, headers: @headers)
|
59
|
+
subject.reload
|
60
|
+
changes.each do |key, value|
|
61
|
+
assert_equal subject.send(key), value
|
62
|
+
end
|
63
|
+
update_assertions_status_and_message
|
64
|
+
end
|
65
|
+
|
66
|
+
def update_assertions_status_and_message
|
67
|
+
response_assertions(status: 200)
|
68
|
+
assert_equal I18n.t(*@message), json['success']
|
69
|
+
assert_kind_of Hash, json_response_name unless @skip_json_response_name
|
70
|
+
end
|
71
|
+
|
72
|
+
def do_update_request_and_assert_invalid(url, invalid_params)
|
73
|
+
patch(url, params: invalid_params, headers: @headers)
|
74
|
+
subject.reload
|
75
|
+
changes.each do |key, value|
|
76
|
+
assert_not_equal subject.send(key), value
|
77
|
+
end
|
78
|
+
response_assertions(status: 422)
|
79
|
+
assert_kind_of Hash, json['errors']
|
80
|
+
assert_kind_of Array, json['full_error_messages']
|
81
|
+
end
|
82
|
+
|
83
|
+
def assert_request_update_not_found_i18n_all(url_not_found)
|
84
|
+
assert_i18n_for_all_locales do
|
85
|
+
patch(url_not_found, params: @params, headers: @headers)
|
86
|
+
assert_not_found_request
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveRecord
|
4
|
+
def have_foreign_key(table, fk)
|
5
|
+
HaveForeignKeyMatcher.new(table, fk)
|
6
|
+
end
|
7
|
+
|
8
|
+
# @private
|
9
|
+
class HaveForeignKeyMatcher
|
10
|
+
def initialize(table, fk)
|
11
|
+
@table = table
|
12
|
+
@fk = fk
|
13
|
+
@options = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def matches?(subject)
|
17
|
+
@subject = subject
|
18
|
+
|
19
|
+
foreign_keys = ::ActiveRecord::Base.connection
|
20
|
+
.foreign_keys(table_name)
|
21
|
+
.map do |foreign_key|
|
22
|
+
{ to_table: foreign_key['to_table'].to_sym,
|
23
|
+
fk: foreign_key['options'][:column].to_sym }
|
24
|
+
end
|
25
|
+
|
26
|
+
foreign_keys.include? to_table: @table, fk: @fk
|
27
|
+
end
|
28
|
+
|
29
|
+
def failure_message
|
30
|
+
"Expected #{expectation} (#{@missing})"
|
31
|
+
end
|
32
|
+
alias failure_message_for_should failure_message
|
33
|
+
|
34
|
+
def failure_message_when_negated
|
35
|
+
"Did not expect #{expectation}"
|
36
|
+
end
|
37
|
+
alias failure_message_for_should_not failure_message_when_negated
|
38
|
+
|
39
|
+
def description
|
40
|
+
"have a foreign_key to table #{@table}"
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def expectation
|
46
|
+
"#{model_class.name} to #{description}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def model_class
|
50
|
+
@subject.class
|
51
|
+
end
|
52
|
+
|
53
|
+
def table_name
|
54
|
+
model_class.table_name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|