Skip to content

Commit ac30708

Browse files
authored
Extract interface from ElementActionRetrier (#53)
* Extract interface from ElementActionRetrier and Allow to pass ignored exceptions in constructor * Allow to override IsExceptionHandled decision mechanism * fix tested type in ApplicationNotStartedTests
1 parent fbde33b commit ac30708

File tree

8 files changed

+108
-25
lines changed

8 files changed

+108
-25
lines changed

Aquality.Selenium.Core/src/Aquality.Selenium.Core/Applications/Startup.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public virtual IServiceCollection ConfigureServices(IServiceCollection services,
3838
services.AddSingleton<IRetryConfiguration, RetryConfiguration>();
3939
services.AddSingleton<ILocalizationManager, LocalizationManager>();
4040
services.AddSingleton<ILocalizedLogger, LocalizedLogger>();
41-
services.AddSingleton<ElementActionRetrier>();
41+
services.AddSingleton<IElementActionRetrier, ElementActionRetrier>();
4242

4343
services.AddTransient<ConditionalWait>();
4444
services.AddTransient<IElementFinder, ElementFinder>();

Aquality.Selenium.Core/src/Aquality.Selenium.Core/Aquality.Selenium.Core.xml

Lines changed: 40 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Aquality.Selenium.Core/src/Aquality.Selenium.Core/Elements/Element.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ protected virtual IElementCacheHandler Cache
4747
}
4848
}
4949

50-
protected abstract ElementActionRetrier ActionRetrier { get; }
50+
protected abstract IElementActionRetrier ActionRetrier { get; }
5151

5252
protected abstract IApplication Application { get; }
5353

Aquality.Selenium.Core/src/Aquality.Selenium.Core/Utilities/ElementActionRetrier.cs

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,53 @@
11
using Aquality.Selenium.Core.Configurations;
22
using OpenQA.Selenium;
33
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
46
using System.Threading;
57

