From 79312512a5590c0ab864da12ca2f68a9b2360446 Mon Sep 17 00:00:00 2001 From: Carla Martinez Date: Thu, 6 Aug 2026 16:36:49 +0200 Subject: [PATCH] Add tests for OTP tokens pages The tests should cover all the use cases of the 'OTP tokens' pages (main, 'Settings', and 'Is managed by'). Assisted-by: Claude Signed-off-by: Carla Martinez --- cypress/e2e/common/ui/select.ts | 4 +- .../e2e/otp_tokens/otp_token_management.ts | 48 +++++ cypress/e2e/otp_tokens/otp_tokens.feature | 194 +++++++++++++++++ .../otp_tokens/otp_tokens_managedby.feature | 72 +++++++ .../otp_tokens/otp_tokens_settings.feature | 201 ++++++++++++++++++ cypress/support/commands.ts | 3 +- src/pages/OtpTokens/OtpTokensSettings.tsx | 19 +- 7 files changed, 521 insertions(+), 20 deletions(-) create mode 100644 cypress/e2e/otp_tokens/otp_token_management.ts create mode 100644 cypress/e2e/otp_tokens/otp_tokens.feature create mode 100644 cypress/e2e/otp_tokens/otp_tokens_managedby.feature create mode 100644 cypress/e2e/otp_tokens/otp_tokens_settings.feature diff --git a/cypress/e2e/common/ui/select.ts b/cypress/e2e/common/ui/select.ts index d5fca43f9..49bc01ef9 100644 --- a/cypress/e2e/common/ui/select.ts +++ b/cypress/e2e/common/ui/select.ts @@ -17,7 +17,9 @@ Then( export const selectOption = (option: string, selector: string) => { cy.dataCy(selector + "-toggle").click(); cy.dataCy(selector + "-toggle").should("have.attr", "aria-expanded", "true"); - cy.dataCy(selector + "-" + option).click(); + cy.dataCy(selector + "-" + option) + .find("button") + .click({ force: true }); }; export const isOptionSelected = (option: string, selector: string) => { diff --git a/cypress/e2e/otp_tokens/otp_token_management.ts b/cypress/e2e/otp_tokens/otp_token_management.ts new file mode 100644 index 000000000..ae86d7038 --- /dev/null +++ b/cypress/e2e/otp_tokens/otp_token_management.ts @@ -0,0 +1,48 @@ +import { Given } from "@badeball/cypress-cucumber-preprocessor"; +import { IPA_PREFIX } from "../../support/utils"; + +Given( + "OTP token {string} exists for user {string} with type {string} and description {string}", + (tokenId: string, owner: string, type: string, description: string) => { + cy.ipa({ + command: "otptoken-add", + name: tokenId, + specificOptions: `--owner="${owner}" --desc="${description}" --type=${type}`, + }); + } +); + +Given( + "an OTP token exists for user {string} with type {string} and description {string}", + (owner: string, type: string, description: string) => { + cy.exec( + `${IPA_PREFIX} otptoken-add --owner="${owner}" --desc="${description}" --type=${type}` + ); + } +); + +Given("I delete OTP token {string}", (tokenId: string) => { + cy.ipa({ + command: "otptoken-del", + name: tokenId, + }); +}); + +Given("OTP token {string} is disabled", (tokenId: string) => { + cy.ipa({ + command: "otptoken-mod", + name: tokenId, + specificOptions: "--disabled=TRUE", + }); +}); + +Given( + "user {string} is manager of OTP token {string}", + (userName: string, tokenId: string) => { + cy.ipa({ + command: "otptoken-add-managedby", + name: tokenId, + specificOptions: `--users="${userName}"`, + }); + } +); diff --git a/cypress/e2e/otp_tokens/otp_tokens.feature b/cypress/e2e/otp_tokens/otp_tokens.feature new file mode 100644 index 000000000..1b38d7dfc --- /dev/null +++ b/cypress/e2e/otp_tokens/otp_tokens.feature @@ -0,0 +1,194 @@ +Feature: OTP tokens manipulation + Create, search, enable, disable and delete OTP tokens + + @seed + Scenario: Prep: Create user for TOTP test + Given User "otpuser" "OTP" "User" exists and is using password "Secret123" + + @test + Scenario: Add a new TOTP token with owner + Given I am logged in as admin + And I am on "otp-tokens" page + + When I click on the "otp-tokens-button-add" button + Then I should see "add-otp-token-modal" modal + And I should see the "modal-radio-totp" radio button is selected + + When I type in the "modal-textbox-description" textbox text "totp_token" + Then I should see "totp_token" in the "modal-textbox-description" textbox + + When I select "otpuser" option in the "modal-select-owner" selector + Then I should see "otpuser" option in the "modal-select-owner" selector + + When I click on the "modal-button-add" button + Then I should not see "add-otp-token-modal" modal + + @cleanup + Scenario: Cleanup: Delete test data after TOTP test + Given I delete user "otpuser" + + @seed + Scenario: Prep: Create user for HOTP test + Given User "otpuser" "OTP" "User" exists and is using password "Secret123" + + @test + Scenario: Add a new HOTP token with owner + Given I am logged in as admin + And I am on "otp-tokens" page + + When I click on the "otp-tokens-button-add" button + Then I should see "add-otp-token-modal" modal + + When I click on the "modal-radio-hotp" radio button + Then I should see the "modal-radio-hotp" radio button is selected + And I should see the "modal-radio-totp" radio button is not selected + + When I type in the "modal-textbox-description" textbox text "hotp_token" + Then I should see "hotp_token" in the "modal-textbox-description" textbox + + When I select "otpuser" option in the "modal-select-owner" selector + Then I should see "otpuser" option in the "modal-select-owner" selector + + When I click on the "modal-button-add" button + Then I should not see "add-otp-token-modal" modal + + @cleanup + Scenario: Cleanup: Delete test data after HOTP test + Given I delete user "otpuser" + + @seed + Scenario: Prep: Create user and token for search test + Given User "otpuser" "OTP" "User" exists and is using password "Secret123" + And an OTP token exists for user "otpuser" with type "totp" and description "search_token" + + @test + Scenario: Search for an OTP token by owner + Given I am logged in as admin + And I am on "otp-tokens" page + + When I search for "otpuser" in the data table + Then I should see "otpuser" entry in the data table with ID "otp-tokens-table" + + @test + Scenario: Cancel creation of an OTP token + Given I am logged in as admin + And I am on "otp-tokens" page + + When I click on the "otp-tokens-button-add" button + Then I should see "add-otp-token-modal" modal + + When I type in the "modal-textbox-description" textbox text "cancel_token" + Then I should see "cancel_token" in the "modal-textbox-description" textbox + + When I click on the "modal-button-cancel" button + Then I should not see "add-otp-token-modal" modal + + @test + Scenario: TOTP is the default token type + Given I am logged in as admin + And I am on "otp-tokens" page + + When I click on the "otp-tokens-button-add" button + Then I should see "add-otp-token-modal" modal + And I should see the "modal-radio-totp" radio button is selected + And I should see the "modal-radio-hotp" radio button is not selected + + When I click on the "modal-button-cancel" button + Then I should not see "add-otp-token-modal" modal + + @test + Scenario: Delete button is disabled when no token is selected + Given I am logged in as admin + And I am on "otp-tokens" page + + Then I should see the "otp-tokens-button-delete" button is disabled + + @test + Scenario: Enable button is disabled when no token is selected + Given I am logged in as admin + And I am on "otp-tokens" page + + Then I should see the "otp-tokens-button-enable" button is disabled + + @test + Scenario: Disable button is disabled when no token is selected + Given I am logged in as admin + And I am on "otp-tokens" page + + Then I should see the "otp-tokens-button-disable" button is disabled + + @cleanup + Scenario: Cleanup: Delete search test data + Given I delete user "otpuser" + + @seed + Scenario: Prep: Create user and token for disable test + Given User "otpuser" "OTP" "User" exists and is using password "Secret123" + And an OTP token exists for user "otpuser" with type "totp" and description "disable_token" + + @test + Scenario: Disable an OTP token + Given I am logged in as admin + And I am on "otp-tokens" page + + When I search for "otpuser" in the data table + Then I should see "otpuser" entry in the data table with ID "otp-tokens-table" + + When I select "otpuser" entry in the data table with ID "otp-tokens-table" + Then I should see "otpuser" entry selected in the data table with ID "otp-tokens-table" + + When I click on the "otp-tokens-button-disable" button + Then I should see "enable-disable-otp-tokens-modal" modal + + When I click on the "modal-button-ok" button + Then I should not see "enable-disable-otp-tokens-modal" modal + And I should see "success" alert + + @test + Scenario: Enable a disabled OTP token + Given I am logged in as admin + And I am on "otp-tokens" page + + When I search for "otpuser" in the data table + Then I should see "otpuser" entry in the data table with ID "otp-tokens-table" + + When I select "otpuser" entry in the data table with ID "otp-tokens-table" + Then I should see "otpuser" entry selected in the data table with ID "otp-tokens-table" + + When I click on the "otp-tokens-button-enable" button + Then I should see "enable-disable-otp-tokens-modal" modal + + When I click on the "modal-button-ok" button + Then I should not see "enable-disable-otp-tokens-modal" modal + And I should see "success" alert + + @cleanup + Scenario: Cleanup: Delete disable/enable test data + Given I delete user "otpuser" + + @seed + Scenario: Seed: Create user and OTP token for delete test + Given User "otpuser" "OTP" "User" exists and is using password "Secret123" + And an OTP token exists for user "otpuser" with type "totp" and description "delete_token" + + @test + Scenario: Delete an OTP token + Given I am logged in as admin + And I am on "otp-tokens" page + + When I search for "otpuser" in the data table + Then I should see "otpuser" entry in the data table with ID "otp-tokens-table" + + When I select "otpuser" entry in the data table with ID "otp-tokens-table" + Then I should see "otpuser" entry selected in the data table with ID "otp-tokens-table" + + When I click on the "otp-tokens-button-delete" button + Then I should see "delete-otp-tokens-modal" modal + + When I click on the "modal-button-ok" button + Then I should see "remove-otp-tokens-success" alert + And I should not see "delete-otp-tokens-modal" modal + + @cleanup + Scenario: Cleanup: Delete test data and remaining tokens + Given I delete user "otpuser" diff --git a/cypress/e2e/otp_tokens/otp_tokens_managedby.feature b/cypress/e2e/otp_tokens/otp_tokens_managedby.feature new file mode 100644 index 000000000..a0ce1b943 --- /dev/null +++ b/cypress/e2e/otp_tokens/otp_tokens_managedby.feature @@ -0,0 +1,72 @@ +Feature: OTP tokens - Is managed by page + Manage OTP token managers (users) + + @seed + Scenario: Prep: Create users and OTP token for add manager test + Given User "otpmgdbyuser" "OTPManaged" "User" exists and is using password "Secret123" + And User "otpmanager" "OTP" "Manager" exists and is using password "Secret123" + And OTP token "managedby_token" exists for user "otpmgdbyuser" with type "totp" and description "managedby_token" + + @test + Scenario: Add a user manager to OTP token + Given I am logged in as admin + And I am on "otp-tokens/managedby_token" page + + When I click on the "otp-tokens-tab-managedby" tab + Then I should see "otp-tokens-tab-managedby" tab selected + + When I click on the "member-of-button-add" button + Then I should see "member-of-add-modal" modal + And I should see "item-otpmanager" dual list item on the left + + When I click on "item-otpmanager" dual list item + Then I should see "item-otpmanager" dual list item selected + When I click on the "dual-list-add-selected" button + Then I should see "item-otpmanager" dual list item on the right + + When I click on the "modal-button-add" button + Then I should not see "member-of-add-modal" modal + And I should see "add-managedby-success" alert + + When I search for "otpmanager" in the members table + Then I should see "otpmanager" entry in the data table + + @cleanup + Scenario: Cleanup: Delete add manager test data + Given I delete OTP token "managedby_token" + And I delete user "otpmgdbyuser" + And I delete user "otpmanager" + + @seed + Scenario: Prep: Create users, OTP token, and manager for remove test + Given User "otpmgdbyuser" "OTPManaged" "User" exists and is using password "Secret123" + And User "otpmanager" "OTP" "Manager" exists and is using password "Secret123" + And OTP token "managedby_token" exists for user "otpmgdbyuser" with type "totp" and description "managedby_token" + And user "otpmanager" is manager of OTP token "managedby_token" + + @test + Scenario: Remove a user manager from OTP token + Given I am logged in as admin + And I am on "otp-tokens/managedby_token" page + + When I click on the "otp-tokens-tab-managedby" tab + Then I should see "otp-tokens-tab-managedby" tab selected + + When I select entry "otpmanager" in the members table + Then I should see "otpmanager" entry selected in the data table + + When I click on the "member-of-button-delete" button + Then I should see "member-of-delete-modal" modal + + When I click on the "modal-button-delete" button + Then I should not see "member-of-delete-modal" modal + And I should see "remove-managedby-success" alert + + When I search for "otpmanager" in the members table + Then I should not see "otpmanager" entry in the data table + + @cleanup + Scenario: Cleanup: Delete remove manager test data + Given I delete OTP token "managedby_token" + And I delete user "otpmgdbyuser" + And I delete user "otpmanager" diff --git a/cypress/e2e/otp_tokens/otp_tokens_settings.feature b/cypress/e2e/otp_tokens/otp_tokens_settings.feature new file mode 100644 index 000000000..cc8d5c820 --- /dev/null +++ b/cypress/e2e/otp_tokens/otp_tokens_settings.feature @@ -0,0 +1,201 @@ +Feature: OTP tokens - Settings page + Modify OTP token settings + + @seed + Scenario: Prep: Create user and OTP token for save/revert buttons test + Given User "otpsettingsuser" "OTP" "Settings" exists and is using password "Secret123" + And OTP token "settings_token" exists for user "otpsettingsuser" with type "totp" and description "settings_token" + + @test + Scenario: Save and Revert buttons are disabled when no changes + Given I am logged in as admin + And I am on "otp-tokens/settings_token" page + + Then I should see the "otp-tokens-tab-settings-button-save" button is disabled + And I should see the "otp-tokens-tab-settings-button-revert" button is disabled + + @cleanup + Scenario: Cleanup: Delete save/revert buttons test data + Given I delete OTP token "settings_token" + And I delete user "otpsettingsuser" + + @seed + Scenario: Prep: Create user and OTP token for set description test + Given User "otpsettingsuser" "OTP" "Settings" exists and is using password "Secret123" + And OTP token "settings_token" exists for user "otpsettingsuser" with type "totp" and description "settings_token" + + @test + Scenario: Set Description field + Given I am logged in as admin + And I am on "otp-tokens/settings_token" page + + When I type in the "otp-tokens-tab-settings-textbox-description" textbox text "Updated description" + Then I should see "Updated description" in the "otp-tokens-tab-settings-textbox-description" textbox + And I should see the "otp-tokens-tab-settings-button-save" button is enabled + And I should see the "otp-tokens-tab-settings-button-revert" button is enabled + + When I click on the "otp-tokens-tab-settings-button-save" button + Then I should see "success" alert + And I should see the "otp-tokens-tab-settings-button-save" button is disabled + And I should see the "otp-tokens-tab-settings-button-revert" button is disabled + + @cleanup + Scenario: Cleanup: Delete set description test data + Given I delete OTP token "settings_token" + And I delete user "otpsettingsuser" + + @seed + Scenario: Prep: Create user and OTP token for set vendor test + Given User "otpsettingsuser" "OTP" "Settings" exists and is using password "Secret123" + And OTP token "settings_token" exists for user "otpsettingsuser" with type "totp" and description "settings_token" + + @test + Scenario: Set Vendor field + Given I am logged in as admin + And I am on "otp-tokens/settings_token" page + + When I type in the "otp-tokens-tab-settings-textbox-ipatokenvendor" textbox text "TestVendor" + Then I should see "TestVendor" in the "otp-tokens-tab-settings-textbox-ipatokenvendor" textbox + And I should see the "otp-tokens-tab-settings-button-save" button is enabled + + When I click on the "otp-tokens-tab-settings-button-save" button + Then I should see "success" alert + + @cleanup + Scenario: Cleanup: Delete set vendor test data + Given I delete OTP token "settings_token" + And I delete user "otpsettingsuser" + + @seed + Scenario: Prep: Create user and OTP token for revert test + Given User "otpsettingsuser" "OTP" "Settings" exists and is using password "Secret123" + And OTP token "settings_token" exists for user "otpsettingsuser" with type "totp" and description "settings_token" + + @test + Scenario: Revert changes + Given I am logged in as admin + And I am on "otp-tokens/settings_token" page + + When I type in the "otp-tokens-tab-settings-textbox-description" textbox text "Reverted description" + Then I should see "Reverted description" in the "otp-tokens-tab-settings-textbox-description" textbox + And I should see the "otp-tokens-tab-settings-button-revert" button is enabled + + When I click on the "otp-tokens-tab-settings-button-revert" button + Then I should see "revert-success" alert + And I should see the "otp-tokens-tab-settings-button-save" button is disabled + And I should see the "otp-tokens-tab-settings-button-revert" button is disabled + + @cleanup + Scenario: Cleanup: Delete revert test data + Given I delete OTP token "settings_token" + And I delete user "otpsettingsuser" + + @seed + Scenario: Prep: Create user and OTP token for refresh test + Given User "otpsettingsuser" "OTP" "Settings" exists and is using password "Secret123" + And OTP token "settings_token" exists for user "otpsettingsuser" with type "totp" and description "settings_token" + + @test + Scenario: Refresh button is available + Given I am logged in as admin + And I am on "otp-tokens/settings_token" page + + Then I should see the "otp-tokens-tab-settings-button-refresh" button is enabled + When I click on the "otp-tokens-tab-settings-button-refresh" button + + @cleanup + Scenario: Cleanup: Delete refresh test data + Given I delete OTP token "settings_token" + And I delete user "otpsettingsuser" + + @seed + Scenario: Prep: Create user and OTP token for kebab menu test + Given User "otpsettingsuser" "OTP" "Settings" exists and is using password "Secret123" + And OTP token "settings_token" exists for user "otpsettingsuser" with type "totp" and description "settings_token" + + @test + Scenario: Kebab menu opens and contains actions + Given I am logged in as admin + And I am on "otp-tokens/settings_token" page + + When I click on the "otp-tokens-tab-settings-kebab" kebab menu + Then I should see "otp-tokens-tab-settings-kebab" kebab menu expanded + + @cleanup + Scenario: Cleanup: Delete kebab menu test data + Given I delete OTP token "settings_token" + And I delete user "otpsettingsuser" + + @seed + Scenario: Prep: Create user and OTP token for disable test + Given User "otpsettingsuser" "OTP" "Settings" exists and is using password "Secret123" + And OTP token "settings_token" exists for user "otpsettingsuser" with type "totp" and description "settings_token" + + @test + Scenario: Disable token from settings kebab + Given I am logged in as admin + And I am on "otp-tokens/settings_token" page + + When I click on the "otp-tokens-tab-settings-kebab" kebab menu + Then I should see "otp-tokens-tab-settings-kebab" kebab menu expanded + + When I click on the "otp-tokens-tab-settings-kebab-disable" button + Then I should see "enable-disable-otp-tokens-modal" modal + + When I click on the "modal-button-ok" button + Then I should not see "enable-disable-otp-tokens-modal" modal + And I should see "success" alert + + @cleanup + Scenario: Cleanup: Delete disable test data + Given I delete OTP token "settings_token" + And I delete user "otpsettingsuser" + + @seed + Scenario: Prep: Create user and disabled OTP token for enable test + Given User "otpsettingsuser" "OTP" "Settings" exists and is using password "Secret123" + And OTP token "settings_token" exists for user "otpsettingsuser" with type "totp" and description "settings_token" + And OTP token "settings_token" is disabled + + @test + Scenario: Enable token from settings kebab + Given I am logged in as admin + And I am on "otp-tokens/settings_token" page + + When I click on the "otp-tokens-tab-settings-kebab" kebab menu + Then I should see "otp-tokens-tab-settings-kebab" kebab menu expanded + + When I click on the "otp-tokens-tab-settings-kebab-enable" button + Then I should see "enable-disable-otp-tokens-modal" modal + + When I click on the "modal-button-ok" button + Then I should not see "enable-disable-otp-tokens-modal" modal + And I should see "success" alert + + @cleanup + Scenario: Cleanup: Delete enable test data + Given I delete OTP token "settings_token" + And I delete user "otpsettingsuser" + + @seed + Scenario: Prep: Create user and OTP token for delete test + Given User "otpsettingsuser" "OTP" "Settings" exists and is using password "Secret123" + And OTP token "settings_token" exists for user "otpsettingsuser" with type "totp" and description "settings_token" + + @test + Scenario: Delete token from settings kebab + Given I am logged in as admin + And I am on "otp-tokens/settings_token" page + + When I click on the "otp-tokens-tab-settings-kebab" kebab menu + Then I should see "otp-tokens-tab-settings-kebab" kebab menu expanded + + When I click on the "otp-tokens-tab-settings-kebab-delete" button + Then I should see "delete-otp-tokens-modal" modal + + When I click on the "modal-button-ok" button + Then I should see "remove-otp-tokens-success" alert + + @cleanup + Scenario: Cleanup: Delete remaining test data + Given I delete user "otpsettingsuser" diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index d6ac84b90..51ffb1bfa 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -50,6 +50,7 @@ Cypress.Commands.add( command, name, specificOptions, + options, }: IpaCommandParams): Cypress.Chainable => { const safeName = name.replace(/"/g, '\\"'); let ipaCmd = `${IPA_PREFIX} ${command} "${safeName}"`; @@ -57,6 +58,6 @@ Cypress.Commands.add( ipaCmd = `${IPA_PREFIX} ${command} "${safeName}" ${specificOptions}`; } - return cy.exec(ipaCmd); + return cy.exec(ipaCmd, options); } ); diff --git a/src/pages/OtpTokens/OtpTokensSettings.tsx b/src/pages/OtpTokens/OtpTokensSettings.tsx index 34e35899a..d99c77b71 100644 --- a/src/pages/OtpTokens/OtpTokensSettings.tsx +++ b/src/pages/OtpTokens/OtpTokensSettings.tsx @@ -324,7 +324,6 @@ const OtpTokensSettings = (props: OtpTokensSettingsProps) => { @@ -338,12 +337,7 @@ const OtpTokensSettings = (props: OtpTokensSettingsProps) => { metadata={props.metadata} /> - + { @@ -372,7 +365,6 @@ const OtpTokensSettings = (props: OtpTokensSettingsProps) => { @@ -391,7 +383,6 @@ const OtpTokensSettings = (props: OtpTokensSettingsProps) => { @@ -407,7 +398,6 @@ const OtpTokensSettings = (props: OtpTokensSettingsProps) => { @@ -425,7 +415,6 @@ const OtpTokensSettings = (props: OtpTokensSettingsProps) => { @@ -442,7 +431,6 @@ const OtpTokensSettings = (props: OtpTokensSettingsProps) => { @@ -459,7 +447,6 @@ const OtpTokensSettings = (props: OtpTokensSettingsProps) => { @@ -476,7 +463,6 @@ const OtpTokensSettings = (props: OtpTokensSettingsProps) => { @@ -493,7 +479,6 @@ const OtpTokensSettings = (props: OtpTokensSettingsProps) => { @@ -509,7 +494,6 @@ const OtpTokensSettings = (props: OtpTokensSettingsProps) => { @@ -525,7 +509,6 @@ const OtpTokensSettings = (props: OtpTokensSettingsProps) => {