feat: add linked issue api
This commit is contained in:
@@ -49,6 +49,19 @@ class Api::V1::Accounts::Integrations::LinearController < Api::V1::Accounts::Bas
|
||||
end
|
||||
end
|
||||
|
||||
def linked_issue
|
||||
render json: { error: 'Specify link with parameter link' }, status: :unprocessable_entity if params[:link].blank? && return
|
||||
|
||||
url = params[:link]
|
||||
issues = linear_processor_service.linked_issue(url)
|
||||
|
||||
if issues.is_a?(Hash) && issues[:error]
|
||||
render json: { error: issues[:error] }, status: :unprocessable_entity
|
||||
else
|
||||
render json: issues, status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
def search_issue
|
||||
render json: { error: 'Specify search string with parameter q' }, status: :unprocessable_entity if params[:q].blank? && return
|
||||
|
||||
|
||||
@@ -235,6 +235,7 @@ Rails.application.routes.draw do
|
||||
post :link_issue
|
||||
post :unlink_issue
|
||||
get :search_issue
|
||||
get :linked_issue
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -58,6 +58,13 @@ class Integrations::Linear::ProcessorService
|
||||
response['searchIssues']['nodes'].map(&:as_json)
|
||||
end
|
||||
|
||||
def linked_issue(url)
|
||||
response = linear_client.linked_issue(url)
|
||||
return response if response[:error]
|
||||
|
||||
response['attachmentsForURL']['nodes'].map(&:as_json)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def linear_hook
|
||||
|
||||
@@ -35,6 +35,12 @@ class Linear
|
||||
execute_query(LinearQueries.search_issue(term))
|
||||
end
|
||||
|
||||
def linked_issue(url)
|
||||
raise ArgumentError, 'Missing link' if url.blank?
|
||||
|
||||
execute_query(LinearQueries.linked_issue(url))
|
||||
end
|
||||
|
||||
def create_issue(params)
|
||||
validate_team_and_title(params)
|
||||
validate_priority(params[:priority])
|
||||
|
||||
@@ -58,4 +58,22 @@ module LinearQueries
|
||||
}
|
||||
GRAPHQL
|
||||
end
|
||||
|
||||
def self.linked_issue(url)
|
||||
<<~GRAPHQL
|
||||
query {
|
||||
attachmentsForURL(url: "#{url}") {
|
||||
nodes {
|
||||
id
|
||||
title
|
||||
issue {
|
||||
id
|
||||
title
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GRAPHQL
|
||||
end
|
||||
end
|
||||
|
||||
@@ -219,4 +219,36 @@ RSpec.describe 'Linear Integration API', type: :request do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v1/accounts/:account_id/integrations/linear/linked_issue' do
|
||||
let(:link) { 'https://linear.app/issue1' }
|
||||
|
||||
context 'when it is an authenticated user' do
|
||||
context 'when linked issue is found' do
|
||||
let(:linked_issue) { [{ 'id' => 'issue1', 'title' => 'Sample Issue' }] }
|
||||
|
||||
it 'returns linked issue' do
|
||||
allow(processor_service).to receive(:linked_issue).with(link).and_return(linked_issue)
|
||||
get "/api/v1/accounts/#{account.id}/integrations/linear/linked_issue",
|
||||
params: { link: link },
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(response.body).to include('Sample Issue')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when linked issue is not found' do
|
||||
it 'returns error message' do
|
||||
allow(processor_service).to receive(:linked_issue).with(link).and_return(error: 'error message')
|
||||
get "/api/v1/accounts/#{account.id}/integrations/linear/linked_issue",
|
||||
params: { link: link },
|
||||
headers: agent.create_new_auth_token,
|
||||
as: :json
|
||||
expect(response).to have_http_status(:unprocessable_entity)
|
||||
expect(response.body).to include('error message')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -178,4 +178,31 @@ describe Integrations::Linear::ProcessorService do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#linked_issue' do
|
||||
let(:url) { 'https://example.com' }
|
||||
let(:linked_response) do
|
||||
{
|
||||
'attachmentsForURL' => { 'nodes' => [{ 'id' => 'attachment1', :issue => { 'id' => 'issue1' } }] }
|
||||
}
|
||||
end
|
||||
|
||||
context 'when Linear client returns valid data' do
|
||||
it 'returns parsed linked data' do
|
||||
allow(linear_client).to receive(:linked_issue).with(url).and_return(linked_response)
|
||||
result = service.linked_issue(url)
|
||||
expect(result).to contain_exactly({ 'id' => 'attachment1', 'issue' => { 'id' => 'issue1' } })
|
||||
end
|
||||
end
|
||||
|
||||
context 'when Linear client returns an error' do
|
||||
let(:error_response) { { error: 'Some error message' } }
|
||||
|
||||
it 'returns the error' do
|
||||
allow(linear_client).to receive(:linked_issue).with(url).and_return(error_response)
|
||||
result = service.linked_issue(url)
|
||||
expect(result).to eq(error_response)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -279,4 +279,34 @@ describe Linear do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when querying linked issues' do
|
||||
let(:url) { 'https://example.com' }
|
||||
|
||||
context 'when the API response is success' do
|
||||
before do
|
||||
linear_client.instance_variable_set(:@client, client)
|
||||
stub_request(:post, url)
|
||||
.to_return(status: 200, body: { data: { linkedIssue: { id: 'issue1', title: 'Title' } } }.to_json)
|
||||
end
|
||||
|
||||
it 'returns linked issues' do
|
||||
response = linear_client.linked_issue(url)
|
||||
expect(response).to eq({ 'linkedIssue' => { 'id' => 'issue1', 'title' => 'Title' } })
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the API response is an error' do
|
||||
before do
|
||||
linear_client.instance_variable_set(:@client, client)
|
||||
stub_request(:post, url)
|
||||
.to_return(status: 422, body: { errors: [{ message: 'Error retrieving data' }] }.to_json)
|
||||
end
|
||||
|
||||
it 'raises an exception' do
|
||||
response = linear_client.linked_issue(url)
|
||||
expect(response).to eq({ :error => 'Error: the server responded with status 422' })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user