GithubHelp home page GithubHelp logo

sbabcoc / selenium-foundation Goto Github PK

View Code? Open in Web Editor NEW
57.0 9.0 16.0 34.11 MB

Selenium Foundation is an automation framework designed to extend and enhance the capabilities provided by Selenium (WebDriver).

License: Apache License 2.0

Java 98.34% JavaScript 0.66% HTML 0.99%
selenium selenium-java testng page-object-model configuration screenshot testng-reporter junit-rule junit-runner testng-listener appium htmlunit selenium-grid shadow-dom javascript-exceptions selenium-api driver-targeting junit-runlistener junit-watcher byte-buddy

selenium-foundation's Issues

Document the ShadowRoot feature

Document the ShadowRoot feature in the main README and applicable documentation pages:

  • SeleniumFoundation
  • BuildingPageObjectsWithSeleniumFoundation
  • StructuringPageModelsWithComponents

Enable publication of SNAPSHOT builds to local repository

Currently, SNAPSHOT builds installed to local repository are non-functional due to the lack of a customized POM that correctly identifies transitive dependencies. Gradle build files are dark art, and my efforts to this point have been fruitless.

Add referencial integrity checks to component collections

Due to the auto-recovery behavior of RobustWebElement objects, it's possible to have the items in an existing component collection silently fall out of sync with the actual page content they represent.

All of the solutions I've thought about so far will either impose overhead on every collection access or fire too late to be bulletproof.

This issue is complicated by the prospect of nested collections. When an element goes stale, all of the collections that contain the element must be rebuilt. This will require logic in the reference refresh implementation to check for collection associations. Ultimately, it may prove to be impossible to implement bulletproof auto-recovery for nested collections.

Determine if it's possible to update proxies to run on JDK11

JDK 11 and proxies in a world past sun.misc.Unsafe

This blog post explains the challenges of implementing dynamic proxies on newer versions of Java. Selenium Foundation uses Byte Buddy in three contexts:

  1. Creation of "enhanced" versions of ComponentContainer classes to install method hooks
  2. Creation of "robust" versions of driver-specific WebElement classes to handle stale references
  3. Creation of RevisedCapabilityMatcher to replace the SafariSpecificValidator class

Determine if there's a workable approach for generalized support of the '--default-capabilities' option

'appium' provides the ability to specify default capabilities that get merged into driver session requests. A good rationale for integrating this option as a Selenium Foundation local Grid feature is presented here. The challenge is that default capabilities apply to all session requests; however, each driver plug-in can support multiple "personalities", which can be augmented at runtime through driver-keyed modifications in the configuration.

How do we determine which "defaults" to specify if the aggregation of driver "personalities" and configured modifications yields multiple choices?

Note that the use of the --default-capabilities option may be unnecessary, due to the ability to specify personality-keyed session request modifications in the configuration. Another approach is to simply use the generic APPIUM_CLI_ARGS setting.

Design and implement "target platform" support

The client code defines its own interpretation of what a "platform" is. The framework merely calls the client's implementation to set and check the "platform" on which each test runs.

The "platform" to be activated by any given test is determined in the TestNG method interceptor. Avoid the temptation to allow a single test method to specify multiple "platforms", as it complicates the implementation quite a bit. Test results get very messy as well.

The interceptor encodes the "platform" specifier as JSON and stores it in the method description (which is the only writable attribute available).

Add error page detection feature

Implement the framework for an error page detection feature. Projects that wish to use this feature provide implementations of an ErrorPageMatcher interface and specify them under META-INF/services. The framework will access the specified implementations via the ServiceLoader, iterating through them to see if any of them indicates a match. If a match is found, the framework will throw an exception that indicates the specific error page that was identified.

Implement code to shut down local Grid instances

Whenever Selenium Foundation launches a local Selenium Grid instance, it should subsequently shut it down. The current implementation can fail in any number of ways, leaving the local Grid running. To make sure that such Grid instances get shut down eventually, I propose adding the following:

  • Whenever a local server gets launched, create file that defines its parameters: host, port, role ($TMP ?). These could be encoded in the filename. This way the server can be tracked if the relevant Java process dies.
  • At the end of a Maven run ('install', 'test', or 'verify'), use the 'exec' plugin to run a Java class that processes these server launch semaphores.
  • Before the beginning of a mvn clean.
  • Determine how to identify and shut down "zombie" driver sessions, too.

JsUtility needs to get the JavascriptExecutor from the search context

Currently, there's no way to specify a FirefoxShadowRoot search context as a JavaScript execution argument. This makes component-bound search operations impossible. We need to implement a mechanism that decomposes the search context into its shadow host element and a JavaScript statement to acquire the shadow root.

Implement harness that enables stand-alone execution of Selenium automation

