Skip to content

Commit 075c2da

Browse files
authored
Browser tab management +semver: feature (#172)
* add BrowserTabNavigation with unuit tests * move js scripts to files add possibility to open url in new tab with test * #168 fix review issues * #168 fix review comments * #168 SwitchToTab -> SwitchToTab * #168 SwitchToTab -> SwitchToLastTab
1 parent a013095 commit 075c2da

File tree

12 files changed

+357
-4
lines changed

12 files changed

+357
-4
lines changed

Aquality.Selenium/src/Aquality.Selenium/Aquality.Selenium.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<EmbeddedResource Include="Resources\JavaScripts\GetViewPortCoordinates.js" />
4848
<EmbeddedResource Include="Resources\JavaScripts\IsPageLoaded.js" />
4949
<EmbeddedResource Include="Resources\JavaScripts\MouseHover.js" />
50+
<EmbeddedResource Include="Resources\JavaScripts\OpenInNewTab.js" />
5051
<EmbeddedResource Include="Resources\JavaScripts\ScrollBy.js" />
5152
<EmbeddedResource Include="Resources\JavaScripts\ScrollToBottom.js" />
5253
<EmbeddedResource Include="Resources\JavaScripts\ScrollToElement.js" />
@@ -56,6 +57,7 @@
5657
<EmbeddedResource Include="Resources\JavaScripts\SelectComboBoxValueByText.js" />
5758
<EmbeddedResource Include="Resources\JavaScripts\SetFocus.js" />
5859
<EmbeddedResource Include="Resources\JavaScripts\SetInnerHTML.js" />
60+
<EmbeddedResource Include="Resources\JavaScripts\OpenNewTab.js" />
5961
<EmbeddedResource Include="Resources\JavaScripts\SetValue.js" />
6062
<EmbeddedResource Include="Resources\Localization\en.json" />
6163
<EmbeddedResource Include="Resources\Localization\ru.json" />

Aquality.Selenium/src/Aquality.Selenium/Browsers/Browser.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,15 @@ private INavigation Navigate()
173173
return new BrowserNavigation(Driver);
174174
}
175175

