Merge pull request #401 from Qtoss-Alpha/master

Add Highlight to ElementLocatingArgs
This commit is contained in:
C. Oceania 2024-04-08 10:10:29 -05:00 committed by GitHub
commit e0874112d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 95 additions and 46 deletions

View file

@ -0,0 +1,7 @@
namespace BotSharp.Abstraction.Browsing.Enums;
public enum BroswerActionEnum
{
Click = 1,
InputText = 2,
}

View file

@ -3,8 +3,9 @@ namespace BotSharp.Abstraction.Browsing.Models;
public class BrowserActionResult public class BrowserActionResult
{ {
public bool IsSuccess { get; set; } public bool IsSuccess { get; set; }
public string ErrorMessage { get; set; } public string? Message { get; set; }
public string StackTrace { get; set; } public string? StackTrace { get; set; }
public string Selector { get; set; } public string Selector { get; set; }
public string Body { get; set; } public string Body { get; set; }
public bool IsHighlighted { get; set; }
} }

View file

@ -1,12 +1,23 @@
using BotSharp.Abstraction.Browsing.Enums;
namespace BotSharp.Abstraction.Browsing.Models; namespace BotSharp.Abstraction.Browsing.Models;
public class ElementActionArgs public class ElementActionArgs
{ {
private string _action; private BroswerActionEnum _action;
public string Action => _action; public BroswerActionEnum Action => _action;
public ElementActionArgs(string action) private string _content;
public string Content => _content;
public ElementActionArgs(BroswerActionEnum action)
{ {
_action = action; _action = action;
} }
public ElementActionArgs(BroswerActionEnum action, string content)
{
_action = action;
_content = content;
}
} }

View file

@ -21,4 +21,9 @@ public class ElementLocatingArgs
public string? Selector { get; set; } public string? Selector { get; set; }
public bool FailIfMultiple { get; set; } public bool FailIfMultiple { get; set; }
/// <summary>
/// Draw outline around the element
/// </summary>
public bool Highlight { get; set; }
} }

View file

@ -25,13 +25,13 @@ public partial class PlaywrightWebDriver
var errorMessage = $"Can't locate element by keyword {actionParams.Context.ElementText}"; var errorMessage = $"Can't locate element by keyword {actionParams.Context.ElementText}";
if (count == 0) if (count == 0)
{ {
result.ErrorMessage = errorMessage; result.Message = errorMessage;
return result; return result;
} }
else if (count > 1) else if (count > 1)
{ {
result.ErrorMessage = $"Located multiple elements by {actionParams.Context.ElementText}"; result.Message = $"Located multiple elements by {actionParams.Context.ElementText}";
_logger.LogError(result.ErrorMessage); _logger.LogError(result.Message);
var allElements = await elements.AllAsync(); var allElements = await elements.AllAsync();
foreach (var element in allElements) foreach (var element in allElements)
{ {
@ -44,7 +44,7 @@ public partial class PlaywrightWebDriver
count = await parentElement.CountAsync(); count = await parentElement.CountAsync();
if (count == 0) if (count == 0)
{ {
result.ErrorMessage = errorMessage; result.Message = errorMessage;
return result; return result;
} }
@ -61,13 +61,13 @@ public partial class PlaywrightWebDriver
if (count == 0) if (count == 0)
{ {
result.ErrorMessage = errorMessage; result.Message = errorMessage;
return result; return result;
} }
else if (count > 1) else if (count > 1)
{ {
result.ErrorMessage = $"Located multiple elements by {actionParams.Context.ElementText}"; result.Message = $"Located multiple elements by {actionParams.Context.ElementText}";
_logger.LogError(result.ErrorMessage); _logger.LogError(result.Message);
return result; return result;
} }
@ -87,7 +87,7 @@ public partial class PlaywrightWebDriver
} }
catch (Exception ex) catch (Exception ex)
{ {
result.ErrorMessage = ex.Message; result.Message = ex.Message;
result.StackTrace = ex.StackTrace; result.StackTrace = ex.StackTrace;
_logger.LogError(ex.Message); _logger.LogError(ex.Message);
} }

View file

@ -106,7 +106,7 @@ public partial class PlaywrightWebDriver
} }
catch (Exception ex) catch (Exception ex)
{ {
result.ErrorMessage = ex.Message; result.Message = ex.Message;
result.StackTrace = ex.StackTrace; result.StackTrace = ex.StackTrace;
_logger.LogError(ex.Message); _logger.LogError(ex.Message);
} }

View file

