When to close the child window when parent window is being closed in Angular - window

I've seen many articles but don't seem to find an answer
when I try to close the parent window childWindow doesn't get closed.
So I have these two events so far
#HostListener('window:beforeunload', ['$event'])
beforeUnload(e:any){
if(this.childWindow && !this.childWindow.closed){
e.preventDefault();
e.returnValue = false;
}
}
#HostListener('window:unload', ['$event'])
onUnload(e:any){
if(this.childWindow && !this.childWindow.closed){
this.childWindow.close();
}
}
This code blocks are working fine
but when I close the last parent window, the connected child window doesn't get closed.
note scenario: When I debug the unload event line by line, the child window is getting closed but not when I click continue
probable reason: the parent window's by the time time unload is triggered, it doesn't care about the child window
Am I doing something wrong or is there any other event that I could use?

One way to handle this would be to give the child window some time to close before the parent window is closed. You can use the setTimeout function to delay the closing of the parent window for a short period of time, such as 100ms. This would give the childWindow.close() method enough time to execute and close the child window before the parent window is closed.
#HostListener('window:beforeunload', ['$event'])
beforeUnload(e: any) {
if (this.childWindow && !this.childWindow.closed) {
e.preventDefault();
e.returnValue = false;
setTimeout(() => {
this.childWindow.close();
}, 100);
}
}
As for capturing the user action on the browser's default dialog, it's not possible to capture whether the user has clicked 'Leave' or 'Cancel' as the browser's default dialog does not provide any way to capture the user's choice.
You could try to use e.returnValue to provide your own message on the browser's default dialog and then you could set a flag based on the user's choice, but it will be different across the browsers.
#HostListener('window:beforeunload', ['$event'])
beforeUnload(e: any) {
if (this.childWindow && !this.childWindow.closed) {
e.returnValue = 'Are you sure you want to close the window?';
}
}
You can also try to use localStorage or sessionStorage to store a flag indicating if the user has confirmed to close the window, but this will only work if the user does not clear the browser's storage.
If it is closing the child window, even when user has clicked cancel on dialog
One way to address this would be to use the localStorage or sessionStorage to store a flag indicating whether the user has confirmed that they want to close the window.
You can set this flag to true when the user confirms that they want to close the window, and then check the flag's value in the beforeunload event handler. If the flag is true, you can proceed with closing the child window, otherwise, you can cancel the close operation.
#HostListener('window:beforeunload', ['$event'])
beforeUnload(e: any) {
if (this.childWindow && !this.childWindow.closed) {
if (localStorage.getItem('closeConfirmed') === 'true') {
this.childWindow.close();
} else {
e.preventDefault();
e.returnValue = 'Are you sure you want to close the window?';
}
}
}
// Set the flag when the user confirms they want to close the window
confirmClose() {
localStorage.setItem('closeConfirmed', 'true');
window.close();
}
And you can add a confirm button on your dialog that calls the confirmClose method.
closing windows programmatically may be blocked by some browser so to be on a safer side provide a way for the user to close the window manually.

Related

Test only if element still present

I have a notification message which pops up upon saving a file and wish to close it only if it is still present when I need to press the next button which may be covered by this notification.
So far this is how I have tried to conditionally close the notification
Cypress.Commands.add('notificationClose', () => {
if (cy.get('.notification').should('be.visible')) {
console.log('CLOSE ME');
cy.get('.notification-dismiss').click({mulitple: true});
}else{
console.log('ALREADY GONE');
}
});
I have also tried a jQuery solution I found here too.
Cypress.Commands.add('notificationClose', () => {
if (Cypress.$('.notifications-wrapper') == true) {
cy.get('.notification-dismiss').click({mulitple: true});
}
});
I only use this immediately before needing to click the subsequent button, so the notification may close on its own.
The element in question is only temporarily attached to the DOM after saving the file.
How do I ask if this element is attached to the DOM?
I'm not completely sure that I understand your issue. But this is what I assume you mean:
You have a popup that isn't closed sometimes.
If the popup isn't closed you want to close it.
If the popup is closed you want to continue the test.
If that is correct we only need to fix step 1 and 2 since those are special. Continuing the test is just like you normally do.
To get the behaviour you need to get() the element and assert if it is present. You can do that with this code:
cy.get('body').then($body => {
if ($body.find('.notification').length === 1) {
cy.get('.notification-dismiss').click()
}
})
// continu the test