176+
/// <summary>
177+
/// Provide interface to manage of browser tabs.
178+
/// </summary>
179+
/// <returns>instance of IBrowserTabNavigation.</returns>
180+
public IBrowserTabNavigation Tabs()
181+
{
182+
return new BrowserTabNavigation(Driver);
183+
}
184+
176185
/// <summary>
177186
/// Handles alert.
178187
/// </summary>
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using Aquality.Selenium.Core.Localization;
2+
using OpenQA.Selenium.Remote;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
7+
namespace Aquality.Selenium.Browsers
8+
{
9+
public class BrowserTabNavigation : IBrowserTabNavigation
10+
{
11+
private readonly RemoteWebDriver driver;
12+
13+
internal BrowserTabNavigation(RemoteWebDriver driver)
14+
{
15+
this.driver = driver;
16+
}
17+
18+
private ILocalizedLogger Logger => AqualityServices.LocalizedLogger;
19+
20+
public string CurrentTabHandle
21+
{
22+
get
23+
{
24+
Logger.Info("loc.browser.get.tab.handle");
25+
return driver.CurrentWindowHandle;
26+
}
27+
}
28+
29+
public IList<string> TabHandles
30+
{
31+
get
32+
{
33+
Logger.Info("loc.browser.get.tab.handles");
34+
return driver.WindowHandles;
35+
}
36+
}
37+
38+
public void CloseTab()
39+
{
40+
Logger.Info("loc.browser.tab.close");
41+
driver.Close();
42+
}
43+
44+
public void OpenNewTab(bool switchToNew = true)
45+
{
46+
Logger.Info("loc.browser.tab.open.new");
47+
AqualityServices.Browser.ExecuteScript(JavaScript.OpenNewTab);
48+
if (switchToNew)
49+
{
50+
SwitchToLastTab();
51+
}
52+
}
53+
54+
public void OpenInNewTab(string url)
55+
{
56+
AqualityServices.Browser.ExecuteScript(JavaScript.OpenInNewTab, url);
57+
}
58+
59+
public void SwitchToLastTab(bool closeCurrent = false)
60+
{
61+
Logger.Info("loc.browser.switch.to.new.tab");
62+
CloseAndSwitch(TabHandles.Last(), closeCurrent);
63+
}
64+
65+
public void SwitchToTab(string handle, bool closeCurrent = false)
66+
{
67+
Logger.Info("loc.browser.switch.to.tab.handle", handle);
68+
CloseAndSwitch(handle, closeCurrent);
69+
}
70+
71+
public void SwitchToTab(int index, bool closeCurrent = false)
72+
{
73+
Logger.Info("loc.browser.switch.to.tab.index", index);
74+
var names = TabHandles;
75+
if (index < 0 || names.Count <= index)
76+
{
77+
throw new IndexOutOfRangeException(
78+
$"Index of browser tab '{index}' you provided is out of range {0}..{names.Count}");
79+
}
80+
81+
var newTab = names.ElementAt(index);
82+
CloseAndSwitch(newTab, closeCurrent);
83+
}
84+
85+
private void CloseAndSwitch(string name, bool closeCurrent)
86+
{
87+
if (closeCurrent)
88+
{
89+
CloseTab();
90+
}
91+
92+
driver.SwitchTo().Window(name);
93+
}
94+
}
95+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System.Collections.Generic;
2+
3+
namespace Aquality.Selenium.Browsers
4+
{
5+
/// <summary>
6+
/// Provides functionality to work with browser tab navigation.
7+
/// </summary>
8+
public interface IBrowserTabNavigation
9+
{
10+
/// <summary>
11+
/// Gets current tab handle.
12+
/// </summary>
13+
/// <returns>Current tab handle.</returns>
14+
string CurrentTabHandle { get; }
15+
16+
/// <summary>
17+
/// Gets opened tab handles.
18+
/// </summary>
19+
/// <returns>List of tab handles.</returns>
20+
IList<string> TabHandles { get; }
21+
22+
/// <summary>
23+
/// Switches to tab.
24+
/// </summary>
25+
/// <param name="name">Tab handle.</param>
26+
/// <param name="closeCurrent">Close current tab if true and leave it otherwise.</param>
27+
void SwitchToTab(string tabHandle, bool closeCurrent = false);
28+
29+
/// <summary>
30+
/// Switches to tab.
31+
/// </summary>
32+
/// <param name="index">Tab index.</param>
33+
/// <param name="closeCurrent">Close current tab if true and leave it otherwise.</param>
34+
void SwitchToTab(int index, bool closeCurrent = false);
35+
36+
/// <summary>
37+
/// Switches to the last tab.
38+
/// </summary>
39+
/// <param name="closeCurrent">Close current tab if true and leave it otherwise.</param>
40+
void SwitchToLastTab(bool closeCurrent = false);
41+
42+
/// <summary>
43+
/// Closes curent tab.
44+
/// </summary>
45+
void CloseTab();
46+
47+
/// <summary>
48+
/// Opens new tab.
49+
/// </summary>
50+
/// <param name="switchToNew">Switches to new tab if true and stays at current otherwise.</param>
51+
void OpenNewTab(bool switchToNew = true);
52+
53+
/// <summary>
54+
/// Navigates to desired url in new tab.
55+
/// </summary>
56+
/// <param name="url">String representation of URL.</param>
57+
void OpenInNewTab(string url);
58+
}
59+
}

Aquality.Selenium/src/Aquality.Selenium/Browsers/JavaScript.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ public enum JavaScript
3131
SetFocus,
3232
SetInnerHTML,
3333
SetValue,
34-
GetViewPortCoordinates
34+
GetViewPortCoordinates,
35+
OpenNewTab,
36+
OpenInNewTab
3537
}
3638

3739
/// <summary>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
window.open(arguments[0]);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
window.open();

Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/en.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,12 @@
5757
"loc.waitinvisible": "Wait until element is not visible",
5858
"loc.waitnotexists": "Wait until element does not exist in DOM during {0} seconds",
5959
"loc.no.elements.found.in.state": "No elements with locator '{0}' found in {1} state",
60-
"loc.elements.were.found.but.not.in.state": "Elements were found by locator '{0}'. But {1}"
60+
"loc.elements.were.found.but.not.in.state": "Elements were found by locator '{0}'. But {1}",
61+
"loc.browser.switch.to.tab.handle": "Switching to tab by handle '{0}'",
62+
"loc.browser.switch.to.tab.index": "Switching to tab by index '{0}'",
63+
"loc.browser.switch.to.new.tab": "Switching to new tab",
64+
"loc.browser.get.tab.handles": "Getting tab handles",
65+
"loc.browser.get.tab.handle": "Getting current tab handle",
66+
"loc.browser.tab.open.new": "Opening new tab",
67+
"loc.browser.tab.close": "Closing tab"
6168
}