@ -22,7 +22,7 @@ public partial class PlaywrightWebDriver
var errorMessage = $"Can't locate element by keyword {actionParams.Context.ElementText}"; var errorMessage = $"Can't locate element by keyword {actionParams.Context.ElementText}";
if (count == 0) if (count == 0)
{ {
result.ErrorMessage = errorMessage; result.Message = errorMessage;
return result; return result;
} }
@ -30,7 +30,7 @@ public partial class PlaywrightWebDriver
count = await parentElement.CountAsync(); count = await parentElement.CountAsync();
if (count == 0) if (count == 0)
{ {
result.ErrorMessage = errorMessage; result.Message = errorMessage;
return result; return result;
} }
@ -40,7 +40,7 @@ public partial class PlaywrightWebDriver
if (count == 0) if (count == 0)
{ {
result.ErrorMessage = errorMessage; result.Message = errorMessage;
return result; return result;
} }
@ -53,7 +53,7 @@ public partial class PlaywrightWebDriver
} }
catch (Exception ex) catch (Exception ex)
{ {
result.ErrorMessage = ex.Message; result.Message = ex.Message;
result.StackTrace = ex.StackTrace; result.StackTrace = ex.StackTrace;
_logger.LogError(ex.Message); _logger.LogError(ex.Message);
} }

View file

@ -46,7 +46,7 @@ public partial class PlaywrightWebDriver
if (elements == null) if (elements == null)
{ {
var errorMessage = $"Can't locate element by keyword {actionParams.Context.ElementName}"; var errorMessage = $"Can't locate element by keyword {actionParams.Context.ElementName}";
result.ErrorMessage = errorMessage; result.Message = errorMessage;
return result; return result;
} }
} }
@ -60,7 +60,7 @@ public partial class PlaywrightWebDriver
} }
catch (Exception ex) catch (Exception ex)
{ {
result.ErrorMessage = ex.Message; result.Message = ex.Message;
result.StackTrace = ex.StackTrace; result.StackTrace = ex.StackTrace;
_logger.LogError(ex.Message); _logger.LogError(ex.Message);
} }

View file

@ -42,8 +42,8 @@ public partial class PlaywrightWebDriver
if (count == 0) if (count == 0)
{ {
result.ErrorMessage = $"Can't locate element by keyword {actionParams.Context.ElementText}"; result.Message = $"Can't locate element by keyword {actionParams.Context.ElementText}";
_logger.LogError(result.ErrorMessage); _logger.LogError(result.Message);
} }
else if (count == 1) else if (count == 1)
{ {
@ -57,8 +57,8 @@ public partial class PlaywrightWebDriver
} }
else if (count > 1) else if (count > 1)
{ {
result.ErrorMessage = $"Multiple elements are found by keyword {actionParams.Context.ElementText}"; result.Message = $"Multiple elements are found by keyword {actionParams.Context.ElementText}";
_logger.LogWarning(result.ErrorMessage); _logger.LogWarning(result.Message);
var all = await locator.AllAsync(); var all = await locator.AllAsync();
foreach (var element in all) foreach (var element in all)
{ {

View file

@ -1,3 +1,5 @@
using BotSharp.Abstraction.Browsing.Enums;
namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver; namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
public partial class PlaywrightWebDriver public partial class PlaywrightWebDriver
@ -7,9 +9,13 @@ public partial class PlaywrightWebDriver
var page = _instance.GetPage(message.ConversationId); var page = _instance.GetPage(message.ConversationId);
ILocator locator = page.Locator(result.Selector); ILocator locator = page.Locator(result.Selector);
if (action.Action == "click") if (action.Action == BroswerActionEnum.Click)
{ {
await locator.ClickAsync(); await locator.ClickAsync();
} }
else if (action.Action == BroswerActionEnum.InputText)
{
await locator.FillAsync(action.Content);
}
} }
} }

View file

@ -19,12 +19,12 @@ public partial class PlaywrightWebDriver
} }
else else
{ {
result.ErrorMessage = response.StatusText; result.Message = response.StatusText;
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
result.ErrorMessage = ex.Message; result.Message = ex.Message;
result.StackTrace = ex.StackTrace; result.StackTrace = ex.StackTrace;
_logger.LogError(ex.Message); _logger.LogError(ex.Message);
} }

View file

