Why Cypress test is not able to trigger a script in a child window? - cypress

I have a pop up window containing a script in its head. And this script should be triggered by click on the window button. But after click on this button the script does not run. Could you suggest the reason?
Steps to reproduce:
Click on a button in the main window.
Child window containing a simple form is open.
Move to the child window, fill in the form fields and click on submit button.
Expected result: The click triggers a script located in the child window head. The script process the form and submit it.
Actual result: an error arises: "submitMyForm is not defined" (reference: submitMyForm() is a method containing in the script mentioned above).
So the problem is that the child window form fields can be populated and form button can be clicked but the script bounded to the button by means of the link <a href="javascript:submitMyForm();"> does not work as the function submitMyForm() is not found. Obviously the reason of the test failure is stubbing the child window which is performed to prevent having 2 windows at the same time. After this the child window is opening in the same browser tab as Cypress is not able to work with 2 windows open in the same time. But in this case the script stops working neither from the test nor by performing the click manually.
Here is a code snippet from the Cypress test:
const pop_url = `/dir1/dir2/file.php?id=${sectionId}`; // Here is a new window URL
cy.window().then( win => {
const stub = cy.stub(win, 'open').as('windowopen');
newSurveySectionListObj.AddNewBtnClick(); // Triggers form opening in the new window
cy.get('#windowopen').should('be.called.with', pop_url);
cy.window().then( $win => {
$win.location.href = pop_url
newSurveySectionListObj.typeDropdownSelect('Matrix'); // works fine
newSurveySectionListObj.modalDescriptionFldType('Cypress test string'); // works fine
newSurveySectionListObj.responseTypeDropdownSelect('Checkbox'); // works fine
cy.get('a[href="javascript:submitMyForm();"]').click(); // Does not work despite the button is clicked. An error "submitMyForm is // not defined" arises
});
});

You are going beyond what Cypress is capable of/designed for.
I would question why you are using a separate window in your app? You will run afoul of pop-up blockers that will prevent the new window being opened anyway. A percentage of users won't be able to work it out.
There are 2 approaches to this:
Use a modal dialog to achieve this (not great on mobile)
Use another route/page to display your form, return to the prev page when done
These have the advantage that they won't break with pop-up blockers, and your Cypress tests will work, as they are still in the same window.

Related

How to capture and display text for auto appearing and disappearing pop-up using cypress

i Would like to know the method on How to capture and display text for auto appearing and disappearing pop-up using cypress.
I had used the window methods for capturing the text and displaying it, but it doesn't capture the message.
The pop-up/alert is designed to appear whenever user generates a report and it automatically disappears after 3 secs.
Please help
Depends on what creates the popup.
For window alert, this question How can we test the alert and text uses stub to capture the call.
It asserts the stub is called with certain text.
const stub = cy.stub()
cy.on ('window:alert', stub)
cy.get('button').contains('Generate Report').click()
.then(() => {
expect(stub).to.be.calledWith('I am an alert box!')
})
From Cypress Window-Alert
If the popup is generated by framework, e.g React the approach is the same as any text on the page.
You might need to use cy.clock() to control the timing, presuming you want to assert the appear/disappear cycle.

Can I detect if an element (button) is "clickable" in my rspecs?

