behave_manners.pagelems.dom_components module

Proxies of selenium WebElements into abstract structure of page’s information

Goal of the PageTemplates/Component is to reduce the multi-level DOM structure of a web-page to a compact structure of /Components/ , which then convey the semantic information of that DOM and are easy to assert in testing. Components may be trivial, corresponding to single DOM elements, or not, being abstractions over complex DOM structures. They /should/ have their entry point mapped to a particular DOM element.

Components must have a well-defined /path/ to be addressed with. This cannot be guaranteed by this framework, but rather should be achieved through careful design of the page templates. Heavily dependant on the web-page’s structure and technology. A good path is one that would map the “same” DOM element to a specific path, through subsequent readings of the webpage. Even if the webpage’s DOM has been re-built by the JS framework of the page (React, Angular, etc.) .

Example: a table. Using a <pe-repeat> template element, rows of that table could be mapped to components. For static tables, path could just be the row number of those rows. But this becomes non-deterministic for tables that are, say, grids with dynamic sorting or infinite scroll. On those, key to the rows should be some primary key of the row data, like the remote database ID or unique name of that row-data.

Components should be considered volatile. By design, this framewor does NOT hold a reference of children components to one, but rather re-maps children on demand. Likewise, values of attributes shall always be fetched from the remote, each time the Component attribute is read. No caching. It is the caller’s responsibility to copy the Component attributes to some other variable, if caching (rather than multiple WebDriver requests) is desired.

Unreachable components should be handled graceously. They would still raise an exception all the way up, but plugins may help in debugging, like by highlighting the visual position in the webpage where something is missing.

class CSSProxy(parent)

Bases: object

class ComponentProxy(name, parent, pagetmpl, webelem, scope)

Bases: behave_manners.pagelems.dom_components._SomeProxy

Cross-breed of a Selenium element and DPO page object

component_name
filter(clause, safe=True)

Iterator over sub-components that satisfy a condition

Usage:

for row in table.filter(lambda r: r['col_4'].text == "bingo!"):
    print("Found the bingo row:", row)

equivalent to:

for row in table.values():
    if row['col_4'].text == "bingo!":
        print("Found the bingo row:", row)

clause must be a function, which evaluates against a component and returns True whenever that component should participate in the result.

IFF clause is simple enough, filter() may optimize it to resolve the iteration in a very efficient search.

filter_gen(clause, safe=True)

Generator of .filter() functions

Just because the optimization in .filter() may be expensive to compute, it can be done once (offline) and re-applied multiple times to generate many iterator instances

path
class PageProxy(pagetmpl, webdriver, scope)

Bases: behave_manners.pagelems.dom_components._SomeProxy

Root of Components, the webpage

Holds reference to remote WebDriver, has no parent

path