[ARVADOS-WORKBENCH2] created: 2.4.0-12-g444c41ca

Git user git at public.arvados.org
Tue Apr 12 20:22:28 UTC 2022


        at  444c41ca81c90ff172c7b1d99ff78f52bff991e8 (commit)


commit 444c41ca81c90ff172c7b1d99ff78f52bff991e8
Author: Stephen Smith <stephen at curii.com>
Date:   Tue Apr 12 16:19:58 2022 -0400

    16068: Fix flaky test maybe
    
    Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>

diff --git a/cypress/integration/collection.spec.js b/cypress/integration/collection.spec.js
index 74acd056..79a66a4c 100644
--- a/cypress/integration/collection.spec.js
+++ b/cypress/integration/collection.spec.js
@@ -334,7 +334,7 @@ describe('Collection panel tests', function () {
                     'bar' // make sure we can go back to the original name as a last step
                 ];
                 eachPair(names, (from, to) => {
-                    cy.get('[data-cy=collection-files-panel]')
+                    cy.waitForDom().get('[data-cy=collection-files-panel]')
                         .contains(`${from}`).rightclick();
                     cy.get('[data-cy=context-menu]')
                         .contains('Rename')
diff --git a/cypress/support/commands.js b/cypress/support/commands.js
index 5a2428b2..5764808c 100644
--- a/cypress/support/commands.js
+++ b/cypress/support/commands.js
@@ -381,3 +381,73 @@ function b64toBlob(b64Data, contentType = '', sliceSize = 512) {
     const blob = new Blob(byteArrays, { type: contentType });
     return blob
 }
+
+// From https://github.com/cypress-io/cypress/issues/7306#issuecomment-1076451070=
+// This command requires the async package (https://www.npmjs.com/package/async)
+Cypress.Commands.add('waitForDom', () => {
+    cy.window().then(win => {
+      let timeElapsed = 0;
+
+      cy.log("Waiting for DOM mutations to complete");
+
+      return new Cypress.Promise((resolve) => {
+        // set the required variables
+        let async = require("async");
+        let observerConfig = { attributes: true, childList: true, subtree: true };
+        let items = Array.apply(null, { length: 50 }).map(Number.call, Number);
+        win.mutationCount = 0;
+        win.previousMutationCount = null;
+
+        // create an observer instance
+        let observer = new win.MutationObserver((mutations) => {
+          mutations.forEach((mutation) => {
+            // Only record "attributes" type mutations that are not a "class" mutation.
+            // If the mutation is not an "attributes" type, then we always record it.
+            if (mutation.type === 'attributes' && mutation.attributeName !== 'class') {
+              win.mutationCount += 1;
+            } else if (mutation.type !== 'attributes') {
+              win.mutationCount += 1;
+            }
+          });
+
+          // initialize the previousMutationCount
+          if (win.previousMutationCount == null) win.previousMutationCount = 0;
+        });
+
+        // watch the document body for the specified mutations
+        observer.observe(win.document.body, observerConfig);
+
+        // check the DOM for mutations up to 50 times for a maximum time of 5 seconds
+        async.eachSeries(items, function iteratee(item, callback) {
+          // keep track of the elapsed time so we can log it at the end of the command
+          timeElapsed = timeElapsed + 100;
+
+          // make each iteration of the loop 100ms apart
+          setTimeout(() => {
+            if (win.mutationCount === win.previousMutationCount) {
+              // pass an argument to the async callback to exit the loop
+              return callback('Resolved - DOM changes complete.');
+            } else if (win.previousMutationCount != null) {
+              // only set the previous count if the observer has checked the DOM at least once
+              win.previousMutationCount = win.mutationCount;
+              return callback();
+            } else if (win.mutationCount === 0 && win.previousMutationCount == null && item === 4) {
+              // this is an early exit in case nothing is changing in the DOM. That way we only
+              // wait 500ms instead of the full 5 seconds when no DOM changes are occurring.
+              return callback('Resolved - Exiting early since no DOM changes were detected.');
+            } else {
+              // proceed to the next iteration
+              return callback();
+            }
+          }, 100);
+        }, function done() {
+          // Log the total wait time so users can see it
+          cy.log(`DOM mutations ${timeElapsed >= 5000 ? "did not complete" : "completed"} in ${timeElapsed} ms`);
+
+          // disconnect the observer and resolve the promise
+          observer.disconnect();
+          resolve();
+        });
+      });
+    });
+  });
diff --git a/cypress/support/index.d.ts b/cypress/support/index.d.ts
new file mode 100644
index 00000000..d74d5b3d
--- /dev/null
+++ b/cypress/support/index.d.ts
@@ -0,0 +1,24 @@
+/**
+  * This command tries to ensure that the elements in the DOM are actually visible
+  * and done (re)rendering. This is due to how React re-renders components.
+  *
+  * IMPORTANT NOTES:
+  *    => You should only use this command in instances where a test is failing due
+  *       to detached elements. Cypress will probably give you a warning along the lines
+  *       of, "Element has an effective width/height of 0". This warning is not very useful
+  *       in pointing out it is due to the element being detached from the DOM AFTER the
+  *       cy.get command had already retrieved it. This command can save you from that
+  *       by explicitly waiting for the DOM to stop changing.
+  *    => This command can take anywhere from 100ms to 5 seconds to complete
+  *    => This command will exit early (500ms) when no changes are occurring in the DOM.
+  *       We wait a minimum of 500ms because sometimes it can take up to around that time
+  *       for mutations to start occurring.
+  *
+  * GitHub Issues:
+  *    * https://github.com/cypress-io/cypress/issues/695 (Closed - no activity)
+  *    * https://github.com/cypress-io/cypress/issues/7306 (Open - re-get detached elements)
+  *
+  * @example Wait for the DOM to stop changing before retrieving an element
+  * cy.waitForDom().get('#an-elements-id')
+  */
+ waitForDom(): Chainable<any>

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list