glasses 1.6.2 → 1.7.0
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/lib/glasses.rb +254 -10
- data/lib/glasses/version.rb +1 -1
- data/spec/dummy/app/controllers/search_controller.rb +29 -17
- data/spec/dummy/app/views/search/full_raw_search_range.html.erb +0 -0
- data/spec/dummy/app/views/search/full_search.html.erb +0 -0
- data/spec/dummy/app/views/search/full_search_range.html.erb +0 -0
- data/spec/dummy/app/views/search/range_search.html.erb +30 -0
- data/spec/dummy/app/views/search/raw_full_search.html.erb +0 -0
- data/spec/dummy/app/views/search/raw_range_search.html.erb +25 -0
- data/spec/dummy/app/views/search/simple_search.html.erb +4 -2
- data/spec/dummy/config/routes.rb +3 -54
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/seeds.rb +2 -1
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +2628 -0
- data/spec/dummy/log/test.log +42280 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/-n4kyDOdRxiiiIJEFA9cId9azJmW5g6hmwbs8SJ4qRg.cache +1 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/2SBt5E86bhaTcl7TkcrIXPVQyQtH9yIRArRC_UxPck4.cache +1 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/2Tqd0MZWTPMTu8CoqlOCudnpF2UapAVb-1Qd3gZnzWs.cache +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/4m7rzZ6NLrCLYY8Klx2qByvjsF9EwTrhkqhffC_ddIU.cache +1 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/4wucpOHsDYdErjU4sC9i1FT33L-WRugEHtfQdiz-CXY.cache +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/AE40Tp96RkdOo7EhY00dhAOG17GUBn6QkZxp0HQVRQA.cache +2 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/CtIOdYL64ZUZ8_1ALDOZWNEis9WeBXUYTZ95MGCwJxk.cache +2 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/DMb_4zR5zBmQGRtZlXIrUCrkOrY-Wzw_ESjc3NoXX6s.cache +1 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/FfRbjoX7fHHQqnXiehqlD233T1kj4rzNPybfmQ_GUWI.cache +2 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/JlLKJj3SMeXmPLYJvdO955A6OPH9wSTWF3QFOvbaT0k.cache +2 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/Mo_r4nJu9qt0iEhVH0CXGZkIh_SCKfu3LoDU6GlMT-U.cache +2 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/PjzZwmbYJUPXBPEKfYAIld32mtAk3H0hBz7ONWVqza4.cache +2 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/QYBC6SiWic96YuGP27vORM8frM2yoCxYATSeAuu3q3s.cache +2 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/QfZ4TPv_vTZ6WmGKJEhbsZ0Ou73XHsnuUlsaYV3ZQEY.cache +1 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/XIp7H1NvI9qObEEUnVrJoJ0TgF9dsNRmdw7bkMLyf64.cache +1 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/aCkopDHgOZcXcLJcYI3sgc_SuAZhhr9RkRQshzmldF8.cache +1 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/bkZWDwb871tTLoM-W80twc_qhQ_ziPfInIfbzCcLnpE.cache +1 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/gLJlx0p_IOKb7r9m3hjLdN2jGSicQ_Ns4SS1jWlFDAQ.cache +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/i9TsnRfu6oqRsV9V2v_6Ulubst2IVveepQEkimUU6QE.cache +1 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/iEVE5Kzzv15cyQWfQGEbgnKSSO0xiblZzP-sO26AYGQ.cache +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/rRXYm5yDdh2lrn8etfERia5zGqWg3_cJ3siQQG6h9UU.cache +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/t3hd5M5Qs7xWqz8gFCvXf781-4lYaem1SZCLRh47qCc.cache +1 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/yHIJ2OseWB_qclWx7fwHLHPAVYOch64QqS8Y07WHhRk.cache +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/yuW5Zfj9wAku7kLsnPBHwLsetLDeWKm9ju_dm_GLgf0.cache +1 -0
- data/spec/features/full_search_form_test.rb +0 -0
- data/spec/features/range_search_form_test.rb +79 -0
- data/spec/features/search_performance_test_in_app.rb +0 -0
- data/spec/features/simple_search_form_test.rb +34 -9
- data/spec/glasses_spec.rb +8 -1
- data/spec/test_only_methods/example_only_methods.rb +65 -0
- data/spec/tests/full_search_test.rb +63 -0
- data/spec/tests/parameters_priority_test.rb +51 -0
- data/spec/tests/performance_test.rb +0 -0
- data/spec/tests/range_search_test.rb +43 -0
- data/spec/tests/sanitized_search_test.rb +19 -7
- data/spec/tests/search_test.rb +18 -8
- metadata +78 -4
- data/spec/scratches/example_only_methods.rb +0 -26
|
@@ -0,0 +1 @@
|
|
|
1
|
+
I"�file:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/stylesheets/application.css?type=text/css&pipeline=self&id=4da1c8ce87c7c652239d0e67030d4918f796d37e2f3bce447badc8d2f783aeb1:ET
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"%֧�NTZq�בH�L��#p3��Jg!��)
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
I"�file:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/stylesheets/application.css?type=text/css&id=6bde0bbabf49d0acbb323983a3903fa84ee1429caee35b736c506b4ad6bf53d4:ET
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"%L�m�u���cÀ�]e���m͏��
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
[o:Set:
|
|
2
|
+
@hash{I"environment-version:ETTI"environment-paths;TTI">processors:type=text/css&file_type=text/css&pipeline=self;TTI"vfile-digest:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/stylesheets/application.css;TTI"ffile-digest:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/stylesheets;TTI"qfile-digest:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/stylesheets/search.css;TT
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
[o:Set:
|
|
2
|
+
@hash{I"environment-version:ETTI"environment-paths;TTI"Lprocessors:type=application/javascript&file_type=application/javascript;TTI"ufile-digest:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/javascripts/application.js;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTI"pfile-digest:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/javascripts/search.js;TTI"ffile-digest:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/javascripts;TT
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
[o:Set:
|
|
2
|
+
@hash{I"environment-version:ETTI"environment-paths;TTI"Zprocessors:type=application/javascript&file_type=application/javascript&pipeline=self;TTI"ufile-digest:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/javascripts/application.js;TTI"ffile-digest:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/javascripts;TTI"pfile-digest:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/javascripts/search.js;TT
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
[o:Set:
|
|
2
|
+
@hash{I"environment-version:ETTI"environment-paths;TTI"0processors:type=text/css&file_type=text/css;TTI"vfile-digest:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/stylesheets/application.css;TTI">processors:type=text/css&file_type=text/css&pipeline=self;TTI"qfile-digest:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/stylesheets/search.css;TTI"ffile-digest:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/stylesheets;TT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
I"�file:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/javascripts/application.js?type=application/javascript&pipeline=self&id=7fde357b9eb6873868c89caa44207528dc578512439622fcfd9c3cebcb905cdc:ET
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
I"�file:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/javascripts/search.js?type=application/javascript&pipeline=self&id=fa727172541f6e7d9128e043a1734b40da3e3e7eb3909784614b21b100897cec:ET
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
I"�file:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/javascripts/application.js?type=application/javascript&id=994fc115aaf0b2f40165a45906d6c62bbfecf910708075a2d5d73e22d9ccfca5:ET
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"%�W\�yho9S���ƫ˥��)|�~���(���
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"%&P�꽠�9�/sB��k�b~LnJo��UJ��
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
I"�file:///Users/otamm/Documents/Code/Ruby/gems/glasses/gem/spec/dummy/app/assets/stylesheets/search.css?type=text/css&pipeline=self&id=5a9397f790a4eb98cae05e656658464b83abf79a64d5befc05bc166e496ab495:ET
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"%Ѱč@�����6H�uZoX�Z�gbh0W��V
|
|
File without changes
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
describe "search with a range constraint within web app", type: :feature do
|
|
2
|
+
|
|
3
|
+
context 'search with params sanitized by ActiveRecord' do
|
|
4
|
+
|
|
5
|
+
before :each do
|
|
6
|
+
visit 'range_search'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'returns all the results with a field bigger than or equal to some arbitrary value' do
|
|
10
|
+
fill_in 'Minimum Age:', with: '110'
|
|
11
|
+
click_button "Search"
|
|
12
|
+
page.should have_content 'GR8 SUCCESS'
|
|
13
|
+
page.should have_content '3'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'returns all the results with a field lesser than or equal to some arbitrary value' do
|
|
17
|
+
fill_in 'Maximum Age:', with: '110'
|
|
18
|
+
click_button "Search"
|
|
19
|
+
page.should have_content 'GR8 SUCCESS'
|
|
20
|
+
page.should have_content '8'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'returns all the results with a field bigger than or equal to some arbitrary value and with another field lesser than or equal to some other arbitrary value' do
|
|
24
|
+
fill_in 'Minimum Age:', with: '20'
|
|
25
|
+
fill_in 'Maximum Age:', with: '110'
|
|
26
|
+
click_button "Search"
|
|
27
|
+
page.should have_content 'GR8 SUCCESS'
|
|
28
|
+
page.should have_content '8'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'returns all the results which satisfies both "field in the range" and "field with same prefix" conditions' do
|
|
32
|
+
fill_in 'First Name:', with: 'Jane'
|
|
33
|
+
fill_in 'Minimum Age:', with: '110'
|
|
34
|
+
click_button "Search"
|
|
35
|
+
page.should have_content 'GR8 SUCCESS'
|
|
36
|
+
page.should have_content '1'
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context 'search without params sanitized by ActiveRecord' do
|
|
42
|
+
|
|
43
|
+
before :each do
|
|
44
|
+
visit 'raw_range_search'
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'returns all the results with a field bigger than or equal to some arbitrary value' do
|
|
48
|
+
fill_in 'Minimum Age:', with: '110'
|
|
49
|
+
click_button "Search"
|
|
50
|
+
page.should have_content 'GR8 SUCCESS'
|
|
51
|
+
page.should have_content '3'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'returns all the results with a field lesser than or equal to some arbitrary value' do
|
|
55
|
+
fill_in 'Maximum Age:', with: '110'
|
|
56
|
+
click_button "Search"
|
|
57
|
+
page.should have_content 'GR8 SUCCESS'
|
|
58
|
+
page.should have_content '8'
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'returns all the results with a field bigger than or equal to some arbitrary value and with another field lesser than or equal to some other arbitrary value' do
|
|
62
|
+
fill_in 'Minimum Age:', with: '20'
|
|
63
|
+
fill_in 'Maximum Age:', with: '110'
|
|
64
|
+
click_button "Search"
|
|
65
|
+
page.should have_content 'GR8 SUCCESS'
|
|
66
|
+
page.should have_content '8'
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'returns all the results which satisfies both "field in the range" and "field with same prefix" conditions' do
|
|
70
|
+
fill_in 'First Name:', with: 'Jane'
|
|
71
|
+
fill_in 'Minimum Age:', with: '110'
|
|
72
|
+
click_button "Search"
|
|
73
|
+
page.should have_content 'GR8 SUCCESS'
|
|
74
|
+
page.should have_content '1'
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
describe "
|
|
1
|
+
describe "search within web app", type: :feature do
|
|
2
2
|
|
|
3
|
-
context "search params
|
|
3
|
+
context "search params sanitized in ActiveRecord" do
|
|
4
4
|
|
|
5
5
|
before :each do
|
|
6
6
|
visit 'simple_search'
|
|
@@ -13,15 +13,40 @@ describe "a simple search", type: :feature do
|
|
|
13
13
|
page.should have_content '1'
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
it "is vulnerable to SQL injections when no defenses are present" do
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
end
|
|
16
|
+
#it "is vulnerable to SQL injections when no defenses are present" do
|
|
17
|
+
# fill_in "First Name:", with: "' OR 1 = 1 ) --"
|
|
18
|
+
# click_button "Search"
|
|
19
|
+
# page.should have_content "GR8 SUCCESS"
|
|
20
|
+
# page.should have_content "10 entries"
|
|
21
|
+
#end
|
|
22
|
+
|
|
23
|
+
#context "search with a boolean value as one of the params" do
|
|
24
|
+
|
|
25
|
+
it "correctly return values when a boolean value is passed to the form and there are matches" do
|
|
26
|
+
fill_in 'First Name:', with: 'Jane'
|
|
27
|
+
#all('input[type=checkbox]').each { |checkbox| check(checkbox) }
|
|
28
|
+
# forms checkboxes are checked "true" by default.
|
|
29
|
+
click_button 'Search'
|
|
30
|
+
page.should have_content 'GR8 SUCCESS'
|
|
31
|
+
page.should have_content '1'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "correctly return values when a boolean value is passed to the form and there are no matches" do
|
|
35
|
+
fill_in 'First Name:', with: 'Rachel'
|
|
36
|
+
#all('input[type=checkbox]').each { |checkbox| check(checkbox) }
|
|
37
|
+
# forms checkboxes are checked "true" by default.
|
|
38
|
+
click_button 'Search'
|
|
39
|
+
#puts page.body
|
|
40
|
+
page.should have_content 'WOPS'
|
|
41
|
+
page.should have_content '0'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
#end
|
|
22
45
|
|
|
23
46
|
end
|
|
24
47
|
|
|
48
|
+
=begin
|
|
49
|
+
commented out. This part has become redundant.
|
|
25
50
|
context "search params sanitized in a search method of this gem with built-in defense" do
|
|
26
51
|
|
|
27
52
|
before :each do
|
|
@@ -43,6 +68,7 @@ describe "a simple search", type: :feature do
|
|
|
43
68
|
end
|
|
44
69
|
|
|
45
70
|
end
|
|
71
|
+
=end
|
|
46
72
|
|
|
47
73
|
context "search params sanitized in a controller method" do
|
|
48
74
|
|
|
@@ -53,7 +79,6 @@ describe "a simple search", type: :feature do
|
|
|
53
79
|
it "correctly searches and displays matches" do
|
|
54
80
|
fill_in 'First Name:', with: 'Jan'
|
|
55
81
|
click_button "Search"
|
|
56
|
-
puts page.body
|
|
57
82
|
page.should have_content 'GR8 SUCCESS'
|
|
58
83
|
page.should have_content '1'
|
|
59
84
|
end
|
data/spec/glasses_spec.rb
CHANGED
|
@@ -2,5 +2,12 @@ require 'spec_helper'
|
|
|
2
2
|
#tests in a raw environment with a hash serving as input (the default ruby web app frameworks "params" hash is the emulated input)
|
|
3
3
|
require 'tests/search_test'
|
|
4
4
|
require 'tests/sanitized_search_test'
|
|
5
|
+
require 'tests/full_search_test'
|
|
6
|
+
require 'tests/range_search_test'
|
|
7
|
+
require 'tests/performance_test'
|
|
8
|
+
require 'tests/parameters_priority_test'
|
|
5
9
|
#tests in a simulated webpage environment using Capybara
|
|
6
|
-
require 'features/simple_search_form_test'
|
|
10
|
+
require 'features/simple_search_form_test'
|
|
11
|
+
require 'features/full_search_form_test'
|
|
12
|
+
require 'features/range_search_form_test'
|
|
13
|
+
require 'features/search_performance_test_in_app'
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module BrokenGlasses
|
|
2
|
+
def search_within_range(model_to_search,params_hash)
|
|
3
|
+
params_array = params_hash.to_a
|
|
4
|
+
query = ""
|
|
5
|
+
consecutive_ints = 0
|
|
6
|
+
params_array.each_with_index do |pair, index|
|
|
7
|
+
if !pair[1].empty?
|
|
8
|
+
if pair[0].to_s[key.size-3,key.size] == "_id" || pair[] ~= /\A[-+]?[0-9]+\z/ # checks if value is basically an integer within quotes
|
|
9
|
+
|
|
10
|
+
possible_query = "#{key} = #{val} AND "
|
|
11
|
+
consecutive_ints += 1
|
|
12
|
+
if consecutive_ints % 2 == 0 #check if the case is of an integer field followed by another
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
query += possible_query
|
|
16
|
+
else
|
|
17
|
+
query += "#{key} LIKE '#{val}%' AND " # percent sign matches any string of 0 or more chars.
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
if !query.empty?
|
|
22
|
+
query = query[0,query.size-5]
|
|
23
|
+
model_to_search.where(query)
|
|
24
|
+
else
|
|
25
|
+
[]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.full_search_range(model_to_search, params_hash)
|
|
30
|
+
query = []
|
|
31
|
+
query_params = []
|
|
32
|
+
params_hash.each do |key,val|
|
|
33
|
+
if !val.empty?
|
|
34
|
+
key_suffix = key.to_s[key.size-3,key.size]
|
|
35
|
+
if key_suffix == "min"
|
|
36
|
+
query.push("#{key[0,key.size-4]} >= ?")
|
|
37
|
+
query_params.push(val.to_s)
|
|
38
|
+
elsif key_suffix == "max"
|
|
39
|
+
query.push("#{key[0,key.size-4]} <= ?")
|
|
40
|
+
query_params.push(val.to_s)
|
|
41
|
+
elsif key_suffix == "_id"
|
|
42
|
+
query.push("#{key} = ?")
|
|
43
|
+
query_params.push(val.to_s)
|
|
44
|
+
else
|
|
45
|
+
query.push("#{key} LIKE ?") # percent sign matches any string of 0 or more chars.
|
|
46
|
+
query_params.push("%" + val + "%")
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
if !query.empty?
|
|
51
|
+
if query.size == 1
|
|
52
|
+
return model_to_search.where(query.pop(), query_params.pop())
|
|
53
|
+
else
|
|
54
|
+
results = model_to_search.where(query.pop(), query_params.pop())
|
|
55
|
+
(results.size).times do |search|
|
|
56
|
+
results = results.where(query.pop(), query_params.pop()) # important to note that ".where()" is not hitting the database on this line.
|
|
57
|
+
end
|
|
58
|
+
return results
|
|
59
|
+
end
|
|
60
|
+
else
|
|
61
|
+
[]
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
describe 'performs a full search on strings, looking for fragments of text instead of prefixes.' do
|
|
2
|
+
|
|
3
|
+
context 'performs a full search that is sanitized by ActiveRecord' do
|
|
4
|
+
|
|
5
|
+
it 'returns results which contain the fragment' do
|
|
6
|
+
(Glasses.full_search(Player, {first_name: "bb"}).size).should == 1
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'returns results which contain the fragment and other parameters' do
|
|
10
|
+
(Glasses.full_search(Player, {first_name: "bb", email: ".com"}).size).should == 1
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'does not return anything when no params match any text fragment for that column' do
|
|
14
|
+
(Glasses.full_search(Player, {first_name: "zidbb"}).size).should == 0
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'does not return anything when there is no record which matches all the params' do
|
|
18
|
+
(Glasses.full_search(Player, {first_name: "zidbb", email: "@"}).size).should == 0
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'returns all the results which satisfies both "field in the range" and "field with text fragment" conditions' do
|
|
22
|
+
(Glasses.full_search_range(Player, {first_name: 'ane', age_min: '110'}).size).should == 1
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context 'performs a full search which includes a range that is not sanitized by ActiveRecord' do
|
|
26
|
+
|
|
27
|
+
it 'returns all the results which satisfies both "field in the range" and "field with text fragment" conditions' do
|
|
28
|
+
(Glasses.full_search_range(Player, {first_name: 'ane', age_min: '110'}).size).should == 1
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context 'performs a full search that is not sanitized by ActiveRecord' do
|
|
36
|
+
|
|
37
|
+
it 'returns results which contain the fragment' do
|
|
38
|
+
(Glasses.full_raw_search(Player, {first_name: "bb"}).size).should == 1
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'returns results which contain the fragment and other parameters' do
|
|
42
|
+
(Glasses.full_raw_search(Player, {first_name: "bb", email: ".com"}).size).should == 1
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'does not return anything when no params match any text fragment for that column' do
|
|
46
|
+
(Glasses.full_raw_search(Player, {first_name: "zidbb"}).size).should == 0
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'does not return anything when there is no record which matches all the params' do
|
|
50
|
+
(Glasses.full_raw_search(Player, {first_name: "zidbb", email: "@"}).size).should == 0
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context 'performs a full search which includes a range that is not sanitized by ActiveRecord' do
|
|
54
|
+
|
|
55
|
+
it 'returns all the results which satisfies both "field in the range" and "field with text fragment" conditions' do
|
|
56
|
+
(Glasses.full_raw_search_range(Player, {first_name: 'ane', age_min: '110'}).size).should == 1
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
describe "search params are reordered in a way to give first entrance to quicker queries; the arrays will be .pop()ed, so 'prioritized' == 'last_element' here." do
|
|
2
|
+
|
|
3
|
+
context "params include strings and ints/bools" do
|
|
4
|
+
|
|
5
|
+
it "puts integers before strings" do
|
|
6
|
+
Glasses.prioritize_ints_over_strings(["user_id = ?","first_name LIKE ?", "last_name LIKE ?"], ["666", "Johnny", "Rotten"]).should == [["last_name LIKE ?", "first_name LIKE ?", "user_id = ?"],["Rotten", "Johnny", "666"]]
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "puts booleans before strings" do
|
|
10
|
+
Glasses.prioritize_ints_over_strings(["is_cokehead_bool = ?", "first_name LIKE ?", "last_name LIKE ?"], ["1", "Johnny", "Rotten"]).should == [["last_name LIKE ?", "first_name LIKE ?", "is_cokehead_bool = ?"],["Rotten", "Johnny", "1"]]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "puts both integers and booleans before strings" do
|
|
14
|
+
Glasses.prioritize_ints_over_strings(["user_id = ?", "is_cokehead_bool = ?", "first_name LIKE ?", "last_name LIKE ?"], ["666", "1", "Johnny", "Rotten"]).should == [["last_name LIKE ?", "first_name LIKE ?", "user_id = ?", "is_cokehead_bool = ?"],["Rotten", "Johnny", "666", "1"]]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "returns the same query with inverted params if it does not contain more than one kind of input (strings)" do
|
|
18
|
+
Glasses.prioritize_ints_over_strings(["first_name LIKE ?", "last_name LIKE ?"], ["Johnny", "Rotten"]).should == [["last_name LIKE ?", "first_name LIKE ?"], ["Rotten", "Johnny"]]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context "params include strings, ints/bools and ranges" do
|
|
24
|
+
|
|
25
|
+
it "puts integers before strings" do
|
|
26
|
+
Glasses.prioritize_ints_over_strings_and_ranges(["user_id = ?","first_name LIKE ?", "last_name LIKE ?"], ["666", "Johnny", "Rotten"]).should == [["last_name LIKE ?", "first_name LIKE ?", "user_id = ?"],["Rotten", "Johnny", "666"]]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "puts booleans before strings" do
|
|
30
|
+
Glasses.prioritize_ints_over_strings_and_ranges(["is_cokehead_bool = ?", "first_name LIKE ?", "last_name LIKE ?"], ["1", "Johnny", "Rotten"]).should == [["last_name LIKE ?", "first_name LIKE ?", "is_cokehead_bool = ?"],["Rotten", "Johnny", "1"]]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "puts both integers and booleans before strings" do
|
|
34
|
+
Glasses.prioritize_ints_over_strings_and_ranges(["user_id = ?", "is_cokehead_bool = ?", "first_name LIKE ?", "last_name LIKE ?"], ["666", "1", "Johnny", "Rotten"]).should == [["last_name LIKE ?", "first_name LIKE ?", "user_id = ?", "is_cokehead_bool = ?"],["Rotten", "Johnny", "666", "1"]]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "puts integers, booleans and ranges before strings" do
|
|
38
|
+
Glasses.prioritize_ints_over_strings_and_ranges(["user_id = ?", "is_cokehead_bool = ?", "age_min >= ?", "age_max <= ?", "first_name LIKE ?", "last_name LIKE ?"], ["666", "1", "2", "456", "Johnny", "Rotten"]).should == [["last_name LIKE ?", "first_name LIKE ?", "age_max <= ?", "age_min >= ?", "user_id = ?", "is_cokehead_bool = ?"],["Rotten", "Johnny", "456", "2", "666", "1"]]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "puts ints/booleans before ranges" do
|
|
42
|
+
Glasses.prioritize_ints_over_strings_and_ranges(["user_id = ?", "is_cokehead_bool = ?", "age_min >= ?", "age_max <= ?"], ["666", "1", "2", "456"]).should == [["age_max <= ?", "age_min >= ?", "user_id = ?", "is_cokehead_bool = ?"],["456", "2", "666", "1"]]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "returns the same query with inverted params if it does not contain more than one kind of input (strings)" do
|
|
46
|
+
Glasses.prioritize_ints_over_strings_and_ranges(["first_name LIKE ?", "last_name LIKE ?"], ["Johnny", "Rotten"]).should == [["last_name LIKE ?", "first_name LIKE ?"], ["Rotten", "Johnny"]]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
describe 'search entries which have a value within a specific range' do
|
|
2
|
+
|
|
3
|
+
context 'search with params sanitized by ActiveRecord' do
|
|
4
|
+
|
|
5
|
+
it 'returns all the results with a field bigger than or equal to some arbitrary value' do
|
|
6
|
+
(Glasses.search_range(Player, {age_min: '110'}).size).should == 3
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'returns all the results with a field lesser than or equal to some arbitrary value' do
|
|
10
|
+
(Glasses.search_range(Player, {age_max: '110'}).size).should == 8
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'returns all the results with a field bigger than or equal to some arbitrary value and with another field lesser than or equal to some other arbitrary value' do
|
|
14
|
+
(Glasses.search_range(Player, {age_min: '20', age_max: '110'}).size).should == 4
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'returns all the results which satisfies both "field in the range" and "field with same prefix" conditions' do
|
|
18
|
+
(Glasses.search_range(Player, {first_name: 'Jane', age_min: '110'}).size).should == 1
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context 'search without params sanitized by ActiveRecord' do
|
|
24
|
+
|
|
25
|
+
it 'returns all the results with a field bigger than or equal to some arbitrary value' do
|
|
26
|
+
(Glasses.raw_search_range(Player, {age_min: '110'}).size).should == 3
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'returns all the results with a field lesser than or equal to some arbitrary value' do
|
|
30
|
+
(Glasses.raw_search_range(Player, {age_max: '110'}).size).should == 8
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'returns all the results with a field bigger than or equal to some arbitrary value and with another field lesser than or equal to some other arbitrary value' do
|
|
34
|
+
(Glasses.raw_search_range(Player, {age_min: '20', age_max: '110'}).size).should == 4
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'returns all the results which satisfies both "field in the range" and "field with same prefix" conditions' do
|
|
38
|
+
(Glasses.raw_search_range(Player, {first_name: 'Jane', age_min: '110'}).size).should == 1
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|