Skip to content

Commit

Permalink
[#50543] added vcr unit tests for queries
Browse files Browse the repository at this point in the history
- open_file_link_query
- open_storage_query
  • Loading branch information
Kharonus committed Oct 18, 2023
1 parent c4b4a20 commit 87036b9
Show file tree
Hide file tree
Showing 11 changed files with 502 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,6 @@
expect(method.parameters).to contain_exactly(%i[keyreq storage], %i[keyreq user], %i[keyreq file_id], %i[key open_location])
end

it 'returns the url for opening the storage if no file id is provided' do
url = described_class.call(storage:, user:, file_id: nil).result
expect(url).to eq("#{storage.host}/index.php/apps/files")
end

it 'returns the url for opening the file on storage' do
url = described_class.call(storage:, user:, file_id:).result
expect(url).to eq("#{storage.host}/index.php/f/#{file_id}?openfile=1")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# frozen_string_literal: true

#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2023 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++

require 'spec_helper'
require_module_spec_helper

RSpec.describe Storages::Peripherals::StorageInteraction::Nextcloud::OpenStorageQuery do
let(:storage) { create(:nextcloud_storage, host: 'https://example.com') }
let(:user) { create(:user) }

it 'responds to .call' do
expect(described_class).to respond_to(:call)

method = described_class.method(:call)
expect(method.parameters).to contain_exactly(%i[keyreq storage], %i[keyreq user])
end

it 'returns the url for opening the file on storage' do
url = described_class.call(storage:, user:).result
expect(url).to eq("#{storage.host}/index.php/apps/files")
end

context 'with a storage with host url with a sub path' do
let(:storage) { create(:nextcloud_storage, host: 'https://example.com/html') }

it 'returns the url for opening the file on storage' do
url = described_class.call(storage:, user:).result
expect(url).to eq("#{storage.host}/index.php/apps/files")
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -31,72 +31,89 @@
require 'spec_helper'
require_module_spec_helper

RSpec.describe Storages::Peripherals::StorageInteraction::OneDrive::OpenFileLinkQuery, :webmock do
include JsonResponseHelper
RSpec.describe Storages::Peripherals::StorageInteraction::OneDrive::OpenFileLinkQuery, :vcr, :webmock do
using Storages::Peripherals::ServiceResultRefinements

let(:storage) do
create(:one_drive_storage,
:with_oauth_client,
drive_id: 'b!-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd')
end
let(:user) { create(:user) }
let(:token) { create(:oauth_client_token, user:, oauth_client: storage.oauth_client) }
let(:folder_id) { '01BYE5RZ5MYLM2SMX75ZBIPQZIHT6OAYPB' }
let(:file_id) { '01BYE5RZ7T3DFLFS6TCRH2QAPWXL5APDLE' }
let(:not_found_json) { not_found_response }
let(:forbidden_json) { forbidden_response }

it 'responds to .call' do
expect(described_class).to respond_to(:call)
let(:storage) { create(:sharepoint_dev_drive_storage, oauth_client_token_user: user) }
let(:file_id) { '01AZJL5PJTICED3C5YSVAY6NWTBNA2XERU' }

method = described_class.method(:call)
expect(method.parameters).to contain_exactly(%i[keyreq storage], %i[keyreq user], %i[keyreq file_id], %i[key open_location])
end
subject { described_class.new(storage) }

it 'returns the url for opening the file on storage' do
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}?$select=webUrl")
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
.to_return(status: 200, body: read_json('file_drive_item_1'), headers: {})

url = described_class.call(storage:, user:, file_id:).result
expect(url).to eq('https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/_layouts/15/Doc.aspx?sourcedoc=%7BB2CAD8F3-D3CB-4F14-A801-F6BAFA078D64%7D&file=Popular%20Mixed%20Drinks.xlsx&action=default&mobileredirect=true')
end
describe '#call' do
it 'responds with correct parameters' do
expect(described_class).to respond_to(:call)

