Really fix regression introduced in 23879bc (fixes #2220)

This commit is contained in:
Ryan Lue 2018-09-04 11:49:44 +02:00
parent 19319d9d83
commit b58fcbb5fc
12 changed files with 23836 additions and 58 deletions

View file

@ -164,8 +164,9 @@ group :development, :test do
# mock http calls
gem 'webmock'
# record and replay TCP transactions
# record and replay TCP/HTTP transactions
gem 'tcr'
gem 'vcr'
end
# Want to extend Zammad with additional gems?

View file

@ -461,6 +461,7 @@ GEM
valid_email2 (2.1.0)
activemodel (>= 3.2)
mail (~> 2.5)
vcr (4.0.0)
viewpoint (1.1.0)
httpclient
logging
@ -565,6 +566,7 @@ DEPENDENCIES
uglifier
unicorn
valid_email2
vcr
viewpoint
webmock
writeexcel

View file

@ -25,8 +25,7 @@ module Import
end
def find(id)
(@lookup_map[id] ||= @connection.get_folder(id)) ||
id_folder_map[id]
@lookup_map[id] ||= @connection.get_folder(id)
end
def all
@ -43,8 +42,8 @@ module Import
end
def display_path(folder)
display_name = folder.display_name&.utf8_encode(fallback: :read_as_sanitized_binary)
parent_folder = find(folder.parent_folder_id)
display_name = folder.display_name.utf8_encode(fallback: :read_as_sanitized_binary)
parent_folder = id_folder_map[folder.parent_folder_id]
return display_name if parent_folder.blank?

View file

@ -2,81 +2,74 @@ require 'rails_helper'
RSpec.describe Import::Exchange::Folder do
# see https://github.com/zammad/zammad/issues/2152
# WARNING! This test is closely tied to the implementation. :(
describe '#display_path (#2152)' do
let(:subject) { described_class.new(connection) }
let(:connection) { instance_double('Viewpoint::EWSClient') }
let(:root_folder) { double('EWS Folder') }
let(:child_folder) { double('EWS Folder') }
let(:exception_case) { double('EWS Folder') }
let(:subject) { described_class.new(ews_connection) }
let(:ews_connection) { Viewpoint::EWSClient.new(endpoint, user, pass) }
let(:endpoint) { 'https://exchange.example.com/EWS/Exchange.asmx' }
let(:user) { 'user@example.com' }
let(:pass) { 'password' }
let(:grandchild_of_root) { ews_connection.get_folder_by_name('Inbox') }
let(:child_of_root) { ews_connection.get_folder(grandchild_of_root.parent_folder_id) }
context 'when folder.display_name returns nil' do
before do
allow(root_folder).to receive(:display_name).and_return(nil)
allow(root_folder).to receive(:parent_folder_id).and_return(nil)
allow(subject).to receive(:find).with(any_args).and_return(root_folder)
allow(subject).to receive(:find).with(nil).and_return(nil)
end
it 'returns nil' do
expect(subject.display_path(root_folder)).to be(nil)
end
around do |example|
cassette_name = example.description.gsub(/[^0-9A-Za-z.\-]+/, '_')
VCR.use_cassette("lib/import/exchange/folder/#{cassette_name}") { example.run }
end
context 'when server returns valid UTF-8' do
before do
allow(root_folder).to receive(:display_name).and_return('Root')
allow(root_folder).to receive(:parent_folder_id).and_return(nil)
allow(child_folder).to receive(:display_name).and_return('Leaf')
allow(child_folder).to receive(:parent_folder_id).and_return(1)
allow(exception_case).to receive(:display_name).and_return('Error-Raising Leaf')
allow(exception_case).to receive(:parent_folder_id).and_raise(Viewpoint::EWS::EwsError)
allow(subject).to receive(:find).with(any_args).and_return(root_folder)
allow(subject).to receive(:find).with(nil).and_return(nil)
end
context 'and target folder is directory root' do
context 'and target folder is in root directory' do
it 'returns the display name of the folder' do
expect(subject.display_path(root_folder)).to eq('Root')
expect(subject.display_path(child_of_root))
.to eq('Top of Information Store')
end
end
context 'and target folder is NOT directory root' do
context 'and target folder is in subfolder of root' do
it 'returns the full path from root to target' do
expect(subject.display_path(child_folder)).to eq('Root -> Leaf')
expect(subject.display_path(grandchild_of_root))
.to eq('Top of Information Store -> Inbox')
end
end
context 'and walking up directory tree raises EwsError' do
it 'returns the partial path from error to target folder' do
expect(subject.display_path(exception_case)).to eq('Error-Raising Leaf')
allow(subject)
.to receive(:id_folder_map).with(any_args).and_raise(Viewpoint::EWS::EwsError)
expect(subject.display_path(grandchild_of_root))
.to eq('Inbox')
end
end
end
context 'when server returns invalid UTF-8' do
before do
allow(root_folder).to receive(:display_name).and_return('你好'.b)
allow(root_folder).to receive(:parent_folder_id).and_return(nil)
context 'and target folder is in root directory' do
it 'returns the display name of the folder in valid UTF-8' do
allow(child_of_root)
.to receive(:display_name).and_return('你好'.b)
allow(child_folder).to receive(:display_name).and_return('你好'.b)
allow(child_folder).to receive(:parent_folder_id).and_return(1)
allow(exception_case).to receive(:display_name).and_return('你好'.b)
allow(exception_case).to receive(:parent_folder_id).and_raise(Viewpoint::EWS::EwsError)
allow(subject).to receive(:find).with(any_args).and_return(root_folder)
allow(subject).to receive(:find).with(nil).and_return(nil)
expect { subject.display_path(child_of_root).to_json }.not_to raise_error
end
end
it 'returns a valid UTF-8 string' do
expect { subject.display_path(root_folder).to_json }.not_to raise_error
expect { subject.display_path(child_folder).to_json }.not_to raise_error
expect { subject.display_path(exception_case).to_json }.not_to raise_error
context 'and target folder is in subfolder of root' do
it 'returns the full path from root to target in valid UTF-8' do
allow(grandchild_of_root)
.to receive(:display_name).and_return('你好'.b)
expect { subject.display_path(grandchild_of_root).to_json }.not_to raise_error
end
end
context 'and walking up directory tree raises EwsError' do
it 'returns the partial path from error to target folder in valid UTF-8' do
allow(grandchild_of_root)
.to receive(:display_name).and_return('你好'.b)
allow(subject)
.to receive(:id_folder_map).with(any_args).and_raise(Viewpoint::EWS::EwsError)
expect { subject.display_path(grandchild_of_root).to_json }.not_to raise_error
end
end
end
end

5
spec/support/vcr.rb Normal file
View file

@ -0,0 +1,5 @@
VCR.configure do |config|
config.cassette_library_dir = 'test/data/vcr_cassettes'
config.hook_into :webmock
config.allow_http_connections_when_no_cassette = true
end

View file

@ -2,7 +2,7 @@
# - Zammad webservices
# - Google (calendar)
allowed_sites = lambda do |uri|
['zammad.com', 'google.com'].any? do |site|
['zammad.com', 'google.com', 'exchange.example.com'].any? do |site|
uri.host.include?(site)
end
end

View file

@ -0,0 +1,97 @@
---
http_interactions:
- request:
method: post
uri: https://exchange.example.com/EWS/Exchange.asmx
body:
encoding: UTF-8
string: |
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
<soap:Header>
<t:RequestServerVersion Version="Exchange2010"/>
</soap:Header>
<soap:Body>
<FindFolder xmlns="http://schemas.microsoft.com/exchange/services/2006/messages" Traversal="Shallow">
<FolderShape>
<t:BaseShape>Default</t:BaseShape>
</FolderShape>
<m:Restriction>
<t:IsEqualTo>
<t:FieldURI FieldURI="folder:DisplayName"/>
<t:FieldURIOrConstant>
<t:Constant Value="Inbox"/>
</t:FieldURIOrConstant>
</t:IsEqualTo>
</m:Restriction>
<m:ParentFolderIds>
<t:DistinguishedFolderId Id="msgfolderroot"/>
</m:ParentFolderIds>
</FindFolder>
</soap:Body>
</soap:Envelope>
headers:
User-Agent:
- HTTPClient/1.0 (2.8.3, ruby 2.4.4 (2018-03-28))
Accept:
- "*/*"
Date:
- Tue, 04 Sep 2018 05:12:45 GMT
Content-Type:
- text/xml
Cookie:
- ClientId=TMH9PMQHUMIOL0RLW
Authorization:
- Negotiate TlRMTVNTUAADAAAAGAAYAEQAAADGAMYAXAAAAAAAAAAiAQAARABEACIBAAAAAAAAZgEAAAAAAABmAQAABYKJAgAAAACKsgCrRMWhrvDR0QJjG0Dtb4IfWD0Uc2cyO1jML/8FAggCPZ0gmtrTAQEAAAAAAACAxOXpDUTUAW+CH1g9FHNnAAAAAAIAEABFAFgAQwBIAEEATgBHAEUAAQAMAEUAWABGAEUAMAA2AAQAGABFAFgAQwBIAEEATgBHAEUALgBJAE4AVAADACYARQBYAEYARQAwADYALgBFAFgAQwBIAEEATgBHAEUALgBJAE4AVAAFABgARQBYAEMASABBAE4ARwBFAC4ASQBOAFQABwAIACN63+kNRNQBAAAAAAAAAABjAHUAcwB0AG8AbQBlAHIAMwBAAGEANQAzADEAMgA3ADQALgBlAHgAYwBoAGEAbgBnAGUALQBtAGEAaQBsAC4AZQB1AA==
response:
status:
code: 200
message: OK
headers:
Cache-Control:
- private
Transfer-Encoding:
- chunked
Content-Type:
- text/xml; charset=utf-8
Server:
- Microsoft-IIS/8.0
Request-Id:
- 9144d49b-057c-4840-8032-80911701fed9
X-Calculatedbetarget:
- exdag20-2.exchange.int
X-Diaginfo:
- EXDAG20-2
X-Beserver:
- EXDAG20-2
X-Aspnet-Version:
- 4.0.30319
Set-Cookie:
- X-BackEndCookie=S-1-5-21-2149852636-2334046265-983485362-135679=u56Lnp2ejJqBzpnGyczNzMjSy8nOydLLnJzM0seamc/SzMjJxs6bm8eazZnIgYHNz87H0s7P0s/Lq8/Kxc7NxcvK;
expires=Thu, 04-Oct-2018 05:12:45 GMT; path=/EWS; secure; HttpOnly
- exchangecookie=43aef8df84174a8098242a61c783c8ef; expires=Wed, 04-Sep-2019
05:12:45 GMT; path=/; HttpOnly
Persistent-Auth:
- 'true'
X-Powered-By:
- ASP.NET
X-Feserver:
- EXFE06
Date:
- Tue, 04 Sep 2018 05:12:44 GMT
body:
encoding: UTF-8
string: <?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Header><h:ServerVersionInfo
MajorVersion="15" MinorVersion="0" MajorBuildNumber="1293" MinorBuildNumber="6"
Version="V2_23" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/></s:Header><s:Body
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><m:FindFolderResponse
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"><m:ResponseMessages><m:FindFolderResponseMessage
ResponseClass="Success"><m:ResponseCode>NoError</m:ResponseCode><m:RootFolder
TotalItemsInView="1" IncludesLastItemInRange="true"><t:Folders><t:Folder><t:FolderId
Id="AQMkADRjMTk4NmJlLTNjMGUtNDk1Yy04MjAxLWE2Nzk0NWYzY2MANTcALgAAA9shP4dg44BKifl+6m/8GgMBALoafj1aZ5lBsuy9VYcX6tAAAAIBDAAAAA=="
ChangeKey="AQAAABYAAAC6Gn49WmeZQbLsvVWHF+rQAAAAABsE"/><t:DisplayName>Inbox</t:DisplayName><t:TotalCount>0</t:TotalCount><t:ChildFolderCount>1</t:ChildFolderCount><t:UnreadCount>0</t:UnreadCount></t:Folder></t:Folders></m:RootFolder></m:FindFolderResponseMessage></m:ResponseMessages></m:FindFolderResponse></s:Body></s:Envelope>
http_version:
recorded_at: Tue, 04 Sep 2018 05:12:45 GMT
recorded_with: VCR 4.0.0

View file

@ -0,0 +1,97 @@
---
http_interactions:
- request:
method: post
uri: https://exchange.example.com/EWS/Exchange.asmx
body:
encoding: UTF-8
string: |
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
<soap:Header>
<t:RequestServerVersion Version="Exchange2010"/>
</soap:Header>
<soap:Body>
<FindFolder xmlns="http://schemas.microsoft.com/exchange/services/2006/messages" Traversal="Shallow">
<FolderShape>
<t:BaseShape>Default</t:BaseShape>
</FolderShape>
<m:Restriction>
<t:IsEqualTo>
<t:FieldURI FieldURI="folder:DisplayName"/>
<t:FieldURIOrConstant>
<t:Constant Value="Inbox"/>
</t:FieldURIOrConstant>
</t:IsEqualTo>
</m:Restriction>
<m:ParentFolderIds>
<t:DistinguishedFolderId Id="msgfolderroot"/>
</m:ParentFolderIds>
</FindFolder>
</soap:Body>
</soap:Envelope>
headers:
User-Agent:
- HTTPClient/1.0 (2.8.3, ruby 2.4.4 (2018-03-28))
Accept:
- "*/*"
Date:
- Tue, 04 Sep 2018 05:29:21 GMT
Content-Type:
- text/xml
Cookie:
- ClientId=E0YFFWDNP0GXXFCYTFUW
Authorization:
- Negotiate TlRMTVNTUAADAAAAGAAYAEQAAADGAMYAXAAAAAAAAAAiAQAARABEACIBAAAAAAAAZgEAAAAAAABmAQAABYKJAgAAAABMEJ04Cv8NvAxULJlH62pCu8GOV5tsEyoaVzgkOoBRqzPDFGW7sfpKAQEAAAAAAACATo87EETUAbvBjlebbBMqAAAAAAIAEABFAFgAQwBIAEEATgBHAEUAAQAMAEUAWABGAEUAMAA2AAQAGABFAFgAQwBIAEEATgBHAEUALgBJAE4AVAADACYARQBYAEYARQAwADYALgBFAFgAQwBIAEEATgBHAEUALgBJAE4AVAAFABgARQBYAEMASABBAE4ARwBFAC4ASQBOAFQABwAIAJ1LzDsQRNQBAAAAAAAAAABjAHUAcwB0AG8AbQBlAHIAMwBAAGEANQAzADEAMgA3ADQALgBlAHgAYwBoAGEAbgBnAGUALQBtAGEAaQBsAC4AZQB1AA==
response:
status:
code: 200
message: OK
headers:
Cache-Control:
- private
Transfer-Encoding:
- chunked
Content-Type:
- text/xml; charset=utf-8
Server:
- Microsoft-IIS/8.0
Request-Id:
- cf74b089-0c14-487e-9f18-15e65ba17d14
X-Calculatedbetarget:
- exdag20-2.exchange.int
X-Diaginfo:
- EXDAG20-2
X-Beserver:
- EXDAG20-2
X-Aspnet-Version:
- 4.0.30319
Set-Cookie:
- X-BackEndCookie=S-1-5-21-2149852636-2334046265-983485362-135679=u56Lnp2ejJqBzpnGyczNzMjSy8nOydLLnJzM0seamc/SzMjJxs6bm8eazZnIgYHNz87H0s7P0s/Lq8/Kxc3Gxc3O;
expires=Thu, 04-Oct-2018 05:29:21 GMT; path=/EWS; secure; HttpOnly
- exchangecookie=36481ec209524d17beb8a645d1e9a389; expires=Wed, 04-Sep-2019
05:29:21 GMT; path=/; HttpOnly
Persistent-Auth:
- 'true'
X-Powered-By:
- ASP.NET
X-Feserver:
- EXFE06
Date:
- Tue, 04 Sep 2018 05:29:21 GMT
body:
encoding: UTF-8
string: <?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Header><h:ServerVersionInfo
MajorVersion="15" MinorVersion="0" MajorBuildNumber="1293" MinorBuildNumber="6"
Version="V2_23" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/></s:Header><s:Body
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><m:FindFolderResponse
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"><m:ResponseMessages><m:FindFolderResponseMessage
ResponseClass="Success"><m:ResponseCode>NoError</m:ResponseCode><m:RootFolder
TotalItemsInView="1" IncludesLastItemInRange="true"><t:Folders><t:Folder><t:FolderId
Id="AQMkADRjMTk4NmJlLTNjMGUtNDk1Yy04MjAxLWE2Nzk0NWYzY2MANTcALgAAA9shP4dg44BKifl+6m/8GgMBALoafj1aZ5lBsuy9VYcX6tAAAAIBDAAAAA=="
ChangeKey="AQAAABYAAAC6Gn49WmeZQbLsvVWHF+rQAAAAABsE"/><t:DisplayName>Inbox</t:DisplayName><t:TotalCount>0</t:TotalCount><t:ChildFolderCount>1</t:ChildFolderCount><t:UnreadCount>0</t:UnreadCount></t:Folder></t:Folders></m:RootFolder></m:FindFolderResponseMessage></m:ResponseMessages></m:FindFolderResponse></s:Body></s:Envelope>
http_version:
recorded_at: Tue, 04 Sep 2018 05:29:21 GMT
recorded_with: VCR 4.0.0