I want to test a file download. It is made programmatically on click a button that uses this function:
export function downloadURI(uri, target) {
const link = document.createElement('a')
if (target) link.target = target
link.href = uri
link.click()
}
The problem is that when you do cy.click() on that button the new tab is opened and the tests fail. I am checking that the download is successful by asserting the loading modal is visible after clicking the button (while the file is being generated via an HTTP request) and is Not visible after the download was generated.
How can I prevent this tab from opening so that the tests do not fail?
This works for me:
cy.get('a').invoke('removeAttr', 'target').click()
From the official document it says that cypress does not support multiple tabs testing.
Also there is a recipe including 3 solutions about how to handle this.
Have a read and see if it can help.
Related
How to handle the windows in Cypress?
The problem I'm facing is that when I click a button, a new browser window gets opened in a new tab with the actual page to test.
I have tried everything -> window.open and window.location.replace without success (the target _blank is not possible because there is not that tag in the button)
How can I handle that functionality?
Thanks in advance.
The problem is window.open can't be stubbed in the usual (simple) way, a security feature to prevent browser hijack.
This article Stub window.open has an alternative
TLDR - modify the window before it hits the browser
// ✅ CORRECT SOLUTION
it('opens a new window', () => {
// create a single stub we will use
const stub = cy.stub().as('open')
cy.on('window:before:load', (win) => {
cy.stub(win, 'open').callsFake(stub)
})
cy.visit('/')
// triggers the application to call window.open
cy.get('button').click('Open new window')
cy.get('#open').should('have.been.calledOnce')
I found many different approaches to stubbing the window.open call, but none of them worked out of the box.
In my use case there's a button that launches a click event. The click event then opens a new tab with a dynamic url that I wanted to grab.
The answer is a mix of a great post: https://glebbahmutov.com/blog/stub-window-open/ and Cypress: Stub open window.
This example should work with Cypress 10.x
// Listen to window:before:load events, modify the window object before the app code runs between page transitions
// Create a stub with the alias windowOpen, choose whatever you like
// Grab the url parameter that the page was trying to open and visit the page
cy.on('window:before:load', (win) => {
cy.stub(win, 'open').as('windowOpen').callsFake(url => {
cy.visit(url);
})
})
// Start by visiting the page you'll run your tests in. I'm using the baseUrl here.
cy.visit("/");
// Do whatever tests need to be done before the action the opens a new tab
// Now the element that fires a click event which then uses window.open to open a new tab
cy.contains("Ok").click();
// The stub should now have picked the url and called cy.visit(url)
// The page that would normally open in a new tab, should be visible in the same page
// Now the next commands are intended to run in the new page and should be able to complete
cy.get(".whateverselectoryouwant")
.should('have.text', 'whateveryourtextisonthenewpage')
If I have a link in my website. Eg. go to Google and I want to make a test:
GIVEN link (html tag a)
WHEN click the link
THEN browser opens new tab and URL of this tab includes 'google.com'
I know that this does not work:
cy.get('a').click();
cy.url().should('include', 'google.com');
Since the a has a target attribute you can do this.
cy.get('a')
.should('be.visible')
.then(($a) => {
expect($a).to.have.attr('target','_blank')
// update attr to open in same tab
$a.attr('target', '_self')
})
.click()
cy.url().should('include', 'google.com')
Depending on your app and what you are wanting to test, using cy.request() and checking on 200 status code may suffice for an external url.
You can use removeAttr to remove target and then click the link and assert. Something like:
cy.get('a').invoke('removeAttr', 'target').click()
cy.url().should('include', 'google.com')
I have a webview inside my application and when an external link is clicked (that in normal browser is open in a new tab), I can't then go back to my website.
It is possible when a new tab is open to have the menu closed that tab like Gmail do ?
The objective is that, whenever a link is clicked, the user would have the choice to choose which option to view the content with, e.g. Clicking a link would suggest open youtube app or google chrome. The purpose is to appear the google chrome option
Or what suggestions do you have to handle this situation ?
If I understood you correctly, you want to have the option to select how to open the web link - inside your app, or within another app's (browser) context.
If this is correct, then you can use Xamarin.Essentials: Browser functionality.
public async Task OpenBrowser(Uri uri)
{
await Browser.OpenAsync(uri, BrowserLaunchMode.SystemPreferred);
}
Here the important property is the BrowserLaunchMode flag, which you can learn more about here
Basically, you have 2 options - External & SystemPreferred.
The first one is clear, I think - it will open the link in an external browser.
The second options takes advantage of Android's Chrome Custom Tabs & for iOS - SFSafariViewController
P.S. You can also customise the PreferredToolbarColor, TitleMode, etc.
Edit: Based from your feedback in the comments, you want to control how to open href links from your website.
If I understood correctly, you want the first time that you open your site, to not have the nav bar at the top, and after that to have it. Unfortunately, this is not possible.
You can have the opposite behaviour achieved - the first time that you open a website, to have the nav bar and if the user clicks on any link, to open it externally (inside a browser). You have 2 options for this:
To do it from your website - change the a tag's target to be _blank like this;
To do it from your mobile app - create a Custom renderer for the WebView. In the Android project's renderer implementation, change the Control's WebViewClient like so:
public class CustomWebViewClient : WebViewClient
{
public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request)
{
Intent intent = new Intent(Intent.ActionView, request.Url);
CrossCurrentActivity.Current.StartActivity(intent);
return true;
}
}
Lightswitch provides a Logout button on the Home page by default, but I'd like to have the option to log out on other pages as well. Is it possible to place the logout button on multiple pages?
If you're working with the HTML client, this can easily be achieved by replacing the following line of code in the LightSwitch library's _determineButtons function: -
result.showLogOut = msls_shell.getHomeScreen() === navigationUnit.screen.details.getModel();
With the following line of code: -
result.showLogOut = true;
This function is located in Scripts\msls-?.?.?.js file and, in order for this type of library file change to be applied, you'll need to reference the un-minified version of the LightSwitch library by making the following change in your HTML client's default.htm file: -
<!--<script type="text/javascript" src="Scripts/msls-?.?.?.min.js"></script>-->
<script type="text/javascript" src="Scripts/msls-?.?.?.js"></script>
The question marks in the msls reference will need to mirror the version you're using e.g. msls-2.5.2.js (for Visual Studio 2013 Update 4).
The above approach will force the LogOut button to appear on every page. However, if you need more control over when the LogOut button appears, you could use the following alternative change in the _determineButtons function: -
result.showLogOut = window.msls.showLogOut;
Then, in the created method of each screen, set the msls.showLogOut property to true when you wish the button to appear and to false when you don't e.g.: -
myapp.BrowseContacts.created = function (screen) {
// Write code here.
msls.showLogOut = true;
};
You don't say what version or language. This is VB for VS2012, Lightswitch web application.
Add a button to the Screen Command Bar, call it Logout (you can choose an image for it in the Properties panel later if you want). Right click the button and select Edit Execute Code. Use the following:
Private Sub Logout_Execute()
Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(
Sub()
System.Windows.Browser.HtmlPage.Window.Navigate(New Uri("../LogOut.aspx", UriKind.Relative))
End Sub)
End Sub
Works for me.
Phil
I'd like to extend my WatiN automated tests to drive a page that guards against the user accidentally leaving the page without saving changes.
The page uses the "beforeunload" technique to seek confirmation from the user:
$(window).bind('beforeunload', function (event) {
if (confirmationRequired) {
return "Sure??";
}
});
My WatIn test is driving the page using IE. I cannot find a way to get WatIn to attach to the popup dialog so I can control it from my test.
All the following have failed (where the hard-coded strings refer to strings that I can see on the popup):
Browser.AttachTo<IE>(Find.ByTitle("Windows Internet Explorer");
browser.HtmlDialog(Find.FindByTitle("Windows Internet Explorer));
browser.HtmlDialog(Find.FindByTitle("Are you sure you want to leave this page?));
browser.HtmlDialog(Find.FindFirst());
Thanks!
You'll need to create and add the dialog handler.
Example Go to example site, click link, click leave page on confirmation dialog:
IE browser = new IE();
browser.GoTo("http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/refs/onbeforeunload.htm");
WatiN.Core.DialogHandlers.ReturnDialogHandlerIe9 myHandler = new WatiN.Core.DialogHandlers.ReturnDialogHandlerIe9();
browser.AddDialogHandler(myHandler);
browser.Link(Find.ByUrl("http://www.microsoft.com")).ClickNoWait();
myHandler.WaitUntilExists();
myHandler.OKButton.Click();
browser.RemoveDialogHandler(myHandler);
The above is working on WatiN2.1, IE9, Win7. If using IE8 or before, you will likely need to use the ReturnDialogHandler object instead of the Ie9 specific handler