"baseUrl": "https://localhost:3000/",
"chromeWebSecurity": false,
"viewportWidth": 1920,
- "viewportHeight": 1080
+ "viewportHeight": 1080,
+ "downloadsFolder": "cypress/downloads"
}
//
// SPDX-License-Identifier: AGPL-3.0
+const path = require('path');
+
describe('Collection panel tests', function () {
let activeUser;
let adminUser;
+ let downloadsFolder;
before(function () {
// Only set up common users once. These aren't set up as aliases because
activeUser = this.activeUser;
}
);
+ downloadsFolder = Cypress.config('downloadsFolder');
});
beforeEach(function () {
cy.clearLocalStorage();
});
+ it('allows to download mountain duck config for a collection', () => {
+ cy.createCollection(adminUser.token, {
+ name: `Test collection ${Math.floor(Math.random() * 999999)}`,
+ owner_uuid: activeUser.user.uuid,
+ manifest_text: ". 37b51d194a7513e45b56f6524f2d51f2+3 0:3:bar\n"
+ })
+ .as('testCollection').then(function (testCollection) {
+ cy.loginAs(activeUser);
+ cy.goToPath(`/collections/${testCollection.uuid}`);
+
+ cy.get('[data-cy=collection-panel-options-btn]').click();
+ cy.get('[data-cy=context-menu]').contains('Open as network folder or S3 bucket').click();
+ cy.get('[data-cy=download-button').click();
+
+ const filename = path.join(downloadsFolder, `${testCollection.name}.duck`);
+
+ cy.readFile(filename, { timeout: 15000 })
+ .then((body) => {
+ const childrenCollection = Array.prototype.slice.call(Cypress.$(body).find('dict')[0].children);
+ const map = {};
+ let i, j = 2;
+
+ for (i=0; i < childrenCollection.length; i += j) {
+ map[childrenCollection[i].outerText] = childrenCollection[i + 1].outerText;
+ }
+
+ cy.get('#simple-tabpanel-0').find('a')
+ .then((a) => {
+ const [host, port] = a.text().split('@')[1].split('/')[0].split(':');
+ expect(map['Protocol']).to.equal('davs');
+ expect(map['UUID']).to.equal(testCollection.uuid);
+ expect(map['Username']).to.equal(activeUser.user.username);
+ expect(map['Port']).to.equal(port);
+ expect(map['Hostname']).to.equal(host);
+ if (map['Path']) {
+ expect(map['Path']).to.equal(`/c=${testCollection.uuid}`);
+ }
+ });
+ })
+ .then(() => cy.task('clearDownload', { filename }));
+ });
+ });
+
it('uses the property editor with vocabulary terms', function () {
cy.createCollection(adminUser.token, {
name: `Test collection ${Math.floor(Math.random() * 999999)}`,
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
+const fs = require('fs');
+const path = require('path');
+
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
+ on("before:browser:launch", (browser = {}, launchOptions) => {
+ const downloadDirectory = path.join(__dirname, "..", "downloads");
+ if (browser.family === 'chromium' && browser.name !== 'electron') {
+ launchOptions.preferences.default["download"] = {
+ default_directory: downloadDirectory
+ };
+ }
+ return launchOptions;
+ });
+
+ on('task', {
+ clearDownload({ filename }) {
+ fs.unlinkSync(filename);
+ return null;
+ }
+ });
}
"@types/sinon": "7.5",
"@types/uuid": "3.4.4",
"axios-mock-adapter": "1.17.0",
- "cypress": "6.2.1",
+ "cypress": "6.3.0",
"enzyme": "3.6.0",
"enzyme-adapter-react-16": "1.5.0",
"jest-localstorage-mock": "2.2.0",
import { ServiceRepository } from "~/services/services";
import { dialogActions } from '~/store/dialog/dialog-actions';
import { getNewExtraToken } from "../auth/auth-action";
+import { CollectionResource } from "~/models/collection";
export const COLLECTION_WEBDAV_S3_DIALOG_NAME = 'collectionWebdavS3Dialog';
localCluster: string;
username: string;
activeTab: number;
+ collectionName: string;
setActiveTab: (event: any, tabNr: number) => void;
}
localCluster: getState().auth.localCluster,
username: getState().auth.user!.username,
activeTab: activeTab || 0,
+ collectionName: (getState().resources[uuid] as CollectionResource).name,
setActiveTab: (event: any, tabNr: number) => dispatch<any>(openWebDavS3InfoDialog(uuid, tabNr)),
uuid
}
import { WithDialogProps } from '~/store/dialog/with-dialog';
import { compose } from 'redux';
import { DetailsAttribute } from "~/components/details-attribute/details-attribute";
+import { DownloadIcon } from "~/components/icon/icon";
-export type CssRules = 'details';
+export type CssRules = 'details' | 'downloadButton';
const styles: StyleRulesCallback<CssRules> = theme => ({
details: {
marginLeft: theme.spacing.unit * 3,
marginRight: theme.spacing.unit * 3,
+ },
+ downloadButton: {
+ marginTop: theme.spacing.unit * 2,
}
});
);
}
+const isValidIpAddress = (ipAddress: string): Boolean => {
+ if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(ipAddress)) {
+ return true;
+ }
+
+ return false;
+};
+
+const mountainduckTemplate = ({
+ uuid,
+ username,
+ cyberDavStr,
+ collectionsUrl
+}: any) => {
+
+ return `<?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+ <plist version="1.0">
+ <dict>
+ <key>Protocol</key>
+ <string>davs</string>
+ <key>Provider</key>
+ <string>iterate GmbH</string>
+ <key>UUID</key>
+ <string>${uuid}</string>
+ <key>Hostname</key>
+ <string>${collectionsUrl.replace('https://', ``).replace('*', uuid).split(':')[0]}</string>
+ <key>Port</key>
+ <string>${(cyberDavStr.split(':')[2] || '443').split('/')[0]}</string>
+ <key>Username</key>
+ <string>${username}</string>${isValidIpAddress(collectionsUrl.replace('https://', ``).split(':')[0])?
+ `
+ <key>Path</key>
+ <string>/c=${uuid}</string>` : ''}
+ <key>Labels</key>
+ <array>
+ </array>
+ </dict>
+ </plist>`.split(/\r?\n/).join('\n');
+};
+
+const downloadMountainduckFileHandler = (filename: string, text: string) => {
+ const element = document.createElement('a');
+ element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
+ element.setAttribute('download', filename);
+
+ element.style.display = 'none';
+ document.body.appendChild(element);
+
+ element.click();
+
+ document.body.removeChild(element);
+};
+
export const WebDavS3InfoDialog = compose(
withDialog(COLLECTION_WEBDAV_S3_DIALOG_NAME),
withStyles(styles),
value={props.data.token}
copyValue={props.data.token} />
+ <Button
+ data-cy='download-button'
+ className={props.classes.downloadButton}
+ onClick={() => downloadMountainduckFileHandler(`${props.data.collectionName || props.data.uuid}.duck`, mountainduckTemplate({ ...props.data, cyberDavStr }))}
+ variant='contained'
+ color='primary'
+ size='small'>
+ <DownloadIcon />
+ Download Cyber/Mountain Duck bookmark
+ </Button>
+
<h3>Gnome</h3>
<ol>
<li>Open Files</li>
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
-cypress@6.2.1:
- version "6.2.1"
- resolved "https://registry.yarnpkg.com/cypress/-/cypress-6.2.1.tgz#27d5fbcf008c698c390fdb0c03441804176d06c4"
- integrity sha512-OYkSgzA4J4Q7eMjZvNf5qWpBLR4RXrkqjL3UZ1UzGGLAskO0nFTi/RomNTG6TKvL3Zp4tw4zFY1gp5MtmkCZrA==
+cypress@6.3.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/cypress/-/cypress-6.3.0.tgz#e27bba01d7e493265700e1e85333dca0b0127ede"
+ integrity sha512-Ec6TAFOxdSB2HPINNJ1f7z75pENXcfCaQkz+A9j0eGSvusFJ2NNErq650DexCbNJAnCQkPqXB4XPH9kXnSQnUA==
dependencies:
"@cypress/listr-verbose-renderer" "^0.4.1"
"@cypress/request" "^2.88.5"