How to get the current tab's history in a Web Extension in Firefox?

Is there an API that makes it possible to get the current tab's history in a Web Extension in Firefox? Just like when clicking and holding on the Back button, a dropdown will appear to show the current tab's history.
No. You cannot ask for the list for a certain tab by default.
You can, however, listen for the tab events onUpdated, onCreated etc. Using the tabId which stays the same, you can keep a list of URLs in a background script (background.js) which is always running if the addon is enabled.
You would do it like this:
let arr=[]; // At the top of background.js
browser.tabs.onCreated.addListener(handleCreated); // Somewhere in background.js
function handleCreated(tab) {
let tabId = tab.id;
if(arr[tabId]==null) arr[tabId] = [];
arr[tabId].push(url);
}
function getHistoryForCurrentTab(){
function currentTabs(tabs) {
// browser.tabs.query returns an array, lets assume the first one (it's safe to assume)
let tab = tabs[0];
// tab.url requires the `tabs` permission (manifest.json)
// We will now log the tab history to the console.
for(let url of arr[tab.id]){
console.log(url);
}
}
function onError(error) {
console.log(`This should not happen: ${error}`);
}
browser.tabs.query({currentWindow: true, active: true}).then(currentTabs, onError);
}
The above code is a proof of concept. Some improvements you will need to consider: implement onClosed which resets the tab history for that id (arr[tabId] = null), implement onUpdated (will be needed for sure, same logic as in handleCreated).
Links:
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs

How to get handle of popup window (WebdriverIO)

I am very very new to automated testing and I am currently completely stuck with the following issue:
I have a webpage open(first window)
In the same test I call a .newWindow(second window) and do some stuff in that window. The last action opens new popup window(popup window).
What I need, is to set the focus on a popup window.
According to WebdriverIO API I can use .switchTab http://webdriver.io/api/window/switchTab.html
But to be able to switch to a popup window I have to indicate handle, but I don't understand how to get the handle of a popup window :(
That s my piece of code:
//this is the part where I have already second window open
it('should open email letter', function(done) {
client
.pause(2000)
.clickAndWait('[title="Password restore"]', 4000)
.clickAndWait('[title="Restore password"]', 7000) //this is the part where popup window opens
.pause(2000)
.windowHandles(function(err,res){
console.log(res, handles)
}) // I have got three handles but i dont know how to use them now
.........
There is a lot of examples in java, but i didnt find anything that would fit mine language.
Please, excuse me my dumbness, I am really a very beginner and I will appreciate if somebody could explain that to me.
Thanks a lot in advance!
we not use getCurrentTabId to remember the handle of the currently open window?
For example:
var main, popup; //your window handles
client
.getCurrentTabId(function (err, handle) {
main = handle;
})
.newWindow('http://localhost:9001/') //you are on popup window
.getCurrentTabId(function (err, handle) {
popup = handle;
})
.switchTab(main) //you are back to main window
.switchTab(popup) //you are on popup again
.close(popup) //extra bonus!
I notice you stated "The last action opens new popup window(popup window). What I need, is to set the focus on a popup window."
I had this issue. But the new window was opened when clicking on login with facebook. This caused an issue on finding the handle for the new window because I could not use .newWindow('http://localhost:9001/'). The API keys and all sorts are added as parameters when using a social login. So one has little control
To handle this I registered each window ID as its opened.
The first background step in my feature is Given I open the url "/a.html"
In the step you can set an empty array as the variable windowID with let let windowID = []
So my step file would look like this
const url = 'http://localhost:8080'
let windowID = []
this.Given(/^I open the url "([^"]*)"$/, (path) => {
browser
.url(url + path)
console.log(`# Navigating to ${url + path}`)
expect(browser.getUrl()).toEqual(url + path)
windowID.main = browser.getTabIds()
});
During the step after clicking the Facebook button you can then check all the open window ID's and drop the one that matches windowID.main
this.When(/^I authenticate with facebook$/, function (arg1) {
// log the ID of the main window
console.log('Main Window ID' + windowID.main)
browser
.pause(2000)
.getTabIds().forEach(function (value) {
if (value === windowID.main) {
// we do not need to do anything with windowID.main as it's already set
return
}
// if the value does not match windowID.main then we know its the new facebook login window
windowID.facebook = value
})
// log both of these
console.log('Main Window ID: ' + windowID.main)
console.log('Facebook Window ID: ' + windowID.facebook)
// Do the login
browser
.switchTab(windowID.facebook)
.setValue('input[name="email"]', process.env.FACEBOOK_EMAIL)
.setValue('input[name="pass"]', process.env.FACEBOOK_PASSWORD)
.submitForm('form')
});
note that I add credentials as an environment variable. This is a good idea, you don't want to commit your personal credentials to the code base. One may think well obviously, but you may not, who knows.
You had your question answered years ago, but I found this post first when trying to find a solution so it seems a sensible place to put this addition.

