Merge branch '19991-breadcrumbs-missing-bug' into main. Closes #19991
authorStephen Smith <stephen@curii.com>
Mon, 21 Aug 2023 17:34:00 +0000 (13:34 -0400)
committerStephen Smith <stephen@curii.com>
Mon, 21 Aug 2023 17:34:00 +0000 (13:34 -0400)
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen@curii.com>

cypress/integration/collection.spec.js
cypress/integration/project.spec.js
cypress/integration/search.spec.js
cypress/integration/side-panel.spec.js
cypress/integration/virtual-machine-admin.spec.js
src/store/breadcrumbs/breadcrumbs-actions.ts
tools/run-integration-tests.sh

index d5b1b9ebcf7169dec5649e89d1f82de52b3a250c..a2841eb827fb432a75bcffe7b7af2f5bad229306 100644 (file)
@@ -876,6 +876,7 @@ describe('Collection panel tests', function () {
                     .should('contain', '3').and('contain', '3 B');
 
                 // Check context menus on version browser
+                cy.waitForDom();
                 cy.get('[data-cy=collection-version-browser-select-3]').rightclick()
                 cy.get('[data-cy=context-menu]')
                     .should('contain', 'Add to favorites')
@@ -932,7 +933,7 @@ describe('Collection panel tests', function () {
 
                 cy.waitForDom().get('.layout-pane-primary', { timeout: 12000 }).contains('Projects').click();
 
-                cy.get('main').contains(`Files extracted from: ${this.collection.name}`).click();
+                cy.waitForDom().get('main').contains(`Files extracted from: ${this.collection.name}`).click();
                 cy.get('[data-cy=collection-files-panel]')
                         .and('contain', 'bar');
             });
index eff4d4e9f18651fc322b7374b0d4b03adf613fbb..fd14cc4226323b331a22c09ea35724748a07f6b7 100644 (file)
@@ -554,7 +554,7 @@ describe('Project tests', function() {
         cy.get('[data-cy=context-menu]').contains('Copy to clipboard').click();
         cy.window().then((win) => (
             win.navigator.clipboard.readText().then((text) => {
-                expect(text).to.match(/https\:\/\/localhost\:[0-9]+\/projects\/[a-z0-9]{5}-[a-z0-9]{5}-[a-z0-9]{15}/,);
+                expect(text).to.match(/https\:\/\/127\.0\.0\.1\:[0-9]+\/projects\/[a-z0-9]{5}-[a-z0-9]{5}-[a-z0-9]{15}/,);
             })
         ));
 
index c8e262f011097b43ad9b5902a7d75bacdfa26cf1..085298dcd0e05e1c485167c83f5b13a4291e6c27 100644 (file)
@@ -161,12 +161,12 @@ describe('Search tests', function() {
     });
 
     it('shows search context menu', function() {
-        const colName = `Collection ${Math.floor(Math.random() * Math.floor(999999))}`;
-        const federatedColName = `Collection ${Math.floor(Math.random() * Math.floor(999999))}`;
+        const colName = `Home Collection ${Math.floor(Math.random() * Math.floor(999999))}`;
+        const federatedColName = `Federated Collection ${Math.floor(Math.random() * Math.floor(999999))}`;
         const federatedColUuid = "xxxxx-4zz18-000000000000000";
 
         // Intercept config to insert remote cluster
-        cy.intercept({method: 'GET', hostname: 'localhost', url: '**/arvados/v1/config?nocache=*'}, (req) => {
+        cy.intercept({method: 'GET', hostname: '127.0.0.1', url: '**/arvados/v1/config?nocache=*'}, (req) => {
             req.reply((res) => {
                 res.body.RemoteClusters = {
                     "*": res.body.RemoteClusters["*"],
@@ -280,6 +280,7 @@ describe('Search tests', function() {
                 cy.contains('View details');
 
                 cy.contains('Copy to clipboard').click();
+                cy.waitForDom();
                 cy.window().then((win) => (
                     win.navigator.clipboard.readText().then((text) => {
                         expect(text).to.match(new RegExp(`/collections/${testCollection.uuid}$`));
@@ -291,6 +292,7 @@ describe('Search tests', function() {
             cy.get('[data-cy=search-results]').contains(colName).rightclick();
             cy.get('[data-cy=context-menu]').within(() => {
                 cy.contains('Open in new tab').click();
+                cy.waitForDom();
                 cy.get('@Open').should('have.been.calledOnceWith', `${window.location.origin}/collections/${testCollection.uuid}`)
             });
 
@@ -298,6 +300,7 @@ describe('Search tests', function() {
             cy.get('[data-cy=search-results]').contains(federatedColName).rightclick();
             cy.get('[data-cy=context-menu]').within(() => {
                 cy.contains('Copy to clipboard').click();
+                cy.waitForDom();
                 cy.window().then((win) => (
                     win.navigator.clipboard.readText().then((text) => {
                         expect(text).to.equal(`https://wb2.xxxxx.fakecluster.tld/collections/${federatedColUuid}`);
@@ -308,6 +311,7 @@ describe('Search tests', function() {
             cy.get('[data-cy=search-results]').contains(federatedColName).rightclick();
             cy.get('[data-cy=context-menu]').within(() => {
                 cy.contains('Open in new tab').click();
+                cy.waitForDom();
                 cy.get('@Open').should('have.been.calledWith', `https://wb2.xxxxx.fakecluster.tld/collections/${federatedColUuid}`)
             });
 
index e187d533ead19b2b43e9ed01aae24215f84c4955..92181150edddd2f07c2e67a56e63ec03327732ce 100644 (file)
@@ -65,7 +65,7 @@ describe('Side panel tests', function() {
             {url: '/all_processes', label: 'All Processes'},
             {url: '/trash', label: 'Trash'},
         ].map(function(section) {
-            cy.goToPath(section.url);
+            cy.waitForDom().goToPath(section.url);
             cy.get('[data-cy=breadcrumb-first]')
                 .should('contain', section.label);
             cy.get('[data-cy=side-panel-button]')
index 49cb12394648138417404b52a001f2698002a541..80d649777bfb436d6f9052f17dd74ccbfd0d63ae 100644 (file)
@@ -50,7 +50,7 @@ describe('Virtual machine login manage tests', function() {
                     cy.get('input').type('VMAdmin');
                   })
             });
-        cy.get('[role=tooltip]').click();
+        cy.waitForDom().get('[role=tooltip]').click();
         cy.get('[data-cy=form-dialog]').as('add-login-dialog')
             .should('contain', 'Add login permission')
             .within(() => {
@@ -269,11 +269,11 @@ describe('Virtual machine login manage tests', function() {
         cy.get('@removeButton').click();
         cy.get('[data-cy=confirmation-dialog-ok-btn]').click();
 
-        cy.get('[data-cy=vm-admin-table]')
+        cy.waitForDom().get('[data-cy=vm-admin-table]')
             .contains(vmHost)
             .parents('tr')
             .within(() => {
-                cy.get('div[role=button]').should('not.contain', 'admin');
+                cy.get('div[role=button]').should('not.exist');
             });
 
         // Check admin's vm page for login
index a7e42510b1239ffe643c809b0b7ecf884c881299..9c9baf08ad76977d708d41107acf1873fee6b440 100644 (file)
@@ -6,8 +6,6 @@ import { Dispatch } from 'redux';
 import { RootState } from 'store/store';
 import { getUserUuid } from "common/getuser";
 import { getResource } from 'store/resources/resources';
-import { TreePicker } from '../tree-picker/tree-picker';
-import { getSidePanelTreeBranch, getSidePanelTreeNodeAncestorsIds } from '../side-panel-tree/side-panel-tree-actions';
 import { propertiesActions } from '../properties/properties-actions';
 import { getProcess } from 'store/processes/process';
 import { ServiceRepository } from 'services/services';
@@ -57,25 +55,40 @@ const resourceToBreadcrumb = (resource: CollectionResource | ContainerRequestRes
     icon: resourceToBreadcrumbIcon(resource),
 })
 
-const getSidePanelTreeBreadcrumbs = (uuid: string) => (treePicker: TreePicker): Breadcrumb[] => {
-    const nodes = getSidePanelTreeBranch(uuid)(treePicker);
-    return nodes.map(node =>
-        typeof node.value === 'string'
-            ? {
-                label: node.value,
-                uuid: node.id,
-                icon: getSidePanelIcon(node.value)
-            }
-            : resourceToBreadcrumb(node.value));
-};
-
 export const setSidePanelBreadcrumbs = (uuid: string) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-        const { treePicker, collectionPanel: { item } } = getState();
-        const breadcrumbs = getSidePanelTreeBreadcrumbs(uuid)(treePicker);
+        const ancestors = await services.ancestorsService.ancestors(uuid, '');
+        dispatch(updateResources(ancestors));
+
+        let breadcrumbs: Breadcrumb[] = [];
+        const { collectionPanel: { item } } = getState();
+
         const path = getState().router.location!.pathname;
         const currentUuid = path.split('/')[2];
         const uuidKind = extractUuidKind(currentUuid);
+        const rootUuid = getUserUuid(getState());
+
+        if (ancestors.find(ancestor => ancestor.uuid === rootUuid)) {
+            // Handle home project uuid root
+            breadcrumbs.push({
+                label: SidePanelTreeCategory.PROJECTS,
+                uuid: SidePanelTreeCategory.PROJECTS,
+                icon: getSidePanelIcon(SidePanelTreeCategory.PROJECTS)
+            });
+        } else if (Object.values(SidePanelTreeCategory).includes(uuid as SidePanelTreeCategory)) {
+            // Handle SidePanelTreeCategory root
+            breadcrumbs.push({
+                label: uuid,
+                uuid: uuid,
+                icon: getSidePanelIcon(uuid)
+            });
+        }
+
+        breadcrumbs = ancestors.reduce((breadcrumbs, ancestor) =>
+            ancestor.kind === ResourceKind.GROUP
+                ? [...breadcrumbs, resourceToBreadcrumb(ancestor)]
+                : breadcrumbs,
+            breadcrumbs);
 
         if (uuidKind === ResourceKind.COLLECTION) {
             const collectionItem = item ? item : await services.collectionService.get(currentUuid);
@@ -189,10 +202,10 @@ const getCollectionParent = (collection: CollectionResource) =>
 
 
 export const setProjectBreadcrumbs = (uuid: string) =>
-    (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
-        const ancestors = getSidePanelTreeNodeAncestorsIds(uuid)(getState().treePicker);
+    async (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
+        const ancestors = await services.ancestorsService.ancestors(uuid, '');
         const rootUuid = getUserUuid(getState());
-        if (uuid === rootUuid || ancestors.find(uuid => uuid === rootUuid)) {
+        if (uuid === rootUuid || ancestors.find(ancestor => ancestor.uuid === rootUuid)) {
             dispatch(setSidePanelBreadcrumbs(uuid));
         } else {
             dispatch(setSharedWithMeBreadcrumbs(uuid));
index 367ccecd3512d90f261adc30b85405aac3f6176a..1f2b7c5ee585a0b7ec4d9250005a8f5d155472dd 100755 (executable)
@@ -139,10 +139,10 @@ exec 8<&"${wb2[0]}"; coproc consume_wb2_stdout (cat <&8 >&2)
 
 # Wait for workbench2 to be up.
 # Using https-get to avoid false positive 'ready' detection.
-yarn run wait-on --timeout 300000 https-get://localhost:${WB2_PORT} || exit 1
+yarn run wait-on --timeout 300000 https-get://127.0.0.1:${WB2_PORT} || exit 1
 
 echo "Running tests..."
 CYPRESS_system_token=systemusertesttoken1234567890aoeuidhtnsqjkxbmwvzpy \
     CYPRESS_controller_url=${controllerURL} \
-    CYPRESS_BASE_URL=https://localhost:${WB2_PORT} \
+    CYPRESS_BASE_URL=https://127.0.0.1:${WB2_PORT} \
     yarn run cypress ${CYPRESS_MODE}