it 'returns the url for opening the file\'s location on storage' do
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}?$select=parentReference")
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
.to_return(status: 200, body: read_json('file_drive_item_1'), headers: {})
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{folder_id}?$select=webUrl")
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
.to_return(status: 200, body: read_json('folder_drive_item'), headers: {})
method = described_class.method(:call)
expect(method.parameters).to contain_exactly(%i[keyreq storage], %i[keyreq user], %i[keyreq file_id], %i[key open_location])
end

url = described_class.call(storage:, user:, file_id:, open_location: true).result
expect(url).to eq('https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/Documents/Business%20Data')
end
context 'with outbound requests successful' do
context 'with open location flag not set', vcr: 'one_drive/open_file_link_query_success' do
it 'returns the url for opening the file on storage' do
call = subject.call(user:, file_id:)
expect(call).to be_success
expect(call.result).to eq('https://finn.sharepoint.com/sites/openprojectfilestoragetests/_layouts/15/Doc.aspx?sourcedoc=%7B3D884033-B88B-4195-8F36-D30B41AB9234%7D&file=Document.docx&action=default&mobileredirect=true')
end
end

context 'with open location flag set', vcr: 'one_drive/open_file_link_location_query_success' do
it 'returns the url for opening the file on storage' do
call = subject.call(user:, file_id:, open_location: true)
expect(call).to be_success
expect(call.result).to eq('https://finn.sharepoint.com/sites/openprojectfilestoragetests/VCR/Folder')
end
end
end

describe 'error handling' do
it 'returns a notfound error if the API call returns a 404' do
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}?$select=webUrl")
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
.to_return(status: 404, body: not_found_json, headers: {})
context 'with not existent oauth token' do
let(:user_without_token) { create(:user) }

open_link_result = described_class.call(storage:, user:, file_id:)
it 'must return unauthorized when called' do
result = subject.call(user: user_without_token, file_id:)
expect(result).to be_failure
expect(result.error_source).to be_a(OAuthClients::ConnectionManager)

expect(open_link_result).to be_failure
expect(open_link_result.result).to eq(:not_found)
expect(open_link_result.errors.data.payload.to_json).to eq(not_found_json)
result.match(
on_failure: ->(error) { expect(error.code).to eq(:unauthorized) },
on_success: ->(file_infos) { fail "Expected failure, got #{file_infos}" }
)
end
end

it 'returns a forbidden error if the API call returns a 403' do
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}?$select=webUrl")
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
.to_return(status: 403, body: forbidden_json, headers: {})
context 'with not existent file id', vcr: 'one_drive/open_file_link_query_missing_file_id' do
let(:file_id) { 'iamnotexistent' }

open_link_result = described_class.call(storage:, user:, file_id:)
it 'must return not found' do
result = subject.call(user:, file_id:)
expect(result).to be_failure
expect(result.error_source).to be_a(Storages::Peripherals::StorageInteraction::OneDrive::Internal::DriveItemQuery)

result.match(
on_failure: ->(error) { expect(error.code).to eq(:not_found) },
on_success: ->(file_infos) { fail "Expected failure, got #{file_infos}" }
)
end
end

expect(open_link_result).to be_failure
expect(open_link_result.result).to eq(:forbidden)
expect(open_link_result.errors.data.payload.to_json).to eq(forbidden_json)
context 'with invalid oauth token', vcr: 'one_drive/open_file_link_query_invalid_token' do
before do
token = build_stubbed(:oauth_client_token, oauth_client: storage.oauth_client)
allow(Storages::Peripherals::StorageInteraction::OneDrive::Util)
.to receive(:using_user_token)
.and_yield(token)
end

it 'must return unauthorized' do
result = subject.call(user:, file_id:)
expect(result).to be_failure
expect(result.error_source).to be_a(Storages::Peripherals::StorageInteraction::OneDrive::Internal::DriveItemQuery)

result.match(
on_failure: ->(error) { expect(error.code).to eq(:unauthorized) },
on_success: ->(file_infos) { fail "Expected failure, got #{file_infos}" }
)
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -32,59 +32,62 @@
require_module_spec_helper

RSpec.describe Storages::Peripherals::StorageInteraction::OneDrive::OpenStorageQuery, :webmock do
include JsonResponseHelper

