-
Notifications
You must be signed in to change notification settings - Fork 15
Added tabbar and tab representation #126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
1 similar comment
foxpuppet/windows/browser/tab_bar.py
Outdated
from foxpuppet.region import Region | ||
|
||
|
||
class Tab_bar(Region): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use CamelCase naming convention (TabBar
) as prescribed in pep8
tabs = [self.Tab(self, el) for el in | ||
self.selenium.find_elements(*self._tabs_locator)] | ||
# Assign handles | ||
for tab, handle in zip(tabs, self.selenium.window_handles): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we be sure that the tab elements and window handles will be returned in the same order? What if there are two windows, each with multiple tabs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll look into this. I was under the impression that it will be in order of tab opened since it is a list.
Now thinking about the multiple window situation...technically, geckodriver would see it as the same session since you can have multiple windows per profile already. I don't know if there is a way to differentiate tabs from windows as far as window_handles
goes. I think they are all in one.
Its a little tricky because do we assume that a user testing this will only open one window? If there is no way to tell a window and a tab apart, unless we create a foxpuppet tracking object that has a dict
object and can tell the user which is which depending on when they opened it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we assume that a user testing this will only open one window?
I wouldn't make this assumption. We're providing them with an API for opening new windows and now tabs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no order of window handles at all. Also note that window handles can change right now given if the tab is moved to a different content process (like remoteness change).
Chrome windows of Firefox are handled via chrome_window_handles
but not sure if we pass those through geckodriver yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going along with whimboo, it seems as if it doesn't matter if you open a window or a tab, selenium sees that as a window_handle
.
We could either keep track of each event with a dict but would that be necessary? It seems as if we need an easy way to differentiate between a chrome
window handle and a "Normal" window_handle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are going to open a new tab, you are interested in that tab aka window_handle
and not the window aka chrome_window_handle
. Also it doesn't matter for the test in which window this tab is located in.
foxpuppet/windows/browser/tab_bar.py
Outdated
with self.selenium.context(self.selenium.CONTEXT_CHROME): | ||
self.selenium.find_element(*self._new_tab_button_locator).click() | ||
self.wait.until( | ||
lambda _: len(self.selenium.window_handles) != current_tabs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should wait for there to be one additional tab open. This would also return true if a window/tab closed, or several new windows/tabs opened.
foxpuppet/windows/browser/tab_bar.py
Outdated
'anonid', 'close-button') | ||
button.click() | ||
self.wait.until( | ||
lambda _: len(self.selenium.window_handles) != current_tabs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, we should narrow this condition to mean this tab is closed. We could wait for the current handle to be removed, rather than wait for the count of handles to change. Perhaps @whimboo has other suggestions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have nothing additional to add here.
foxpuppet/windows/browser/tab_bar.py
Outdated
""" | ||
self.selenium.switch_to.window(self.handle) | ||
return self |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why return the tab?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you select or 'Focus' that tab, you should be able to get info about it. i.e.: name, close button, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You already have a reference to the tab though, in order to call this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reference before does not switch selenium over to the tab.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should only affect content though? Is the tab region itself not possible to interact with without switching the window?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct. Should we focus
the tab when we open it?
I could follow firefox puppeteer and check if it is selected and if so switch to it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the default behaviour of Firefox is to select the new tab, however I believe it's possible to change this via a preference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes so firefox will focus it, but selenium won't it seems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Selenium requires an explicit update of the current window handle. As long as you don't do that the browsing context will remain in the opener tab.
foxpuppet/windows/browser/tab_bar.py
Outdated
self.selenium.find_element(*self._new_tab_button_locator).click() | ||
self.wait.until( | ||
lambda _: len(self.selenium.window_handles) != current_tabs) | ||
return self.tabs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why return the list of tabs? It would make more sense to return the new tab so we could do something like:
new_tab = tab_bar.open_new_tab()
new_tab.close()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would all make more sense if code or the technique which we have already written for Firefox Puppet would be taken. It said this already a couple of times, and here is one more example. It would help us to not have such a lot of review cycles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently in Firefox Puppeteer:
Wait(self.marionette).until(
lambda mn: len(mn.window_handles) == len(start_handles) + 1,
message='No new tab has been opened.')
handles = self.marionette.window_handles
[new_handle] = list(set(handles) - set(start_handles))
[new_tab] = [tab for tab in self.tabs if tab.handle == new_handle]
# if the new tab is the currently selected tab, switch to it
if new_tab == self.selected_tab:
new_tab.switch_to()
Which is what Dave is suggesting anyways. I will model this a little closer.
"""Test close Tab.""" | ||
browser.tab_bar.open_new_tab() | ||
browser.tab_bar.tabs[1].close() | ||
assert len(browser.tab_bar.tabs) == 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also ensure the handle for the new tab is not in the list of handles.
def test_close_tab(browser, selenium): | ||
"""Test close Tab.""" | ||
browser.tab_bar.open_new_tab() | ||
browser.tab_bar.tabs[1].close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If open_new_tab
returned the tab region, then we could simplify this to:
tab = browser.tab_bar.open_new_tab()
tab.close()
Returns: :py:class:`Tab`. | ||
""" | ||
self.selenium.switch_to.window(self.handle) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't show the tab if is not the current tab. In this case, we would want to click on the tab. It's also possible that the tab is scrolled out of view on the tab bar, so we'd need to bring it into view before clicking it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to bring it into view if selenium knows where it is? I mean technically it is there, its not hidden or anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if you'll be able to click on an element that's not in view. We're simulating a user, and a user can't switch to a tab without being able to click it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that Marionette currently doesn't know about tabs which haven't been restored via sessionstore. Those don't have a browser, and as such will not be returned.
tabs = browser.tab_bar.open_new_tab() | ||
tabs[-1].select() | ||
assert 'about:newtab' in selenium.current_url | ||
tabs[0].select() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes me feel like we should have a way to access the currently displayed tab, but that can be a later enhancement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean? Selenium has to switch_to
that tab even though firefox switches to it automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean like browser.tab_bar.current_tab
or an attribute on the tab to indicate if it's the currently selected tab. This would allow you to store the currently selected tab, open a tab, close the new tab, and assert that we're back to the original tab.
@m8ttyB This is the PR. |
I found this for making sure the handle is not a window:
Thoughts? I see there is a TODO on that function. I am thinking we modify |
@jrbenny35 you've mentioned this is blocking some other work. I'm wondering if we can reduce the scope of this so whatever it's blocking can be unblocked. Do you have details of what's required by the blocked work? |
@davehunt yeah this is for testing lockbox. I need to install the extension, select the tab the extension opens and then interact with what is on that page. I can use what I have now to get it done but we should still hash this out and find a good solution. I've made a lot of changes that bring it more in line with puppeteer but the question of what handles are mapped to what windows is still what I am working on. |
Why would we need to know what window handle is a window vs a tab. If the user opened a new window that has a tab, they could still interact with the window. i.e.: refresh/back/forward etc. If the tab is in another window, firefox will switch to it and so will selenium. Technically each tab can be its own 'window' as well. |
I assume we can close this PR given that it didn't receive any update for more than a year. |
This is a matured version of PR #69.
Solves #1, #2, #3, #5, #6