blacklight_advanced_search 6.0.2 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/.rubocop.yml +15 -0
  4. data/.rubocop_todo.yml +351 -0
  5. data/.solr_wrapper.yml +5 -0
  6. data/.travis.yml +4 -7
  7. data/Gemfile +18 -11
  8. data/Rakefile +24 -34
  9. data/VERSION +1 -1
  10. data/app/controllers/advanced_controller.rb +5 -7
  11. data/app/controllers/blacklight_advanced_search/advanced_controller.rb +5 -8
  12. data/app/helpers/advanced_helper.rb +4 -6
  13. data/blacklight_advanced_search.gemspec +11 -8
  14. data/lib/blacklight_advanced_search.rb +29 -34
  15. data/lib/blacklight_advanced_search/advanced_query_parser.rb +12 -13
  16. data/lib/blacklight_advanced_search/advanced_search_builder.rb +28 -32
  17. data/lib/blacklight_advanced_search/catalog_helper_override.rb +11 -34
  18. data/lib/blacklight_advanced_search/controller.rb +1 -1
  19. data/lib/blacklight_advanced_search/filter_parser.rb +7 -9
  20. data/lib/blacklight_advanced_search/parsing_nesting_parser.rb +5 -8
  21. data/lib/blacklight_advanced_search/redirect_legacy_params_filter.rb +23 -25
  22. data/lib/blacklight_advanced_search/render_constraints_override.rb +46 -33
  23. data/lib/blacklight_advanced_search/version.rb +0 -1
  24. data/lib/generators/blacklight_advanced_search/assets_generator.rb +4 -8
  25. data/lib/generators/blacklight_advanced_search/blacklight_advanced_search_generator.rb +0 -2
  26. data/lib/generators/blacklight_advanced_search/install_generator.rb +9 -5
  27. data/lib/generators/blacklight_advanced_search/templates/advanced_controller.rb +0 -2
  28. data/lib/parsing_nesting/grammar.rb +22 -25
  29. data/lib/parsing_nesting/tree.rb +156 -168
  30. data/solr/conf/_rest_managed.json +3 -0
  31. data/solr/conf/admin-extra.html +31 -0
  32. data/solr/conf/elevate.xml +36 -0
  33. data/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
  34. data/solr/conf/protwords.txt +21 -0
  35. data/solr/conf/schema.xml +635 -0
  36. data/solr/conf/scripts.conf +24 -0
  37. data/solr/conf/solrconfig.xml +411 -0
  38. data/solr/conf/spellings.txt +2 -0
  39. data/solr/conf/stopwords.txt +58 -0
  40. data/solr/conf/stopwords_en.txt +58 -0
  41. data/solr/conf/synonyms.txt +31 -0
  42. data/solr/conf/xslt/example.xsl +132 -0
  43. data/solr/conf/xslt/example_atom.xsl +67 -0
  44. data/solr/conf/xslt/example_rss.xsl +66 -0
  45. data/solr/conf/xslt/luke.xsl +337 -0
  46. data/solr/sample_solr_documents.yml +2692 -0
  47. data/spec/features/blacklight_advanced_search_form_spec.rb +0 -2
  48. data/spec/helpers/advanced_helper_spec.rb +0 -2
  49. data/spec/integration/blacklight_stub_spec.rb +0 -2
  50. data/spec/lib/advanced_search_builder_spec.rb +7 -14
  51. data/spec/lib/blacklight_advanced_search/render_constraints_override_spec.rb +39 -0
  52. data/spec/lib/deep_merge_spec.rb +109 -34
  53. data/spec/lib/filter_parser_spec.rb +8 -14
  54. data/spec/parsing_nesting/build_tree_spec.rb +73 -81
  55. data/spec/parsing_nesting/consuming_spec.rb +2 -12
  56. data/spec/parsing_nesting/to_solr_spec.rb +93 -130
  57. data/spec/spec_helper.rb +0 -3
  58. data/spec/test_app_templates/app/controllers/catalog_controller.rb +3 -3
  59. data/spec/test_app_templates/lib/generators/test_app_generator.rb +3 -3
  60. metadata +63 -13
  61. data/spec/spec.opts +0 -4
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe "Blacklight Advanced Search Form" do
4
2
  before(:all) do