@ -34,7 +34,7 @@ public partial class PlaywrightWebDriver
} }
catch (Exception ex) catch (Exception ex)
{ {
result.ErrorMessage = ex.Message; result.Message = ex.Message;
result.StackTrace = ex.StackTrace; result.StackTrace = ex.StackTrace;
_logger.LogError(ex.Message); _logger.LogError(ex.Message);
} }

View file

@ -16,8 +16,8 @@ public partial class PlaywrightWebDriver
if (password == null) if (password == null)
{ {
result.ErrorMessage = $"Can't locate the password element by '{actionParams.Context.ElementName}'"; result.Message = $"Can't locate the password element by '{actionParams.Context.ElementName}'";
_logger.LogError(result.ErrorMessage); _logger.LogError(result.Message);
return result; return result;
} }
@ -29,7 +29,7 @@ public partial class PlaywrightWebDriver
} }
catch (Exception ex) catch (Exception ex)
{ {
result.ErrorMessage = ex.Message; result.Message = ex.Message;
result.StackTrace = ex.StackTrace; result.StackTrace = ex.StackTrace;
_logger.LogError(ex.Message); _logger.LogError(ex.Message);
} }

View file

@ -61,7 +61,7 @@ public partial class PlaywrightWebDriver
} }
catch (Exception ex) catch (Exception ex)
{ {
result.ErrorMessage = ex.Message; result.Message = ex.Message;
result.StackTrace = ex.StackTrace; result.StackTrace = ex.StackTrace;
_logger.LogError(ex.Message); _logger.LogError(ex.Message);
} }

View file

@ -27,7 +27,7 @@ public partial class PlaywrightWebDriver
} }
catch(Exception ex) catch(Exception ex)
{ {
result.ErrorMessage = ex.Message; result.Message = ex.Message;
result.StackTrace = ex.StackTrace; result.StackTrace = ex.StackTrace;
_logger.LogError(ex.Message); _logger.LogError(ex.Message);
} }

View file

@ -2,6 +2,12 @@ namespace BotSharp.Plugin.WebDriver.Drivers.PlaywrightDriver;
public partial class PlaywrightWebDriver public partial class PlaywrightWebDriver
{ {
/// <summary>
/// Using attributes or text to locate element and return the selector
/// </summary>
/// <param name="message"></param>
/// <param name="location"></param>
/// <returns></returns>
public async Task<BrowserActionResult> LocateElement(MessageInfo message, ElementLocatingArgs location) public async Task<BrowserActionResult> LocateElement(MessageInfo message, ElementLocatingArgs location)
{ {
var result = new BrowserActionResult(); var result = new BrowserActionResult();
@ -53,8 +59,8 @@ public partial class PlaywrightWebDriver
if (count == 0) if (count == 0)
{ {
result.ErrorMessage = $"Can't locate element by keyword {location.Text}"; result.Message = $"Can't locate element by keyword {location.Text}";
_logger.LogError(result.ErrorMessage); _logger.LogError(result.Message);
} }
else if (count == 1) else if (count == 1)
{ {
@ -67,8 +73,8 @@ public partial class PlaywrightWebDriver
{ {
if (location.FailIfMultiple) if (location.FailIfMultiple)
{ {
result.ErrorMessage = $"Multiple elements are found by {locator}"; result.Message = $"Multiple elements are found by {locator}";
_logger.LogError(result.ErrorMessage); _logger.LogError(result.Message);
foreach (var element in await locator.AllAsync()) foreach (var element in await locator.AllAsync())
{ {
@ -83,6 +89,19 @@ public partial class PlaywrightWebDriver
} }
} }
// Hightlight the element
if (result.IsSuccess && location.Highlight)
{
var handle = await page.QuerySelectorAsync(result.Selector);
await page.EvaluateAsync($@"
(element) => {{
element.style.outline = '2px solid red';
}}", handle);
result.IsHighlighted = true;
}
return result; return result;
} }
} }

View file

@ -26,7 +26,7 @@ public class ChangeCheckboxFn : IFunctionCallback
var content = $"{(args.UpdateValue == "check" ? "Check" : "Uncheck")} checkbox of '{args.ElementText}'"; var content = $"{(args.UpdateValue == "check" ? "Check" : "Uncheck")} checkbox of '{args.ElementText}'";
message.Content = result.IsSuccess ? message.Content = result.IsSuccess ?
$"{content} successfully" : $"{content} successfully" :
$"{content} failed. {result.ErrorMessage}"; $"{content} failed. {result.Message}";
var webDriverService = _services.GetRequiredService<WebDriverService>(); var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId); var path = webDriverService.GetScreenshotFilePath(message.MessageId);

View file

@ -26,7 +26,7 @@ public class ChangeListValueFn : IFunctionCallback
var content = $"Change value to '{args.UpdateValue}' for {args.ElementName}"; var content = $"Change value to '{args.UpdateValue}' for {args.ElementName}";
message.Content = result.IsSuccess ? message.Content = result.IsSuccess ?
$"{content} successfully" : $"{content} successfully" :
$"{content} failed. {result.ErrorMessage}"; $"{content} failed. {result.Message}";
var webDriverService = _services.GetRequiredService<WebDriverService>(); var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId); var path = webDriverService.GetScreenshotFilePath(message.MessageId);

View file

@ -26,7 +26,7 @@ public class CheckRadioButtonFn : IFunctionCallback
var content = $"Check value of '{args.UpdateValue}' for radio button '{args.ElementName}'"; var content = $"Check value of '{args.UpdateValue}' for radio button '{args.ElementName}'";
message.Content = result.IsSuccess ? message.Content = result.IsSuccess ?
$"{content} successfully" : $"{content} successfully" :
$"{content} failed. {result.ErrorMessage}"; $"{content} failed. {result.Message}";
var webDriverService = _services.GetRequiredService<WebDriverService>(); var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId); var path = webDriverService.GetScreenshotFilePath(message.MessageId);

View file

@ -26,7 +26,7 @@ public class ClickButtonFn : IFunctionCallback
var content = $"Click button of '{args.ElementName}'"; var content = $"Click button of '{args.ElementName}'";
message.Content = result.IsSuccess ? message.Content = result.IsSuccess ?
$"{content} successfully" : $"{content} successfully" :
$"{content} failed. {result.ErrorMessage}"; $"{content} failed. {result.Message}";
var webDriverService = _services.GetRequiredService<WebDriverService>(); var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId); var path = webDriverService.GetScreenshotFilePath(message.MessageId);

View file

@ -26,7 +26,7 @@ public class ClickElementFn : IFunctionCallback
var content = $"Click element {args.MatchRule} text '{args.ElementText}'"; var content = $"Click element {args.MatchRule} text '{args.ElementText}'";
message.Content = result.IsSuccess ? message.Content = result.IsSuccess ?
$"{content} successfully" : $"{content} successfully" :
$"{content} failed. {result.ErrorMessage}"; $"{content} failed. {result.Message}";
var webDriverService = _services.GetRequiredService<WebDriverService>(); var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId); var path = webDriverService.GetScreenshotFilePath(message.MessageId);

