-
Notifications
You must be signed in to change notification settings - Fork 17
Architectural Overview
As mentioned in the architectural overview for darcy-ui, there are three essential ingredients for a darcy implementation:
- Implementations of the relevant element APIs
- An ElementContext implementation
- One or more Locator strategies supported in that ElementContext
Of course, implementing those APIs is not merely providing methods with matching signatures; the documented behavior must be followed. This is where the WebDriver implementation becomes not-so-straightforward.
In darcy, every Context reference must be independent. In WebDriver, a single driver is the entry point for a number of different windows or frames. This means that multiple contexts in darcy may have the same underlying driver, and they may be used in any order. With WebDriver, this would mean switching to the various targets as needed. Darcy must do this automatically, behind the scenes. This is the purpose of the TargetedWebDriver
.
TargetedWebDriver is an interface that is implemented by means of a dynamic proxy. This proxy wraps a WebDriver, and switches it to its designated target before every call, forwarding the call to the correct target. The target is decided at instantiation of the targeted driver. To prevent unnecessary switches, darcy uses a TargetLocator
implementation that caches the current target. If the current target is the same as the requested, no call to the driver is made.
WebDriverBrowser
is the core starting point for the WebDriver implementation. It, as you might expect, implements the Browser API defined in darcy-web by forwarding calls to a constructor-injected TargetedWebDriver instance. However, darcy's promise is that no code proceeds unless it is in sync with the UI being controlled, and so WebDriverBrowser also waits for the expected view to be loaded after every navigation.
The API for frames and browsers is implemented by the same class. In WebDriver there is no distinction.
Browsers can find elements, as well as other browser windows launched within the same session. WebDriverElementContext
has the responsibility of finding those elements and instantiating darcy versions of their APIs. WebDriverParentContext
does the same for other contexts. The browser implements both of these interfaces, and forwards calls to an appropriate implementation based on the desired type of object.
Finding an element in WebDriver is an immediate action, where an exception will be thrown if none is found. Darcy works much differently; no element is actually looked up until some action is attempted on that element. So the implementations of elements in darcy-webdriver do accept a WebElement directly, but instead a supplier of a WebElement. The element implementations will attempt to get the underlying WebElement and cache it if successful. Otherwise, they report no element is present or displayed, or worst case throw an exception if some action requiring that element's presence as attempted.