5
3
  AdvancedController.copy_blacklight_config_from(CatalogController)
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe AdvancedHelper do
4
2
  describe '#advanced_search_facet_partial_name' do
5
3
  let(:field) { double(name: "field_name") }
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe 'Blacklight Test Application' do
4
2
  it "should have a Blacklight module" do
5
3
  expect(Blacklight).to be_a_kind_of(Module)
@@ -1,12 +1,8 @@
1
- require 'spec_helper'
2
-
3
1
  describe BlacklightAdvancedSearch::AdvancedSearchBuilder do
4
-
5
2
  describe "#add_advanced_parse_q_to_solr" do
6
-
7
3
  let(:blacklight_config) do
8
4
  Blacklight::Configuration.new do |config|
9
- config.advanced_search = { }
5
+ config.advanced_search = {}
10
6
  config.add_search_field "all_fields"
11
7
  config.add_search_field "special_field" do |field|
12
8
  field.advanced_parse = false
@@ -19,7 +15,7 @@ describe BlacklightAdvancedSearch::AdvancedSearchBuilder do
19
15
  cattr_accessor :blacklight_config
20
16
  include Blacklight::SearchHelper
21
17
  include BlacklightAdvancedSearch::AdvancedSearchBuilder
22
- def initialize blacklight_config
18
+ def initialize(blacklight_config)
23
19
  self.blacklight_config = blacklight_config
24
20
  end
25
21
  end
@@ -30,20 +26,20 @@ describe BlacklightAdvancedSearch::AdvancedSearchBuilder do
30
26
  let(:solr_params) { {} }
31
27
 
32
28
  describe "a simple example" do
33
- let(:params) { double("params", params: {:q => "one two AND three OR four"} ) }
29
+ let(:params) { double("params", params: { :q => "one two AND three OR four" }) }
34
30
  before { allow(obj).to receive(:scope).and_return(params) }
35
31
  it "catches the query" do
36
- obj.add_advanced_parse_q_to_solr(solr_params)
32
+ obj.add_advanced_parse_q_to_solr(solr_params)
37
33
  expect(solr_params[:defType]).to eq("lucene")
38
34
  # We're not testing succesful parsing here, just that it's doing
39
- # something that looks like we expect with subqueries.
35
+ # something that looks like we expect with subqueries.
40
36
  expect(solr_params[:q]).to start_with("_query_:")
41
37
  end
42
38
  end
43
39
 
44
40
  describe "an unparseable example" do
45
41
  let(:unparseable_q) { "foo bar\'s AND" }
46
- let(:params) { double("params", params: {:q => unparseable_q} ) }
42
+ let(:params) { double("params", params: { :q => unparseable_q }) }
47
43
  before { allow(obj).to receive(:scope).and_return(params) }
48
44
  it "passes through" do
49
45
  obj.add_advanced_parse_q_to_solr(solr_params)
@@ -52,16 +48,13 @@ describe BlacklightAdvancedSearch::AdvancedSearchBuilder do
52
48
  end
53
49
 
54
50
  context "when advanced_parse is false" do
55
- let(:params) { double("params", params: { :search_field => "special_field", :q => "one two AND three OR four" } ) }
51
+ let(:params) { double("params", params: { :search_field => "special_field", :q => "one two AND three OR four" }) }
56
52
  before { allow(obj).to receive(:scope).and_return(params) }
57
53
  it "ignores fields" do
58
54
  obj.add_advanced_parse_q_to_solr(solr_params)
59
55
  expect(solr_params).not_to have_key(:q)
60
56
  end
61
57
  end
62
-
63
58
  end
64
-
65
59
  end
66
-
67
60
  end
