This topic describes typical issues that are caused by browser differences and tells how to resolve them:
Tip: | To handle some of the described issues, you may need to determine the browser in which the test is being executed. See the Checking the Current Browser topic to learn how to do this. |
Browser GUI Elements
Only the Web page access API is cross-browser; the browser's GUI object model is not. Browser GUI elements are different for each browser – menus, Option dialogs, Home/Back buttons, informative and warning pop-ups and so on. Actions over the browser’s GUI elements are browser-specific.
Browser Messages and Dialogs
TestComplete provides special test objects (Alert
, Confirm
, Prompt
and Login
) for automating some of the most frequently used browser and JavaScript dialogs. Actions over these test objects can be performed in any web browser. (See Handling JavaScript Popups and Browser Dialogs.) However, when a pop-up window or dialog cannot be recognized as one of these test objects, the corresponding window should be handled in a browser-specific manner.
For instance, when opening pages from local disks, Internet Explorer may ask you whether you want to allow active content on these pages. The other browsers do not display any warnings in the same case. Therefore, to make a test compatible with any browser, you should handle notifications in Internet Explorer:
JavaScript, JScript
...
browser = Browsers.Item(i);
browser.Run("file:///C:/Work//MyPage.htm");
if (browser.Family == Browsers.btIExplorer) AllowActiveContent();
...
Python
...
browser = Browsers.Item[i];
browser.Run("file:///C:/Work//MyPage.htm");
if (browser.Family == Browsers.btIExplorer):
AllowActiveContent();
...
VBScript
...
Set browser = Browsers.Item(i)
browser.Run("file:///C:/Work//MyPage.htm")
If (browser.Family = Browsers.btIExplorer) Then
AllowActiveContent()
End If
...
DelphiScript
...
browser := Browsers.Item(i);
browser.Run('file:///C:/Work//MyPage.htm');
if (browser.Family = Browsers.btIExplorer) then AllowActiveContent();
...
C++Script, C#Script
...
browser = Browsers["Item"](i);
browser["Run"]("file:///C:/Work//MyPage.htm");
if (browser["Family"] == Browsers["btIExplorer"]) AllowActiveContent();
...
Edge-specific note: In all the supported browsers, except for Edge, the Window
object that correspond to standard dialogs like Open File, Select Folder and others belong to the browser’s main process. In the Edge browser, the Window
objects that represent these dialogs belong to a separate helper process named PickerHost
. Therefore, to make a test compatible with any browser, you should handle the standard dialogs invoked from Edge:
JavaScript, JScript
...
if (Browsers.CurrentBrowser.Family == Browsers.btEdge)
var OpenDlg = Sys.Process("PickerHost").Window("#32770", "Open", 1);
else
var OpenDlg = Sys.Browser().Window("#32770", "Open", 1);
...
Python
...
if (Browsers.CurrentBrowser.Family == Browsers.btEdge):
OpenDlg = Sys.Process("PickerHost").Window("#32770", "Open", 1);
else:
OpenDlg = Sys.Browser().Window("#32770", "Open", 1);
...
VBScript
...
If (Browsers.CurrentBrowser.Family = Browsers.btEdge) Then
Set OpenDlg = Sys.Process("PickerHost").Window("#32770", "Open", 1)
Else
Set OpenDlg = Sys.Browser().Window("#32770", "Open", 1)
End If
...
DelphiScript
...
if (Browsers.CurrentBrowser.Family = Browsers.btEdge) then
OpenDlg := Sys.Process('PickerHost').Window('#32770', 'Open', 1);
else
OpenDlg := Sys.Browser().Window('#32770', 'Open', 1);
...
C++Script, C#Script
...
if (Browsers["CurrentBrowser"]["Family"] == Browsers["btEdge"])
var OpenDlg = Sys["Process"]("PickerHost")["Window"]("#32770", "Open", 1);
else
var OpenDlg = Sys["Browser"]()["Window"]("#32770", "Open", 1);
...
There can be several PickerHost
processes in the system. In this case, you should use indexes to specify the process to which the needed dialog belongs:
JavaScript, JScript
Sys.Process("PickerHost", 2).Window("#32770", "Open", 1)
Python
Sys.Process("PickerHost", 2).Window("#32770", "Open", 1)
VBScript
Sys.Process("PickerHost", 2).Window("#32770", "Open", 1)
DelphiScript
Sys.Process('PickerHost', 2).Window('#32770', 'Open', 1)
C++Script, C#Script
Sys["Process"]("PickerHost", 2)["Window"]("#32770", "Open", 1)
Non-Matching Sets of DOM Methods and Properties
The layout engines (Trident, EdgeHTML, Blink, Gecko) used in web browsers to render web pages provide slightly dissimilar sets of methods and properties of web elements. The elements displayed in one of the layout engines do not always have the same set of methods and properties in other layout engines. Some members may have the same name and functionality, some members may have a similar functionality but different names, the other may have no analogs at all.
A typical example of non-matching properties is properties that provide access to a DOM document and to an element's text content. Any browser has these properties, however, their names do not coincide. To improve cross-browser compatibility, TestComplete adds special analogs:
-
To access the DOM document object of a web page:
Page.contentDocument
syntax for Chrome, Edge, Firefox, and Internet Explorer 10 and later. You can also use the commonPage.contentDocument
syntax for all supported browsers. For more information, see Accessing DOM document Object. -
To get the textual content of a web page object and its child objects in Firefox and Chrome, the
textContent
property is used, whereas to get the same data in Internet Explorer or Edge you should use theinnerText
property. TestComplete introduces an analogous property,contentText
, which is available in all browsers.
The above-mentioned properties are most frequently used. To deal with other non-matching properties, you should first check whether a property is available or not.
Verifying if the browser or page element supports certain method or property
Since the set of methods and properties provided by different browsers may vary (see above), you should check whether the desired member is available in the current browser before using this method or property. To perform such verification, you can use the aqObject.IsSupported
method.
The following code gets the window
object associated with the document. In Internet Explorer 10 and later, as well as in Chrome, Edge, and Firefox, the window
object is returned by the document.defaultView
property.
JavaScript, JScript
function GetDocWindow()
{
var document, window;
document = Aliases.browser.myTestedPage.contentDocument;
// Check if the document.parentWindow property is available
if (aqObject.IsSupported(document, "parentWindow"))
window = document.parentWindow
// Check if the document.defaultView property is available
else if (aqObject.IsSupported(document, "defaultView"))
window = document.defaultView
else
Log.Error("Unknown browser that doesn't support document.defaultView or document.parentWindow.");
}
Python
def GetDocWindow():
document = Aliases.browser.myTestedPage.contentDocument;
# Check if the document.parentWindow property is available
if (aqObject.IsSupported(document, "parentWindow")):
window = document.parentWindow;
# Check if the document.defaultView property is available
else:
if (aqObject.IsSupported(document, "defaultView")):
window = document.defaultView;
else:
Log.Error("Unknown browser that doesn't support document.defaultView or document.parentWindow.");
VBScript
Sub GetDocWindow
Dim document, window
Set document = Aliases.browser.myTestedPage.contentDocument
' Check if the document.parentWindow property is available
If (aqObject.IsSupported(document, "parentWindow")) Then
Set window = document.parentWindow
' Check if the document.defaultView property is available
Else If (aqObject.IsSupported(document, "defaultView")) Then
Set window = document.defaultView
Else
Log.Error("Unknown browser that doesn't support document.defaultView or document.parentWindow.")
End If
End If
End Sub
DelphiScript
procedure GetDocWindow;
var document, window: OleVariant;
begin
document := Aliases.browser.myTestedPage.contentDocument;
// Check if the document.parentWindow property is available
if (aqObject.IsSupported(document, 'parentWindow')) then
window := document.parentWindow
// Check if the document.defaultView property is available
else if (aqObject.IsSupported(document, 'defaultView')) then
window := document.defaultView
else
Log.Error('Unknown browser that doesn''t support document.defaultView or document.parentWindow.');
end;
C++Script, C#Script
function GetDocWindow()
{
var document, window;
document = Aliases["browser"]["myTestedPage"]["contentDocument"];
// Check if the document.parentWindow property is available
if (aqObject["IsSupported"](document, "parentWindow"))
window = document.parentWindow
// Check if the document.defaultView property is available
else if (aqObject["IsSupported"](document, "defaultView"))
window = document.defaultView
else
Log["Error"]("Unknown browser that doesn't support document.defaultView or document.parentWindow.");
}
Attribute Values
Different browsers can report CSS style property values in different formats. For example, Internet Explorer can report colors as #ff0000 whereas Firefox and Chrome report them as rgb(255, 0, 0). You should take this into account when creating your tests.
For instance, when verifying element colors, you may check values in any notation, or convert one notation to another:
JavaScript, JScript
function CheckHeaderColor()
{
...
var strColor = getStyle(header, "backgroundColor");
//Compare the obtained color with two possible notations of the expected color
if ((strColor=="rgb(255, 0, 0)") || (strColor=="#ff0000"))
Log.Message("The header is as Red, as expected")
else
Log.Warning("The header is in another color.")
...
}
function CheckHeaderColor2()
{
...
var strColor = getStyle(header, "backgroundColor");
//Convert color notation for Internet Explorer
if (Browsers.CurrentBrowser.Family==btIExplorer)
strColor = html2rgb(strColor)
//Compare the obtained color with the expected color
if (strColor=="rgb(255, 0, 0)")
Log.Message("The header is as Red, as expected")
else
Log.Warning("The header is in another color.")
...
}
Python
def CheckHeaderColor():
# ...
strColor = getStyle(header, "backgroundColor");
# Compare the obtained color with two possible notations of the expected color
if ((strColor=="rgb(255, 0, 0)") or (strColor=="#ff0000")):
Log.Message("The header is as Red, as expected");
else:
Log.Warning("The header is in another color.");
# ...
def CheckHeaderColor2():
# ...
strColor = getStyle(header, "backgroundColor");
# Convert color notation for Internet Explorer and Opera
if (Browsers.CurrentBrowser.Family==btIExplorer):
strColor = html2rgb(strColor);
# Compare the obtained color with the expected color
if (strColor=="rgb(255, 0, 0)"):
Log.Message("The header is as Red, as expected");
else:
Log.Warning("The header is in another color.");
# ...
VBScript
Sub CheckHeaderColor
...
strColor = getStyle(header, "backgroundColor")
'Compare the obtained color with two possible notations of the expected color
If ((strColor="rgb(255, 0, 0)") Or (strColor="#ff0000")) Then
Log.Message("The header is as Red, as expected")
Else
Log.Warning("The header is in another color.")
End If
...
End Sub
Sub CheckHeaderColor2
...
strColor = getStyle(header, "backgroundColor")
'Convert color notation for Internet Explorer
If ( Browsers.CurrentBrowser.Family=btIExplorer) Then
strColor = html2rgb(strColor)
End If
'Compare the obtained color with the expected color
If (strColor="rgb(255, 0, 0)") Then
Log.Message("The header is as Red, as expected")
Else
Log.Warning("The header is in another color.")
End If
...
End Sub
DelphiScript
procedure CheckHeaderColor;
begin
...
strColor := getStyle(header, 'backgroundColor');
//Compare the obtained color with two possible notations of the expected color
if ((strColor='rgb(255, 0, 0)') or (strColor='#ff0000')) then
Log.Message('The header is as Red, as expected')
else
Log.Warning('The header is in another color.')
...
end;
procedure CheckHeaderColor2;
begin
...
strColor := getStyle(header, 'backgroundColor');
//Convert color notation for Internet Explorer
if (Browsers.CurrentBrowser.Family=btIExplorer) then
strColor := html2rgb(strColor);
//Compare the obtained color with the expected color
if (strColor='rgb(255, 0, 0)') then
Log.Message('The header is as Red, as expected')
else
Log.Warning('The header is in another color.')
...
end;
C++Script, C#Script
function CheckHeaderColor()
{
...
var strColor = getStyle(header, "backgroundColor");
//Compare the obtained color with two possible notations of the expected color
if ((strColor=="rgb(255, 0, 0)") || (strColor=="#ff0000"))
Log["Message"]("The header is as Red, as expected")
else
Log["Warning"]("The header is in another color.")
...
}
function CheckHeaderColor2()
{
...
var strColor = getStyle(header, "backgroundColor");
//Convert color notation for Internet Explorer
if (Browsers["CurrentBrowser"].Family==btIExplorer)
strColor = html2rgb(strColor)
//Compare the obtained color with the expected color
if (strColor=="rgb(255, 0, 0)")
Log["Message"]("The header is as Red, as expected")
else
Log["Warning"]("The header is in another color.")
...
}
See Also
About Cross-Browser Testing in TestComplete
Creating Cross Browser Tests
Running Tests in Multiple Browsers