Context: In my rspec (using Ruby and Capybara)
I click on a link to test an action in my app: adding a branch to my app.
A modal window opens, where I select the branch, and then I click a "submit" button to add the branch to my app. After clicking "submit" the modal window is closed.
The rspecs continues by clicking "Save" in the main screen, to save the state of the application (and effectively saving adding the branch).
Problem: The rspec is failing because (seemingly) it is trying to click the "Save" button on the main screen while the modal window that is used to select the branch is still present. The test doesn't complain that it can't find the "Save" button component, but that it can't be clicked.
The error in the log is:
[...]Save</button> is not clickable at point (692, 23). Other element would receive the click[...]
A gotcha: this rspec passes correctly on some environments, like when it is run against my local server, but it fails when it is executed by our automation server. Thus, this test has been tagged as "flaky".
Potential solutions: Things we have tried so far:
Play around our "clicks configuration", making sure we are on "ready state" and that the modal window is gone. We failed with this, since we kept hitting the same error.
Implement a "wait". We added a loop to sleep for a bit while the modal window seemed to exist
XYZ.add_new_branch_name(#branch_name)
while Utilities.element_visible?(:xpath, myElement)
sleep(0.5)
end
XYZ.save
The while condition checks if the "submit" button of the modal window exists. The element_visible function uses
find(method,element).visible?
but I'm not sure if find should already take into account that the button may exist and be visible but not be clickable.
Since this still fails, in spite of all our effort to make sure that the modal is gone before we attempt to click on the "save" button, I want tot ask:
Is there a proper way to detect if an element behind a modal window is clickable or not using rspecs?
find only cares about "visibility", not "clickability" (and different drivers may have slightly different interpretations of "visibility"). The reason for the flakiness you're seeing is most likely speed of the machine running the tests which affects the timing of the modal animating away. The best way to solve this issue is to disable animations in the test mode (how you do that is dependent on exactly what library and/or CSS you're using for the animations). The other way is to do as you're doing - checking that the modal has disappeared before clicking the 'Save' button, however you should just be using the Capybara provided methods (which include waiting/retrying behavior) rather than writing your own loop for that.
expect(page).not_to have_css('css selector of the modal') # RSpec version
assert_no_css('css selector of the modal') # minitest version
After looking at the mouse position from your error, one other potential issue you may be having is with screen size and scrolling. If the page requires to be scrolled to get to the 'Save' button and (692, 23) would put the button behind a fixed header (you should be able to verify that by taking a screenshot before the button click attempt) then it may not be possible for whatever driver you're using to click the button. In that case you'd need to use execute_script to scroll the page to a different location so the button is not covered on the page and/or increase the "browser" size so scrolling isn't necessary in the test.
I had a similar problem and solved it by writing my own click_on_with_wait helper function:
def click_on_with_wait(text, wait_time: Capybara.default_max_wait_time)
success = false
(wait_time * 10).round.times do
click_on text
success = true
break
rescue Selenium::WebDriver::Error::WebDriverError
sleep(0.1)
end
# Try clicking one last time, so that the error will get raised if it still doesn't work
click_on text unless success
end
This will try to click on the element. If it's still hidden by the modal, the function will wait 100ms and then try again, until the given wait_time is reached.
Using Rails, I put it in system_spec_helpers.rb so that I can simply replace click_on 'Submit Form' with click_on_with_wait 'Submit Form'.

How to show a dialog from another dialog?

I am newbie to MFC. I have a native C++ MFC app. I want to show a dialog from main dialog. In the main dialog I am having three button (Back, Next, Cancel) respectively.
On the Next button click event I am calling DoModal to show another dialog by hiding the main dialog as follows,
void CFirstPage::OnBnNextButton()
{
::ShowWindow(this->GetSafeHwnd(),SW_HIDE);
CSecondPage secondDlg;
secondDlg.DoModal();
}
void CSecondPage::OnBnBackBtnClicked()
{
::ShowWindow(this->GetSafeHwnd(),SW_HIDE);
CFirstPage FirstPage;
FirstPage.DoModal();
}
After executing this code snippet, the main dialog got hidden and even the application icon also disappears from the taskbar and again appears when the other dialog pops up.
(Basically I am having the same icon for both the dialogs, the icon should not get disappeared and appear again. It has to remain same without appearing and disappearing .)
How can show the icon in the taskbar without any flickering effect?
During traversing from back to next in middle I clicked cancel and the Cancel event is handled as follows,
void CFirstPage::OnCancel()
{
CDialog::EndDialog(TRUE);//For closing the dialog.
}
void CSecondPage::OnCancel()
{
CDialog::EndDialog(TRUE);//For closing the dialog.
}
Steps1:Click Next in the main dialog
Step2: Click Cancel in the second page
Now the application closes. But still instance is active in the "TaskManager". As per my understanding no instance should be alive once windows is closed ?
I suspect as the first dialog is only hidden not ended that instance is still existing in the TaskManager. Is this understanding correct?
How can I resolve this issue?
Can anyone kindly help me to resolve this issue.
As said by Iinspectable property sheets are best suited for your your problem statement.A very good example on how to use CPropertysheets can be found in codeproject
CProperty sheet example
Probably your main windows is still hidden after you end dialog with second page. Ending dialog of CSecondPage does not close application only closes active CSecondPage dialog.
Also OnCancel/OnOK does not need to be overriden if you just EndDialog with it. There is default behaviour implemented in OnCancel, which will close the dialog.
After secondPage.DoModal() show your main dialog again, or close it if that is the behaviour you want to achieve.
FirstPage isn't the original first dialog now, so you should store the first dialog object by yourself. You can do that like this:
void CFirstPage::OnBnNextButton()
{
::ShowWindow(this->GetSafeHwnd(),SW_HIDE);
CSecondPage secondDlg;
secondDlg.setFirstDialog(this); //customer function to store first dialig object
secondDlg.DoModal();
}
void CSecondPage::OnBnBackBtnClicked()
{
::ShowWindow(this->GetSafeHwnd(),SW_HIDE);
::ShowWindow(m_firstDialog->GetSafeHwnd(), SW_SHOW);
}