View file

@ -27,7 +27,7 @@ public class GoToPageFn : IFunctionCallback
url = url.Replace("https://https://", "https://"); url = url.Replace("https://https://", "https://");
var result = await _browser.GoToPage(convService.ConversationId, url); var result = await _browser.GoToPage(convService.ConversationId, url);
message.Content = result.IsSuccess ? $"Page {url} is open." : $"Page {url} open failed. {result.ErrorMessage}"; message.Content = result.IsSuccess ? $"Page {url} is open." : $"Page {url} open failed. {result.Message}";
var path = webDriverService.GetScreenshotFilePath(message.MessageId); var path = webDriverService.GetScreenshotFilePath(message.MessageId);

View file

@ -25,7 +25,7 @@ public class HttpRequestFn : IFunctionCallback
message.Content = result.IsSuccess ? message.Content = result.IsSuccess ?
result.Body : result.Body :
$"Http request failed. {result.ErrorMessage}"; $"Http request failed. {result.Message}";
return true; return true;
} }

View file

@ -31,7 +31,7 @@ public class InputUserTextFn : IFunctionCallback
message.Content = result.IsSuccess ? message.Content = result.IsSuccess ?
content + " successfully" : content + " successfully" :
content + $" failed. {result.ErrorMessage}"; content + $" failed. {result.Message}";
var webDriverService = _services.GetRequiredService<WebDriverService>(); var webDriverService = _services.GetRequiredService<WebDriverService>();
var path = webDriverService.GetScreenshotFilePath(message.MessageId); var path = webDriverService.GetScreenshotFilePath(message.MessageId);

View file

@ -31,7 +31,7 @@ public class OpenBrowserFn : IFunctionCallback
} }
else else
{ {
message.Content = $"Launch browser failed. {result.ErrorMessage}"; message.Content = $"Launch browser failed. {result.Message}";
} }
var path = webDriverService.GetScreenshotFilePath(message.MessageId); var path = webDriverService.GetScreenshotFilePath(message.MessageId);