using Storages::Peripherals::ServiceResultRefinements

let(:storage) do
create(:one_drive_storage,
:with_oauth_client,
drive_id: 'b!-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd')
end
let(:user) { create(:user) }
let(:token) { create(:oauth_client_token, user:, oauth_client: storage.oauth_client) }
let(:not_found_json) { not_found_response }
let(:forbidden_json) { forbidden_response }
let(:storage) { create(:sharepoint_dev_drive_storage, oauth_client_token_user: user) }

it 'responds to .call' do
expect(described_class).to respond_to(:call)
subject { described_class.new(storage) }

method = described_class.method(:call)
expect(method.parameters).to contain_exactly(%i[keyreq storage], %i[keyreq user])
end
describe '#call' do
it 'responds with correct parameters' do
expect(described_class).to respond_to(:call)

it 'returns the url for opening the drive root on storage' do
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}?$select=webUrl")
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
.to_return(status: 200, body: read_json('root_drive'), headers: {})
method = described_class.method(:call)
expect(method.parameters).to contain_exactly(%i[keyreq storage], %i[keyreq user])
end

url = described_class.call(storage:, user:).result
expect(url).to eq('https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/Documents')
end
context 'with outbound requests successful', vcr: 'one_drive/open_storage_query_success' do
it 'returns the url for opening the storage' do
call = subject.call(user:)
expect(call).to be_success
expect(call.result).to eq('https://finn.sharepoint.com/sites/openprojectfilestoragetests/VCR')
end
end

describe 'error handling' do
it 'returns a notfound error if the API call returns a 404' do
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}?$select=webUrl")
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
.to_return(status: 404, body: not_found_json, headers: {})
context 'with not existent oauth token' do
let(:user_without_token) { create(:user) }

open_drive_link_result = described_class.call(storage:, user:)
it 'must return unauthorized when called' do
result = subject.call(user: user_without_token)
expect(result).to be_failure
expect(result.error_source).to be_a(OAuthClients::ConnectionManager)

expect(open_drive_link_result).to be_failure
expect(open_drive_link_result.result).to eq(:not_found)
expect(open_drive_link_result.error_payload.to_json).to eq(not_found_json)
result.match(
on_failure: ->(error) { expect(error.code).to eq(:unauthorized) },
on_success: ->(file_infos) { fail "Expected failure, got #{file_infos}" }
)
end
end

it 'returns a forbidden error if the API call returns a 403' do
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}?$select=webUrl")
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
.to_return(status: 403, body: forbidden_json, headers: {})
context 'with invalid oauth token', vcr: 'one_drive/open_storage_query_invalid_token' do
before do
token = build_stubbed(:oauth_client_token, oauth_client: storage.oauth_client)
allow(Storages::Peripherals::StorageInteraction::OneDrive::Util)
.to receive(:using_user_token)
.and_yield(token)
end

open_drive_link_result = described_class.call(storage:, user:)
it 'must return unauthorized' do
result = subject.call(user:)
expect(result).to be_failure
expect(result.error_source).to be_a(described_class)

expect(open_drive_link_result).to be_failure
expect(open_drive_link_result.result).to eq(:forbidden)
expect(open_drive_link_result.error_payload.to_json).to eq(forbidden_json)
result.match(
on_failure: ->(error) { expect(error.code).to eq(:unauthorized) },
on_success: ->(file_infos) { fail "Expected failure, got #{file_infos}" }
)
end
end
end
end
2 changes: 2 additions & 0 deletions modules/storages/spec/features/storages_menu_links_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
require_module_spec_helper

RSpec.describe 'Project menu', :js, :with_cuprite do
include API::V3::Utilities::PathHelper

let(:storage) { create(:nextcloud_storage, name: "Storage 1") }
let(:another_storage) { create(:nextcloud_storage, name: "Storage 2") }
let(:unlinked_storage) { create(:nextcloud_storage, name: "Storage 3") }
Expand Down
Loading

0 comments on commit 87036b9

Please sign in to comment.