@@ -0,0 +1,39 @@
1
+ describe BlacklightAdvancedSearch::RenderConstraintsOverride, type: :helper do
2
+ let(:blacklight_config) do
3
+ Blacklight::Configuration.new do |config|
4
+ config.add_facet_field 'type'
5
+ end
6
+ end
7
+
8
+ let(:advanced_query) do
9
+ BlacklightAdvancedSearch::QueryParser.new(params, blacklight_config)
10
+ end
11
+
12
+ describe "#render_constraints_filters" do
13
+ before do
14
+ allow(helper).to receive(:blacklight_config).and_return(blacklight_config)
15
+ allow(helper).to receive(:advanced_query).and_return(advanced_query)
16
+ allow(helper).to receive(:search_action_path) do |*args|
17
+ search_catalog_path(*args)
18
+ end
19
+ end
20
+
21
+ subject(:rendered) { helper.render_constraints_filters({}) }
22
+
23
+ context 'with an array of facet params' do
24
+ let(:params) { ActionController::Parameters.new f_inclusive: { 'type' => ['a'] } }
25
+
26
+ it "renders nothing" do
27
+ expect(rendered).to have_text 'Remove constraint Type: a'
28
+ end
29
+ end
30
+
31
+ context 'with scalar facet limit params' do
32
+ let(:params) { ActionController::Parameters.new f_inclusive: { 'type' => 'a' } }
33
+
34
+ it "renders the scalar value" do
35
+ expect(rendered).to have_text 'Remove constraint Type: a'
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,45 +1,120 @@
1
- require 'spec_helper'
2
-
3
- describe "BlacklightAdvancedSearch#deep_merge!" do
4
- before do
5
- @ahash = {"a" => "a", "b" => "b",
6
- "array1" => [1,2], "array2" => [3,4],
7
- "hash1" => {"a" => "a", "array" => [1], "b" => "b"},
8
- "hash2" => {"a2" => "a2", "array2" => [12], "b2" => "b2"}
1
+ describe 'BlacklightAdvancedSearch#deep_merge' do
2
+ let(:hash_X) do
3
+ {
4
+ 'a' => 'a',
5
+ 'b' => 'b',
6
+ 'array1' => [1, 2],
7
+ 'array2' => [3, 4],
8
+ 'hash1' => { 'a' => 'a', 'array' => [1], 'b' => 'b' },
9
+ 'hash2' => { 'a2' => 'a2', 'array2' => [12], 'b2' => 'b2' }
10
+ }
11
+ end
12
+ let(:hash_Y) do
13
+ {
14
+ 'a' => 'NEW A',
15
+ 'c' => 'NEW C',
16
+ 'array1' => [3, 4],
17
+ 'hash1' => { 'array' => [2], 'b' => 'NEW B' }
9
18
  }
10
-
11
- BlacklightAdvancedSearch.deep_merge!(@ahash, {
12
- "a" => "NEW A",
13
- "array1" => [3, 4],
14
- "hash1" => {
15
- "array" => [2],
16
- "b" => "NEW B"
17
- },
18
- "c" => "NEW C"
19
- })
20
19
  end
20
+ let(:ahash) do
21
+ BlacklightAdvancedSearch.deep_merge(hash_x, hash_y)
22
+ end
23
+
24
+ RSpec.shared_examples 'Mergable Parameters' do # this name referenced below
25
+ it 'does not modify the param hashes' do
26
+ dup_x = hash_x.dup
27
+ dup_y = hash_y.dup
28
+ expect(ahash).not_to eq hash_x # this was the old behavior
29
+ expect(dup_x).to eq hash_x
30
+ expect(dup_y).to eq hash_y
31
+ end
32
+
33
+ it 'leaves un-collided content alone' do
34
+ expect(ahash['b']).to eq('b')
35
+ expect(ahash['array2']).to eq([3, 4])
36
+ expect(ahash['hash2']).to eq('a2' => 'a2', 'array2' => [12], 'b2' => 'b2')
37
+ end
38
+
39
+ it 'adds new content' do
40
+ expect(ahash['c']).to eq('NEW C')
41
+ end
42
+
43
+ it 'merges a hash, recursive like' do
44
+ expect(ahash['hash1']).to eq('a' => 'a', 'array' => [1, 2], 'b' => 'NEW B')
45
+ end
46
+
47
+ it 'merges boolean values (false)' do
48
+ expect(BlacklightAdvancedSearch.deep_merge({ a: false }, a: true)).to eq(a: true)
49
+ expect(BlacklightAdvancedSearch.deep_merge({ a: true }, a: false)).to eq(a: false)
50
+ end
21
51
 
52
+ it 'does not merge nil values over existing keys' do
53
+ expect(BlacklightAdvancedSearch.deep_merge({ a: 1 }, a: nil)).to eq(a: 1)
54
+ end
22
55
 
23
- it "leaves un-collided content alone" do
24
- expect(@ahash["b"]).to eq("b")
25
- expect(@ahash["array2"]).to eq([3,4])
26
- expect(@ahash["hash2"]).to eq({"a2" => "a2", "array2" => [12], "b2" => "b2"})
56
+ it 'does merge nil values when the key is not yet present' do
57
+ expect(BlacklightAdvancedSearch.deep_merge({}, a: nil)).to eq(a: nil)
58
+ end
59
+
60
+ it 'does not merge empty strings over existing keys' do
61
+ expect(BlacklightAdvancedSearch.deep_merge({ a: 1 }, a: '')).to eq(a: 1)
62
+ expect(BlacklightAdvancedSearch.deep_merge({ a: nil }, a: '')).to eq(a: nil)
63
+ end
64
+
65
+ it 'does not merge empty strings when the key is not yet present' do
66
+ expect(BlacklightAdvancedSearch.deep_merge({}, a: '')).to eq(a: '')
67
+ end
68
+
69
+ context 'Arrays' do
70
+ it 'merges an array' do
71
+ expect(ahash['array1']).to eq([1, 2, 3, 4])
72
+ end
73
+
74
+ it 'collapse to uniq values when merging' do
75
+ expect(BlacklightAdvancedSearch.deep_merge({ a: [1, 1, 2, 1] }, a: [3, 2])).to eq(a: [1, 2, 3])
76
+ end
77
+
78
+ it 'does not collapse to uniq values if not merging' do
79
+ expect(BlacklightAdvancedSearch.deep_merge({ a: [1, 1, 2, 1] }, a: [])).to eq(a: [1, 1, 2, 1])
80
+ end
81
+ end
82
+ end
83
+
84
+ describe Hash do
85
+ it_behaves_like 'Mergable Parameters' do
86
+ let(:hash_x) { hash_X }
87
+ let(:hash_y) { hash_Y }
88
+ end
27
89
  end
28
90
 
29
- it "adds new content" do
30
- expect(@ahash["c"]).to eq("NEW C")
91
+ describe HashWithIndifferentAccess do
92
+ it_behaves_like 'Mergable Parameters' do
93
+ let(:hash_x) { hash_X.with_indifferent_access }
94
+ let(:hash_y) { hash_Y.with_indifferent_access }
95
+ end
31
96
  end
32
97
 
33
- it "merges an array" do
34
- expect(@ahash["array1"]).to eq([1,2,3,4])
98
+ describe 'Mixed Hash and HWIA' do
99
+ it_behaves_like 'Mergable Parameters' do
100
+ let(:hash_x) { hash_X }
101
+ let(:hash_y) { hash_Y.with_indifferent_access }
102
+ end
103
+
104
+ it_behaves_like 'Mergable Parameters' do
105
+ let(:hash_x) { hash_X.with_indifferent_access }
106
+ let(:hash_y) { hash_Y }
107
+ end
35
108
  end
36
109
 
37
- it "merges a hash, recursive like" do
38
- expect(@ahash["hash1"]).to eq({
39
- "a" => "a",
40
- "array" => [1,2],
41
- "b" => "NEW B"
42
- })
110
+ # from http://apidock.com/rails/v4.2.1/Hash/deep_merge
111
+ describe 'reference example' do
112
+ it 'gives the same result as Rails Hash .deep_merge' do
113
+ h1 = { a: true, b: { c: [1, 2, 3] } }
114
+ h2 = { a: false, b: { x: [3, 4, 5] } }
115
+ merged = { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
116
+ expect(h1.deep_merge(h2)).to eq(merged)
117
+ expect(BlacklightAdvancedSearch.deep_merge(h1, h2)).to eq(merged)
118
+ end
43
119
  end
44
-
45
- end
120
+ end
@@ -1,28 +1,22 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
-
3
1
  def setFilters(f)
4
2
  @filters = f
5
3
  end
6
4
 
5
+ ## These should be reworked, but attr_reader actually breaks it.
6
+ # rubocop:disable Style/TrivialAccessors
7
7
  def filters
8
8
  @filters
9
9
  end
10
10
 
11
-
12
11
  describe "BlacklightAdvancedSearch::FilterParser" do
13
12
  include BlacklightAdvancedSearch::FilterParser
14
-
13
+
15
14
  describe "filter processing" do
16
15
  it "should generate an appropriate fq param" do
17
- setFilters(:format => ["Book", "Thesis"], :location=>["Online", "Library"])
18
-
16
+ setFilters(:format => %w(Book Thesis), :location => %w(Online Library))
19
17
  fq_params = generate_solr_fq
20
-
21
- expect(fq_params.find {|a| a =~ /format\:\((\"Book\"|\"Thesis\") +OR +(\"Thesis\"|\"Book\")/}).not_to be_nil
22
-
23
- expect(fq_params.find {|a| a =~ /location\:\((\"Library\"|\"Online\") +OR +(\"Library\"|\"Online\")/}).not_to be_nil
24
-
25
-
26
- end
18
+ expect(fq_params.find { |a| a =~ /format\:\((\"Book\"|\"Thesis\") +OR +(\"Thesis\"|\"Book\")/ }).not_to be_nil
19
+ expect(fq_params.find { |a| a =~ /location\:\((\"Library\"|\"Online\") +OR +(\"Library\"|\"Online\")/ }).not_to be_nil
20
+ end
27
21
  end
28
- end
22
+ end
@@ -1,58 +1,57 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
-
3
1
  require 'parsing_nesting/grammar'
4
2
  require 'parsing_nesting/tree'
5
3
 
6
-
7
4
  module ParseTreeSpecHelper
8
5
  include ParsingNesting::Tree
9
-
6
+
10
7
  def parse(s)
11
8
  ParsingNesting::Tree.parse(s)
12
9
  end
13
-
14
- # for things expected to be a one-element list,
10
+
11
+ # for things expected to be a one-element list,
15
12
  # make sure they are and return the element
16
13
  def parse_one_element(s)
17
14
  l = parse(s)
18
- expect(l).to be_kind_of( List )
15
+ expect(l).to be_kind_of(List)
19
16
  expect(l.list.length).to eq(1)
20
- return l.list.first
17
+ l.list.first
21
18
  end
22
-
19
+
23
20
  def should_be_and_list(graph)
24
- expect(graph).to be_kind_of( AndList )
21
+ expect(graph).to be_kind_of(AndList)
25
22
  yield graph.list if block_given?
26
23
  end
27
-
24
+
28
25
  def should_be_list(graph)
29
- expect(graph).to be_kind_of( List)
26
+ expect(graph).to be_kind_of(List)
30
27
  yield graph.list if block_given?
31
28
  end
32
-
29
+
33
30
  def should_be_or_list(graph)
34
- expect(graph).to be_kind_of( OrList )
31
+ expect(graph).to be_kind_of(OrList)
35
32
  yield graph.list if block_given?
36
33
  end
37
-
34
+
38
35
  def should_be_term(graph, value)
39
- expect(graph).to be_kind_of( Term )
36
+ expect(graph).to be_kind_of(Term)
40
37
  expect(graph.value).to eq(value)
41
38
  end
42
-
39
+
43
40
  def should_be_phrase(graph, value)
44
- expect(graph).to be_kind_of( Phrase )
41
+ expect(graph).to be_kind_of(Phrase)
45
42
  expect(graph.value).to eq(value)
46
43
  end
47
-
44
+
48
45
  def should_be_mandatory(graph)
49
46
  expect(graph).to be_kind_of(MandatoryClause)
50
47
  yield graph.operand if block_given?
51
48
  end
49
+
52
50
  def should_be_excluded(graph)
53
51
  expect(graph).to be_kind_of(ExcludedClause)
54
52
  yield graph.operand if block_given?
55
53
  end
54
+
56
55
  def should_be_not_expression(graph)
57
56
  expect(graph).to be_kind_of(NotExpression)
58
57
  yield graph.operand if block_given?
@@ -60,38 +59,37 @@ module ParseTreeSpecHelper
60
59
  end
61
60
 
62
61
  describe "NestingParser" do
63
- describe "Building an Object parse tree" do
62
+ describe "Building an Object parse tree" do
64
63
  include ParseTreeSpecHelper
65
-
66
-
64
+
67
65
  it "should build for term list" do
68
- should_be_list parse("one two three") do |list|
66
+ should_be_list parse("one two three") do |list|
69
67
  expect(list.length).to eq(3)
70
68
  should_be_term list[0], "one"
71
69
  should_be_term list[1], "two"
72
- should_be_term list[2], "three"
73
- end
70
+ should_be_term list[2], "three"
71
+ end
74
72
  end
75
-
73
+
76
74
  it "should build AND list" do
77
75
  should_be_and_list parse_one_element("one AND two AND three") do |list|
78
76
  expect(list.length).to eq(3)
79
-
77
+
80
78
  should_be_term list[0], "one"
81
79
  should_be_term list[1], "two"
82
- should_be_term list[2], "three"
80
+ should_be_term list[2], "three"
83
81
  end
84
82
  end
85
-
83
+
86
84
  it "should build OR list" do
87
- should_be_or_list parse_one_element("one OR two OR three") do |list|
85
+ should_be_or_list parse_one_element("one OR two OR three") do |list|
88
86
  expect(list.length).to eq(3)
89
87
  should_be_term list[0], "one"
90
88
  should_be_term list[1], "two"
91
- should_be_term list[2], "three"
92
- end
89
+ should_be_term list[2], "three"
90
+ end
93
91
  end
94
-
92
+
95
93
  it "allows AND list of lists" do
96
94
  should_be_and_list parse_one_element('(one two) AND (blue yellow)') do |and_list|
97
95
  expect(and_list.length).to eq(2)
@@ -100,125 +98,123 @@ describe "NestingParser" do
100
98
  should_be_term(list[1], "two")
101
99
  end
102
100
  should_be_list and_list[1]
103
- end
101
+ end
104
102
  end
105
-
103
+
106
104
  it "should build for mandatory and excluded" do
107
105
  should_be_list parse("+one -two") do |list|
108
106
  expect(list.length).to eq(2)
109
-
107
+
110
108
  should_be_mandatory list[0] do |operand|
111
109
  should_be_term(operand, "one")
112
110
  end
113
-
111
+
114
112
  should_be_excluded list[1] do |operand|
115
113
  should_be_term(operand, "two")
116
114
  end
117
- end
115
+ end
118
116
  end
119
-
117
+
120
118
  it "should build phrases" do
121
119
  should_be_list parse('"quick brown" +"jumps over" -"lazy dog"') do |list|
122
120
  expect(list.length).to eq(3)
123
-
121
+
124
122
  should_be_phrase(list[0], "quick brown")
125
-
123
+
126
124
  should_be_mandatory(list[1]) do |operand|
127
125
  should_be_phrase(operand, "jumps over")
128
- end
126
+ end
129
127
  end
130
128
  end
131
-
129
+
132
130
  it "should leave phrase literals literal, including weird chars" do
133
- phrase_content = "foo+bar -i: '(baz"
134
- should_be_phrase parse_one_element("\"#{phrase_content}\""), phrase_content
131
+ phrase_content = "foo+bar -i: '(baz"
132
+ should_be_phrase parse_one_element("\"#{phrase_content}\""), phrase_content
135
133
  end
136
-
134
+
137
135
  it "should build for NOT on term" do
138
136
  should_be_list parse("one two three NOT four") do |list|
139
137
  should_be_not_expression list[3] do |operand|
140
138
  should_be_term(operand, "four")
141
139
  end
142
- end
140
+ end
143
141
  end
144
-
142
+
145
143
  it "should build for NOT on phrase" do
146
144
  should_be_list parse('one two three NOT "quick brown"') do |list|
147
145
  should_be_not_expression list[3] do |operand|
148
146
  should_be_phrase(operand, "quick brown")
149
147
  end
150
- end
148
+ end
151
149
  end
152
-
150
+
153
151
  it "should build NOT on expression" do
154
152
  should_be_list parse('one two NOT (blue OR yellow)') do |list|
155
153
  should_be_not_expression list[2] do |operand|
156
154
  should_be_or_list(operand)
157
155
  end
158
- end
156
+ end
159
157
  end
160
-
158
+
161
159
  it "should build NOT preceded by binary op" do
162
160
  should_be_or_list parse_one_element('one OR NOT two') do |list|
163
161
  should_be_not_expression list[1] do |operand|
164
162
  should_be_term(operand, "two")
165
163
  end
166
- end
164
+ end
167
165
  end
168
-
169
-
166
+
170
167
  it "should bind OR more tightly than AND" do
171
- should_be_and_list parse_one_element("grey AND big OR small AND tail") do |list|
168
+ should_be_and_list parse_one_element("grey AND big OR small AND tail") do |list|
172
169
  expect(list.length).to eq(3)
173
-
170
+
174
171
  should_be_term list[0], "grey"
175
-
172
+
176
173
  should_be_or_list list[1] do |or_list|
177
- expect(or_list.length).to eq(2)
178
- should_be_term or_list[0], "big"
179
- should_be_term or_list[1], "small"
174
+ expect(or_list.length).to eq(2)
175
+ should_be_term or_list[0], "big"
176
+ should_be_term or_list[1], "small"
180
177
  end
181
-
178
+
182
179
  should_be_term list[2], "tail"
183
- end
180
+ end
184
181
  end
185
-
186
- it "should parse AND'd lists" do
187
- should_be_and_list parse_one_element("(foo bar one AND two) AND (three four ten OR twelve)") do |list|
188
- expect(list.length).to eq(2)
189
-
182
+
183
+ it "should parse AND'd lists" do
184
+ should_be_and_list parse_one_element("(foo bar one AND two) AND (three four ten OR twelve)") do |list|
185
+ expect(list.length).to eq(2)
186
+
190
187
  should_be_list(list[0]) do |first_half|
191
188
  expect(first_half[0].value).to eq('foo')
192
189
  expect(first_half[1].value).to eq("bar")
193
- should_be_and_list(first_half[2])
190
+ should_be_and_list(first_half[2])
194
191
  end
195
-
192
+
196
193
  should_be_list(list[1]) do |second_half|
197
194
  expect(second_half[0].value).to eq("three")
198
195
  expect(second_half[1].value).to eq("four")
199
- should_be_or_list second_half[2]
196
+ should_be_or_list second_half[2]
200
197
  end
201
198
  end
202
199
  end
203
-
200
+
204
201
  it "should build for a crazy complicated one" do
205
202
  should_be_list parse("mark +twain AND huck OR fun OR ((jim AND river) AND (red -dogs))") do |list|
206
203
  should_be_term list[0], "mark"
207
204
  should_be_and_list list[1] do |and_list|
208
-
209
205
  should_be_mandatory and_list[0] do |operand|
210
206
  should_be_term operand, "twain"
211
207
  end
212
-
208
+
213
209
  should_be_or_list and_list[1] do |or_list|
214
210
  should_be_term or_list[0], "huck"
215
211
  should_be_term or_list[1], "fun"
216
-
212
+
217
213
  should_be_and_list or_list[2] do |and_list|
218
214
  expect(and_list.length).to eq(2)
219
-
215
+
220
216
  should_be_and_list and_list[0]
221
-
217
+
222
218
  should_be_list and_list[1] do |terms|
223
219
  should_be_term terms[0], "red"
224
220
  should_be_excluded terms[1] do |operand|
@@ -226,13 +222,9 @@ describe "NestingParser" do
226
222
  end
227
223
  end
228
224
  end
229
-
230
225
  end
231
226
  end
232
227
  end
233
228
  end
234
-
235
229
  end
236
230
  end
237
-
238
-