Skip to content

iceteagroup/wisej-selenium

Repository files navigation

wisej-selenium

Selenium WebDriver test automation support for Wisej .NET development platform.

wisej-selenium is based on QxWebDriver-NET with additional classes to support Wisej development platform.

THIS FILE WAS ADAPTED FROM QxWebDriver-NET AND IS A WORK IN PROGRESS.

Project Status

wisej-selenium is a work in progress. The API is subject to change without notice, not all of Wisej widgets/controls are supported. Don't let that stop you from playing with it, giving us feedback on the issues tab and sending pull requests. Thanks!

Currently includes

  • WisejWebDriver library
  • helper library for MSTest test framework

Still To Come

  • more complete support for Wisej UI classes.
  • NuGet package
  • helper library for NUnit test framework

Project Goal

The goal of this project is to provide an API that facilitates writing WebDriver-based interaction tests for Wisej applications by abstracting away the implementation details of qooxdoo/Wisej JavaScript widgets.

This is the WisejWebDriver library that embeds QxWebDriver and extends it with classes that try to match Wisej UI classes.

This library is a set of helper classes to simplify the manipulation of Wisej widgets. Most methods handle assertions as needed (eg. close Form and assert it's closed). This library uses MSTest (ASSERT is test framework dependent).

Widget Interfaces

WisejWebDriver provides a set of widget classes similar to WebDriver's support classes, each of which implements Qooxdoo.WebDriver.UI.IWidget or one or more of the interfaces inheriting from it, such as ITouchable, ISelectable or IScrollable. These interfaces allow complex actions to be performed by relatively few API calls.

Widgets are obtained by calling QxWebDriver.FindWidget(by). where by is any locator strategy that finds a DOM element which is part of a qooxdoo/Wisej widget. FindWidget will determine the qooxdoo/Wisej class of the widget, its inheritance hierarchy and the interfaces it implements, and use this information to decide which IWidget implementation to return.

Similar to IWebElement.FindElement, IWidget.FindWidget will restrict the search to children of the current widget.

Examples

The best way to learn about the various widget interfaces is to check out the demo integration tests in Wisej.SeleniumDemo.

Sample status on January 2018 as follows:

  • Chrome - main development target. Runs flawlessly every time.
  • Firefox - one standing issue concerning TreeView nodes.
  • Edge - unstable: lots of workarounds and one intermittent issue with a specific TextBox.

Locating Widget Elements

WebDriver's built-in "By" strategies like By.XPath or By.ClassName generally don't work too well with the entangled and dynamic DOM structures generated by qx.Desktop applications. The By.Qxh strategy (Qx for qooxdoo, h for hierarchy) provides an alternative approach that searches for elements by using JavaScript to traverse the application's widget hierarchy.

For example, the qooxdoo Feed Reader's UI hierarchy looks like this (easily determined by opening the Feed Reader in the Inspector):

qx.ui.root.Application
- qx.ui.container.Composite
  - feedreader.view.desktop.Header
  - feedreader.view.desktop.ToolBar
    - qx.ui.toolbar.Button
  [...]

A Qxh locator that finds a toolbar button with the label Reload could look like this:

By by = By.Qxh("child[0]/feedreader.view.desktop.ToolBar/[@label=Reload]");

As you can see, the syntax is similar to XPath, consisting of location steps separated by slashes. While searching, each location step selects a widget which will be used as the root for the rest of the search.

Supported Steps

  • foo.bar.Baz A string containing dots will be interpreted as the class name of a widget. Uses instanceof internally so inheriting widgets will be found as well.

  • child[N] Signifies the Nth child of the object returned by the previous step.

  • [@attrib{=value}] Selects a child that has a property attrib which has a value of value. "Property" here covers both qooxdoo as well as generic JavaScript properties. As for the values, only string comparisons are possible, but you can specify a RegExp which the property value will be matched against. toString() is used to compare non-String values.

  • * is a wildcard operator. The wildcard can span zero to multiple levels of the object hierarchy. This saves you from always specifying absolute locators, e.g. the example above could be rewritten as

    By by = By.Qxh("*/[@label=Reload]");

This will recursively search from the first level below the search root for an object with a label property that matches the regular expression /Reload/. As you might expect, these recursive searches take more time than other searches, so it is good practice to be as specific in your locator as possible.

Note that the Qxh strategy will only return the first match for the locator expression, so it can't be used with WebDriver.FindElements.

Relative Locators

The root node where a By.Qxh locator will begin searching is determined by its context: When used with QxWebDriver.FindWidget, the children of the qooxdoo application's root widget will be matched against the first step. When used with IWidget.FindWidget, the widget itself will be the root node for the search.

Extending WisejWebDriver

FindWidget uses a IWidgetFactory to determine which widget class to instantiate. An alternative class implementing IWidgetFactory and probably extending DefaultWidgetFactory can be passed to the QxWebDriver constructor to support custom widgets.

Browser Support

In theory, WisejWebDriver should work with any WebDriver that implements IJavascriptExecutor. Drivers for Chrome, Firefox, Edge and Opera do work all right although the Edge driver only supports one running instance. The current Internet Explorer driver is said to work but in practice is too hard to get it working.