From 10cbb523e503b2003278cfbf8d0803b7d4086d36 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Mon, 2 Jun 2025 13:52:35 +0200 Subject: [PATCH] Bug 40051: Remove cy.wait(delay) from cypress tests We should not use cy.wait(delay), it's a poor pattern and can cause random failures. Test plan: All cypress tests should still pass after this patchset. Note that t/cypress/integration/ERM/Titles_spec.ts is currently failing. --- .../integration/Acquisitions/Vendors_spec.ts | 5 ++--- .../integration/AdditionalFields_spec.ts | 12 ++++++------ t/cypress/integration/ERM/Agreements_spec.ts | 9 ++++----- .../integration/ERM/DataProviders_spec.ts | 13 ++++++------- t/cypress/integration/ERM/Licenses_spec.ts | 12 ++++++------ t/cypress/integration/ERM/Packages_spec.ts | 15 +++++++-------- t/cypress/integration/ERM/Titles_spec.ts | 19 +++++++++---------- .../integration/InfiniteScrollSelect_spec.ts | 1 - .../integration/KohaTable/KohaTable_spec.ts | 8 ++------ 9 files changed, 42 insertions(+), 52 deletions(-) diff --git a/t/cypress/integration/Acquisitions/Vendors_spec.ts b/t/cypress/integration/Acquisitions/Vendors_spec.ts index 7935d40d4f6..dacb0ac3cd0 100644 --- a/t/cypress/integration/Acquisitions/Vendors_spec.ts +++ b/t/cypress/integration/Acquisitions/Vendors_spec.ts @@ -200,7 +200,6 @@ describe("Vendor CRUD operations", () => { // Click the 'Edit' button from the list cy.get("#vendors_list table tbody tr:first").contains("Edit").click(); cy.wait("@get-vendor"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#vendor_add h1").contains("Edit vendor"); // Form has been correctly filled in @@ -229,8 +228,9 @@ describe("Vendor CRUD operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-vendors"); cy.visit("/cgi-bin/koha/acquisition/vendors"); + cy.wait("@get-vendors"); cy.intercept( "GET", new RegExp("/api/v1/acquisitions/vendors/(?!config$).+"), @@ -242,7 +242,6 @@ describe("Vendor CRUD operations", () => { ); name_link.should("have.text", vendor.name + " (#" + vendor.id + ")"); name_link.click(); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#vendors_show h1").contains(vendor.name); // TODO Test contracts table diff --git a/t/cypress/integration/AdditionalFields_spec.ts b/t/cypress/integration/AdditionalFields_spec.ts index 8d8907fae1b..a8c65041167 100644 --- a/t/cypress/integration/AdditionalFields_spec.ts +++ b/t/cypress/integration/AdditionalFields_spec.ts @@ -774,7 +774,7 @@ describe("Additional Fields operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-licenses"); cy.intercept("GET", "/api/v1/erm/licenses/*", license).as( "get-license" ); @@ -804,9 +804,9 @@ describe("Additional Fields operations", () => { ).as("avcategories"); cy.visit("/cgi-bin/koha/erm/licenses"); + cy.wait("@get-licenses"); cy.get("#licenses_list table tbody tr:first").contains("Edit").click(); cy.wait("@get-license"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! // All additional fields should be pre-populated cy.get("#additional_fields #additional_field_1 .vs__selected").contains( @@ -1167,7 +1167,7 @@ describe("Additional Fields operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-agreements"); cy.intercept("GET", "/api/v1/erm/agreements/*", agreement).as( "get-agreement" ); @@ -1197,11 +1197,11 @@ describe("Additional Fields operations", () => { ).as("avcategories"); cy.visit("/cgi-bin/koha/erm/agreements"); + cy.wait("@get-agreements"); cy.get("#agreements_list table tbody tr:first") .contains("Edit") .click(); cy.wait("@get-agreement"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! // All additional fields should be pre-populated cy.get("#additional_fields #additional_field_1 .vs__selected").contains( @@ -1574,7 +1574,7 @@ describe("Additional Fields operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-eholdings-packages"); cy.intercept( "GET", "/api/v1/erm/eholdings/local/packages/*", @@ -1606,9 +1606,9 @@ describe("Additional Fields operations", () => { ).as("avcategories"); cy.visit("/cgi-bin/koha/erm/eholdings/local/packages"); + cy.wait("@get-eholdings-packages"); cy.get("#packages_list table tbody tr:first").contains("Edit").click(); cy.wait("@get-eholdings-package"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! // All additional fields should be pre-populated cy.get("#additional_fields #additional_field_1 .vs__selected").contains( diff --git a/t/cypress/integration/ERM/Agreements_spec.ts b/t/cypress/integration/ERM/Agreements_spec.ts index 0b55448ee6d..42c06182b03 100644 --- a/t/cypress/integration/ERM/Agreements_spec.ts +++ b/t/cypress/integration/ERM/Agreements_spec.ts @@ -440,7 +440,6 @@ describe("Agreement CRUD operations", () => { .contains("Edit") .click(); cy.wait("@get-agreement"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#agreements_add h2").contains("Edit agreement"); cy.left_menu_active_item_is("Agreements"); @@ -499,10 +498,10 @@ describe("Agreement CRUD operations", () => { statusCode: 500, delay: 1000, }); - }); + }).as("edit-agreement"); cy.get("#agreements_add").contains("Submit").click(); cy.get("main div[class='modal_centered']").contains("Submitting..."); - cy.wait(1000); + cy.wait("@edit-agreement"); cy.get("main div[class='alert alert-warning']").contains( "Something went wrong: Error: Internal Server Error" ); @@ -529,11 +528,12 @@ describe("Agreement CRUD operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-agreements"); cy.intercept("GET", "/api/v1/erm/agreements/*", agreement).as( "get-agreement" ); cy.visit("/cgi-bin/koha/erm/agreements"); + cy.wait("@get-agreements"); let id_cell = cy.get("#agreements_list table tbody tr:first td:first"); id_cell.contains(agreement.agreement_id); @@ -544,7 +544,6 @@ describe("Agreement CRUD operations", () => { name_link.should("have.text", agreement.name); name_link.click(); cy.wait("@get-agreement"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#agreements_show h2").contains( "Agreement #" + agreement.agreement_id ); diff --git a/t/cypress/integration/ERM/DataProviders_spec.ts b/t/cypress/integration/ERM/DataProviders_spec.ts index 9c2ba4ecc5a..cf29b48059c 100644 --- a/t/cypress/integration/ERM/DataProviders_spec.ts +++ b/t/cypress/integration/ERM/DataProviders_spec.ts @@ -168,7 +168,7 @@ describe("Data provider CRUD operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-data-providers"); cy.intercept( "GET", "/api/v1/erm/usage_data_providers/*", @@ -188,11 +188,11 @@ describe("Data provider CRUD operations", () => { ); cy.visit("/cgi-bin/koha/erm/eusage/usage_data_providers"); + cy.wait("@get-data-providers"); cy.get("#usage_data_providers_list table tbody tr:first") .contains("Edit") .click(); cy.wait("@get-data-provider"); - cy.wait(1000); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#data_providers_add h2").contains("Edit usage data provider"); // Form has been correctly filled in @@ -290,7 +290,6 @@ describe("Data provider CRUD operations", () => { ); name_link.click(); cy.wait("@get-data-provider"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#usage_data_providers_show h2").contains( "Data provider #" + dataProvider.erm_usage_data_provider_id ); @@ -359,13 +358,14 @@ describe("Data provider CRUD operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-data-providers"); cy.intercept( "GET", "/api/v1/erm/usage_data_providers/*", dataProvider ).as("get-data-provider"); cy.visit("/cgi-bin/koha/erm/eusage/usage_data_providers"); + cy.wait("@get-data-providers"); let name_link = cy.get( "#usage_data_providers_list table tbody tr:first td:first a" ); @@ -378,7 +378,6 @@ describe("Data provider CRUD operations", () => { ); name_link.click(); cy.wait("@get-data-provider"); - cy.wait(500); cy.get("#usage_data_providers_show h2").contains( "Data provider #" + dataProvider.erm_usage_data_provider_id ); @@ -501,13 +500,14 @@ describe("Data provider tab options", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-data-providers"); cy.intercept( "GET", "/api/v1/erm/usage_data_providers/*", dataProvider ).as("get-data-provider"); cy.visit("/cgi-bin/koha/erm/eusage/usage_data_providers"); + cy.wait("@get-data-providers"); let name_link = cy.get( "#usage_data_providers_list table tbody tr:first td:first a" ); @@ -520,7 +520,6 @@ describe("Data provider tab options", () => { ); name_link.click(); cy.wait("@get-data-provider"); - cy.wait(500); }); it("Should display provider details", () => { diff --git a/t/cypress/integration/ERM/Licenses_spec.ts b/t/cypress/integration/ERM/Licenses_spec.ts index 170d28e3eed..372078bad85 100644 --- a/t/cypress/integration/ERM/Licenses_spec.ts +++ b/t/cypress/integration/ERM/Licenses_spec.ts @@ -167,14 +167,14 @@ describe("License CRUD operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-licenses"); cy.intercept("GET", "/api/v1/erm/licenses/*", license).as( "get-license" ); cy.visit("/cgi-bin/koha/erm/licenses"); + cy.wait("@get-licenses"); cy.get("#licenses_list table tbody tr:first").contains("Edit").click(); cy.wait("@get-license"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#licenses_add h2").contains("Edit license"); cy.left_menu_active_item_is("Licenses"); @@ -241,11 +241,12 @@ describe("License CRUD operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-licenses"); cy.intercept("GET", "/api/v1/erm/licenses/*", license).as( "get-license" ); cy.visit("/cgi-bin/koha/erm/licenses"); + cy.wait("@get-licenses"); let id_cell = cy.get("#licenses_list table tbody tr:first td:first"); id_cell.contains(license.license_id); @@ -256,7 +257,6 @@ describe("License CRUD operations", () => { name_link.should("have.text", license.name); name_link.click(); cy.wait("@get-license"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#licenses_show h2").contains("License #" + license.license_id); cy.left_menu_active_item_is("Licenses"); }); @@ -319,11 +319,12 @@ describe("License CRUD operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-licenses"); cy.intercept("GET", "/api/v1/erm/licenses/*", license).as( "get-license" ); cy.visit("/cgi-bin/koha/erm/licenses"); + cy.wait("@get-licenses"); let id_cell = cy.get("#licenses_list table tbody tr:first td:first"); id_cell.contains(license.license_id); @@ -334,7 +335,6 @@ describe("License CRUD operations", () => { name_link.should("have.text", license.name); name_link.click(); cy.wait("@get-license"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#licenses_show h2").contains("License #" + license.license_id); cy.get("#licenses_show #toolbar").contains("Delete").click(); diff --git a/t/cypress/integration/ERM/Packages_spec.ts b/t/cypress/integration/ERM/Packages_spec.ts index f0157b97591..2436c8c6815 100644 --- a/t/cypress/integration/ERM/Packages_spec.ts +++ b/t/cypress/integration/ERM/Packages_spec.ts @@ -135,13 +135,14 @@ describe("Package CRUD operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-packages"); cy.intercept( "GET", "/api/v1/erm/eholdings/local/packages/*", erm_package ).as("get-package"); cy.visit("/cgi-bin/koha/erm/eholdings/local/packages"); + cy.wait("@get-packages"); // Intercept related agreements request after entering agreement edit cy.intercept("GET", "/api/v1/erm/agreements*", { statusCode: 200, @@ -149,7 +150,6 @@ describe("Package CRUD operations", () => { }).as("get-related-agreements"); cy.get("#packages_list table tbody tr:first").contains("Edit").click(); cy.wait("@get-package"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#packages_add h2").contains("Edit package"); cy.left_menu_active_item_is("Packages"); @@ -194,13 +194,14 @@ describe("Package CRUD operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-packages"); cy.intercept( "GET", "/api/v1/erm/eholdings/local/packages/*", erm_package ).as("get-package"); cy.visit("/cgi-bin/koha/erm/eholdings/local/packages"); + cy.wait("@get-packages"); let name_link = cy.get( "#packages_list table tbody tr:first td:first a" ); @@ -210,7 +211,6 @@ describe("Package CRUD operations", () => { ); name_link.click(); cy.wait("@get-package"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#packages_show h2").contains( "Package #" + erm_package.package_id ); @@ -249,9 +249,8 @@ describe("Package CRUD operations", () => { } ).as("get-resource"); cy.visit("/cgi-bin/koha/erm/eholdings/local/packages/1"); - cy.contains("Titles (1)"); cy.wait("@get-resource"); - cy.wait(500); + cy.contains("Titles (1)"); cy.get("#title_list_result table").contains("A great title"); }); @@ -317,13 +316,14 @@ describe("Package CRUD operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-packages"); cy.intercept( "GET", "/api/v1/erm/eholdings/local/packages/*", erm_package ).as("get-package"); cy.visit("/cgi-bin/koha/erm/eholdings/local/packages"); + cy.wait("@get-packages"); let name_link = cy.get( "#packages_list table tbody tr:first td:first a" ); @@ -333,7 +333,6 @@ describe("Package CRUD operations", () => { ); name_link.click(); cy.wait("@get-package"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#packages_show h2").contains( "Package #" + erm_package.package_id ); diff --git a/t/cypress/integration/ERM/Titles_spec.ts b/t/cypress/integration/ERM/Titles_spec.ts index 05646453318..01799296092 100644 --- a/t/cypress/integration/ERM/Titles_spec.ts +++ b/t/cypress/integration/ERM/Titles_spec.ts @@ -44,7 +44,7 @@ describe("Title CRUD operations", () => { body: [], }).as("get-empty-packages"); cy.visit("/cgi-bin/koha/erm/eholdings/local/titles"); - cy.wait(500); + cy.wait("@get-empty-packages"); cy.get("#toolbar a").contains("Import from list").click(); cy.get("h2").contains("Import from a list"); cy.left_menu_active_item_is("Titles"); @@ -56,9 +56,9 @@ describe("Title CRUD operations", () => { body: get_packages_to_relate(), }).as("get-related-packages"); cy.visit("/cgi-bin/koha/erm/eholdings/local/titles"); + cy.wait("@get-related-packages"); cy.get("#toolbar a").contains("Import from list").click(); cy.get("h2").contains("Import from a list"); - cy.wait(500); // Prepare background job response to the POST cy.intercept("POST", "/api/v1/erm/eholdings/local/titles/import", { @@ -125,7 +125,6 @@ describe("Title CRUD operations", () => { // Click the button in the toolbar cy.visit("/cgi-bin/koha/erm/eholdings/local/titles"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.contains("New title").click(); cy.get("#titles_add h2").contains("New title"); cy.left_menu_active_item_is("Titles"); @@ -234,13 +233,14 @@ describe("Title CRUD operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-titles"); cy.intercept( "GET", "/api/v1/erm/eholdings/local/titles/*", erm_title ).as("get-title"); cy.visit("/cgi-bin/koha/erm/eholdings/local/titles"); + cy.wait("@get-titles"); // Intercept related packages request after entering title edit cy.intercept("GET", "/api/v1/erm/eholdings/local/packages*", { statusCode: 200, @@ -249,7 +249,6 @@ describe("Title CRUD operations", () => { cy.get("#titles_list table tbody tr:first").contains("Edit").click(); cy.wait("@get-title"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#titles_add h2").contains("Edit title"); cy.left_menu_active_item_is("Titles"); @@ -376,7 +375,7 @@ describe("Title CRUD operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-titles"); // Title with empty resources. cy.intercept( { @@ -393,6 +392,7 @@ describe("Title CRUD operations", () => { } ).as("get-title"); cy.visit("/cgi-bin/koha/erm/eholdings/local/titles"); + cy.wait("@get-titles"); let title_link = cy.get("#titles_list table tbody tr:first td:first a"); title_link.should( "have.text", @@ -400,7 +400,6 @@ describe("Title CRUD operations", () => { ); cy.get("#titles_list table tbody tr:first td:first a").click(); cy.wait("@get-title"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#eholdings_title_show h2").contains( "Title #" + erm_title.title_id ); @@ -418,8 +417,8 @@ describe("Title CRUD operations", () => { // List packages cy.visit("/cgi-bin/koha/erm/eholdings/local/titles/1"); + cy.wait("@get-title"); cy.contains("Packages (1)"); - cy.wait(500); // Visit resource let related_package = erm_title.resources[0]; @@ -485,7 +484,7 @@ describe("Title CRUD operations", () => { "X-Base-Total-Count": "1", "X-Total-Count": "1", }, - }); + }).as("get-titles"); // Title with empty resources. cy.intercept( { @@ -502,6 +501,7 @@ describe("Title CRUD operations", () => { } ).as("get-title"); cy.visit("/cgi-bin/koha/erm/eholdings/local/titles"); + cy.wait("@get-titles"); let title_link = cy.get("#titles_list table tbody tr:first td:first a"); title_link.should( "have.text", @@ -509,7 +509,6 @@ describe("Title CRUD operations", () => { ); cy.get("#titles_list table tbody tr:first td:first a").click(); cy.wait("@get-title"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! cy.get("#eholdings_title_show h2").contains( "Title #" + erm_title.title_id ); diff --git a/t/cypress/integration/InfiniteScrollSelect_spec.ts b/t/cypress/integration/InfiniteScrollSelect_spec.ts index 73daf8bc150..fda6379de56 100644 --- a/t/cypress/integration/InfiniteScrollSelect_spec.ts +++ b/t/cypress/integration/InfiniteScrollSelect_spec.ts @@ -396,7 +396,6 @@ describe("Infinite scroll", () => { .contains("Edit") .click(); cy.wait("@get-agreement"); - cy.wait(500); // Cypress is too fast! Vue hasn't populated the form yet! // Licenses should be labelled correctly cy.get("#agreement_license_0 #license_id_0 .vs__selected").contains( diff --git a/t/cypress/integration/KohaTable/KohaTable_spec.ts b/t/cypress/integration/KohaTable/KohaTable_spec.ts index 035404c11ae..3d74754efaa 100644 --- a/t/cypress/integration/KohaTable/KohaTable_spec.ts +++ b/t/cypress/integration/KohaTable/KohaTable_spec.ts @@ -288,22 +288,18 @@ describe("kohaTable (using REST API)", () => { }); }); - it("Jump to the configuration page", () => { + it.only("Jump to the configuration page", () => { cy.visit("/cgi-bin/koha/admin/branches.pl"); cy.get(`#${table_id}_wrapper .dt_button_configure_table`).click(); cy.url().should("contain", "module=admin"); cy.url().should("contain", "page=libraries"); cy.url().should("contain", "table=libraries"); - cy.wait(2000); // ensure the animation completes, random failures? cy.get("#admin_panel") .contains("Table id: libraries") .should("be.visible"); - cy.window().then(win => { - const scrollTop = win.scrollY || win.pageYOffset; - expect(scrollTop).to.be.greaterThan(0); // Ensure some scrolling happened - }); + cy.window().its("scrollY").should("be.gt", 0); // Ensure some scrolling happened }); }); -- 2.34.1