Execute a MEL command after a window has opened

I'm writing a MEL script which involves opening the grease pencil UI toolbar. I want to remove the close button on that toolbar. I tried doing
GreasePencilTool;
window -edit -tbm 0 greasePencilFloatingWindow;
but get Error: line 2: window: Object 'greasePencilFloatingWindow' not found.
Further tests reveal that running
GreasePencilTool;
window -q -exists greasePencilFloatingWindow;
will return a result of 0.
Running GreasePencilTool; and then window -edit -tbm 0 greasePencilFloatingWindow; at separate times works as expected, as does running window -edit -tbm 0 greasePencilFloatingWindow; when the toolbar is already open.
However, I need to be able to remove the close button immediately when the toolbar opens.
The closest thing I can think of that illustrates what I want to do are Javascript callback functions, where another function can be executed once the current function is finished... but is there a way to do something like that in MEL?
I've also tried using the evalDeferred command without success.
The grease pencil tool is launched asynchronously so the window will not be present for some unknown length of time. This means the best you could do is trigger a function which would check periodically and do it the next time you find the correctly named window; you could attach this to an idle time script job.
It's ugly. But it is probably the only way since there's no event that will notify when thje window arrives. If you do that, make the script job suicide after it fires so it's not sitting there on every idle check till the end of time.

How do I open browser + click with TestComplete?

I'm trying to just open http://espn.go.com/ and then click on the "NBA" tab using TestComplete.
Could someone tell me how to do this to get me started?
Thanks!
In the example below, you need a unique property name and value of the tab you want to click to be able to find it on the page. You can find this by clicking the tab using the Object Spy tool in test complete.
function nbaTest(){
var nbaTab;
//open browser at espn page
Browsers.Item("iexplore").Run("http://espn.go.com");
//search page for nba tab using a unique property name and corresponding property value of the nba tab
nbaTab = Sys.browser('iexplore').page("*").Find(propertyName,propertyValue,"1000","TRUE");
if (nbaTab.exists){
nbaTab.click();
}
else{
Log.Warning("NBA tab not found");
return;
}
}
I've tried using TestComplete' Recording feature - the script looks reliable. This is what was recorded:
var page;
Browsers.Item(btIExplorer).Navigate("http://espn.go.com/");
page = Aliases.browser.Page("http://espn.go.com/");
page.Panel(1).Panel("content").Panel("nav_wrapper").Panel("nav_wrapper_container").Panel("nav_main").Link("lpos_sitenavdefault_lid_sitenav_nba").Click();
Keyword test to open http://espn.go.com/ and then click on the "NBA" tab:
Steps:
Run TestComplete (I'm using version 10)
Launch the recording (By clicking "Record New Test" or "Append to Test")
Open IE and type the URL http://espn.go.com/ on address bar -> Click NBA tab -> Close the browser
Stop recording and see the KeywordTest you recorded in TestComplete IDE
My KeywordTest I recorded was as below:
Run Browser Parametrized (Internet Explorer, "", pX64) "http://espn.go.com/", ... Launches the specified browser and opens the specified URL in it.
pageEspnTheWorldwideLeaderInSpor Wait Waits until the browser loads the page and is ready to accept user input.
linkTennisM HoverMouse 0, 0 Moves the mouse pointer over the 'linkTennisM' control.
pageEspnTheWorldwideLeaderInSpor Wait Waits until the browser loads the page and is ready to accept user input.
panelModContainerModTabsModNoFoo ClickTab "NBA" Selects the 'NBA' tab of the 'panelModContainerModTabsModNoFoo' tab control.
linkNba HoverMouse 8, 6 Moves the mouse pointer over the 'linkNba' control.
panelHeader HoverMouse 658, 25 Moves the mouse pointer over the 'panelHeader' control.
ToolbarWindow32 ClickItemXY "&File", 16, 8, false Clicks at point (16, 8) of the '&File' item of the 'ToolbarWindow32' toolbar.
PopupMenu Click "Exit" Moves the mouse cursor to the menu item specified and then simulates a single click.
Not sure if this will help but you might be able to automate the step of opening your browser as well.
I use:
Call Sys.OleObject("WScript.Shell").Exec("cmd /c start /MAX iexplore ""http://espn.go.com""")
From there, you can automate the rest as usual (might need to wait for the page to load here as well).

Resources