esearch 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/.gitignore +5 -0
  2. data/.rspec +6 -0
  3. data/.travis.yml +19 -0
  4. data/Changelog.md +27 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.devtools +60 -0
  7. data/Guardfile +18 -0
  8. data/LICENSE +20 -0
  9. data/README.md +93 -0
  10. data/Rakefile +2 -0
  11. data/TODO +3 -0
  12. data/config/devtools.yml +2 -0
  13. data/config/flay.yml +3 -0
  14. data/config/flog.yml +3 -0
  15. data/config/mutant.yml +3 -0
  16. data/config/reek.yml +103 -0
  17. data/config/yardstick.yml +2 -0
  18. data/esearch.gemspec +26 -0
  19. data/lib/esearch.rb +43 -0
  20. data/lib/esearch/cluster.rb +85 -0
  21. data/lib/esearch/command.rb +158 -0
  22. data/lib/esearch/command/cluster.rb +28 -0
  23. data/lib/esearch/command/document.rb +111 -0
  24. data/lib/esearch/command/exist.rb +37 -0
  25. data/lib/esearch/command/index.rb +66 -0
  26. data/lib/esearch/command/search.rb +24 -0
  27. data/lib/esearch/command/status.rb +24 -0
  28. data/lib/esearch/connection.rb +36 -0
  29. data/lib/esearch/document.rb +53 -0
  30. data/lib/esearch/index.rb +61 -0
  31. data/lib/esearch/indices.rb +52 -0
  32. data/lib/esearch/mixin.rb +111 -0
  33. data/lib/esearch/presenter.rb +43 -0
  34. data/lib/esearch/presenter/aspect.rb +17 -0
  35. data/lib/esearch/presenter/aspect/range.rb +63 -0
  36. data/lib/esearch/presenter/aspect/term.rb +19 -0
  37. data/lib/esearch/presenter/cluster.rb +84 -0
  38. data/lib/esearch/presenter/document.rb +102 -0
  39. data/lib/esearch/presenter/facet.rb +72 -0
  40. data/lib/esearch/presenter/hit.rb +70 -0
  41. data/lib/esearch/presenter/hits.rb +60 -0
  42. data/lib/esearch/presenter/index.rb +23 -0
  43. data/lib/esearch/presenter/search.rb +32 -0
  44. data/lib/esearch/presenter/status.rb +18 -0
  45. data/lib/esearch/request.rb +90 -0
  46. data/lib/esearch/type.rb +40 -0
  47. data/spec/integration/esearch/spike_spec.rb +50 -0
  48. data/spec/spec_helper.rb +65 -0
  49. data/spec/support/example_group_methods.rb +7 -0
  50. data/spec/support/ice_nine_config.rb +6 -0
  51. data/spec/unit/esearch/cluster/class_methods/connect_spec.rb +16 -0
  52. data/spec/unit/esearch/cluster/health_spec.rb +10 -0
  53. data/spec/unit/esearch/cluster/index_spec.rb +11 -0
  54. data/spec/unit/esearch/cluster/indices_spec.rb +11 -0
  55. data/spec/unit/esearch/cluster/path_spec.rb +11 -0
  56. data/spec/unit/esearch/command/class_methods/run_spec.rb +16 -0
  57. data/spec/unit/esearch/command/cluster/health/run_spec.rb +14 -0
  58. data/spec/unit/esearch/command/document/delete/run_spec.rb +13 -0
  59. data/spec/unit/esearch/command/document/get/result_spec.rb +27 -0
  60. data/spec/unit/esearch/command/document/index/create/run_spec.rb +17 -0
  61. data/spec/unit/esearch/command/document/index/run_create_spec.rb +17 -0
  62. data/spec/unit/esearch/command/document/index/run_spec.rb +15 -0
  63. data/spec/unit/esearch/command/document/index/run_update_spec.rb +15 -0
  64. data/spec/unit/esearch/command/document/index/update/run_spec.rb +15 -0
  65. data/spec/unit/esearch/command/exist/result_spec.rb +39 -0
  66. data/spec/unit/esearch/command/index/create/run_spec.rb +14 -0
  67. data/spec/unit/esearch/command/index/delete/run_spec.rb +13 -0
  68. data/spec/unit/esearch/command/index/refresh/run_spec.rb +13 -0
  69. data/spec/unit/esearch/command/result_spec.rb +68 -0
  70. data/spec/unit/esearch/command/search/run_spec.rb +14 -0
  71. data/spec/unit/esearch/command/status/run_spec.rb +13 -0
  72. data/spec/unit/esearch/connection/class_methods/build_spec.rb +29 -0
  73. data/spec/unit/esearch/connection/run_spec.rb +36 -0
  74. data/spec/unit/esearch/document/connection_spec.rb +12 -0
  75. data/spec/unit/esearch/document/delete_spec.rb +12 -0
  76. data/spec/unit/esearch/document/get_spec.rb +12 -0
  77. data/spec/unit/esearch/index/create_spec.rb +12 -0
  78. data/spec/unit/esearch/index/delete_spec.rb +11 -0
  79. data/spec/unit/esearch/index/type_spec.rb +12 -0
  80. data/spec/unit/esearch/indices/all/path_spec.rb +12 -0
  81. data/spec/unit/esearch/mixin/document/index_create_spec.rb +31 -0
  82. data/spec/unit/esearch/mixin/document/index_spec.rb +31 -0
  83. data/spec/unit/esearch/mixin/document/index_update_spec.rb +31 -0
  84. data/spec/unit/esearch/mixin/exist/exist_predicate_spec.rb +16 -0
  85. data/spec/unit/esearch/mixin/index/refresh_spec.rb +16 -0
  86. data/spec/unit/esearch/mixin/index/status_spec.rb +16 -0
  87. data/spec/unit/esearch/mixin/search/search_spec.rb +18 -0
  88. data/spec/unit/esearch/presenter/aspect/range/from_spec.rb +24 -0
  89. data/spec/unit/esearch/presenter/aspect/range/to_spec.rb +24 -0
  90. data/spec/unit/esearch/presenter/class_methods/new_spec.rb +37 -0
  91. data/spec/unit/esearch/presenter/facet/build_spec.rb +26 -0
  92. data/spec/unit/esearch/presenter/facet/class_methods/build_spec.rb +26 -0
  93. data/spec/unit/esearch/presenter/hit/fields_spec.rb +24 -0
  94. data/spec/unit/esearch/presenter/hit/source_spec.rb +24 -0
  95. data/spec/unit/esearch/presenter/hits/each_spec.rb +15 -0
  96. data/spec/unit/esearch/presenter/hits/size_spec.rb +13 -0
  97. data/spec/unit/esearch/request/initialize_spec.rb +39 -0
  98. data/spec/unit/esearch/request/run_spec.rb +39 -0
  99. data/spec/unit/esearch/type/connection_spec.rb +15 -0
  100. data/spec/unit/esearch/type/document_spec.rb +12 -0
  101. metadata +330 -0
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Command::Document::Index::Create, '.run' do
4
+ subject { object.run(context, document, options) }
5
+
6
+ let(:object) { described_class }
7
+ let(:document) { mock('Document') }
8
+ let(:options) { { :foo => :bar } }
9
+
10
+ let(:expected_request) do
11
+ Esearch::Request.new(:post, '/foo', document, { :foo => :bar, :op_type => :create })
12
+ end
13
+
14
+ expect_presenter(Esearch::Presenter::Document::Operation::Index) do
15
+ let(:status) { 201 }
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Command::Document::Index, '.run' do
4
+ subject { object.run(context, document, options) }
5
+
6
+ let(:object) { described_class }
7
+ let(:document) { mock('Document') }
8
+ let(:options) { { :foo => :bar } }
9
+
10
+ let(:expected_request) do
11
+ Esearch::Request.new(:post, '/foo', document, options)
12
+ end
13
+
14
+ expect_presenter(Esearch::Presenter::Document::Operation::Index)
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Command::Document::Index::Update, '.run' do
4
+ subject { object.run(context, document, options) }
5
+
6
+ let(:object) { described_class }
7
+ let(:document) { mock('Document') }
8
+ let(:options) { { :foo => :bar } }
9
+
10
+ let(:expected_request) do
11
+ Esearch::Request.new(:post, '/foo', document, { :foo => :bar, :op_type => :index })
12
+ end
13
+
14
+ expect_presenter(Esearch::Presenter::Document::Operation::Index)
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Command::Document::Index::Update, '.run' do
4
+ subject { object.run(context, document, options) }
5
+
6
+ let(:object) { described_class }
7
+ let(:document) { mock('Document') }
8
+ let(:options) { { :foo => :bar } }
9
+
10
+ let(:expected_request) do
11
+ Esearch::Request.new(:post, '/foo', document, { :foo => :bar, :op_type => :index })
12
+ end
13
+
14
+ expect_presenter(Esearch::Presenter::Document::Operation::Index)
15
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Command::Exist, '.run' do
4
+ subject { object.run(context) }
5
+
6
+ let(:object) { described_class }
7
+
8
+ let(:expected_request) do
9
+ Esearch::Request.new(:head, '/foo', {}, {})
10
+ end
11
+
12
+ before do
13
+ connection.should_receive(:run).with(expected_request).and_return(response)
14
+ end
15
+
16
+ let(:context) { mock('Context', :connection => connection, :path => Pathname.new('/foo')) }
17
+ let(:connection) { mock('Connection') }
18
+
19
+ let(:headers) { {'content-type' => 'application/json; charset=UTF-8'} }
20
+ let(:response) { mock('Response', :frozen? => true, :status => status, :headers => headers, :body => '{}') }
21
+
22
+ context 'with status 200' do
23
+ let(:status) { 200 }
24
+ it { should be(true) }
25
+ end
26
+
27
+ context 'with status 404' do
28
+ let(:status) { 404 }
29
+ it { should be(false) }
30
+ end
31
+
32
+ context 'with other status' do
33
+ let(:status) { 500 }
34
+
35
+ it 'should raise error' do
36
+ expect { subject }.to raise_error
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Command::Index::Create, '.run' do
4
+ subject { object.run(context, settings) }
5
+
6
+ let(:object) { described_class }
7
+ let(:settings) { mock('Settings') }
8
+
9
+ let(:expected_request) do
10
+ Esearch::Request.new(:put, '/foo', settings, {})
11
+ end
12
+
13
+ expect_presenter(Esearch::Presenter::Index::Create)
14
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Command::Index::Delete, '.run' do
4
+ subject { object.run(context) }
5
+
6
+ let(:object) { described_class }
7
+
8
+ let(:expected_request) do
9
+ Esearch::Request.new(:delete, '/foo', {}, {})
10
+ end
11
+
12
+ expect_presenter(Esearch::Presenter::Index::Delete)
13
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Command::Index::Refresh, '.run' do
4
+ subject { object.run(context) }
5
+
6
+ let(:object) { described_class }
7
+
8
+ let(:expected_request) do
9
+ Esearch::Request.new(:post, '/foo/_refresh', {}, {})
10
+ end
11
+
12
+ expect_presenter(Esearch::Presenter::Index::Refresh)
13
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Command, '#result' do
4
+ let(:object) { class_under_test.new(context) }
5
+
6
+ subject { object.result }
7
+
8
+ class DummyPresenter
9
+ include Concord.new(:raw)
10
+ end
11
+
12
+ let(:class_under_test) do
13
+ Class.new(described_class) do
14
+ const_set('PRESENTER', DummyPresenter)
15
+ def request
16
+ Esearch::Request.new(:get, context_path)
17
+ end
18
+ end
19
+ end
20
+
21
+
22
+ let(:context) { mock('Context', :connection => connection, :path => Pathname.new('/foo')) }
23
+ let(:connection) { mock('Connection') }
24
+
25
+ let(:headers) { {'content-type' => content_type } }
26
+ let(:content_type) { 'application/json; charset=UTF-8' }
27
+ let(:response) { mock('Response', :frozen? => true, :status => status, :headers => headers, :body => body) }
28
+ let(:body) { '{}' }
29
+
30
+ let(:status) { 200 }
31
+
32
+ let(:expected_request) do
33
+ Esearch::Request.new(:get, context.path)
34
+ end
35
+
36
+ before do
37
+ connection.should_receive(:run).with(expected_request).and_return(response)
38
+ end
39
+
40
+ it { should eql(DummyPresenter.new({})) }
41
+
42
+ context 'when content type is not expected' do
43
+ let(:content_type) { 'text/plain' }
44
+
45
+ it 'should raise error' do
46
+ expect { subject }.to raise_error(Esearch::ProtocolError, 'Expected json content type, but got: "text/plain"')
47
+ end
48
+ end
49
+
50
+ context 'when status code is not expected' do
51
+ let(:status) { 201 }
52
+
53
+ context 'with json body' do
54
+ it 'should raise error' do
55
+ expect { subject }.to raise_error(Esearch::ProtocolError, 'expected response stati: [200] but got: 201, remote message: {}')
56
+ end
57
+ end
58
+
59
+ context 'with other body' do
60
+ let(:content_type) { 'text/plain' }
61
+ let(:body) { 'message' }
62
+
63
+ it 'should raise error' do
64
+ expect { subject }.to raise_error(Esearch::ProtocolError, 'expected response stati: [200] but got: 201, remote message: "message"')
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Command::Search, '.run' do
4
+ subject { object.run(context, query) }
5
+
6
+ let(:object) { described_class }
7
+ let(:query) { mock('Query') }
8
+
9
+ let(:expected_request) do
10
+ Esearch::Request.new(:get, '/foo/_search', query, {})
11
+ end
12
+
13
+ expect_presenter(Esearch::Presenter::Search)
14
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Command::Status, '.run' do
4
+ subject { object.run(context) }
5
+
6
+ let(:object) { described_class }
7
+
8
+ let(:expected_request) do
9
+ Esearch::Request.new(:get, '/foo/_status', {}, {})
10
+ end
11
+
12
+ expect_presenter(Esearch::Presenter::Status)
13
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Connection, '.build' do
4
+ let(:object) { described_class }
5
+
6
+ subject { object.build(*arguments) }
7
+
8
+ let(:url) { mock('URL') }
9
+ let(:logger) { mock('Logger') }
10
+ let(:connection) { mock('Connection') }
11
+
12
+ before do
13
+ Faraday.should_receive(:new).with(url).and_return(connection)
14
+ end
15
+
16
+ context 'with one argument' do
17
+ let(:arguments) { [url] }
18
+
19
+ its(:raw_connection) { should be(connection) }
20
+ its(:logger) { should be(NullLogger.instance) }
21
+ end
22
+
23
+ context 'with twi arguments' do
24
+ let(:arguments) { [url, logger] }
25
+
26
+ its(:raw_connection) { should be(connection) }
27
+ its(:logger) { should be(logger) }
28
+ end
29
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Connection, '#run' do
4
+ subject { object.run(request) }
5
+
6
+ let(:object) { described_class.new(connection, logger) }
7
+
8
+ let(:connection) { mock('Connection') }
9
+ let(:logger) { DummyLogger.new }
10
+ let(:request) { mock('Request', :log_string => 'the-logged-string') }
11
+ let(:response) { mock('Response', :status => 200) }
12
+
13
+ class DummyLogger
14
+ attr_reader :messages
15
+
16
+ def initialize
17
+ @messages = []
18
+ end
19
+
20
+ def debug
21
+ @messages << yield
22
+ end
23
+ end
24
+
25
+ before do
26
+ request.should_receive(:run).with(connection).and_return(response)
27
+ end
28
+
29
+ it { should be(response) }
30
+
31
+ it 'should log requests' do
32
+ subject
33
+ logger.messages.should eql(%w(the-logged-string 200))
34
+ end
35
+
36
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Document, '#connection' do
4
+ subject { object.connection }
5
+
6
+ let(:object) { described_class.new(type, id) }
7
+ let(:type) { mock('Type', :connection => connection) }
8
+ let(:connection) { mock('Connection') }
9
+ let(:id) { '1' }
10
+
11
+ it { should be(connection) }
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Document, '#delete' do
4
+ subject { object.delete}
5
+
6
+ let(:object) { described_class.new(type, id) }
7
+ let(:type) { mock('Type') }
8
+ let(:id) { '1' }
9
+ let(:expected_arguments) { [] }
10
+
11
+ expect_to_run_command(Esearch::Command::Document::Delete)
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Document, '#get' do
4
+ subject { object.get}
5
+
6
+ let(:object) { described_class.new(type, id) }
7
+ let(:type) { mock('Type') }
8
+ let(:id) { '1' }
9
+ let(:expected_arguments) { [] }
10
+
11
+ expect_to_run_command(Esearch::Command::Document::Get)
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Index, '#create' do
4
+ subject { object.create(settings) }
5
+
6
+ let(:object) { described_class.new(connection, index_name) }
7
+ let(:index_name) { 'foo' }
8
+ let(:settings) { { :my => :settings } }
9
+ let(:expected_arguments) { [settings] }
10
+
11
+ expect_to_run_command(Esearch::Command::Index::Create)
12
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Index, '#delete' do
4
+ subject { object.delete }
5
+
6
+ let(:object) { described_class.new(connection, index_name) }
7
+ let(:index_name) { 'foo' }
8
+ let(:expected_arguments) { [] }
9
+
10
+ expect_to_run_command(Esearch::Command::Index::Delete)
11
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Index, '#type' do
4
+ subject { object.type(name) }
5
+
6
+ let(:object) { described_class.new(connection, index_name) }
7
+ let(:connection) { mock('Connection') }
8
+ let(:index_name) { 'foo' }
9
+ let(:name) { 'bar' }
10
+
11
+ it { should eql(Esearch::Type.new(object, name)) }
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Indices::All, '#path' do
4
+ subject { object.path }
5
+
6
+ let(:object) { described_class.new(connection) }
7
+ let(:connection) { mock('Connection') }
8
+
9
+ it { should eql(Pathname.new('/_all')) }
10
+
11
+ it_should_behave_like 'an idempotent method'
12
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Esearch::Mixin::Document, '#index_create' do
4
+
5
+ let(:object) { class_under_test.new(connection) }
6
+
7
+ let(:class_under_test) do
8
+ Class.new do
9
+ include Concord.new(:connection), Esearch::Mixin::Document
10
+ end
11
+ end
12
+
13
+ context 'with one arg' do
14
+ subject { object.index_create(document) }
15
+ let(:document) { mock('Document') }
16
+
17
+ let(:expected_arguments) { [document, {}] }
18
+
19
+ expect_to_run_command(Esearch::Command::Document::Index::Create)
20
+ end
21
+
22
+ context 'with two args' do
23
+ subject { object.index_create(document, options) }
24
+ let(:document) { mock('Document') }
25
+ let(:options) { mock('Options') }
26
+
27
+ let(:expected_arguments) { [document, options] }
28
+
29
+ expect_to_run_command(Esearch::Command::Document::Index::Create)
30
+ end
31
+ end