ChangeValueHandler not fired when clicking on the back button In GWT

I have a form and I want to display a confirmation dialogBox when the user presses the back button. Let say that I have one Texbonx that listens to a ChangeValueHandler
addValueChangeHandler(new ValueChangeHandler<String>() {
#Override
public void onValueChange(ValueChangeEvent<String> event) {
setChanged(true);
}
});
This is the short scenario
1) I enter text in the TextBox
2) I hit the back button
3) The ValueChangeEvent is not called
I tried the fire the BlurEvent programmatically on the TextBox with textBox.fireEvent(new BlurEvent() { }); but still no result.
Any suggestions ?
When the page is closed (by pressing the back button, or closing the page) no events will be fired by the controls. What will fire first is window.onbeforeunload to give you a chance to warn the user about data loss and offer to stay on the page. If the user chooses to stay on the page, then all the events that were supposed to be fired, will fire (so your change event will fire).
You can attach a handler to the native onbeforeunload event by using Window.addClosingHandler.
Window.addWindowClosingHandler(new ClosingHandler() {
#Override
public void onWindowClosing( ClosingEvent event )
{
event.setMessage("If you leave the page now all data will be lost.");
}
});
It's worth noting that the ClosingEvent and it's underlying onbeforeunload event, cannot, under any circumstances, be cancelled programmatically. The only way to prevent the user from leaving the page is if the user itself chooses "Stay On This Page" in the popup that results from the code above.
What I did is to set the focus of the TextBox to False and then check if it's changed, that forces the TextBox to unfocus when hiting the back button.
This is the code that check if a form is changed
public boolean isChanged(){
if(formPanel == null) return false;
for (int i = 0; i < formPanel.getWidgetCount(); i++) {
if(formPanel.getWidget(i) instanceof BaseWidget){
BaseWidget w= (BaseWidget) formPanel.getWidget(i);
w.setFocus(false);
if(w.isChanged()){
return true;
}
}
}
return false;
}

jQuery click event behaves differently with live function in Firefox

Using the event click with live function leads to strange behavior when using Firefox*.
With live in Firefox, click is triggered when right-clicking also! The same does not happen in Internet Explorer 7 neither in Google Chrome.
Example:
Without live, go to demo and try right clicking
the paragraphs. A dialog menu should
appear.
With live, go to demo and try right
clicking "Click me!". Now both dialog
menu and "Another paragraph" appear.
*tested with firefox 3.5.3
As far as I know, that is a known issue (bug?). You can easily work around it by testing which button was clicked as follows:
$('a.foo').live("click", function(e) {
if (e.button == 0) { // 0 = left, 1 = middle, 2 = right
//left button was clicked
} else {
//other button was clicked (do nothing?)
//return false or e.preventDefault()
}
});
you might prefer using a switch depending on your specific requirements, but generally you would probably just want to do nothing (or or simply return) if any button other than the left button is clicked, as above:
$('a.foo').live("click", function(e) {
switch(e.button) {
case 0 : alert('Left button was clicked');break;
default: return false;
}
});
I think it's a known "bug", you could potentially query the event object after attaching the click handler ( which gets attached to the document ) and see if its a right click, otherwise manually attach the click handler after you manipulate the DOM.
After looking it up, e.button is the property you want to query:
.live('click', function(e){
if ( e.button == 2 ) return false; // exit if right clicking
// normal action
});
See my answer here: if you don't mind changing the jQuery source a bit, adding a single line in the liveHandler() works around the problem entirely.

Resources