forest_liana 3.0.0.pre.beta.10 → 3.0.0.pre.beta.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/app/services/forest_liana/resources_getter.rb +10 -2
  3. data/lib/forest_liana/engine.rb +13 -15
  4. data/lib/forest_liana/version.rb +1 -1
  5. data/spec/dummy/README.rdoc +28 -0
  6. data/spec/dummy/Rakefile +6 -0
  7. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  8. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  9. data/spec/dummy/app/config/routes.rb +3 -0
  10. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  11. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  12. data/spec/dummy/app/models/island.rb +5 -0
  13. data/spec/dummy/app/models/tree.rb +5 -0
  14. data/spec/dummy/app/models/user.rb +4 -0
  15. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  16. data/spec/dummy/bin/bundle +3 -0
  17. data/spec/dummy/bin/rails +4 -0
  18. data/spec/dummy/bin/rake +4 -0
  19. data/spec/dummy/bin/setup +29 -0
  20. data/spec/dummy/config.ru +4 -0
  21. data/spec/dummy/config/application.rb +26 -0
  22. data/spec/dummy/config/boot.rb +5 -0
  23. data/spec/dummy/config/database.yml +25 -0
  24. data/spec/dummy/config/environment.rb +5 -0
  25. data/spec/dummy/config/environments/development.rb +41 -0
  26. data/spec/dummy/config/environments/production.rb +79 -0
  27. data/spec/dummy/config/environments/test.rb +42 -0
  28. data/spec/dummy/config/initializers/assets.rb +11 -0
  29. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  30. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  31. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  32. data/spec/dummy/config/initializers/forest_liana.rb +2 -0
  33. data/spec/dummy/config/initializers/inflections.rb +16 -0
  34. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  35. data/spec/dummy/config/initializers/session_store.rb +3 -0
  36. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  37. data/spec/dummy/config/routes.rb +3 -0
  38. data/spec/dummy/config/secrets.yml +22 -0
  39. data/spec/dummy/db/migrate/20190226172951_create_user.rb +9 -0
  40. data/spec/dummy/db/migrate/20190226173051_create_isle.rb +10 -0
  41. data/spec/dummy/db/migrate/20190226174951_create_tree.rb +12 -0
  42. data/spec/dummy/db/schema.rb +42 -0
  43. data/spec/dummy/db/test.sqlite3 +0 -0
  44. data/spec/dummy/log/development.log +80 -0
  45. data/spec/dummy/log/test.log +22549 -0
  46. data/spec/helpers/forest_liana/query_helper_spec.rb +74 -0
  47. data/spec/rails_helper.rb +61 -0
  48. data/spec/requests/resources_spec.rb +97 -0
  49. data/spec/services/forest_liana/apimap_sorter_spec.rb +172 -0
  50. data/spec/services/forest_liana/ip_whitelist_checker_spec.rb +203 -0
  51. data/spec/services/forest_liana/schema_adapter_spec.rb +17 -0
  52. data/spec/spec_helper.rb +99 -0
  53. data/test/dummy/config/routes.rb +0 -1
  54. data/test/dummy/db/test.sqlite3 +0 -0
  55. data/test/dummy/log/test.log +812 -0
  56. data/test/routing/route_test.rb +0 -2
  57. metadata +98 -2
