Skip to content

Commit

Permalink
[#99] NEW: add Configuration.LogOuterHtmlOnFailure (false by default)
Browse files Browse the repository at this point in the history
+ fix implementing INavigation for SeleneDriver
+ fix some cs warnings
  • Loading branch information
yashaka committed Aug 28, 2024
1 parent 873dee2 commit fea6580
Show file tree
Hide file tree
Showing 19 changed files with 167 additions and 41 deletions.
17 changes: 13 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@

- deprecate the majority of `Selene.*` (except S, SS) when providing alternative API via `Browser.*`

## 1.0.0-alpha14 (to be released on 2024.08.28)

- add Configuration.LogOuterHtmlOnFailure (false by default)
- to disable previously mandatory logging of outer html of elements in error messages
that was the reason of failures when working with Appium

## 1.0.0-alpha13 (released on 2024.02.13)

- fix element.GetAttribute to call webelement.GetAttribute instead of webelement.GetDomAttribute
Expand Down Expand Up @@ -49,28 +55,31 @@
- added SeleneElement.GetShadowRoot as wrapper over WebElement.GetShadowRoot

## 1.0.0-alpha09 (to be released on 2021.05.19)

- improved error messages for cases of inner element search
- like error on S(".parent").Find(".child").Click() when .parent is absent or not visible
- FIXED experimental Configuration._HookWaitAction application to Should methods on SeleneElement and SeleneCollection
(was not working, just being skipped)

## 1.0.0-alpha08 (released on 2021.05.18)

- added waiting to SeleneElementJsExtensions:
- JsClick
- JsType
- JsSetValue
- JsSetValue

## 1.0.0-alpha07 (released on 2021.05.13)
- improved error messsages
- now condition in Should method will be rendered like:

- improved error messsages
- now condition in Should method will be rendered like:
`... .Should(Be.Visible)` over just `... .Visible`
- deprecated SeleneElement#config, use SeleneElement#Config instead (same for SeleneCollection)
- yet be attentive... the fate of keeping SeleneElement#Config as public is also vague...
- added experimental feature: Configuration._HookWaitAction
- prefixed with underscore implies that this feature is kind of "publically available private property that might be changed/renamed/removed/etc in future;)", so use it on your own risk!!!
- by default equals to null, making internally call waiting algorithm for actions as it is, without additional customization
- specified to something like:
```
```cs
Configuration._HookWaitAction = (entityObject, describeComputation, wait) => {
Console.WriteLine($"STARTED WAITING FOR: {entityObject}.{describeComputation()}");
try
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2015-2021 Iakiv Kramarenko
Copyright (c) 2015 Iakiv Kramarenko

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
6 changes: 5 additions & 1 deletion NSelene/Conditions/Attribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ public override void Invoke(SeleneElement entity)
? $"Actual {this.name}: Null (attribute is absent)\n"
: $"Actual {this.name}: «{maybeActual}»\n"
)
+ $"Actual webelement: {webelement.GetAttribute("outerHTML")}"
+ (
entity.Config.LogOuterHtmlOnFailure ?? false
? $"Actual webelement: {webelement.GetAttribute("outerHTML")}"
: ""
)
);
}
}
Expand Down
6 changes: 5 additions & 1 deletion NSelene/Conditions/AttributeWithValueMatching.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ public override void Invoke(SeleneElement entity)
? $"Actual {this.name}: Null (attribute is absent)\n"
: $"Actual {this.name}: «{maybeActual}»\n"
)
+ $"Actual webelement: {webelement.GetAttribute("outerHTML")}"
+ (
entity.Config.LogOuterHtmlOnFailure ?? false
? $"Actual webelement: {webelement.GetAttribute("outerHTML")}"
: ""
)
);
}
}
Expand Down
8 changes: 6 additions & 2 deletions NSelene/Conditions/Enabled.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ public override void Invoke(SeleneElement entity)
if (!webelement.Enabled)
{
throw new ConditionNotMatchedException(() =>
"Found element is not enabled: "
+ webelement.GetAttribute("outerHTML")
"Found element is not enabled"
+ (
(entity.Config.LogOuterHtmlOnFailure ?? false)
? $": {webelement.GetAttribute("outerHTML")}"
: ""
)
);
}
}
Expand Down
8 changes: 6 additions & 2 deletions NSelene/Conditions/Selected.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ public override void Invoke(SeleneElement entity)
if (!webelement.Selected)
{
throw new ConditionNotMatchedException(() =>
"Found element is not selected: "
+ webelement.GetAttribute("outerHTML")
"Found element is not selected"
+ (
(entity.Config.LogOuterHtmlOnFailure ?? false)
? $": {webelement.GetAttribute("outerHTML")}"
: ""
)
);
}
}
Expand Down
12 changes: 10 additions & 2 deletions NSelene/Conditions/Text.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ public override void Invoke(SeleneElement entity)
{
throw new ConditionNotMatchedException(() =>
$"Actual text: «{actual}»\n"
+ $"Actual webelement: {webelement.GetAttribute("outerHTML")}"
+ (
entity.Config.LogOuterHtmlOnFailure ?? false
? $"Actual webelement: {webelement.GetAttribute("outerHTML")}"
: ""
)
);
}
}
Expand Down Expand Up @@ -54,7 +58,11 @@ public override void Invoke(SeleneElement entity)
{
throw new ConditionNotMatchedException(() =>
$"Actual text: «{actual}»\n"
+ $"Actual webelement: {webelement.GetAttribute("outerHTML")}"
+ (
entity.Config.LogOuterHtmlOnFailure ?? false
? $"Actual webelement: {webelement.GetAttribute("outerHTML")}"
: ""
)
);
}
}
Expand Down
2 changes: 0 additions & 2 deletions NSelene/Conditions/Title.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ namespace Conditions
public class Title : Condition<IWebDriver>
{
private string expected;
private bool result;

public Title (string expected)
{
Expand All @@ -35,7 +34,6 @@ public override void Invoke(IWebDriver entity)
public class TitleContaining : Condition<IWebDriver>
{
private string expected;
private bool result;

public TitleContaining (string expected)
{
Expand Down
2 changes: 0 additions & 2 deletions NSelene/Conditions/Url.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ namespace Conditions
public class Url : Condition<IWebDriver>
{
private string expected;
private bool result;

public Url (string expected)
{
Expand All @@ -35,7 +34,6 @@ public override void Invoke(IWebDriver entity)
public class UrlContaining : Condition<IWebDriver>
{
private string expected;
private bool result;

public UrlContaining (string expected)
{
Expand Down
15 changes: 9 additions & 6 deletions NSelene/Conditions/Visible.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ public class Visible : Condition<SeleneElement>
public override void Invoke(SeleneElement entity)
{
var webelement = entity.ActualWebElement;
if (!webelement.Displayed)
if (!webelement.Displayed)
{
throw new ConditionNotMatchedException(() =>
"Found element is not visible: "
+ webelement.GetAttribute("outerHTML")
throw new ConditionNotMatchedException(() =>
"Found element is not visible" + (
(entity.Config.LogOuterHtmlOnFailure ?? false)
? $": {webelement.GetAttribute("outerHTML")}"
: ""
)
);
}
}
Expand All @@ -25,12 +28,12 @@ public override void Invoke(SeleneElement entity)

public static partial class Be
{
public static Conditions.Condition<SeleneElement> Visible
public static Conditions.Condition<SeleneElement> Visible
=> new Conditions.Visible();

static partial class Not
{
public static Conditions.Condition<SeleneElement> Visible
public static Conditions.Condition<SeleneElement> Visible
=> Be.Visible.Not;
}
}
Expand Down
41 changes: 41 additions & 0 deletions NSelene/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public interface _SeleneSettings_
bool? TypeByJs { get; set; }
bool? ClickByJs { get; set; }
bool? WaitForNoOverlapFoundByJs { get; set; }
bool? LogOuterHtmlOnFailure { get; set; }
Action<object, Func<string>, Action> _HookWaitAction { get; set; }
string BaseUrl { get; set; }
}
Expand Down Expand Up @@ -153,6 +154,19 @@ IWebDriver _SeleneSettings_.Driver
}
}

private Ref<bool?> _refLogOuterHtmlOnFailure = new Ref<bool?>();
bool? _SeleneSettings_.LogOuterHtmlOnFailure
{
get
{
return this._refLogOuterHtmlOnFailure.Value;
}
set
{
this._refLogOuterHtmlOnFailure.Value = value;
}
}

private Ref<Action<object, Func<string>, Action>> _ref_HookWaitAction;// = new Ref<Action<object, Func<string>, Action>>();
Action<object, Func<string>, Action> _SeleneSettings_._HookWaitAction
{
Expand Down Expand Up @@ -182,6 +196,7 @@ private Configuration(
Ref<bool?> refTypeByJs,
Ref<bool?> refClickByJs,
Ref<bool?> refWaitForNoOverlapFoundByJs,
Ref<bool?> refLogOuterHtmlOnFailure,
Ref<Action<object, Func<string>, Action>> _ref_HookWaitAction,
Ref<string> refBaseUrl)
{
Expand All @@ -192,6 +207,7 @@ private Configuration(
_refTypeByJs = refTypeByJs ?? new Ref<bool?>();
_refClickByJs = refClickByJs ?? new Ref<bool?>();
_refWaitForNoOverlapFoundByJs = refWaitForNoOverlapFoundByJs ?? new Ref<bool?>();
_refLogOuterHtmlOnFailure = refLogOuterHtmlOnFailure ?? new Ref<bool?>();
this._ref_HookWaitAction = _ref_HookWaitAction ?? new Ref<Action<object, Func<string>, Action>>();
_refBaseUrl = refBaseUrl ?? new Ref<string>();
}
Expand All @@ -208,6 +224,7 @@ internal Configuration()
refTypeByJs: null,
refClickByJs: null,
refWaitForNoOverlapFoundByJs: null,
refLogOuterHtmlOnFailure: null,
_ref_HookWaitAction: null,
refBaseUrl: null
) {}
Expand All @@ -220,6 +237,7 @@ public static _SeleneSettings_ _New_(
bool typeByJs = false,
bool clickByJs = false,
bool waitForNoOverlapFoundByJs = false,
bool logOuterHtmlOnFailure = false,
Action<object, Func<string>, Action> _hookWaitAction = null,
string baseUrl = ""
)
Expand All @@ -233,6 +251,7 @@ public static _SeleneSettings_ _New_(
next.TypeByJs = typeByJs;
next.ClickByJs = clickByJs;
next.WaitForNoOverlapFoundByJs = waitForNoOverlapFoundByJs;
next.LogOuterHtmlOnFailure = logOuterHtmlOnFailure;
next._HookWaitAction = _hookWaitAction;
next.BaseUrl = baseUrl;

Expand Down Expand Up @@ -270,6 +289,10 @@ internal static _SeleneSettings_ Shared
getter: () => Configuration.WaitForNoOverlapFoundByJs,
setter: value => Configuration.WaitForNoOverlapFoundByJs = value ?? false
),
refLogOuterHtmlOnFailure: new Ref<bool?>(
getter: () => Configuration.LogOuterHtmlOnFailure,
setter: value => Configuration.LogOuterHtmlOnFailure = value ?? false
),
_ref_HookWaitAction: new Ref<Action<object, Func<string>, Action>>(
getter: () => Configuration._HookWaitAction,
setter: value => Configuration._HookWaitAction = value
Expand All @@ -291,6 +314,7 @@ public static _SeleneSettings_ _With_(
bool? typeByJs = null,
bool? clickByJs = null,
bool? waitForNoOverlapFoundByJs = null,
bool? logOuterHtmlOnFailure = null,
Action<object, Func<string>, Action> _hookWaitAction = null,
string baseUrl = null
)
Expand All @@ -304,6 +328,7 @@ public static _SeleneSettings_ _With_(
next.TypeByJs = typeByJs;
next.ClickByJs = clickByJs;
next.WaitForNoOverlapFoundByJs = waitForNoOverlapFoundByJs;
next.LogOuterHtmlOnFailure = logOuterHtmlOnFailure;
next._HookWaitAction = _hookWaitAction;
next.BaseUrl = baseUrl;

Expand Down Expand Up @@ -336,6 +361,9 @@ _SeleneSettings_ overrides
refWaitForNoOverlapFoundByJs: overrides.WaitForNoOverlapFoundByJs == null
? this._refWaitForNoOverlapFoundByJs
: new Ref<bool?>(overrides.WaitForNoOverlapFoundByJs),
refLogOuterHtmlOnFailure: overrides.LogOuterHtmlOnFailure == null
? this._refLogOuterHtmlOnFailure
: new Ref<bool?>(overrides.LogOuterHtmlOnFailure),
_ref_HookWaitAction: overrides._HookWaitAction == null
? this._ref_HookWaitAction
: new Ref<Action<object, Func<string>, Action>>(overrides._HookWaitAction),
Expand Down Expand Up @@ -449,6 +477,19 @@ public static bool WaitForNoOverlapFoundByJs
}
}

private static ThreadLocal<bool?> _LogOuterHtmlOnFailure = new ThreadLocal<bool?>();
public static bool LogOuterHtmlOnFailure
{
get
{
return Configuration._LogOuterHtmlOnFailure.Value ?? false;
}
set
{
Configuration._LogOuterHtmlOnFailure.Value = value;
}
}

private static ThreadLocal<Action<object, Func<string>, Action>> __HookWaitAction = new ThreadLocal<Action<object, Func<string>, Action>>();
public static Action<object, Func<string>, Action> _HookWaitAction
{
Expand Down
9 changes: 5 additions & 4 deletions NSelene/NSelene.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>NSelene</PackageId>
<Version>1.0.0-alpha13</Version>
<Version>1.0.0-alpha14</Version>
<Authors>yashaka</Authors>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Copyright>Copyright (c) 2015-2021 Iakiv Kramarenko</Copyright>
<Copyright>Copyright (c) 2015 Iakiv Kramarenko</Copyright>
<RepositoryUrl>https://github.com/yashaka/NSelene</RepositoryUrl>
<Title>NSelene - User-oriented Web UI browser tests in .NET (Selenide port from Java)</Title>
<PackageTags>selenium;webdriver;wrapper;web;browser;test;automation;autotest;selenide;selene</PackageTags>
Expand All @@ -23,8 +23,9 @@
</PackageDescription>

<PackageReleaseNotes>
- fix element.GetAttribute to call webelement.GetAttribute instead of webelement.GetDomAttribute
- correspondingly the behavior of element.Value is also fixed, becaused is based on element.GetAttribute
- add Configuration.LogOuterHtmlOnFailure (false by default)
- to disable previously mandatory logging of outer html of elements in error messages
that was the reason of failures when working with Appium
</PackageReleaseNotes>

<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
Expand Down
2 changes: 2 additions & 0 deletions NSelene/SeleneCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public SeleneCollection With(
bool? typeByJs = null,
bool? clickByJs = null,
bool? waitForNoOverlapFoundByJs = null,
bool? logOuterHtmlOnFailure = null,
Action<object, Func<string>, Action> _hookWaitAction = null
)
{
Expand All @@ -93,6 +94,7 @@ public SeleneCollection With(
customized.TypeByJs = typeByJs;
customized.ClickByJs = clickByJs;
customized.WaitForNoOverlapFoundByJs = waitForNoOverlapFoundByJs;
customized.LogOuterHtmlOnFailure = logOuterHtmlOnFailure;
customized._HookWaitAction = _hookWaitAction;

/* same but another style and not so obvious with harder override logic:
Expand Down
Loading

0 comments on commit fea6580

Please sign in to comment.