How to upgrade to Atata 2 considering breaking changes.
The first migration step is to ensure or upgrade your Atata to v1.14.0. Then fix all Atata warnings telling that some class/member is obsolete, as those items should be removed in v2.
The Atata package now targets .NET Standard 2.0, which supports .NET 5+, .NET Framework 4.6.1+ and .NET Core/Standard 2.0+. Dropped support of .NET 4.0 - .NET 4.6.
Thus, if your project uses the .NET Framework version prior to 4.6.1, either upgrade the project to the newer version or just stay with Atata v1.
The biggest change in Atata 2 is the upgrade of Selenium.WebDriver to v4. Please check out the Upgrade to Selenium 4 to see what changed and make appropriate modifications after the upgrade to Atata v2. Pay attention to driver configuration changes. All WebDriver configuration changes are reflected in Atata and Atata.Configuration.Json. Check out the updated Atata.Configuration.Json / JSON Schema if you use Atata JSON configuration files.
IWebDriver is used instead of RemoteWebDriverA usage of RemoteWebDriver was everywhere replaced with IWebDriver:
AtataContext.Driver propertyUIComponent.Driver propertyTriggerContext<TOwner>.Driver propertyAtataContextBuilder.UseDriver methodsIDriverFactory.Create methodDriverAtataContextBuilder<TBuilder>.CreateDriver methodDriverAtataContextBuilder<TBuilder, TService, TOptions>.CreateDriver methodDriver.ExecuteScript(...) -> Driver.AsScriptExecutor().ExecuteScript(...)Driver.GetScreenshot() -> Driver.AsScreenshotTaker().GetScreenshot()Most other properties and methods of RemoteWebDriver are also present in IWebDriver.
Visibility is changed from Visible to AnyIn Atata v1 when Visibility of control is not specified explicitly, Visibility.Visible is used by default to find the control’s element, which filters only visible elements. That is useful filtering in a case when you have hidden HTML elements on a page and don’t want Atata to find and interact with hidden elements. But a drawback of such filtering is performance decrease, as each element visibility check is a separate WebDriver command request.
Ensure that you want this feature to be enabled for your website under test. If you have a lot of hidden/invisible HTML elements (for example, check grey HTML tags in browser developer tools) and you still want Atata to filter them out, you may consider disabling this feature. Right after the upgrade to Atata v2, run all your tests and check out the test failures. If there are not many failures because of elements visibility, and they can be solved by setting Visibility.Visible to particular controls, then you are good to go with this feature. Otherwise, you can consider the ability to disable this feature globally.
Visible by default globallyVisibility.Any behavior can be easily reverted to the one with Visibility.Visible filter that was in Atata v1 by one of the following ways:
UseDefaultControlVisibility configuration method:
AtataContext.GlobalConfiguration.
UseDefaultControlVisibility(Visibility.Visible);
{
"defaultControlVisibility": "Visible"
}
Visible to particular controlsFindAttribute[FindBy("some-id")]
->
[FindBy("some-id", Visibility = Visibility.Visible)]
ControlDefinitionAttribute[ControlDefinition("li")]
->
[ControlDefinition("li", Visibility = Visibility.Visible)]
FindSettingsAttribute[FindSettings(OuterXPath = "./")]
->
[FindSettings(OuterXPath = "./", Visibility = Visibility.Visible)]
FindOnlyVisibleAttribute[FindBy("some-id")]
public TextInput<_> Name { get; private set; }
->
[FindBy("some-id")]
[FindOnlyVisible]
public TextInput<_> Name { get; private set; }
You can also declare [FindOnlyVisible(TargetAllChildren = true)] on page object or parent control to target it to all child controls.
var input = page.Find<TextInput<SomePage>>(new FindByNameAttribute("name1"));
->
var input = page.Find<TextInput<SomePage>>(new FindByNameAttribute("name1").Visible());
"" is returned instead of null as value of string-based field componentIn Atata v1, when input or content field is empty, null is returned as a value.
In Atata v2, an empty string is returned instead.
Take into account to change the assertions like:
SomeInput.Should.BeNull();
to:
SomeInput.Should.BeEmpty();
ComponentScopeLocateOptions -> ComponentScopeFindOptionsComponentScopeLocateResult -> ComponentScopeFindResultXPathComponentScopeLocateStrategy -> XPathComponentScopeFindStrategyFindAttribute.CreateStrategy() -> FindAttribute.CreateStrategy(UIComponentMetadata metadata)FindAttribute.BuildComponentName() -> FindAttribute.BuildComponentName(UIComponentMetadata metadata)AddLogConsumer(...) -> LogConsumers.Add(...)AddScreenshotConsumer(...) -> ScreenshotConsumers.Add(...)AddScreenshotFileSaving() -> ScreenshotConsumers.AddFile()LogConsumerInfo -> LogConsumerConfigurationAtataBuildingContext.LogConsumers -> AtataBuildingContext.LogConsumerConfigurationsAtataContextInitEvent -> AtataContextInitStartedEventDataProvider<TData, TOwner> -> ValueProvider<TData, TOwner>IDataProvider<out TData, out TOwner> -> IObjectProvider<TData, TOwner>UIComponent<TOwner>.GetOrCreateDataProvider<TValue>(providerName, valueGetFunction) -> UIComponent<TOwner>.CreateValueProvider<TValue>(providerName, valueGetFunction)UIComponent<TOwner>.CreateDataProvider<TValue>(providerName, valueGetFunction) -> UIComponent<TOwner>.CreateValueProvider<TValue>(providerName, valueGetFunction)IUIComponent<TOwner>.GetOrCreateDataProvider<TValue>(providerName, valueGetFunction) -> UIComponent<TOwner>.CreateValueProvider<TValue>(providerName, valueGetFunction)DataVerificationProvider<TData, TOwner> -> ObjectVerificationProvider<TObject, TOwner>IDataVerificationProvider<TData, TOwner> -> IObjectVerificationProvider<TObject, TOwner>IObjectProvider<TObject>.Value -> IObjectProvider<TObject>.ObjectIObjectProvider<TObject, TOwner>.IsValueDynamic -> IObjectProvider<TObject, TOwner>.IsDynamicIObjectSource<TObject>.Value -> IObjectSource<TObject>.ObjectEnumerableProvider<TItem, TOwner> -> EnumerableValueProvider<TItem, TOwner>[Wait(...)] -> [WaitSeconds(...)]ExtendedStringFormatter -> AtataTemplateStringFormatterContentSource values: FirstChildTextNode, LastChildTextNode and ChildTextNodesTrimmedAndSpaceJoined"" instead of null as value of string-based field componentTriggers property of UIComponent<TOwner>LogConsumerInfo to LogConsumerConfigurationDirectorySubject.Directories property to SubdirectoriesProviderDirectorySubject.Files property to DirectoryFilesProviderExtendedStringFormatter to AtataTemplateStringFormatterApplyMetadata method from UIComponentInitValueTermOptions method with GetValueTermOptions in Field<T, TOwner>ValueTermOptions property from IDataProvider<out TData, out TOwner> and all classes implementing itTitleTermFormatter to not lowercase “from” and “with”IPropertySettings with IHasOptionalPropertiesPropertyBagUIComponentMetadata parameter to CreateStrategy and BuildComponentName method of FindAttributeProperties property from MulticastAttributeRemoteWebDriverLoggingExtensions with IJavaScriptExecutorLoggingExtensionsRemoteWebDriver usage with IWebDriverWithCapability method of DriverAtataContextBuilder<TBuilder, TService, TOptions> with AddAdditionalBrowserOptionWithGlobalCapability method of driver AtataContextBuilder’s with AddAdditionalOptionAtataContext.ModeOfCurrent property to AtataContextModeOfCurrent.AsyncLocalWaitAttribute to WaitSecondsAttributeComponent property from IDataProvider<out TData, out TOwner>IDataProvider<out TData, out TOwner> with IObjectProvider<out TObject, out TOwner>DataProvider<TData, TOwner> and IDataProvider<TData, TOwner>ControlList<TItem, TOwner> from IEnumerableProvider<TItem, TOwner> instead of IDataProvider<TData, TOwner>DataVerificationProvider<TData, TOwner> to ObjectVerificationProvider<TObject, TOwner>Value property of IObjectProvider<out TObject> to ObjectIsValueDynamic property of IObjectProvider<out TObject, out TOwner> to IsDynamicValue property of IObjectSource<out TObject> to ObjectEnumerableProvider<TItem, TOwner> to EnumerableValueProvider<TItem, TOwner>VerificationKind property from IVerificationProvider<out TOwner>IVerificationProvider<out TOwner>.GetRetryOptions methodGetShouldText method from IVerificationProvider<out TOwner>ReportFailure method from IVerificationProvider<out TOwner>WithProperties method of AtataContextBuilder<TContext> to extension methodAtataContextBuilder to new LogConsumersAtataContextBuilderAtataContextBuilder to new ScreenshotConsumersAtataContextBuilder{build-start} folder in AtataContext.Artifacts directory path to yyyyMMddTHHmmssFileScreenshotConsumer and NLogFileConsumer to use AtataContext.Artifacts as a default DirectoryPathBuilderVisible to AnyAtataContextInitEvent to AtataContextInitStartedEventFeel free to use any contact channel if you have problems with migration.