@@ -0,0 +1,74 @@
1
+ module ForestLiana
2
+ describe QueryHelper do
3
+ before(:all) do
4
+ Tree.connection
5
+ User.connection
6
+ Island.connection
7
+ end
8
+
9
+ describe 'get_one_associations' do
10
+ context 'on a model having 2 hasMany associations' do
11
+ it 'should not return any one-one associations' do
12
+ associations = QueryHelper.get_one_associations(User)
13
+ expect(associations.length).to eq(0)
14
+ end
15
+ end
16
+
17
+ context 'on a model having 3 belongsTo associations' do
18
+ it 'should return the one-one associations' do
19
+ associations = QueryHelper.get_one_associations(Tree)
20
+ expect(associations.length).to eq(3)
21
+ expect(associations.first.name).to eq(:owner)
22
+ expect(associations.first.klass).to eq(User)
23
+ expect(associations.second.name).to eq(:cutter)
24
+ expect(associations.second.klass).to eq(User)
25
+ expect(associations.third.name).to eq(:island)
26
+ expect(associations.third.klass).to eq(Island)
27
+ end
28
+ end
29
+ end
30
+
31
+ describe 'get_one_association_names_symbol' do
32
+ it 'should return the one-one associations names as symbols' do
33
+ expect(QueryHelper.get_one_association_names_symbol(Tree)).to eq([:owner, :cutter, :island])
34
+ end
35
+ end
36
+
37
+ describe 'get_one_association_names_string' do
38
+ it 'should return the one-one associations names as strings' do
39
+ expect(QueryHelper.get_one_association_names_string(Tree)).to eq(['owner', 'cutter', 'island'])
40
+ end
41
+ end
42
+
43
+ describe 'get_tables_associated_to_relations_name' do
44
+ context 'on a model having 2 hasMany associations' do
45
+ it 'should return an empty hash' do
46
+ tables_associated_to_relations_name =
47
+ QueryHelper.get_tables_associated_to_relations_name(User)
48
+ expect(tables_associated_to_relations_name.keys.length).to eq(0)
49
+ end
50
+ end
51
+
52
+ context 'on a model having 2 belongsTo associations' do
53
+ tables_associated_to_relations_name =
54
+ QueryHelper.get_tables_associated_to_relations_name(Tree)
55
+
56
+ it 'should return the one-one associations' do
57
+ expect(tables_associated_to_relations_name.keys.length).to eq(2)
58
+ end
59
+
60
+ it 'should return relationships having a name different than the targeted model' do
61
+ expect(tables_associated_to_relations_name['users'].length).to eq(2)
62
+ expect(tables_associated_to_relations_name['users'].first).to eq(:owner)
63
+ expect(tables_associated_to_relations_name['users'].second).to eq(:cutter)
64
+ end
65
+
66
+ it 'should return relationships on models having a custom table name' do
67
+ expect(tables_associated_to_relations_name['isle'].length).to eq(1)
68
+ expect(tables_associated_to_relations_name['isle'].first).to eq(:island)
69
+ end
70
+ end
71
+ end
72
+
73
+ end
74
+ end
@@ -0,0 +1,61 @@
1
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
2
+ require 'spec_helper'
3
+ ENV['RAILS_ENV'] ||= 'test'
4
+ require File.expand_path('../dummy/config/environment', __FILE__)
5
+ # Prevent database truncation if the environment is production
6
+ abort("The Rails environment is running in production mode!") if Rails.env.production?
7
+ require 'rspec/rails'
8
+ # Add additional requires below this line. Rails is not loaded until this point!
9
+
10
+ # Requires supporting ruby files with custom matchers and macros, etc, in
11
+ # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
12
+ # run as spec files by default. This means that files in spec/support that end
13
+ # in _spec.rb will both be required and run as specs, causing the specs to be
14
+ # run twice. It is recommended that you do not name files matching this glob to
15
+ # end with _spec.rb. You can configure this pattern with the --pattern
16
+ # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
17
+ #
18
+ # The following line is provided for convenience purposes. It has the downside
19
+ # of increasing the boot-up time by auto-requiring all files in the support
20
+ # directory. Alternatively, in the individual `*_spec.rb` files, manually
21
+ # require only the support files necessary.
22
+ #
23
+ # Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
24
+
25
+ # Checks for pending migrations and applies them before tests are run.
26
+ # If you are not using ActiveRecord, you can remove these lines.
27
+ begin
28
+ ActiveRecord::Migration.maintain_test_schema!
29
+ rescue ActiveRecord::PendingMigrationError => e
30
+ puts e.to_s.strip
31
+ exit 1
32
+ end
33
+ RSpec.configure do |config|
34
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
35
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
36
+
37
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
38
+ # examples within a transaction, remove the following line or assign false
39
+ # instead of true.
40
+ config.use_transactional_fixtures = true
41
+
42
+ # RSpec Rails can automatically mix in different behaviours to your tests
43
+ # based on their file location, for example enabling you to call `get` and
44
+ # `post` in specs under `spec/controllers`.
45
+ #
46
+ # You can disable this behaviour by removing the line below, and instead
47
+ # explicitly tag your specs with their type, e.g.:
48
+ #
49
+ # RSpec.describe UsersController, :type => :controller do
50
+ # # ...
51
+ # end
52
+ #
53
+ # The different available types are documented in the features, such as in
54
+ # https://relishapp.com/rspec/rspec-rails/docs
55
+ config.infer_spec_type_from_file_location!
56
+
57
+ # Filter lines from Rails gems in backtraces.
58
+ config.filter_rails_from_backtrace!
59
+ # arbitrary gems may also be filtered via:
60
+ # config.filter_gems_from_backtrace("gem name")
61
+ end
@@ -0,0 +1,97 @@
1
+ require 'rails_helper'
2
+
3
+ describe 'Requesting Tree resources', :type => :request do
4
+ before(:each) do
5
+ user = User.create(name: 'Michel')
6
+ tree = Tree.create(name: 'Lemon Tree', owner: user, cutter: user)
7
+ end
8
+
9
+ after(:each) do
10
+ User.destroy_all
11
+ Tree.destroy_all
12
+ end
13
+
14
+ before(:each) do
15
+ allow(ForestLiana::IpWhitelist).to receive(:retrieve) { true }
16
+ allow(ForestLiana::IpWhitelist).to receive(:is_ip_whitelist_retrieved) { true }
17
+ allow(ForestLiana::IpWhitelist).to receive(:is_ip_valid) { true }
18
+
19
+ allow_any_instance_of(ForestLiana::PermissionsChecker).to receive(:is_authorized?) { true }
20
+ end
21
+
22
+ headers = {
23
+ 'Accept' => 'application/json',
24
+ 'Content-Type' => 'application/json',
25
+ 'Authorization' => 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJleHAiOiIxODQ5ODc4ODYzIiwiZGF0YSI6eyJpZCI6IjM4IiwidHlwZSI6InVzZXJzIiwiZGF0YSI6eyJlbWFpbCI6Im1pY2hhZWwua2Vsc29AdGhhdDcwLnNob3ciLCJmaXJzdF9uYW1lIjoiTWljaGFlbCIsImxhc3RfbmFtZSI6IktlbHNvIiwidGVhbXMiOiJPcGVyYXRpb25zIn0sInJlbGF0aW9uc2hpcHMiOnsicmVuZGVyaW5ncyI6eyJkYXRhIjpbeyJ0eXBlIjoicmVuZGVyaW5ncyIsImlkIjoxNn1dfX19fQ.U4Mxi0tq0Ce7y5FRXP47McNPRPhUx37LznQ5E3mJIp4'
26
+ }
27
+
28
+ describe 'index' do
29
+ describe 'without any filter' do
30
+ params = {
31
+ fields: { 'Tree' => 'id,name' },
32
+ page: { 'number' => '1', 'size' => '10' },
33
+ searchExtended: '0',
34
+ sort: '-id',
35
+ timezone: 'Europe/Paris'
36
+ }
37
+
38
+ it 'should respond 200' do
39
+ get '/forest/Tree', params, headers
40
+ expect(response.status).to eq(200)
41
+ end
42
+
43
+ it 'should respond the tree data' do
44
+ get '/forest/Tree', params, headers
45
+ expect(JSON.parse(response.body)).to eq({
46
+ "data" => [{
47
+ "type" => "Tree",
48
+ "id" => "1",
49
+ "attributes" => {
50
+ "id" => 1,
51
+ "name" => "Lemon Tree"
52
+ },
53
+ "links" => {
54
+ "self" => "/forest/tree/1"
55
+ }
56
+ }],
57
+ "included" => []
58
+ })
59
+ end
60
+ end
61
+
62
+ describe 'with a filter on an association that is not a displayed column' do
63
+ params = {
64
+ fields: { 'Tree' => 'id,name' },
65
+ filterType: 'and',
66
+ filter: { 'owner:id' => '$present' },
67
+ page: { 'number' => '1', 'size' => '10' },
68
+ searchExtended: '0',
69
+ sort: '-id',
70
+ timezone: 'Europe/Paris'
71
+ }
72
+
73
+ it 'should respond 200' do
74
+ get '/forest/Tree', params, headers
75
+ expect(response.status).to eq(200)
76
+ end
77
+
78
+ it 'should respond the tree data' do
79
+ get '/forest/Tree', params, headers
80
+ expect(JSON.parse(response.body)).to eq({
81
+ "data" => [{
82
+ "type" => "Tree",
83
+ "id" => "1",
84
+ "attributes" => {
85
+ "id" => 1,
86
+ "name" => "Lemon Tree"
87
+ },
88
+ "links" => {
89
+ "self" => "/forest/tree/1"
90
+ }
91
+ }],
92
+ "included" => []
93
+ })
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,172 @@
1
+ module ForestLiana
2
+ describe ApimapSorter do
3
+ describe 'apimap reordering' do
4
+ context 'on a disordered apimap' do
5
+ apimap = {
6
+ 'meta': {
7
+ 'orm_version': '4.34.9',
8
+ 'liana_version': '1.5.24',
9
+ 'database_type': 'postgresql',
10
+ liana: 'forest-rails',
11
+ },
12
+ 'data': [{
13
+ id: 'users',
14
+ type: 'collections',
15
+ attributes: {
16
+ fields: [
17
+ { field: 'id', type: 'Number' },
18
+ { field: 'name', type: 'String' },
19
+ { field: 'firstName', type: 'String' },
20
+ { field: 'lastName', type: 'String' },
21
+ { field: 'email', type: 'String' },
22
+ { field: 'url', type: 'String' },
23
+ { field: 'createdAt', type: 'Date' },
24
+ { field: 'updatedAt', type: 'Date' },
25
+ ],
26
+ name: 'users',
27
+ }
28
+ }, {
29
+ id: 'guests',
30
+ type: 'collections',
31
+ attributes: {
32
+ fields: [
33
+ { field: 'id', type: 'Number' },
34
+ { field: 'email', type: 'String' },
35
+ { field: 'createdAt', type: 'Date' },
36
+ { field: 'updatedAt', type: 'Date' },
37
+ ],
38
+ name: 'guests',
39
+ }
40
+ }, {
41
+ type: 'collections',
42
+ id: 'animals',
43
+ attributes: {
44
+ fields: [
45
+ { 'is-sortable': false, field: 'id', 'is-filterable': false, type: 'Number' },
46
+ { type: 'Date', field: 'createdAt' },
47
+ { field: 'updatedAt', type: 'Date' },
48
+ ],
49
+ name: 'animals',
50
+ integration: 'close.io',
51
+ 'is-virtual': true,
52
+ }
53
+ }],
54
+ 'included': [{
55
+ id: 'users.Women',
56
+ type: 'segments',
57
+ attributes: {
58
+ name: 'Women'
59
+ }
60
+ }, {
61
+ id: 'users.import',
62
+ type: 'actions',
63
+ links: {
64
+ self: '/actions'
65
+ },
66
+ attributes: {
67
+ name: 'import',
68
+ fields: [{
69
+ isRequired: true,
70
+ type: 'Boolean',
71
+ field: 'Save',
72
+ description: 'save the import file if true.',
73
+ defaultValue: 'true'
74
+ }, {
75
+ type: 'File',
76
+ field: 'File'
77
+ }],
78
+ 'http-method': nil
79
+ }
80
+ }, {
81
+ attributes: {
82
+ name: 'Men'
83
+ },
84
+ id: 'users.Men',
85
+ type: 'segments'
86
+ }, {
87
+ id: 'animals.ban',
88
+ type: 'actions',
89
+ links: {
90
+ self: '/actions'
91
+ },
92
+ attributes: {
93
+ name: 'import',
94
+ global: true,
95
+ download: nil,
96
+ endpoint: nil,
97
+ redirect: nil,
98
+ 'http-method': nil
99
+ }
100
+ }]
101
+ }
102
+
103
+ apimap = ActiveSupport::JSON.encode(apimap)
104
+ apimap = ActiveSupport::JSON.decode(apimap)
105
+ apimap_sorted = ApimapSorter.new(apimap).perform
106
+
107
+ it 'should sort the apimap sections' do
108
+ expect(apimap_sorted.keys).to eq(['data', 'included', 'meta'])
109
+ end
110
+
111
+ it 'should sort the data collections' do
112
+ expect(apimap_sorted['data'].map { |collection| collection['id'] }).to eq(
113
+ ['animals', 'guests', 'users'])
114
+ end
115
+
116
+ it 'should sort the data collection values' do
117
+ expect(apimap_sorted['data'][0].keys).to eq(['type', 'id', 'attributes'])
118
+ expect(apimap_sorted['data'][1].keys).to eq(['type', 'id', 'attributes'])
119
+ expect(apimap_sorted['data'][2].keys).to eq(['type', 'id', 'attributes'])
120
+ end
121
+
122
+ it 'should sort the data collections attributes values' do
123
+ expect(apimap_sorted['data'][0]['attributes'].keys).to eq(['name', 'integration', 'is-virtual', 'fields'])
124
+ expect(apimap_sorted['data'][1]['attributes'].keys).to eq(['name', 'fields'])
125
+ expect(apimap_sorted['data'][2]['attributes'].keys).to eq(['name', 'fields'])
126
+ end
127
+
128
+ it 'should sort the data collections attributes fields by name' do
129
+ expect(apimap_sorted['data'][0]['attributes']['fields'].map { |field| field['field'] }).to eq(['createdAt', 'id', 'updatedAt'])
130
+ expect(apimap_sorted['data'][1]['attributes']['fields'].map { |field| field['field'] }).to eq(['createdAt', 'email', 'id', 'updatedAt'])
131
+ expect(apimap_sorted['data'][2]['attributes']['fields'].map { |field| field['field'] }).to eq(['createdAt', 'email', 'firstName', 'id', 'lastName', 'name', 'updatedAt', 'url'])
132
+ end
133
+
134
+ it 'should sort the data collections attributes fields values' do
135
+ expect(apimap_sorted['data'][0]['attributes']['fields'][1].keys).to eq(['field', 'type', 'is-filterable', 'is-sortable'])
136
+ end
137
+
138
+ it 'should sort the included actions and segments objects' do
139
+ expect(apimap_sorted['included'].map { |object| object['id'] }).to eq(
140
+ ['animals.ban', 'users.import', 'users.Men', 'users.Women'])
141
+ end
142
+
143
+ it 'should sort the included actions and segments objects values' do
144
+ expect(apimap_sorted['included'][0].keys).to eq(['type', 'id', 'attributes', 'links'])
145
+ expect(apimap_sorted['included'][1].keys).to eq(['type', 'id', 'attributes', 'links'])
146
+ expect(apimap_sorted['included'][2].keys).to eq(['type', 'id', 'attributes'])
147
+ expect(apimap_sorted['included'][3].keys).to eq(['type', 'id', 'attributes'])
148
+ end
149
+
150
+ it 'should sort the included actions and segments objects attributes values' do
151
+ expect(apimap_sorted['included'][0]['attributes'].keys).to eq(['name', 'download', 'endpoint', 'global', 'http-method', 'redirect'])
152
+ expect(apimap_sorted['included'][1]['attributes'].keys).to eq(['name', 'http-method', 'fields'])
153
+ expect(apimap_sorted['included'][2]['attributes'].keys).to eq(['name'])
154
+ expect(apimap_sorted['included'][3]['attributes'].keys).to eq(['name'])
155
+ end
156
+
157
+ it 'should sort the included action attributes fields by name' do
158
+ expect(apimap_sorted['included'][1]['attributes']['fields'].map { |field| field['field'] }).to eq(['File', 'Save'])
159
+ end
160
+
161
+ it 'should sort the included action fields values' do
162
+ expect(apimap_sorted['included'][1]['attributes']['fields'][1].keys).to eq(['field', 'type', 'defaultValue', 'description', 'isRequired'])
163
+ end
164
+
165
+ it 'should sort the meta values' do
166
+ expect(apimap_sorted['meta'].keys).to eq(
167
+ ['database_type', 'liana', 'liana_version', 'orm_version'])
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,203 @@
1
+ module ForestLiana
2
+ describe IpWhitelistChecker do
3
+ describe 'Check is_ip_matches_rule function' do
4
+ describe 'with IP "90.88.0.1" and "90.88.0.2"' do
5
+ it 'should return false' do
6
+ rule = {
7
+ 'type' => 0,
8
+ 'ip' => '90.88.0.1',
9
+ }
10
+
11
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.0.2', rule)
12
+
13
+ expect(is_matching).to eq(false)
14
+ end
15
+ end
16
+
17
+ describe 'with IP "::1" and "aaaa"' do
18
+ it 'should raise an "ArgumentError" exception with "Unknown IP Address aaaa" message' do
19
+ rule = {
20
+ 'type' => 0,
21
+ 'ip' => '::1',
22
+ }
23
+
24
+ expect {
25
+ IpWhitelistChecker.is_ip_matches_rule('aaaa', rule)
26
+ }.to raise_error(ArgumentError, 'Unknown IP Address aaaa')
27
+ end
28
+ end
29
+
30
+ describe 'with IP "90.88.0.1" and "::1"' do
31
+ it 'should return false' do
32
+ rule = {
33
+ 'type' => 0,
34
+ 'ip' => '90.88.0.1',
35
+ }
36
+
37
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('::1', rule)
38
+
39
+ expect(is_matching).to eq(false)
40
+ end
41
+ end
42
+
43
+ describe 'with IP "::1" and "::1"' do
44
+ it 'should return true' do
45
+ rule = {
46
+ 'type' => 0,
47
+ 'ip' => '::1',
48
+ }
49
+
50
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('::1', rule)
51
+
52
+ expect(is_matching).to eq(true)
53
+ end
54
+ end
55
+
56
+ describe 'with IP "90.88.0.1" and "90.88.0.1"' do
57
+ it 'should return true' do
58
+ rule = {
59
+ 'type' => 0,
60
+ 'ip' => '90.88.0.1',
61
+ }
62
+
63
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.0.1', rule)
64
+
65
+ expect(is_matching).to eq(true)
66
+ end
67
+ end
68
+
69
+ describe 'with IP "90.88.0.0" and "90.88.0.0"' do
70
+ it 'should return true' do
71
+ rule = {
72
+ 'type' => 0,
73
+ 'ip' => '90.88.0.0',
74
+ }
75
+
76
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.0.0', rule)
77
+
78
+ expect(is_matching).to eq(true)
79
+ end
80
+ end
81
+
82
+ describe 'with IP "127.0.0.1" and "::1"' do
83
+ it 'should return true' do
84
+ rule = {
85
+ 'type' => 0,
86
+ 'ip' => '127.0.0.1',
87
+ }
88
+
89
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('::1', rule)
90
+
91
+ expect(is_matching).to eq(true)
92
+ end
93
+ end
94
+
95
+ describe 'with range "90.88.0.0 - 90.88.255.255' do
96
+ rule = {
97
+ 'type' => 1,
98
+ 'ip_minimum' => '90.88.0.0',
99
+ 'ip_maximum' => '90.88.255.255',
100
+ }
101
+
102
+ describe 'with IP "90.89.0.1"' do
103
+ it 'should return false' do
104
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('90.89.0.1', rule)
105
+
106
+ expect(is_matching).to eq(false)
107
+ end
108
+ end
109
+
110
+ describe 'with IP "::ffff:90.89.0.1"' do
111
+ it 'should return false' do
112
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('::ffff:90.89.0.1', rule)
113
+
114
+ expect(is_matching).to eq(false)
115
+ end
116
+ end
117
+
118
+ describe 'with IP "90.88.118.79"' do
119
+ it 'should return false' do
120
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.118.79', rule)
121
+
122
+ expect(is_matching).to eq(true)
123
+ end
124
+ end
125
+ end
126
+
127
+ describe 'with range "90.88.0.1 - 90.88.255.255" and IP "90.88.118.79"' do
128
+ it 'should return true' do
129
+ rule = {
130
+ 'type' => 1,
131
+ 'ip_minimum' => '90.88.0.1',
132
+ 'ip_maximum' => '90.88.255.255',
133
+ }
134
+
135
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.118.79', rule)
136
+
137
+ expect(is_matching).to eq(true)
138
+ end
139
+ end
140
+
141
+ describe 'with range "90.88.0.1 - 90.88.254.254" and IP "90.88.118.79"' do
142
+ it 'should return true' do
143
+ rule = {
144
+ 'type' => 1,
145
+ 'ip_minimum' => '90.88.0.1',
146
+ 'ip_maximum' => '90.88.254.254',
147
+ }
148
+
149
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.118.79', rule)
150
+
151
+ expect(is_matching).to eq(true)
152
+ end
153
+ end
154
+
155
+ describe 'with subnet "90.88.0.0/24"' do
156
+ rule = {
157
+ 'type' => 2,
158
+ 'range' => '90.88.0.0/24',
159
+ }
160
+
161
+ describe 'with IP "90.88.0.1"' do
162
+ it 'should return true' do
163
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.0.1', rule)
164
+
165
+ expect(is_matching).to eq(true)
166
+ end
167
+ end
168
+
169
+ describe 'with IP "90.88.0.0"' do
170
+ it 'should return true' do
171
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.0.0', rule)
172
+
173
+ expect(is_matching).to eq(true)
174
+ end
175
+ end
176
+
177
+ describe 'with IP "90.88.0.254"' do
178
+ it 'should return true' do
179
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.0.254', rule)
180
+
181
+ expect(is_matching).to eq(true)
182
+ end
183
+ end
184
+
185
+ describe 'with IP "90.88.1.1"' do
186
+ it 'should return true' do
187
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('90.88.1.1', rule)
188
+
189
+ expect(is_matching).to eq(false)
190
+ end
191
+ end
192
+
193
+ describe 'with IP "::1"' do
194
+ it 'should return true' do
195
+ is_matching = IpWhitelistChecker.is_ip_matches_rule('::1', rule)
196
+
197
+ expect(is_matching).to eq(false)
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end