Skip to content

Commit

Permalink
1 | Add issue search by summary
Browse files Browse the repository at this point in the history
  • Loading branch information
maciej-szlosarczyk authored Dec 27, 2016
1 parent a00e603 commit 78aecf1
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 44 deletions.
8 changes: 4 additions & 4 deletions lib/terjira/client/issue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ def find(issue, options = {})
build(resp)
end

def search(options = {})
resource.jql(build_jql(options), max_results: 20)
end

def delete(issue)
api_delete("issue/#{issue.key_value}")
end
Expand Down Expand Up @@ -57,10 +61,6 @@ def trans(issue, options = {})
find(issue)
end

def search(options = {})
resource.jql(build_jql(options), max_results: 10)
end

private

def extract_to_update_params(options = {})
Expand Down
41 changes: 32 additions & 9 deletions lib/terjira/client/jql_builder.rb
Original file line number Diff line number Diff line change
@@ -1,30 +1,53 @@
module Terjira
module Client
module JQLBuilder
JQL_KEYS = %w(summary sprint assignee issuetype priority project status statusCategory).freeze
STRICT_KEYS = %w(sprint assignee issuetype priority project status statusCategory).freeze
SEARCH_KEYS = %w(summary description).freeze

def build_jql(options = {})
search = options.select { |k, v| SEARCH_KEYS.include?(k.to_s) }
strict = options.select { |k, v| STRICT_KEYS.include?(k.to_s) }

query = [strict_matching(strict), search_matching(search)]
.reject(&:blank?).join(' AND ')
end

private

def strict_matching(options = {})
q_options = options.inject({}) do |memo, (k, v)|
memo[k.to_s] = v
memo
end.slice(*JQL_KEYS)
end.slice(*STRICT_KEYS)

query = q_options.map do |key, value|
case
when value.is_a?(Array)
if value.is_a? Array
values = value.map { |v| "\"#{v.key_value}\"" }.join(',')
"#{key} IN (#{values})"
when value.key_value.to_s =~ /^\d+$/
"#{key}=#{value.key_value}"
when key.eql?('summary')
"#{key}~\"#{value.key_value}\""
else
"#{key}=\"#{value.key_value}\""
if value.key_value.to_s =~ /^\d+$/
"#{key}=#{value.key_value}"
else
"#{key}=\"#{value.key_value}\""
end
end
end.reject(&:blank?).join(' AND ')

query
end

def search_matching(options = {})
q_options = options.inject({}) do |memo, (k, v)|
memo[k.to_s] = v
memo
end.slice(*SEARCH_KEYS)

query = q_options.map do |key, value|
"#{key}~\"#{value.key_value}\""
end.reject(&:blank?).join(' AND ')

query
end
end
end
end
12 changes: 6 additions & 6 deletions lib/terjira/issue_cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ def assign(*keys)
show(issue.key_value)
end

desc 'search [SUMMARY]', 'Search for an issue by summary'
def search(*keys)
search_term = client_class.search(summary: keys[0])
render_issues(search_term)
end

desc 'trans [ISSUE_KEY] ([STATUS])', 'Do transition'
jira_options :comment, :assignee, :resolution
def trans(*args)
Expand All @@ -131,12 +137,6 @@ def trans(*args)
render_issue_detail(issue)
end

desc 'search \'[ISSUE_SUMMARY]\'', 'Search for an issue by summary'
def search(*keys)
search_term = client_class.search(summary: keys[0])
render_issues(search_term)
end

no_commands do
def default_status_categories
Client::StatusCategory.all.reject { |category| category.key =~ /done/i }.map(&:name)
Expand Down
61 changes: 36 additions & 25 deletions spec/client/jql_builder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,51 @@ class TestJQLBuilder
describe Terjira::Client::JQLBuilder do
subject { TestJQLBuilder }

it 'builds string value jql' do
result = subject.build_jql(sprint: 1)
expect(result).to be == 'sprint=1'
describe 'strict_matching' do
it 'builds string value jql' do
result = subject.send(:strict_matching, {sprint: 1})
expect(result).to be == 'sprint=1'

result = subject.build_jql(issuetype: 'Task')
expect(result).to be == 'issuetype="Task"'
end
result = subject.send(:strict_matching, {issuetype: 'Task'})
expect(result).to be == 'issuetype="Task"'
end

it 'builds array value jql' do
result = subject.build_jql(sprint: [1, 2, 3])
expect(result).to be == 'sprint IN ("1","2","3")'
it 'builds array value jql' do
result = subject.send(:strict_matching, {sprint: [1, 2, 3]})
expect(result).to be == 'sprint IN ("1","2","3")'

result = subject.build_jql(priority: %w(high low))
expect(result).to be == 'priority IN ("high","low")'
end
result = subject.send(:strict_matching, {priority: %w(high low)})
expect(result).to be == 'priority IN ("high","low")'
end

it 'builds multiple key values jql' do
result = subject.build_jql(
sprint: 1, issuetype: %w(Task Done), summary: 'urgent task'
)
it 'builds multiple key values jql' do
result = subject.send(:strict_matching, {sprint: 1, issuetype: %w(Task Done)})

expect(result).to eq(
'summary~"urgent task" AND sprint=1 AND issuetype IN ("Task","Done")'
)
expect(result).to be == 'sprint=1 AND issuetype IN ("Task","Done")'
end
end

it 'builds the ~ query with summary' do
result = subject.build_jql(summary: "My very special task")
describe 'search_matching' do
it 'builds string value jql' do
result = subject.send(:search_matching, {summary: 'very important issue'})
expect(result).to be == 'summary~"very important issue"'
end

expect(result).to be == 'summary~"My very special task"'
it 'filter usupported JQL key' do
result = subject.send(:search_matching, {foo: 'bar'})
expect(result).to be == ''
end
end

it 'filters unkown jql key' do
result = subject.build_jql(unkown: 1)
expect(result).to be == ''
describe 'build_jql' do
it 'merges queries properly' do
result = subject.build_jql(sprint: [1, 2], summary: 'foo')
expect(result).to be == 'sprint IN ("1","2") AND summary~"foo"'
end

it 'handles empty results' do
result = subject.build_jql(sprint: [1, 2])
expect(result).to be == 'sprint IN ("1","2")'
end
end
end

0 comments on commit 78aecf1

Please sign in to comment.