In a recent project, I used Selenium Foundation to create stand-alone automation built on JUnitBase. Due to time constraints, I chose to abandon an attempt to run my automation via JUnitCore. The issue that caused me to change course was lack of a defined mechanism to inject parameters into the test object. Also, although JUnit Foundation is brought in as a transitive dependency, I didn't run the Java agent that installs its hooks. This meant that my code was responsible for:

  • activation and shutdown of the local Grid
  • acquisition and disposal of the driver instance
  • capture of screenshot/page-source on failure

I could have injected parameters via System properties. Also, I could have built on TestNgBase to get full framework support without needing to run a Java agent. TestNG enables on-the-fly creation of XmlTest and XmlSuite objects, which can be used to attach listeners and inject parameters.

Add retry for driver acquisition failures

Occasionally, a driver acquisition request will fail due to some transient condition. To account for this, DriverManager.beforeInvocation() should employ some sort of retry logic.

Add a feature that will automatically select between multiple versions of a component

In production environments, it's common to have multiple presentations of any given feature operating within a single application. For example, different pages within a single application may use different incarnations of a common navigation menu component, depending on whether each page has been updated to use the latest version or not.
To accommodate this reality, add an annotation that associates the base class with a context-matching resolver that returns the component subclass that corresponds to the component version presented by the system under test.

Attempts to include local files on class path fail on Windows

Local grid setup fails on Windows if the dependencies include classes loaded from file. This is caused by a bug in the code that tries to extract the repository root from the file URI. The error is in using the platform-specific file separator. This is a URI, so the separator is always the slash ('/') character.

Document the 'TransitionErrorDetector' feature

The page load completion mechanism of the container method interceptor includes the ability to register transition error detectors - service providers that implement the TransitionErrorDetector interface. This feature enables implementers to provide detectors for scenario-specific error conditions (error messages, error pages, etcetera). In conjunction with its own page load completion checks, the container method interceptor invokes registered transition error detectors to determine if a recognized error condition has been encountered.

This transition error detector feature needs to be documented so implementers are informed of its existence, along with description, examples, and reference implementations.

Document settings

This should mostly be just a copy/paste/format task, because the settings enumeration includes JavaDoc for each setting.

Add support for connecting to existing browser session via Google Chrome's remote debugging feature

https://www.youtube.com/watch?v=4F-laDV9Pl8
This video shows how to use this feature locally, but it's apparently possible to construct a servlet to make this work on Grid sessions: https://stackoverflow.com/questions/48585187/chrome-remote-debugging-in-a-seleniumgrid

Other references: https://stackoverflow.com/questions/6827310/chrome-remote-debugging-doesnt-work-with-ip
https://developers.google.com/web/tools/chrome-devtools/remote-debugging

Potentially applicable to all drivers (not just Chrome): https://tarunlalwani.com/post/reusing-existing-browser-session-selenium/

Question: Once references to the driver object go out of scope, does the server get closed automatically, or would this leave a zombie behind? I probably need to determine how to close the driver without terminating the browser session (if this is possible).

Add a feature that allows the context element of a page component to be "optional"

It pretty common for components to exist under certain conditions, but to be absent in others. To model this sort of "optional" component, we should allow for the specification of an optional element as context. Currently, I think it's possible to specify an optional context element, but the base component implementation lack methods to realize "optional" component behavior.

Add methods to JsUtility to wrap returned element references

Element references returned by JavaScript functions are native WebElement objects, which means that we have no automatic recovery if references go stale. We should provide methods to enable implementers to wrap returned references in RobustWebElement objects.

This is especially useful for JavaScript functions that return lists of references. For this scenario, clients would supply the list of element references and an Xpath locator as a regular expression pattern that includes a placeholder for an index. An example of a scenario for this sort of method can be found in the OPCT project, in SearchResults.getSearchResultRows()

Add support for JUnit 5 Jupiter

The lack of support for JUnit 5 is a serious deficiency at this point. Add this support, examining the possibility of migrating the existing support for TestNG and JUnit 4 into platform-specific subprojects.

Revise hub lifecycle management config

It appears that lifecycle management is available by default on grid hub servers. This means that the LifecycleServlet is unnecessary for hub servers.

Local Grid: Implement method to specify servlets

We should provide a mechanism to specify servlets for the Selenium Grid server to load. Currently, we specify a hardcoded list of servlets that provided the example page used for the project unit tests.

Expand documentation of @PageUrl annotation

Ensure to document the following:

  • Defined path/params contained by [value]
  • Pattern-based landing page verification via [pattern] and [params]
  • Ability to override elements of configured target URI

Local Grid: Implement method to specify node plugins via Selenium Foundation setting

Currently, the only way to specify Local Grid node plugins is via the ServiceLoader provider configuration file. This really doesn't work in the context of command line Grid launchers like local-grid-utility.

In addition to the load method, ServiceLoader provides a loadInstalled method that discovers service provider classes that have already been loaded. To facilitate settings-based local Grid configuration, add a setting to specify a semicolon-delimited list of fully-qualified service provider class names. Each provider will be loaded via Class.forName(String.class), then iterated using ServiceProvider.loadInstalled(Class<S>).

