\$\begingroup\$
\$\endgroup\$
Service Class
# services/search.rb
class Search
include Rails.application.routes.url_helpers
include ActionView::Helpers::TagHelper
def initialize(term, app_ids)
@term = term
@app_ids = app_ids
end
def results
term = @term
app_ids = @app_ids
multi_search = Tire.multi_search do
no_app_indices = [Event, PastEvent, Review].map {|c| c.tire.index_name}
search :without_app, indices: no_app_indices do
query { string term }
end
app_indices = [Question, Answer, Link, ServiceProvider].map {|c| c.tire.index_name}
search :with_app, indices: indices do
query do
filtered do
query { string term }
filter :terms, app_id: app_ids
end
end
end
end
multi_search.results[:with_app].to_a + multi_search.results[:without_app].to_a
end
def autocomplete
results.map do |result|
title, caption, route = set_item_based_on_type(result)
{title: strip_tags(title), label: set_label(strip_tags(title), caption), value: route}
end
end
def strip_tags(title)
title.gsub(%r{</?[^>]+?>}, '').strip
end
Specs
describe Search do
before(:all) do
Question.index.delete
Question.tire.create_elasticsearch_index
@question1 = create :question, content: "Some super question?"
@question2 = create :question, content: "Some extra question?"
app = create :app, name: "Marketing", id: 76
@question1 = create :question, content: "Some super question?", app: app
@question2 = create :question, content: "Some extra question?", app: app
# wait for indexing to finish
sleep 1
end
describe "#results" do
it "returns matched results" do
Search.new("Some", [76]).results.map(&:content).should == ["Some super question?", "Some extra question?"]
end
it "excludes not matching results" do
Search.new("extra", [76]).results.map(&:content).should == ["Some extra question?"]
end
it "returns no matches" do
Search.new("hiper", [76]).results.map(&:content).should == []
end
it "should filter results by app" do
Search.new("some", [77]).results.map(&:content).should == []
end
end
describe "#autocomplete" do
it "returns array with matching items" do
Search.new("super", [76]).autocomplete.should ==
[{
:title=>@question1.content,
:label=>"Some <span class=\"bold\">super</span> question? <span class=\"search-type\">Question</span>",
:value=>"/Marketing/q/#{@question1.id}"
}]
end
end
describe "#strip_tags" do
it "should strip title" do
Search.new("super", [76]).strip_tags("<p>Some text</p> ").should == "Some text"
end
end
Is there a better way to test that methods in service class ?
asked Dec 26, 2012 at 17:30
1 Answer 1
\$\begingroup\$
\$\endgroup\$
Use let
(or let!
) to set up your fixtures instead of the instance variables.
let!(:app) { create :app, name: "Marketing", id: 76 }
let!(:question1) { create :question, content: "Some super question?" }
let!(:question2) { create :question, content: "Some extra question?" }
let!(:with_app1) { create :question, content: "Some super question?", app: app }
let!(:with_app2) { create :question, content: "Some extra question?", app: app }
Use subject
(in combination with let
). Here are some examples:
describe "#results" do
subject { Search.new(keyword, [app_id]).results.map(&:content) }
context "existing app_id" do
let(:app_id) { 76 }
context "multiple matches" do
let(:keyword) { "Some" }
its(:size) { should == 2 }
it { should include(with_app1.content) }
it { should include(with_app2.content) }
end
context "single matches" do
let(:keyword) { "extra" }
its(:size) { should == 1 }
it { should include(with_app2.content) }
end
context "no matches" do
let(:keyword) { "hiper" }
it { should be_empty }
end
end
context "non-exisiting app_id" do
let(:keyword) { "some" }
let(:app_id) { 123 }
it { should be_empty }
end
end
You will end up with more code if you follow this through, but also with more and finer grained examples (each it
or its
block is a single example).
answered Dec 29, 2012 at 4:24
lang-rb