68
namespace Aquality.Selenium.Core.Utilities
79
{
810
/// <summary>
9-
/// Retries an action or function when <see cref="StaleElementReferenceException"/> or <see cref="InvalidElementStateException"/> occures.
11+
/// Retries an action or function when <see cref="HandledExceptions"/> occures.
1012
/// </summary>
11-
public class ElementActionRetrier
13+
public class ElementActionRetrier : IElementActionRetrier
1214
{
1315
private readonly IRetryConfiguration retryConfiguration;
1416

1517
/// <summary>
1618
/// Instantiates the class using retry configuration.
1719
/// </summary>
18-
/// <param name="retryConfiguration"></param>
19-
public ElementActionRetrier(IRetryConfiguration retryConfiguration)
20+
/// <param name="retryConfiguration">Retry configuration.</param>
21+
/// <param name="handledExceptions">Exceptions to be handled.
22+
/// If set to null, <see cref="StaleElementReferenceException"/> and <see cref="InvalidElementStateException"/> will be handled.</param>
23+
public ElementActionRetrier(IRetryConfiguration retryConfiguration, IList<Type> handledExceptions = null)
2024
{
2125
this.retryConfiguration = retryConfiguration;
26+
HandledExceptions = handledExceptions ?? new List<Type> { typeof(StaleElementReferenceException), typeof(InvalidElementStateException) };
2227
}
2328

2429
/// <summary>
25-
/// Retries the action when <see cref="StaleElementReferenceException"/> or <see cref="InvalidElementStateException"/> occures.
30+
/// Exceptions to be ignored during action retrying.
31+
/// Set by the constructor parameter.
32+
/// If were not passed to constructor, <see cref="StaleElementReferenceException"/> and <see cref="InvalidElementStateException"/> will be handled.
33+
/// </summary>
34+
public virtual IList<Type> HandledExceptions { get; }
35+
36+
/// <summary>
37+
/// Decides should the occured exception be handled (ignored during the retry) or not.
38+
/// </summary>
39+
/// <param name="exception">Exception to proceed.</param>
40+
/// <returns>True if the exception should be ignored, false otherwise.</returns>
41+
protected virtual bool IsExceptionHandled(Exception exception)
42+
{
43+
return HandledExceptions.Any(type => type.IsAssignableFrom(exception.GetType()));
44+
}
45+
46+
/// <summary>
47+
/// Retries the action when the handled exception <see cref="HandledExceptions"/> occures.
2648
/// </summary>
2749
/// <param name="action">Action to be applied.</param>
28-
public void DoWithRetry(Action action)
50+
public virtual void DoWithRetry(Action action)
2951
{
3052
DoWithRetry(() =>
3153
{
@@ -35,12 +57,12 @@ public void DoWithRetry(Action action)
3557
}
3658

3759
/// <summary>
38-
/// Retries the function when <see cref="StaleElementReferenceException"/> or <see cref="InvalidElementStateException"/> occures.
60+
/// Retries the function when <see cref="HandledExceptions"/> occures.
3961
/// </summary>
4062
/// <typeparam name="T">Return type of function.</typeparam>
4163
/// <param name="function">Function to be applied.</param>
42-
/// <returns>Result of the function</returns>
43-
public T DoWithRetry<T>(Func<T> function)
64+
/// <returns>Result of the function.</returns>
65+
public virtual T DoWithRetry<T>(Func<T> function)
4466
{
4567
var retryAttemptsLeft = retryConfiguration.Number;
4668
var actualInterval = retryConfiguration.PollingInterval;
@@ -68,10 +90,5 @@ public T DoWithRetry<T>(Func<T> function)
6890

6991
return result;
7092
}
71-
72-
private bool IsExceptionHandled(Exception exception)
73-
{
74-
return exception is StaleElementReferenceException || exception is InvalidElementStateException;
75-
}
7693
}
7794
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using OpenQA.Selenium;
2+
using System;
3+
using System.Collections.Generic;
4+
5+
namespace Aquality.Selenium.Core.Utilities
6+
{
7+
/// <summary>
8+
/// Retries an action or function when <see cref="HandledExceptions"/> occures.
9+
/// </summary>
10+
public interface IElementActionRetrier
11+
{
12+
/// <summary>
13+
/// Exceptions to be ignored during action retrying.
14+
/// By the default implementation, <see cref="StaleElementReferenceException"/> and <see cref="InvalidElementStateException"/> are handled.
15+
/// </summary>
16+
IList<Type> HandledExceptions { get; }
17+
18+
/// <summary>
19+
/// Retries the action when the handled exception <see cref="HandledExceptions"/> occures.
20+
/// </summary>
21+
/// <param name="action">Action to be applied.</param>
22+
void DoWithRetry(Action action);
23+
24+
/// <summary>
25+
/// Retries the function when the handled exception <see cref="HandledExceptions"/> occures.
26+
/// </summary>
27+
/// <typeparam name="T">Return type of function.</typeparam>
28+
/// <param name="function">Function to be applied.</param>
29+
/// <returns>Result of the function.</returns>
30+
T DoWithRetry<T>(Func<T> function);
31+
}
32+
}

Aquality.Selenium.Core/tests/Aquality.Selenium.Core.Tests/Applications/Browser/ApplicationNotStartedTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class ApplicationNotStartedTests : TestWithBrowser
1414
{
1515
private static readonly Type[] TypesNotRequireApplication =
1616
{
17-
typeof(ElementActionRetrier),
17+
typeof(IElementActionRetrier),
1818
typeof(ConditionalWait),
1919
typeof(Logger),
2020
typeof(ILocalizationManager),

Aquality.Selenium.Core/tests/Aquality.Selenium.Core.Tests/Applications/Browser/Elements/WebElement.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ protected WebElement(By locator, string name, ElementState state) : base(locator
1616
{
1717
}
1818

19-
protected override ElementActionRetrier ActionRetrier => AqualityServices.ServiceProvider.GetRequiredService<ElementActionRetrier>();
19+
protected override IElementActionRetrier ActionRetrier => AqualityServices.ServiceProvider.GetRequiredService<IElementActionRetrier>();
2020

2121
protected override IApplication Application => AqualityServices.Application;
2222

Aquality.Selenium.Core/tests/Aquality.Selenium.Core.Tests/Applications/WindowsApp/Elements/WindowElement.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ protected WindowElement(By locator, string name) : base(locator, name, ElementSt
1616
{
1717
}
1818

19-
protected override ElementActionRetrier ActionRetrier => AqualityServices.ServiceProvider.GetRequiredService<ElementActionRetrier>();
19+
protected override IElementActionRetrier ActionRetrier => AqualityServices.ServiceProvider.GetRequiredService<IElementActionRetrier>();
2020

2121
protected override IApplication Application => AqualityServices.Application;
2222

0 commit comments

Comments
 (0)