Skip to content

Conversation

asirvadAbrahamVarghese
Copy link
Contributor

CP4AIOPS-17892
Pr that adds cypress tests for Zone form: Settings > Application Settings > Settings > Zones > Configuration > Add/Edit Zone
 - Validate add form elements
 - Validate edit form elements
 - Add, edit & delete a zone
 
@miq-bot assign @elsamaryv
@miq-bot add-label cypress
@miq-bot add-label test
 

@asirvadAbrahamVarghese asirvadAbrahamVarghese requested a review from a team as a code owner August 4, 2025 18:31
@asirvadAbrahamVarghese asirvadAbrahamVarghese force-pushed the zone-form-automation-testing branch 2 times, most recently from 7e68886 to 3f7777e Compare August 5, 2025 08:47
@asirvadAbrahamVarghese
Copy link
Contributor Author

asirvadAbrahamVarghese commented Aug 5, 2025

TODO:

@asirvadAbrahamVarghese asirvadAbrahamVarghese changed the title Added automated tests with cypress for Zone form [WIP] - Added automated tests with cypress for Zone form Aug 6, 2025
@asirvadAbrahamVarghese asirvadAbrahamVarghese force-pushed the zone-form-automation-testing branch 4 times, most recently from 3d1b598 to a589f51 Compare August 7, 2025 10:42
nameInputFieldId: 'name',
descriptionInputFieldId: 'description',
ipInputFieldId: 'settings\\.proxy_server_ip',
maxScanSelectFieldId: 'settings\\.concurrent_vm_scans',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

name, description, save, cancel, add, reset, etc. might make the test more readable if the simple string is used inline in the test...

maxScanSelectFieldId and maxScanSelectFieldId are complicated enough to be worth leaving as constants. I don't really know.

see also: https://github.com/ManageIQ/manageiq-ui-classic/pull/9549/files#r2263776498

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I too have the opinion that using ids/strings inline makes it more readable

Copy link
Contributor Author

@asirvadAbrahamVarghese asirvadAbrahamVarghese Aug 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I completely agree that input types, button types, and similar HTML values are standard and unlikely to change, so it’s perfectly fine to keep them inline.
For things like button labels or other frequently repeated field names, the goal is to reduce redundancy. That way, if a button label changes - say from “Add” to “Add Zone” we only need to update it in one place - the constants variable (now we have element selector commands(getFormFooterButtonByType) that uses a "contains" check, even “Add” will still match)

Ultimately, the best practice is to maintain a shared constants file for both the component and its test files. This ensures that any updates only need to be made once in that shared file.

Something like this 57ec79fa - which I suggested for the schedule form - this constants file currently holds only IDs, but anything you expect might change in the future such as flash messages, button labels, headers,... can all be included in this

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I think we can have a shared set of constants but simple strings unique to the test can probably be done inline.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keeping simple strings like name, description inline (see) and keeping IP_INPUT_FIELD_ID and MAX_SCAN_SELECT_FIELD_ID as-is since they include escape sequences

cy.getFormInputFieldById(descriptionInputFieldId)
.clear()
.type(updatedServerIp);
cy.getFormSelectFieldById(maxScanSelectFieldId).select(updatedMaxScanLimit);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the question above about the input fields type() possibly doing async stuff afterwards... I'm seeing one run of this test retry 4 times. So, don't waste time trying to debug it until this test actually fails all 10 attempts but wanted to share in case there was something obvious async you saw when you ran this manually.

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the session timing problem is the culprit here again, and doesn’t look like there’s anything async that’s needs to be awaited or handled
image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haha, I didn't get any takers on reviewing #9533 so it's stalled. Reducing our session writes on requests that shouldn't be updating session doesn't fix the problem but it does reduce the likelihood of a timing bug with much less session writes across threads.

@asirvadAbrahamVarghese asirvadAbrahamVarghese force-pushed the zone-form-automation-testing branch from a589f51 to 8afddae Compare August 13, 2025 07:52
@jrafanie
Copy link
Member

Close / open after revert of #9505 via #9553

@jrafanie jrafanie closed this Aug 13, 2025
@jrafanie jrafanie reopened this Aug 13, 2025
cy.wait('@createZone');
}

function validateFormElements(isEditForm = false) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After we do a few pages of these, we'll probably have shared behavior we can extract. It's probably best to get a few of these in first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not really sure about the best approach to extract these, one way would be to have separate methods in a shared helper file for each field, something like:

function validateNameField(isDisabled = false) {
  cy.getFormLabelByInputId('name').should('be.visible');
  cy.getFormInputFieldById('name')
    .should('be.visible')
    .then((nameField) => {
      if (isDisabled) {
        expect(nameField).to.be.disabled;
      } else {
        expect(nameField).to.not.be.disabled;
      }
    });
}

But we might end up with a pile of methods 😴

More flexible one would be to get the set of field configs and then do the assertions:

function validateFormFields(fieldConfigs) {
  fieldConfigs.forEach((config) => {
    const { id, fieldType = 'input', shouldBeDisabled = false } = config;

    // Check label
    cy.getFormLabelByInputId(id).should('be.visible');

    // Check field
    if (fieldType === 'input') {
      cy.getFormInputFieldById(id)
        .should('be.visible')
        .then((field) => {
          if (shouldBeDisabled) {
            expect(field).to.be.disabled;
          } else {
            expect(field).to.not.be.disabled;
          }
        });
    } else if (fieldType === 'select') {
      cy.getFormSelectFieldById(id)
        .should('be.visible')
        .then((field) => {
          if (shouldBeDisabled) {
            expect(field).to.be.disabled;
          } else {
            expect(field).to.not.be.disabled;
          }
        });
    }
  });
}

and use it like:

validateFormFields([
  { id: 'name', shouldBeDisabled: true },
  { id: 'description' },
  { fieldType: 'select', id: 'concurrent_vm_scans' },
]);

Any thoughts?

zonesAccordItem,
`Zone: ${initialZoneDescription}`,
]);
cy.wait('@treeSelectApi');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the same treeSelectApi from the beforeEach? I wonder if this can/should be moved into the selectAccordionItem in the future. Our other functions seem to handle waits for us but this one doesn't. It's stands out to me as odd.

Copy link
Contributor Author

@asirvadAbrahamVarghese asirvadAbrahamVarghese Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the same treeSelectApi from the beforeEach?

Moved it to a common method so that cy.wait will be handled using cy.interceptApi command

I wonder if this can/should be moved into the selectAccordionItem in the future.

As of now we can't entirely shift the treeSelect intercept & wait logic into selectAccordionItem via interceptApi (as of now this will only handle duplicate aliasing) due to mixed behavior with accordion selection.
Sometimes, reselecting an already selected node doesn’t fire the ops/tree_select POST request, which causes cy.wait to fail.
Selecting "Server: EVM" node, api is fired:
image
Reselecting the node, api is not fired:
image

But in other scenarios, it does fire.
Selecting "Environment/Dev" node, api is fired:
image
Reselecting the node, api is fired again:
image

The solution is to improve interceptApi so that it conditionally waits only when a request is actually initiated.
Cypress doesn’t expose a global event for intercepts, I’ll need to explore other common events as a workaround.

@asirvadAbrahamVarghese asirvadAbrahamVarghese force-pushed the zone-form-automation-testing branch from 2fc0b47 to e6a5a69 Compare August 29, 2025 05:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants