17337: Added more tests to cover edge cases
authorDaniel Kutyła <daniel.kutyla@contractors.roche.com>
Fri, 26 Mar 2021 12:54:21 +0000 (13:54 +0100)
committerDaniel Kutyła <daniel.kutyla@contractors.roche.com>
Fri, 26 Mar 2021 12:54:21 +0000 (13:54 +0100)
Arvados-DCO-1.1-Signed-off-by: Daniel Kutyła <daniel.kutyla@contractors.roche.com>

cypress/integration/collection.spec.js
src/common/webdav.ts
src/common/xml.ts
src/services/collection-service/collection-service-files-response.test.ts
src/services/collection-service/collection-service-files-response.ts

index 3041acf5b2cd9e783a4241190862ec27cbdccd2a..7764a8ebbc6264105beffb208d1dfc061ff18fd9 100644 (file)
@@ -206,6 +206,7 @@ describe('Collection panel tests', function () {
                     'some%22file.pdf',
                     'some%20file.pdf',
                     "G%C3%BCnter's%20file.pdf",
                     'some%22file.pdf',
                     'some%20file.pdf',
                     "G%C3%BCnter's%20file.pdf",
+                    'table%&?*2',
                     'bar' // make sure we can go back to the original name as a last step
                 ];
                 eachPair(names, (from, to) => {
                     'bar' // make sure we can go back to the original name as a last step
                 ];
                 eachPair(names, (from, to) => {
index 8d071fa635ce2f0dc58085e447f981191d96e8a7..0b77f8c33262e9b7b0b284b4da682d6ec58ceb85 100644 (file)
@@ -2,7 +2,7 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { customEncodeURI, encodeHash } from "./url";
+import { customEncodeURI } from "./url";
 
 export class WebDAV {
 
 
 export class WebDAV {
 
@@ -80,7 +80,9 @@ export class WebDAV {
                     : ''}${customEncodeURI(config.url)}`);
 
             if (config.headers && config.headers.Destination) {
                     : ''}${customEncodeURI(config.url)}`);
 
             if (config.headers && config.headers.Destination) {
-                config.headers.Destination = encodeHash(config.headers.Destination);
+                const regexp = /(http[s]?:\/\/)?([^\/\s]+\/)(.*)/;
+                const match = decodeURIComponent(config.headers.Destination).match(regexp) || {};
+                config.headers.Destination = `${match[1]}${match[2]}${customEncodeURI(match[3])}`;
             }
 
             const headers = { ...this.defaults.headers, ...config.headers };
             }
 
             const headers = { ...this.defaults.headers, ...config.headers };
index 751a327c77cb48ec64cc23611bb4834c5388e093..e7db3acad8d904b58b4ae0c2061023eaade227b4 100644 (file)
@@ -2,13 +2,17 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-export const getTagValue = (document: Document | Element, tagName: string, defaultValue: string) => {
+import { customDecodeURI } from "./url";
+
+export const getTagValue = (document: Document | Element, tagName: string, defaultValue: string, skipDecoding: boolean = false) => {
     const [el] = Array.from(document.getElementsByTagName(tagName));
     const URI = el ? htmlDecode(el.innerHTML) : defaultValue;
 
     const [el] = Array.from(document.getElementsByTagName(tagName));
     const URI = el ? htmlDecode(el.innerHTML) : defaultValue;
 
-    try {
-        return decodeURI(URI);
-    } catch(e) {}
+    if (!skipDecoding) {
+        try {
+            return customDecodeURI(URI);
+        } catch(e) {}
+    }
 
     return URI;
 };
 
     return URI;
 };
index ad75f572aa6d44836acc47a69cf4b5161062824f..17a1f38820929d6aa8a7809216891db972ded805 100644 (file)
@@ -20,6 +20,19 @@ describe('collection-service-files-response', () => {
             // then
             expect(result).toEqual([{ id: "zzzzz-xxxxx-vvvvvvvvvvvvvvv/2", name: "2", path: "", size: 1582976, type: "file", url: "/c=zzzzz-xxxxx-vvvvvvvvvvvvvvv/2" }, { id: "zzzzz-xxxxx-vvvvvvvvvvvvvvv/table 1 2 3", name: "table 1 2 3", path: "", size: 133352, type: "file", url: "/c=zzzzz-xxxxx-vvvvvvvvvvvvvvv/table 1 2 3" }]);
         });
             // then
             expect(result).toEqual([{ id: "zzzzz-xxxxx-vvvvvvvvvvvvvvv/2", name: "2", path: "", size: 1582976, type: "file", url: "/c=zzzzz-xxxxx-vvvvvvvvvvvvvvv/2" }, { id: "zzzzz-xxxxx-vvvvvvvvvvvvvvv/table 1 2 3", name: "table 1 2 3", path: "", size: 133352, type: "file", url: "/c=zzzzz-xxxxx-vvvvvvvvvvvvvvv/table 1 2 3" }]);
         });
+
+        it('should extract ecoded data and do not encode already encoded props', () => {
+            // given
+            const xmlString = '<?xml version="1.0" encoding="UTF-8"?><D:multistatus xmlns:D="DAV:"><D:response><D:href>/c=zzzzz-xxxxx-vvvvvvvvvvvvvvv/</D:href><D:propstat><D:prop><D:resourcetype><D:collection xmlns:D="DAV:"/></D:resourcetype><D:getlastmodified>Fri, 26 Mar 2021 11:45:50 GMT</D:getlastmodified><D:supportedlock><D:lockentry xmlns:D="DAV:"><D:lockscope><D:exclusive/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockentry></D:supportedlock><D:displayname></D:displayname></D:prop><D:status>HTTP/1.1 200 OK</D:status></D:propstat></D:response><D:response><D:href>/c=zzzzz-xxxxx-vvvvvvvvvvvvvvv/table%25&amp;%3F%2A2</D:href><D:propstat><D:prop><D:resourcetype></D:resourcetype><D:getcontentlength>3</D:getcontentlength><D:getlastmodified>Fri, 26 Mar 2021 11:45:50 GMT</D:getlastmodified><D:getetag>"166fe1e1a403fb683"</D:getetag><D:getcontenttype>text/plain; charset=utf-8</D:getcontenttype><D:supportedlock><D:lockentry xmlns:D="DAV:"><D:lockscope><D:exclusive/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockentry></D:supportedlock><D:displayname>table%&amp;?*2</D:displayname></D:prop><D:status>HTTP/1.1 200 OK</D:status></D:propstat></D:response></D:multistatus>';
+            const parser = new DOMParser();
+            const xmlDoc = parser.parseFromString(xmlString, "text/xml");
+
+            // when
+            const result = extractFilesData(xmlDoc);
+
+            // then
+            expect(result).toEqual([{ id: "zzzzz-xxxxx-vvvvvvvvvvvvvvv/table%&?*2", name: "table%&?*2", path: "", size: 3, type: "file", url: "/c=zzzzz-xxxxx-vvvvvvvvvvvvvvv/table%&?*2" }]);
+        });
     });
 
     describe('getFileFullPath', () => {
     });
 
     describe('getFileFullPath', () => {
index 9583b7a4ebd749ffaa2898ad176830c4214f8573..1be99457c84431cd5d9832d790eb4234832e075d 100644 (file)
@@ -5,7 +5,6 @@
 import { CollectionDirectory, CollectionFile, CollectionFileType, createCollectionDirectory, createCollectionFile } from "../../models/collection-file";
 import { getTagValue } from "~/common/xml";
 import { getNodeChildren, Tree, mapTree } from '~/models/tree';
 import { CollectionDirectory, CollectionFile, CollectionFileType, createCollectionDirectory, createCollectionFile } from "../../models/collection-file";
 import { getTagValue } from "~/common/xml";
 import { getNodeChildren, Tree, mapTree } from '~/models/tree';
-import { customDecodeURI } from "~/common/url";
 
 export const sortFilesTree = (tree: Tree<CollectionDirectory | CollectionFile>) => {
     return mapTree<CollectionDirectory | CollectionFile>(node => {
 
 export const sortFilesTree = (tree: Tree<CollectionDirectory | CollectionFile>) => {
     return mapTree<CollectionDirectory | CollectionFile>(node => {
@@ -26,10 +25,9 @@ export const extractFilesData = (document: Document) => {
         .from(document.getElementsByTagName('D:response'))
         .slice(1) // omit first element which is collection itself
         .map(element => {
         .from(document.getElementsByTagName('D:response'))
         .slice(1) // omit first element which is collection itself
         .map(element => {
-            const name = getTagValue(element, 'D:displayname', '');
-            const size = parseInt(getTagValue(element, 'D:getcontentlength', '0'), 10);
-            const href = getTagValue(element, 'D:href', '');
-            const url = customDecodeURI(href);
+            const name = getTagValue(element, 'D:displayname', '', true); // skip decoding as value should be already decoded
+            const size = parseInt(getTagValue(element, 'D:getcontentlength', '0', true), 10);
+            const url = getTagValue(element, 'D:href', '');
             const nameSuffix = name;
             const collectionUuidMatch = collectionUrlPrefix.exec(url);
             const collectionUuid = collectionUuidMatch ? collectionUuidMatch.pop() : '';
             const nameSuffix = name;
             const collectionUuidMatch = collectionUrlPrefix.exec(url);
             const collectionUuid = collectionUuidMatch ? collectionUuidMatch.pop() : '';