Atata 1.8.0 is released with a new script executor and significant enhancement of the attributes system.
Changelog
New Features
- major #391 Script executor
- major #392 Support attributes declared at property level that target control’s children
- major
#397
AtataContext
attributes - major #398 Global level attributes
- minor
#402 Add
TryGet
method toUIComponentMetadata
- minor
#403 Add
Contains
method toUIComponentMetadata
- minor
#414 Add
Add
methods toUIComponentMetadata
- minor
#415 Add
Remove
andRemoveAll
methods toUIComponentMetadata
- minor
#416 Add
TargetAllChildren
property toMulticastAttribute
- minor
#420
ObjectCreator
Changes and Enhancements
- minor
#394 Add parameterless generic
AddScreenshotConsumer
method toAtataContextBuilder
- minor
#399 Inherit
UrlAttribute
fromMulticastAttribute
- minor
#400 Inherit
NameAttribute
fromMulticastAttribute
- minor
#401 Inherit
NavigationPageObjectCreatorAttribute
fromMulticastAttribute
- minor
#404 Inherit
TraceLogAttribute
fromMulticastAttribute
- minor
#405 Inherit
WindowTitleAttribute
fromMulticastAttribute
- minor
#406 Inherit
ExtraXPathAttribute
fromMulticastAttribute
- minor
#407 Inherit
GoTemporarilyAttribute
fromMulticastAttribute
- minor
#408 Inherit
IdXPathForLabelAttribute
fromMulticastAttribute
- minor
#409 Inherit
RandomizeCountAttribute
fromMulticastAttribute
- minor
#410 Inherit
RandomizeIncludeAttribute
fromMulticastAttribute
- minor
#411 Inherit
RandomizeExcludeAttribute
fromMulticastAttribute
- minor
#412 Inherit
RandomizeNumberSettingsAttribute
fromMulticastAttribute
- minor
#413 Inherit
RandomizeStringSettingsAttribute
fromMulticastAttribute
- minor
#417 Inherit
TriggerAttribute
fromMulticastAttribute
- minor
#418 Make universal
AttributeUsage
ofMulticastAttribute
and inheritors - minor
#419 Update attributes that implement
IFindItemAttribute
Fixes
- fix #393 Fail to log message containing “{“ character
- fix #395 Incorrect order of layered attributes
Script Executor
Idea
The purpose of this feature is a simplification of JavaScript execution.
Currently to execute script you should write the code like Driver.ExecuteScript("...")
(inside page object) or AtataContext.Current.Driver.ExecuteScript("...")
(everywhere else).
There is also a need to simplify passing target element to the script, for example:
Driver.ExecuteScript("arguments[0].click();", SomeComponent.Scope);
It would be better to be able to write the same action with:
SomeComponent.Script.ExecuteAgainst("arguments[0].click();");
Implementation
UIComponentScriptExecutor<TOwner>
is implemented as a part of UIComponent<TOwner>
.
It provides a set of methods for script execution, like:
component.Script.Execute("<some script>");
component.Script.ExecuteAgainst("arguments[0].click();");
component.Script.ExecuteAgainst("arguments[0].value = arguments[1];", "some value");
To execute a script inside a page object or a control:
Script.Execute("...");
Additionally, a set of ready to use script-executing methods are implemented:
SetValue
, SetValueAndDispatchChangeEvent
, Click
, Focus
, ScrollIntoView
.
Complete list of methods can be found in UIComponentScriptExecutor<TOwner>
source file.
Verification
Verification of values returned by the script is also supported:
component.Script.ExecuteAgainst("return arguments[0].value;").Should.Equal("some_value")
AtataContext Attributes
This is the functionality to add extra attributes to components via AtataContext
.
These added attributes has higher order level and can override the attributes of the same kind (and at the same level) declared in a regular manner,
for example FindAttribute
s or behavior attributes.
This feature can be quite useful in testing multi-language applications or applications that have some HTML differences on different environments/version/editions. So you might need to configure the page objects in a bit different way depending on testing environment.
Examples
Apply to Control
AtataContext.GlobalConfiguration
.Attributes.Component(typeof(Button<>)).Add(
new FindByIdAttribute());
Sets all buttons to be found by id
attribute.
Apply to Several Controls
AtataContext.GlobalConfiguration
.Attributes.Global.Add(
new FindByIdAttribute
{
TargetTypes = new[] { typeof(Button<>), typeof(TextInput<>) }
});
Sets all buttons and text inputs to be found by id
attribute.
Apply to Page Object
AtataContext.GlobalConfiguration
.Attributes.Component<SomePage>().Add(
new WaitForAngularJSAjaxAttribute());
Adds WaitForAngularJSAjaxAttribute
trigger to SomePage
.
Apply to Control Property of Page Object
AtataContext.GlobalConfiguration
.Attributes.Component<SomePage>()
.Property(x => x.Save).Add(new FindByContentAttribute("Save"))
.Property(x => x.Cancel).Add(new FindByContentAttribute("Cancel"));
Apply to Components Within Assembly
AtataContext.GlobalConfiguration
.Attributes.Assembly("SomeProduct.SomeAtataComponentsLibrary").Add(
new WaitForAngularJSAjaxAttribute
{
TargetType = typeof(Page<>)
});
Adds WaitForAngularJSAjaxAttribute
trigger to all page classes that are located in “SomeProduct.SomeAtataComponentsLibrary” library (project).
Global Level Attributes
Enable a feature of global level attributes used by UIComponentMetadata
.
As a result, we have 5 attributes levels (ordered by priority):
- Declared
- Parent component
- Assembly
- Global
- Component
Replacable (FindAttribute
’s, behaviors, etc.) attributes from higher level can override similar attributes from lower levels.
Consolidate All Attributes to Be MulticastAttribute
Almost all Atata attributes that were not inherited from MulticastAttribute
are updated to inherit it.
Including triggers.
This gives much richer possibilities to apply attributes at different levels,
and they also can be added thru AtataContext
attributes system.
Support Attributes Declared at Property Level That Target Control’s Children
Example #1
Assume that we have a control class that contains Select
button property:
[ControlDefinition(ContainingClass = "some-class")]
public class SomeControl<TOwner> : Control<TOwner>
where TOwner : PageObject<TOwner>
{
[FindFirst]
public TextInput<TOwner> Input { get; private set; }
[FindByContent("Select...")]
public Button<TOwner> Select { get; private set; }
}
In most cases this button has text “Select…” that is used to identify the control. Regularly this control can be defined this way in page objects:
public SomeControl<_> Control1 { get; private set; }
Let’s also assume that in some particular page the text of this button can be different, for example “…”.
So we need to change the locator of that button
from [FindByContent("Select...")]
to [FindByContent("...")]
only for that page.
Now we can do this using targeting mechanics of Atata MulticastAttribute
s.
[FindByContent("...", TargetName = nameof(SomeControl<_>.Select))]
public SomeControl<_> Control1 { get; private set; }
Example #2
Another example is to change the settings of ItemsControl
items.
The following ItemsControl has all descendant elements as items:
[FindById("some-id")]
public ItemsControl<Control<_>, _> ItemsControlOfDescendantsAsControls { get; private set; }
But this one has only child elements as items:
[FindById("some-id")]
[FindSettings(OuterXPath = "./", TargetName = "Items")]
public ItemsControl<Control<_>, _> ItemsControlOfChildrenAsControls { get; private set; }