NOTE: If this setting is specified, the provider configuration file will be ignored.

Document system setup for building from Gradle and Maven

I need to document system variables and common configuration files for Java, Gradle, and Maven.

There are several tools that need to be installed, global settings that need to be configured, and system properties that must be specified.

Refactor this project and its Selenium 3 clone to eliminate duplication

I few weeks ago, I cloned this project so I could hack together a version that supports Selenium 3. This approach is unsustainable, as it creates a maintenance nightmare. The solution is to create a base project that uses weak references to the core WebDriver API, with sub-projects for Selenium 2 and Selenium 3.

Implement mechanism to enable client projects to inject arbitrary browser capabilities

In its current form, the browser plugin implementation lacks a mechanism to inject arbitrary capabilities into the supported configurations. There's no way to alter the specifications of existing "personalities" to introduce additional capabilities, which makes such things as ignoring certificate issues much more involved.

The only option at this point is to provide a fully-specified JSON capabilities object in the [selenium.browser.caps] System property.

It would be convenient if we provided an "additional capabilities" mechanism to augment the canned "personalities".

JUnit Support - Replace references to RuleChain with Rule order attribute

JUnit added the ability to specify order of execution directly in the @Rule annotation with the order attribute. The documentation here still refers to the deprecated RuleChain, though. Update the documentation to reflect current practice, but include notes on how to update legacy code.
Also revise reference to RuleChainWalker, which is still available but should no longer be necessary.

Java glue lib blows up on certain JavaScript engines

The implementation of javaGlueLib.js causes some JavaScript engines (e.g. - Rhino) to throw errors. Revise this library with less exotic implementation so that it behaves correctly, regardless of the JavaScript engine of the current browser.

Define browser plugin interface

This interface defines the following:

  1. Documentation of dependencies required to add this browser as a Grid node browser.
  2. Specification of class path dependency contexts needed by the Grid node process.
  3. Mode of operation:
    a. Addition to standard node server. The specified dependency contexts are simply appended to the standard set used to launch the node server process.
    b. Execution as a stand-alone node server. For stand-alone execution, the plugin provides a method to launch the node. It accepts the hub server and port, and it returns its own server, node, and process ID.
  4. Specification of at least one associated browser capability record. These records will replace the existing browser capabilities JSON resource files.

The configuration JSON file for the standard node server will be assembled dynamically, based on the drivers that it's configured to provided. If no drivers are specified, the standard node will not be launched. The configuration JSON file for stand-alone node servers must be provided by their associated plugins.

Fix support for locally provided HtmlUnit drivers

Test classes the implement the DriverProvider interface may blow up when we attempt to create a wrapper for the HtmlUnitWebElement class. The issue has to do with the expectation that the concrete implementation of the WebElement class will use the implicit no-argument constructor, and HtmlUnitWebElement uses a three-argument constructor instead.

java.lang.IllegalArgumentException: None of [public org.openqa.selenium.htmlunit.RobustHtmlUnitWebElement(org.openqa.selenium.htmlunit.HtmlUnitDriver,int,com.gargoylesoftware.htmlunit.html.DomElement)] allows for delegation from public abstract java.lang.Object com.nordstrom.automation.selenium.model.RobustElementFactory$InstanceCreator.makeInstance()
	at net.bytebuddy.implementation.bind.MethodDelegationBinder$Processor.bind(MethodDelegationBinder.java:1096)
	at net.bytebuddy.implementation.MethodDelegation$Appender.apply(MethodDelegation.java:1282)
	at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:713)
	at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:698)
	at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:605)
	at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:5133)
	at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1933)
	at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:225)
	at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:198)
	at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3404)
	at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:3600)
	at com.nordstrom.automation.selenium.model.RobustElementFactory.getCreator(RobustElementFactory.java:124)
	at com.nordstrom.automation.selenium.model.RobustElementFactory.makeRobustElement(RobustElementFactory.java:78)
	at com.nordstrom.automation.selenium.model.RobustElementFactory.getElement(RobustElementFactory.java:208)
	at com.nordstrom.automation.selenium.model.RobustElementFactory.getElement(RobustElementFactory.java:195)
	at com.nordstrom.automation.selenium.model.ComponentContainer.findElement(ComponentContainer.java:339)
	at com.nordstrom.automation.selenium.model.EnhancedExamplePage.findElement$accessor$xx432NvJ(Unknown Source)
	at com.nordstrom.automation.selenium.model.EnhancedExamplePage$auxiliary$Q46N7vBr.call(Unknown Source)
	at com.nordstrom.automation.selenium.model.ContainerMethodInterceptor.intercept(ContainerMethodInterceptor.java:124)
	at com.nordstrom.automation.selenium.model.EnhancedExamplePage.findElement(Unknown Source)
	at com.nordstrom.automation.selenium.QuickStart.dummyTest(QuickStart.java:173)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.