Aquality.Selenium/src/Aquality.Selenium/Resources/Localization/ru.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,12 @@
5656
"loc.waitinvisible": "Ожидаем пока элемент исчезнет",
5757
"loc.waitnotexists": "Ожидаем исчезновения элемента из DOM в течении {0}",
5858
"loc.no.elements.found.in.state": "Не удалось найти элементов по локатору '{0}' в {1} состоянии",
59-
"loc.elements.were.found.but.not.in.state": "Удалось найти элементы по локатору '{0}'. Но {1}"
59+
"loc.elements.were.found.but.not.in.state": "Удалось найти элементы по локатору '{0}'. Но {1}",
60+
"loc.browser.switch.to.tab.handle": "Переключение на новую вкладку по дескриптору '{0}'",
61+
"loc.browser.switch.to.tab.index": "Переключение на новую вкладку по индексу '{0}'",
62+
"loc.browser.switch.to.new.tab": "Переключение на новую вкладку",
63+
"loc.browser.get.tab.handles": "Получение списка дескрипторов открытых вкладок",
64+
"loc.browser.get.tab.handle": "Получение дескриптора текущей вкладки",
65+
"loc.browser.tab.open.new": "Открытие новой вкладки",
66+
"loc.browser.tab.close": "Закрытие вкладки"
6067
}
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
using System;
2+
using Aquality.Selenium.Browsers;
3+
using Aquality.Selenium.Tests.Integration.TestApp.TheInternet.Forms;
4+
using NUnit.Framework;
5+
using System.Linq;
6+
7+
namespace Aquality.Selenium.Tests.Integration
8+
{
9+
internal class BrowserTabsTests : UITest
10+
{
11+
private readonly WelcomeForm WelcomeForm = new WelcomeForm();
12+
13+
[SetUp]
14+
public void Before()
15+
{
16+
AqualityServices.Browser.GoTo(WelcomeForm.Url);
17+
}
18+
19+
[Test]
20+
public void Should_BePossibleTo_OpenUrlInNewTab()
21+
{
22+
var url = new WelcomeForm().Url;
23+
var browser = AqualityServices.Browser;
24+
browser.Tabs().OpenInNewTab(url);
25+
browser.Tabs().SwitchToLastTab();
26+
Assert.AreEqual(2, browser.Tabs().TabHandles.Count);
27+
Assert.AreEqual(browser.Driver.Url, url);
28+
}
29+
30+
[Test]
31+
public void Should_BePossibleTo_HandleTab()
32+
{
33+
var browser = AqualityServices.Browser;
34+
var tabHandle = browser.Tabs().CurrentTabHandle;
35+
Assert.IsNotEmpty(tabHandle, "Tab name should not be empty");
36+
}
37+
38+
[Test]
39+
public void Should_BePossibleTo_GetTabHandles()
40+
{
41+
var browser = AqualityServices.Browser;
42+
var tabHandles = browser.Tabs().TabHandles;
43+
Assert.AreEqual(1, tabHandles.Count, "Tab number should be correct");
44+
Assert.IsNotEmpty(tabHandles.First(), "Tab handle should not be empty");
45+
}
46+
47+
[Test]
48+
public void Should_BePossibleTo_OpenNewTab()
49+
{
50+
var browser = AqualityServices.Browser;
51+
var tabHandle = browser.Tabs().CurrentTabHandle;
52+
53+
browser.Tabs().OpenNewTab();
54+
var newTabHandle = browser.Tabs().CurrentTabHandle;
55+
Assert.AreEqual(2, browser.Tabs().TabHandles.Count, "New tab should be opened");
56+
Assert.AreNotEqual(tabHandle, newTabHandle, "Browser should be switched to new tab");
57+
58+
browser.Tabs().OpenNewTab(false);
59+
Assert.AreEqual(3, browser.Tabs().TabHandles.Count, "New tab should be opened");
60+
Assert.AreEqual(newTabHandle, browser.Tabs().CurrentTabHandle, "Browser should not be switched to new tab");
61+
}
62+
63+
[Test]
64+
public void Should_BePossibleTo_CloseTab()
65+
{
66+
var browser = AqualityServices.Browser;
67+
WelcomeForm.ClickElementalSelenium();
68+
Assert.AreEqual(2, browser.Tabs().TabHandles.Count, "New tab should be opened");
69+
browser.Tabs().CloseTab();
70+
Assert.AreEqual(1, browser.Tabs().TabHandles.Count, "New tab should be closed");
71+
}
72+
73+
[Test]
74+
public void Should_BePossibleTo_SwitchToNewTab()
75+
{
76+
CheckSwitchingBy(2, () =>
77+
{
78+
AqualityServices.Browser.Tabs().SwitchToLastTab();
79+
});
80+
}
81+
82+
[Test]
83+
public void Should_BePossibleTo_SwitchToNewTab_AndClose()
84+
{
85+
CheckSwitchingBy(1, () =>
86+
{
87+
AqualityServices.Browser.Tabs().SwitchToLastTab(true);
88+
});
89+
}
90+
91+
[Test]
92+
public void Should_BePossibleTo_SwitchToNewTabByHandle()
93+
{
94+
CheckSwitchingBy(3, () =>
95+
{
96+
var browser = AqualityServices.Browser;
97+
var tabHandle = browser.Tabs().TabHandles.Last();
98+
browser.Tabs().OpenNewTab(false);
99+
browser.Tabs().SwitchToTab(tabHandle);
100+
});
101+
}
102+
103+
[Test]
104+
public void Should_BePossibleTo_SwitchToNewTabByHandle_AndClose()
105+
{
106+
CheckSwitchingBy(2, () =>
107+
{
108+
var browser = AqualityServices.Browser;
109+
var tabHandle = browser.Tabs().TabHandles.Last();
110+
browser.Tabs().OpenNewTab(false);
111+
browser.Tabs().SwitchToTab(tabHandle, true);
112+
});
113+
}
114+
115+
[Test]
116+
public void Should_BePossibleTo_SwitchToNewTabByIndex()
117+
{
118+
CheckSwitchingBy(3, () =>
119+
{
120+
AqualityServices.Browser.Tabs().OpenNewTab(false);
121+
AqualityServices.Browser.Tabs().SwitchToTab(1);
122+
});
123+
}
124+
125+
[Test]
126+
public void Should_BePossibleTo_SwitchToNewTabByIndex_AndClose()
127+
{
128+
CheckSwitchingBy(2, () =>
129+
{
130+
AqualityServices.Browser.Tabs().OpenNewTab(false);
131+
AqualityServices.Browser.Tabs().SwitchToTab(1, true);
132+
});
133+
}
134+
135+
[Test]
136+
public void Should_BeThrow_IfSwitchToNewTab_ByIncorrectIndex()
137+
{
138+
Assert.Throws(typeof(IndexOutOfRangeException), () => { AqualityServices.Browser.Tabs().SwitchToTab(10, true); });
139+
}
140+
141+
private void CheckSwitchingBy(int expectedTabCount, Action switchMethod)
142+
{
143+
var browser = AqualityServices.Browser;
144+
var tabHandle = browser.Tabs().CurrentTabHandle;
145+
WelcomeForm.ClickElementalSelenium();
146+
var newTabHandle = browser.Tabs().TabHandles.Last();
147+
switchMethod.Invoke();
148+
Assert.AreEqual(newTabHandle, browser.Tabs().CurrentTabHandle, "Browser should be switched to correct tab");
149+
Assert.AreEqual(expectedTabCount, browser.Tabs().TabHandles.Count, "Number of tabs should be correct");
150+
}
151+
152+
private void CheckSwitching(int expectedTabCount, Action switchMethod)
153+
{
154+
var browser = AqualityServices.Browser;
155+
var tabHandle = browser.Tabs().CurrentTabHandle;
156+
WelcomeForm.ClickElementalSelenium();
157+
switchMethod.Invoke();
158+
var newTabHandle = browser.Tabs().CurrentTabHandle;
159+
Assert.AreNotEqual(tabHandle, newTabHandle, "Browser should be switched to new tab");
160+
Assert.AreEqual(expectedTabCount, browser.Tabs().TabHandles.Count, "Number of tabs should be correct");
161+
}
162+
}
163+
}

0 commit comments

Comments
 (0)