diff --git a/app/controllers/api/v1/accounts/integrations/linear_controller.rb b/app/controllers/api/v1/accounts/integrations/linear_controller.rb index 1d09f3f7c..61080be04 100644 --- a/app/controllers/api/v1/accounts/integrations/linear_controller.rb +++ b/app/controllers/api/v1/accounts/integrations/linear_controller.rb @@ -3,29 +3,29 @@ class Api::V1::Accounts::Integrations::LinearController < Api::V1::Accounts::Bas def teams teams = linear_processor_service.teams - if teams.is_a?(Hash) && teams[:error] + if teams[:error] render json: { error: teams[:error] }, status: :unprocessable_entity else - render json: teams, status: :ok + render json: teams[:data], status: :ok end end def team_entities team_id = permitted_params[:team_id] - entites = linear_processor_service.team_entities(team_id) - if entites.is_a?(Hash) && entites[:error] - render json: { error: entites[:error] }, status: :unprocessable_entity + team_entities = linear_processor_service.team_entities(team_id) + if team_entities[:error] + render json: { error: team_entities[:error] }, status: :unprocessable_entity else - render json: entites, status: :ok + render json: team_entities[:data], status: :ok end end def create_issue issue = linear_processor_service.create_issue(permitted_params) - if issue.is_a?(Hash) && issue[:error] + if issue[:error] render json: { error: issue[:error] }, status: :unprocessable_entity else - render json: issue, status: :ok + render json: issue[:data], status: :ok end end @@ -33,10 +33,10 @@ class Api::V1::Accounts::Integrations::LinearController < Api::V1::Accounts::Bas issue_id = permitted_params[:issue_id] title = permitted_params[:title] issue = linear_processor_service.link_issue(conversation_link, issue_id, title) - if issue.is_a?(Hash) && issue[:error] + if issue[:error] render json: { error: issue[:error] }, status: :unprocessable_entity else - render json: issue, status: :ok + render json: issue[:data], status: :ok end end @@ -44,20 +44,20 @@ class Api::V1::Accounts::Integrations::LinearController < Api::V1::Accounts::Bas link_id = permitted_params[:link_id] issue = linear_processor_service.unlink_issue(link_id) - if issue.is_a?(Hash) && issue[:error] + if issue[:error] render json: { error: issue[:error] }, status: :unprocessable_entity else - render json: issue, status: :ok + render json: issue[:data], status: :ok end end def linked_issue - issues = linear_processor_service.linked_issue(conversation_link) + issues = linear_processor_service.linked_issues(conversation_link) - if issues.is_a?(Hash) && issues[:error] + if issues[:error] render json: { error: issues[:error] }, status: :unprocessable_entity else - render json: issues, status: :ok + render json: issues[:data], status: :ok end end @@ -66,10 +66,10 @@ class Api::V1::Accounts::Integrations::LinearController < Api::V1::Accounts::Bas term = params[:q] issues = linear_processor_service.search_issue(term) - if issues.is_a?(Hash) && issues[:error] + if issues[:error] render json: { error: issues[:error] }, status: :unprocessable_entity else - render json: issues, status: :ok + render json: issues[:data], status: :ok end end diff --git a/lib/integrations/linear/processor_service.rb b/lib/integrations/linear/processor_service.rb index 99aaf8697..20b04a301 100644 --- a/lib/integrations/linear/processor_service.rb +++ b/lib/integrations/linear/processor_service.rb @@ -3,9 +3,9 @@ class Integrations::Linear::ProcessorService def teams response = linear_client.teams - return response if response[:error] + return { error: response[:error] } if response[:error] - response['teams']['nodes'].map(&:as_json) + { data: response['teams']['nodes'].map(&:as_json) } end def team_entities(team_id) @@ -13,10 +13,12 @@ class Integrations::Linear::ProcessorService return response if response[:error] { - users: response['users']['nodes'].map(&:as_json), - projects: response['projects']['nodes'].map(&:as_json), - states: response['workflowStates']['nodes'].map(&:as_json), - labels: response['issueLabels']['nodes'].map(&:as_json) + data: { + users: response['users']['nodes'].map(&:as_json), + projects: response['projects']['nodes'].map(&:as_json), + states: response['workflowStates']['nodes'].map(&:as_json), + labels: response['issueLabels']['nodes'].map(&:as_json) + } } end @@ -25,8 +27,8 @@ class Integrations::Linear::ProcessorService return response if response[:error] { - id: response['issueCreate']['issue']['id'], - title: response['issueCreate']['issue']['title'] + data: { id: response['issueCreate']['issue']['id'], + title: response['issueCreate']['issue']['title'] } } end @@ -35,9 +37,11 @@ class Integrations::Linear::ProcessorService return response if response[:error] { - id: issue_id, - link: link, - link_id: response.with_indifferent_access[:attachmentLinkURL][:attachment][:id] + data: { + id: issue_id, + link: link, + link_id: response.with_indifferent_access[:attachmentLinkURL][:attachment][:id] + } } end @@ -46,7 +50,7 @@ class Integrations::Linear::ProcessorService return response if response[:error] { - link_id: link_id + data: { link_id: link_id } } end @@ -55,14 +59,14 @@ class Integrations::Linear::ProcessorService return response if response[:error] - response['searchIssues']['nodes'].map(&:as_json) + { data: response['searchIssues']['nodes'].map(&:as_json) } end - def linked_issue(url) - response = linear_client.linked_issue(url) + def linked_issues(url) + response = linear_client.linked_issues(url) return response if response[:error] - response['attachmentsForURL']['nodes'].map(&:as_json) + { data: response['attachmentsForURL']['nodes'].map(&:as_json) } end private diff --git a/lib/linear.rb b/lib/linear.rb index 877dd01c2..63489b060 100644 --- a/lib/linear.rb +++ b/lib/linear.rb @@ -1,6 +1,3 @@ -require_relative 'linear_queries' -require_relative 'linear_mutations' - class Linear BASE_URL = 'https://api.linear.app/graphql'.freeze PRIORITY_LEVELS = (0..4).to_a @@ -12,7 +9,7 @@ class Linear def teams query = { - query: LinearQueries::TEAMS_QUERY + query: Linear::Queries::TEAMS_QUERY } response = post(query) process_response(response) @@ -22,7 +19,7 @@ class Linear raise ArgumentError, 'Missing team id' if team_id.blank? query = { - query: LinearQueries.team_entities_query(team_id) + query: Linear::Queries.team_entities_query(team_id) } response = post(query) process_response(response) @@ -32,17 +29,17 @@ class Linear raise ArgumentError, 'Missing search term' if term.blank? query = { - query: LinearQueries.search_issue(term) + query: Linear::Queries.search_issue(term) } response = post(query) process_response(response) end - def linked_issue(url) + def linked_issues(url) raise ArgumentError, 'Missing link' if url.blank? query = { - query: LinearQueries.linked_issue(url) + query: Linear::Queries.linked_issues(url) } response = post(query) process_response(response) @@ -61,7 +58,7 @@ class Linear priority: params[:priority], labelIds: params[:label_ids] }.compact - mutation = LinearMutations.issue_create(variables) + mutation = Linear::Mutations.issue_create(variables) response = post({ query: mutation }) process_response(response) end @@ -71,7 +68,7 @@ class Linear raise ArgumentError, 'Missing issue id' if issue_id.blank? payload = { - query: LinearMutations.issue_link(issue_id, link, title) + query: Linear::Mutations.issue_link(issue_id, link, title) } response = post(payload) process_response(response) @@ -81,7 +78,7 @@ class Linear raise ArgumentError, 'Missing link id' if link_id.blank? payload = { - query: LinearMutations.unlink_issue(link_id) + query: Linear::Mutations.unlink_issue(link_id) } response = post(payload) process_response(response) diff --git a/lib/linear_mutations.rb b/lib/linear/mutations.rb similarity index 97% rename from lib/linear_mutations.rb rename to lib/linear/mutations.rb index d5ec30fa0..f887c39c8 100644 --- a/lib/linear_mutations.rb +++ b/lib/linear/mutations.rb @@ -1,4 +1,4 @@ -module LinearMutations +module Linear::Mutations def self.graphql_value(value) case value when String diff --git a/lib/linear_queries.rb b/lib/linear/queries.rb similarity index 96% rename from lib/linear_queries.rb rename to lib/linear/queries.rb index d9da707c9..78b2108f9 100644 --- a/lib/linear_queries.rb +++ b/lib/linear/queries.rb @@ -1,4 +1,4 @@ -module LinearQueries +module Linear::Queries TEAMS_QUERY = <<~GRAPHQL.freeze query { teams { @@ -60,7 +60,7 @@ module LinearQueries GRAPHQL end - def self.linked_issue(url) + def self.linked_issues(url) <<~GRAPHQL query { attachmentsForURL(url: "#{url}") { diff --git a/spec/controllers/api/v1/accounts/integrations/linear_controller_spec.rb b/spec/controllers/api/v1/accounts/integrations/linear_controller_spec.rb index 24d1b39fa..d2e9d2a8c 100644 --- a/spec/controllers/api/v1/accounts/integrations/linear_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/integrations/linear_controller_spec.rb @@ -15,7 +15,7 @@ RSpec.describe 'Linear Integration API', type: :request do describe 'GET /api/v1/accounts/:account_id/integrations/linear/teams' do context 'when it is an authenticated user' do context 'when data is retrieved successfully' do - let(:teams_data) { [{ 'id' => 'team1', 'name' => 'Team One' }] } + let(:teams_data) { { data: [{ 'id' => 'team1', 'name' => 'Team One' }] } } it 'returns team data' do allow(processor_service).to receive(:teams).and_return(teams_data) @@ -46,12 +46,12 @@ RSpec.describe 'Linear Integration API', type: :request do context 'when it is an authenticated user' do context 'when data is retrieved successfully' do let(:team_entities_data) do - { + { data: { users: [{ 'id' => 'user1', 'name' => 'User One' }], projects: [{ 'id' => 'project1', 'name' => 'Project One' }], states: [{ 'id' => 'state1', 'name' => 'State One' }], labels: [{ 'id' => 'label1', 'name' => 'Label One' }] - } + } } end it 'returns team entities data' do @@ -96,7 +96,7 @@ RSpec.describe 'Linear Integration API', type: :request do context 'when it is an authenticated user' do context 'when the issue is created successfully' do - let(:created_issue) { { 'id' => 'issue1', 'title' => 'Sample Issue' } } + let(:created_issue) { { data: { 'id' => 'issue1', 'title' => 'Sample Issue' } } } it 'returns the created issue' do allow(processor_service).to receive(:create_issue).with(issue_params.stringify_keys).and_return(created_issue) @@ -131,7 +131,7 @@ RSpec.describe 'Linear Integration API', type: :request do context 'when it is an authenticated user' do context 'when the issue is linked successfully' do - let(:linked_issue) { { 'id' => 'issue1', 'link' => 'https://linear.app/issue1' } } + let(:linked_issue) { { data: { 'id' => 'issue1', 'link' => 'https://linear.app/issue1' } } } it 'returns the linked issue' do allow(processor_service).to receive(:link_issue).with(link, issue_id, title).and_return(linked_issue) @@ -163,7 +163,7 @@ RSpec.describe 'Linear Integration API', type: :request do context 'when it is an authenticated user' do context 'when the issue is unlinked successfully' do - let(:unlinked_issue) { { 'id' => 'issue1', 'link' => 'https://linear.app/issue1' } } + let(:unlinked_issue) { { data: { 'id' => 'issue1', 'link' => 'https://linear.app/issue1' } } } it 'returns the unlinked issue' do allow(processor_service).to receive(:unlink_issue).with(link_id).and_return(unlinked_issue) @@ -195,7 +195,7 @@ RSpec.describe 'Linear Integration API', type: :request do context 'when it is an authenticated user' do context 'when search is successful' do - let(:search_results) { [{ 'id' => 'issue1', 'title' => 'Sample Issue' }] } + let(:search_results) { { data: [{ 'id' => 'issue1', 'title' => 'Sample Issue' }] } } it 'returns search results' do allow(processor_service).to receive(:search_issue).with(term).and_return(search_results) @@ -228,10 +228,10 @@ RSpec.describe 'Linear Integration API', type: :request do context 'when it is an authenticated user' do context 'when linked issue is found' do - let(:linked_issue) { [{ 'id' => 'issue1', 'title' => 'Sample Issue' }] } + let(:linked_issue) { { data: [{ 'id' => 'issue1', 'title' => 'Sample Issue' }] } } it 'returns linked issue' do - allow(processor_service).to receive(:linked_issue).with(link).and_return(linked_issue) + allow(processor_service).to receive(:linked_issues).with(link).and_return(linked_issue) get "/api/v1/accounts/#{account.id}/integrations/linear/linked_issue", params: { conversation_id: conversation.display_id }, headers: agent.create_new_auth_token, @@ -243,7 +243,7 @@ RSpec.describe 'Linear Integration API', type: :request do 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') + allow(processor_service).to receive(:linked_issues).with(link).and_return(error: 'error message') get "/api/v1/accounts/#{account.id}/integrations/linear/linked_issue", params: { conversation_id: conversation.display_id }, headers: agent.create_new_auth_token, diff --git a/spec/lib/integrations/linear/processor_service_spec.rb b/spec/lib/integrations/linear/processor_service_spec.rb index c88d6b2a4..07cf27654 100644 --- a/spec/lib/integrations/linear/processor_service_spec.rb +++ b/spec/lib/integrations/linear/processor_service_spec.rb @@ -20,7 +20,7 @@ describe Integrations::Linear::ProcessorService do it 'returns parsed team data' do allow(linear_client).to receive(:teams).and_return(teams_response) result = service.teams - expect(result).to contain_exactly({ 'id' => 'team1', 'name' => 'Team One' }) + expect(result).to eq({ data: [{ 'id' => 'team1', 'name' => 'Team One' }] }) end end @@ -50,10 +50,10 @@ describe Integrations::Linear::ProcessorService do it 'returns parsed entity data' do allow(linear_client).to receive(:team_entities).with(team_id).and_return(entities_response) result = service.team_entities(team_id) - expect(result).to have_key(:users) - expect(result).to have_key(:projects) - expect(result).to have_key(:states) - expect(result).to have_key(:labels) + expect(result).to eq({ :data => { :users => + [{ 'id' => 'user1', 'name' => 'User One' }], + :projects => [{ 'id' => 'project1', 'name' => 'Project One' }], + :states => [], :labels => [{ 'id' => 'bug', 'name' => 'Bug' }] } }) end end @@ -89,7 +89,7 @@ describe Integrations::Linear::ProcessorService do it 'returns parsed issue data' do allow(linear_client).to receive(:create_issue).with(params).and_return(issue_response) result = service.create_issue(params) - expect(result).to eq({ id: 'issue1', title: 'Issue title' }) + expect(result).to eq({ data: { id: 'issue1', title: 'Issue title' } }) end end @@ -109,7 +109,7 @@ describe Integrations::Linear::ProcessorService do let(:issue_id) { 'issue1' } let(:title) { 'Title' } let(:link_issue_response) { { id: issue_id, link: link, 'attachmentLinkURL': { 'attachment': { 'id': 'attachment1' } } } } - let(:link_response) { { id: issue_id, link: link, link_id: 'attachment1' } } + let(:link_response) { { data: { id: issue_id, link: link, link_id: 'attachment1' } } } context 'when Linear client returns valid data' do it 'returns parsed link data' do @@ -132,7 +132,7 @@ describe Integrations::Linear::ProcessorService do describe '#unlink_issue' do let(:link_id) { 'attachment1' } - let(:unlink_response) { { link_id: link_id } } + let(:unlink_response) { { data: { link_id: link_id } } } context 'when Linear client returns valid data' do it 'returns parsed unlink data' do @@ -165,7 +165,7 @@ describe Integrations::Linear::ProcessorService do it 'returns parsed search data' do allow(linear_client).to receive(:search_issue).with(term).and_return(search_response) result = service.search_issue(term) - expect(result).to contain_exactly({ 'id' => 'issue1', 'title' => 'Issue title', 'description' => 'Issue description' }) + expect(result).to eq({ :data => [{ 'description' => 'Issue description', 'id' => 'issue1', 'title' => 'Issue title' }] }) end end @@ -180,7 +180,7 @@ describe Integrations::Linear::ProcessorService do end end - describe '#linked_issue' do + describe '#linked_issues' do let(:url) { 'https://example.com' } let(:linked_response) do { @@ -190,9 +190,9 @@ describe Integrations::Linear::ProcessorService do 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' } }) + allow(linear_client).to receive(:linked_issues).with(url).and_return(linked_response) + result = service.linked_issues(url) + expect(result).to eq({ :data => [{ 'id' => 'attachment1', 'issue' => { 'id' => 'issue1' } }] }) end end @@ -200,8 +200,8 @@ describe Integrations::Linear::ProcessorService 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) + allow(linear_client).to receive(:linked_issues).with(url).and_return(error_response) + result = service.linked_issues(url) expect(result).to eq(error_response) end end diff --git a/spec/lib/linear_spec.rb b/spec/lib/linear_spec.rb index dac3d531e..a81313d6c 100644 --- a/spec/lib/linear_spec.rb +++ b/spec/lib/linear_spec.rb @@ -281,7 +281,7 @@ describe Linear do end it 'returns linked issues' do - response = linear_client.linked_issue('app.chatwoot.com') + response = linear_client.linked_issues('app.chatwoot.com') expect(response).to eq({ 'linkedIssue' => { 'id' => 'issue1', 'title' => 'Title' } }) end end @@ -294,7 +294,7 @@ describe Linear do end it 'raises an exception' do - response = linear_client.linked_issue('app.chatwoot.com') + response = linear_client.linked_issues('app.chatwoot.com') expect(response).to eq({ :error => { 'errors' => [{ 'message' => 'Error retrieving data' }] }, :error_code => 422 }) end end