diff --git a/src/FluffySpoon.Automation.Web.Puppeteer/PuppeteerRegistrationExtensions.cs b/src/FluffySpoon.Automation.Web.Puppeteer/PuppeteerRegistrationExtensions.cs index 6eae313..7dfd635 100644 --- a/src/FluffySpoon.Automation.Web.Puppeteer/PuppeteerRegistrationExtensions.cs +++ b/src/FluffySpoon.Automation.Web.Puppeteer/PuppeteerRegistrationExtensions.cs @@ -1,16 +1,17 @@ using System; +using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; +using PuppeteerSharp; namespace FluffySpoon.Automation.Web.Selenium { public static class PuppeteerRegistrationExtensions { - public static void AddSeleniumWebAutomationFrameworkInstance(this ServiceCollection services, Func driverConstructor) + public static void AddPuppeteerWebAutomationFrameworkInstance(this ServiceCollection services, Func> driverConstructor) { RegistrationExtensions.AddWebAutomationFrameworkInstance(provider => - new SeleniumWebAutomationFrameworkInstance( - provider.GetRequiredService(), - driverConstructor())); + new PuppeteerWebAutomationFrameworkInstance( + driverConstructor)); } } } diff --git a/src/FluffySpoon.Automation.Web.Puppeteer/PuppeteerWebAutomationFrameworkInstance.cs b/src/FluffySpoon.Automation.Web.Puppeteer/PuppeteerWebAutomationFrameworkInstance.cs index 1504c2b..caa5875 100644 --- a/src/FluffySpoon.Automation.Web.Puppeteer/PuppeteerWebAutomationFrameworkInstance.cs +++ b/src/FluffySpoon.Automation.Web.Puppeteer/PuppeteerWebAutomationFrameworkInstance.cs @@ -17,101 +17,140 @@ class PuppeteerWebAutomationFrameworkInstance : IWebAutomationFrameworkInstance private Browser _browser; private Page _page; + private readonly Func> _driverConstructor; + private readonly IDomTunnel _domTunnel; + + public PuppeteerWebAutomationFrameworkInstance( + Func> driverConstructor, + IDomTunnel domTunnel) + { + _driverConstructor = driverConstructor; + _domTunnel = domTunnel; + } + public string UserAgentName => GetType().Name; - - private string GetSelectorForDomElements(IReadOnlyList domElements) + + private async Task GetElementHandlesFromDomElementsAsync(IReadOnlyList domElements) { var selector = domElements .Select(x => x.CssSelector) .Aggregate((a, b) => $"{a}, {b}"); - return selector; + return await _page.QuerySelectorAllAsync(selector); } - public Task ClickAsync(IReadOnlyList elements, int offsetX, int offsetY) + public async Task ClickAsync(IReadOnlyList elements, int offsetX, int offsetY) { - - return _page.ClickAsync( - GetSelectorForDomElements(elements), - new ClickOptions() { - - }); + foreach (var element in elements) + { + await _page.Mouse.ClickAsync( + element.ClientLeft + offsetX, + element.ClientTop + offsetY); + } } public void Dispose() { - throw new NotImplementedException(); + _page.Dispose(); + _browser.Dispose(); } - public Task DoubleClickAsync(IReadOnlyList elements, int offsetX, int offsetY) + public async Task DoubleClickAsync(IReadOnlyList elements, int offsetX, int offsetY) { - throw new NotImplementedException(); + foreach (var element in elements) + { + await _page.Mouse.ClickAsync( + element.ClientLeft + offsetX, + element.ClientTop + offsetY, + new ClickOptions() { + ClickCount = 2 + }); + } } - public Task DragDropAsync(IDomElement from, int fromOffsetX, int fromOffsetY, IDomElement to, int toOffsetX, int toOffsetY) + public async Task DragDropAsync(IDomElement from, int fromOffsetX, int fromOffsetY, IDomElement to, int toOffsetX, int toOffsetY) { - throw new NotImplementedException(); - } + await _page.Mouse.MoveAsync( + from.ClientLeft + fromOffsetX, + from.ClientTop + fromOffsetY); + await _page.Mouse.DownAsync(); - public Task EnterTextInAsync(IReadOnlyList elements, string text) - { - throw new NotImplementedException(); + await _page.Mouse.MoveAsync( + to.ClientLeft + toOffsetX, + to.ClientTop + toOffsetY); + await _page.Mouse.UpAsync(); } - public Task> EvaluateJavaScriptAsDomElementsAsync(int methodChainOffset, string code) + public async Task EnterTextInAsync(IReadOnlyList elements, string text) { - throw new NotImplementedException(); + var handles = await GetElementHandlesFromDomElementsAsync(elements); + foreach(var handle in handles) + await handle.TypeAsync(text); } - public Task EvaluateJavaScriptAsync(string code) + public async Task EvaluateJavaScriptAsync(string code) { - throw new NotImplementedException(); + var blob = await _page.EvaluateExpressionAsync(code); + return blob.ToString(); } - public Task> FindDomElementsByCssSelectorsAsync(int methodChainOffset, string[] selectors) + public Task> FindDomElementsBySelectorAsync(int methodChainOffset, string selector) { - throw new NotImplementedException(); + return _domTunnel.GetDomElementsFromSelector(this, + methodChainOffset, + selector); } - public Task> FindDomElementsBySelectorAsync(int methodChainOffset, string selector) + public async Task FocusAsync(IDomElement domElement) { - throw new NotImplementedException(); + var handle = await GetElementHandleFromDomElementAsync(domElement); + await handle.FocusAsync(); } - public Task FocusAsync(IDomElement domElement, int offsetX, int offsetY) + private async Task GetElementHandleFromDomElementAsync(IDomElement domElement) { - throw new NotImplementedException(); + return await _page.QuerySelectorAsync(domElement.CssSelector); } - public Task HoverAsync(IDomElement domElement, int offsetX, int offsetY) + public async Task HoverAsync(IDomElement domElement, int offsetX, int offsetY) { - throw new NotImplementedException(); + var handle = await GetElementHandleFromDomElementAsync(domElement); + await _page.Mouse.MoveAsync( + domElement.ClientLeft + offsetX, + domElement.ClientTop + offsetY); } public async Task InitializeAsync() { - await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision); - - _browser = await Puppeteer.LaunchAsync(new LaunchOptions - { - Headless = true - }); + _browser = await _driverConstructor(); _page = await _browser.NewPageAsync(); } public Task OpenAsync(string uri) { - throw new NotImplementedException(); + return _page.GoToAsync(uri); } - public Task RightClickAsync(IReadOnlyList elements, int offsetX, int offsetY) + public async Task RightClickAsync(IReadOnlyList elements, int offsetX, int offsetY) { - throw new NotImplementedException(); + foreach (var element in elements) + { + await _page.Mouse.ClickAsync( + element.ClientLeft + offsetX, + element.ClientTop + offsetY, + new ClickOptions() { + Button = MouseButton.Right + }); + } } - public Task SelectByIndicesAsync(IReadOnlyList elements, int[] byIndices) + public async Task SelectByIndicesAsync(IReadOnlyList elements, int[] byIndices) { - throw new NotImplementedException(); + foreach (var element in elements) + { + var handle = await _page.QuerySelectorAsync(element.CssSelector); + await _page.SelectAsync(handle) + } } public Task SelectByTextsAsync(IReadOnlyList elements, string[] byTexts) @@ -128,5 +167,10 @@ public Task TakeScreenshotAsync() { throw new NotImplementedException(); } + + public Task> FindDomElementsByCssSelectorsAsync(int methodChainOffset, string[] selectors) + { + throw new NotImplementedException(); + } } } diff --git a/src/FluffySpoon.Automation.Web.Sample/Program.cs b/src/FluffySpoon.Automation.Web.Sample/Program.cs index d1ea477..eed46cc 100644 --- a/src/FluffySpoon.Automation.Web.Sample/Program.cs +++ b/src/FluffySpoon.Automation.Web.Sample/Program.cs @@ -18,9 +18,9 @@ static async Task Main(string[] args) { var serviceCollection = new ServiceCollection(); serviceCollection.UseJQueryDomSelector(); - serviceCollection.AddSeleniumWebAutomationFrameworkInstance(GetFirefoxDriver); - serviceCollection.AddSeleniumWebAutomationFrameworkInstance(GetChromeDriver); - serviceCollection.AddSeleniumWebAutomationFrameworkInstance(GetEdgeDriver); + serviceCollection.AddSeleniumWebAutomationFrameworkInstance(GetFirefoxDriverAsync); + serviceCollection.AddSeleniumWebAutomationFrameworkInstance(GetChromeDriverAsync); + serviceCollection.AddSeleniumWebAutomationFrameworkInstance(GetEdgeDriverAsync); var serviceProvider = serviceCollection.BuildServiceProvider(); @@ -53,7 +53,7 @@ await automationEngine } } - private static EdgeDriver GetEdgeDriver() + private static async Task GetEdgeDriverAsync() { var options = new EdgeOptions() { AcceptInsecureCertificates = true, @@ -65,7 +65,7 @@ private static EdgeDriver GetEdgeDriver() return driver; } - private static FirefoxDriver GetFirefoxDriver() + private static async Task GetFirefoxDriverAsync() { var options = new FirefoxOptions() { PageLoadStrategy = PageLoadStrategy.Eager, @@ -77,7 +77,7 @@ private static FirefoxDriver GetFirefoxDriver() return driver; } - private static ChromeDriver GetChromeDriver() + private static async Task GetChromeDriverAsync() { var service = ChromeDriverService.CreateDefaultService(Environment.CurrentDirectory); service.EnableVerboseLogging = false; diff --git a/src/FluffySpoon.Automation.Web.Selenium/SeleniumRegistrationExtensions.cs b/src/FluffySpoon.Automation.Web.Selenium/SeleniumRegistrationExtensions.cs index 1704814..be23929 100644 --- a/src/FluffySpoon.Automation.Web.Selenium/SeleniumRegistrationExtensions.cs +++ b/src/FluffySpoon.Automation.Web.Selenium/SeleniumRegistrationExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using FluffySpoon.Automation.Web.Dom; using Microsoft.Extensions.DependencyInjection; using OpenQA.Selenium; @@ -7,12 +8,12 @@ namespace FluffySpoon.Automation.Web.Selenium { public static class SeleniumRegistrationExtensions { - public static void AddSeleniumWebAutomationFrameworkInstance(this ServiceCollection services, Func driverConstructor) + public static void AddSeleniumWebAutomationFrameworkInstance(this ServiceCollection services, Func> driverConstructor) { RegistrationExtensions.AddWebAutomationFrameworkInstance(provider => new SeleniumWebAutomationFrameworkInstance( - provider.GetRequiredService(), - driverConstructor())); + driverConstructor, + provider.GetRequiredService())); } } } diff --git a/src/FluffySpoon.Automation.Web.Selenium/SeleniumWebAutomationFrameworkInstance.cs b/src/FluffySpoon.Automation.Web.Selenium/SeleniumWebAutomationFrameworkInstance.cs index bfadd99..252d332 100644 --- a/src/FluffySpoon.Automation.Web.Selenium/SeleniumWebAutomationFrameworkInstance.cs +++ b/src/FluffySpoon.Automation.Web.Selenium/SeleniumWebAutomationFrameworkInstance.cs @@ -16,35 +16,29 @@ namespace FluffySpoon.Automation.Web.Selenium { class SeleniumWebAutomationFrameworkInstance : IWebAutomationFrameworkInstance { - private readonly EventFiringWebDriver _driver; + private EventFiringWebDriver _driver; + private readonly SemaphoreSlim _semaphore; - private readonly IDomSelectorStrategy _domSelectorStrategy; - - private readonly static string _uniqueSelectorAttribute; - - private Actions Actions => new Actions(_driver); + private readonly Func> _driverConstructor; - public string UserAgentName { get; } + private readonly IDomTunnel _domTunnel; - static SeleniumWebAutomationFrameworkInstance() - { - _uniqueSelectorAttribute = "fluffyspoon-tag-" + Guid.NewGuid(); - } + private Actions Actions => new Actions(_driver); + + public string UserAgentName { get; private set; } public SeleniumWebAutomationFrameworkInstance( - IDomSelectorStrategy domSelectorStrategy, - IWebDriver driver) - { - UserAgentName = driver.GetType().Name; + Func> driverConstructor, + IDomTunnel domTunnel) + { + _driverConstructor = driverConstructor; + _domTunnel = domTunnel; - _driver = new EventFiringWebDriver(driver); _semaphore = new SemaphoreSlim(1); - - _domSelectorStrategy = domSelectorStrategy; } - public Task FocusAsync(IDomElement domElement, int offsetX, int offsetY) + public Task FocusAsync(IDomElement domElement) { var nativeElement = GetWebDriverElementsFromDomElements(new[] { domElement }).Single(); GetScriptExecutor().ExecuteScript("arguments[0].focus();", nativeElement); @@ -109,100 +103,6 @@ public async Task EnterTextInAsync(IReadOnlyList elements, string t } } - public async Task> EvaluateJavaScriptAsDomElementsAsync( - int methodChainOffset, - string javascriptCode) - { - var scriptExecutor = GetScriptExecutor(); - - var elementFetchJavaScript = WrapJavaScriptInIsolatedFunction( - _domSelectorStrategy.DomSelectorLibraryJavaScript + "; " + javascriptCode); - - var resultJsonBlobs = (IReadOnlyList)scriptExecutor.ExecuteScript(@" - return " + WrapJavaScriptInIsolatedFunction(@" - var elements = " + elementFetchJavaScript + @"; - var returnValues = []; - - for(var i = 0; i < elements.length; i++) { - var element = elements[i]; - - var attributes = []; - var computedStyleProperties = []; - - var tag = element.getAttribute('" + _uniqueSelectorAttribute + @"') || '" + methodChainOffset + @"-'+i; - element.setAttribute('" + _uniqueSelectorAttribute + @"', tag); - - var o; - - for(o = 0; o < element.attributes.length; o++) { - var attribute = element.attributes[o]; - attributes.push({ - name: attribute.name, - value: attribute.value - }); - } - - var computedStyle = getComputedStyle(element); - for(o = 0; o < computedStyle.length; o++) { - var styleKey = computedStyle[o]; - computedStyleProperties.push({ - property: styleKey, - value: computedStyle.getPropertyValue(styleKey) - }); - } - - var boundingClientRectangle = element.getBoundingClientRect(); - - returnValues.push(JSON.stringify({ - tag: tag, - attributes: attributes, - computedStyle: computedStyleProperties, - textContent: element.textContent, - value: element.value, - clientLeft: element.clientLeft, - clientTop: element.clientTop, - clientWidth: element.clientWidth, - clientHeight: element.clientHeight, - boundingClientRectangle: { - left: boundingClientRectangle.left, - right: boundingClientRectangle.right, - top: boundingClientRectangle.top, - bottom: boundingClientRectangle.bottom - } - })); - } - - return returnValues; - ")); - - return resultJsonBlobs - .Cast() - .Select(JsonConvert.DeserializeObject) - .Select(x => - { - var attributes = new DomAttributes(); - foreach (var attribute in x.Attributes) - attributes.Add(attribute.Name, attribute.Value); - - var computedStyle = new DomStyle(x.ComputedStyle); - - var domElement = new DomElement( - cssSelector: "[" + _uniqueSelectorAttribute + "='" + x.Tag + "']", - textContent: x.TextContent, - value: x.Value, - clientLeft: x.ClientLeft, - clientTop: x.ClientTop, - clientWidth: x.ClientWidth, - clientHeight: x.ClientHeight, - boundingClientRectangle: x.BoundingClientRectangle, - attributes: attributes, - computedStyle: computedStyle); - - return domElement; - }) - .ToArray(); - } - public Task EvaluateJavaScriptAsync(string code) { var scriptExecutor = GetScriptExecutor(); @@ -212,11 +112,12 @@ public Task EvaluateJavaScriptAsync(string code) } public async Task> FindDomElementsBySelectorAsync( - int methodChainOffset, + int methodChainOffset, string selector) - { - var scriptToExecute = _domSelectorStrategy.GetJavaScriptForRetrievingDomElements(selector); - return await EvaluateJavaScriptAsDomElementsAsync(methodChainOffset, scriptToExecute); + { + return await _domTunnel.GetDomElementsFromSelector(this, + methodChainOffset, + selector); } public async Task OpenAsync(string uri) @@ -265,17 +166,12 @@ private IJavaScriptExecutor GetScriptExecutor() return scriptExecutor; } - private string WrapJavaScriptInIsolatedFunction(string code) - { - return $"(function() {{{code}}})();"; - } - private IWebElement[] GetWebDriverElementsFromDomElements(IReadOnlyList domElements) { var selector = domElements .Select(x => x.CssSelector) .Aggregate((a, b) => $"{a}, {b}"); - + return _driver .FindElements(By.CssSelector(selector)) .ToArray(); @@ -398,11 +294,18 @@ public async Task> FindDomElementsByCssSelectorsAsync { var combinedSelector = selectors.Aggregate((a, b) => a + ", " + b); var sanitizedSelector = combinedSelector.Replace("'", "\\'"); - return await EvaluateJavaScriptAsDomElementsAsync( - methodChainOffset, + return await _domTunnel.GetDomElementsFromSelector(this, + methodChainOffset, @"return document.querySelectorAll('" + sanitizedSelector + "')"); } + public async Task InitializeAsync() + { + var driver = await _driverConstructor(); + UserAgentName = driver.GetType().Name; + _driver = new EventFiringWebDriver(driver); + } + private class DimensionsWrapper { public int Width { get; set; } @@ -414,22 +317,5 @@ private class GlobalDimensionsWrapper public DimensionsWrapper Window { get; set; } public DimensionsWrapper Document { get; set; } } - - private class ElementWrapper - { - public string Tag { get; set; } - public string TextContent { get; set; } - public string Value { get; set; } - - public int ClientLeft { get; set; } - public int ClientTop { get; set; } - public int ClientWidth { get; set; } - public int ClientHeight { get; set; } - - public DomRectangle BoundingClientRectangle { get; set; } - - public DomAttribute[] Attributes { get; set; } - public DomStyleProperty[] ComputedStyle { get; set; } - } } } diff --git a/src/FluffySpoon.Automation.Web/Dom/DomTunnel.cs b/src/FluffySpoon.Automation.Web/Dom/DomTunnel.cs new file mode 100644 index 0000000..d14c53c --- /dev/null +++ b/src/FluffySpoon.Automation.Web/Dom/DomTunnel.cs @@ -0,0 +1,148 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FluffySpoon.Automation.Web.Dom +{ + class DomTunnel : IDomTunnel + { + private readonly IDomSelectorStrategy _domSelectorStrategy; + + public DomTunnel( + IDomSelectorStrategy domSelectorStrategy) + { + _domSelectorStrategy = domSelectorStrategy; + } + + public async Task> GetDomElementsFromSelector( + IWebAutomationFrameworkInstance automationFrameworkInstance, + int methodChainOffset, + string selector) + { + var scriptToExecute = + _domSelectorStrategy.DomSelectorLibraryJavaScript + "; " + + _domSelectorStrategy.GetJavaScriptForRetrievingDomElements(selector); + return await GetDomElementsFromJavaScriptCode( + automationFrameworkInstance, + methodChainOffset, + scriptToExecute); + } + + public async Task> GetDomElementsFromJavaScriptCode( + IWebAutomationFrameworkInstance automationFrameworkInstance, + int methodChainOffset, + string scriptToExecute) + { + var elementFetchJavaScript = WrapJavaScriptInIsolatedFunction( + scriptToExecute); + + var resultJsonBlobs = await automationFrameworkInstance.EvaluateJavaScriptAsync(@" + return " + WrapJavaScriptInIsolatedFunction(@" + var elements = " + elementFetchJavaScript + @"; + var returnValues = []; + + for(var i = 0; i < elements.length; i++) { + var element = elements[i]; + + var attributes = []; + var computedStyleProperties = []; + + var tag = element.getAttribute('fluffyspoon-tag') || '" + methodChainOffset + @"-'+i; + element.setAttribute('fluffyspoon-tag', tag); + + var o; + + for(o = 0; o < element.attributes.length; o++) { + var attribute = element.attributes[o]; + attributes.push({ + name: attribute.name, + value: attribute.value + }); + } + + var computedStyle = getComputedStyle(element); + for(o = 0; o < computedStyle.length; o++) { + var styleKey = computedStyle[o]; + computedStyleProperties.push({ + property: styleKey, + value: computedStyle.getPropertyValue(styleKey) + }); + } + + var boundingClientRectangle = element.getBoundingClientRect(); + + returnValues.push(JSON.stringify({ + tag: tag, + attributes: attributes, + computedStyle: computedStyleProperties, + textContent: element.textContent, + value: element.value, + clientLeft: element.clientLeft, + clientTop: element.clientTop, + clientWidth: element.clientWidth, + clientHeight: element.clientHeight, + boundingClientRectangle: { + left: boundingClientRectangle.left, + right: boundingClientRectangle.right, + top: boundingClientRectangle.top, + bottom: boundingClientRectangle.bottom + } + })); + } + + return JSON.stringify(returnValues); + ")); + + var blobs = JsonConvert.DeserializeObject(resultJsonBlobs); + return blobs + .Select(x => + { + var attributes = new DomAttributes(); + foreach (var attribute in x.Attributes) + attributes.Add(attribute.Name, attribute.Value); + + var computedStyle = new DomStyle(x.ComputedStyle); + + var domElement = new DomElement( + cssSelector: "[fluffyspoon-tag='" + x.Tag + "']", + textContent: x.TextContent, + value: x.Value, + clientLeft: x.ClientLeft, + clientTop: x.ClientTop, + clientWidth: x.ClientWidth, + clientHeight: x.ClientHeight, + boundingClientRectangle: x.BoundingClientRectangle, + attributes: attributes, + computedStyle: computedStyle); + + return domElement; + }) + .ToArray(); + } + + private string WrapJavaScriptInIsolatedFunction(string code) + { + return $"(function() {{{code}}})();"; + } + + private class ElementWrapper + { + public string Tag { get; set; } + public string TextContent { get; set; } + public string Value { get; set; } + + public int ClientLeft { get; set; } + public int ClientTop { get; set; } + public int ClientWidth { get; set; } + public int ClientHeight { get; set; } + + public DomRectangle BoundingClientRectangle { get; set; } + + public DomAttribute[] Attributes { get; set; } + public DomStyleProperty[] ComputedStyle { get; set; } + } + } +} diff --git a/src/FluffySpoon.Automation.Web/Dom/IDomTunnel.cs b/src/FluffySpoon.Automation.Web/Dom/IDomTunnel.cs new file mode 100644 index 0000000..3f542b3 --- /dev/null +++ b/src/FluffySpoon.Automation.Web/Dom/IDomTunnel.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace FluffySpoon.Automation.Web.Dom +{ + public interface IDomTunnel + { + Task> GetDomElementsFromJavaScriptCode(IWebAutomationFrameworkInstance automationFrameworkInstance, int methodChainOffset, string scriptToExecute); + Task> GetDomElementsFromSelector(IWebAutomationFrameworkInstance automationFrameworkInstance, int methodChainOffset, string selector); + } +} diff --git a/src/FluffySpoon.Automation.Web/Fluent/Focus/FocusMethodChainNode.cs b/src/FluffySpoon.Automation.Web/Fluent/Focus/FocusMethodChainNode.cs index 4599a9e..588c77c 100644 --- a/src/FluffySpoon.Automation.Web/Fluent/Focus/FocusMethodChainNode.cs +++ b/src/FluffySpoon.Automation.Web/Fluent/Focus/FocusMethodChainNode.cs @@ -3,7 +3,7 @@ namespace FluffySpoon.Automation.Web.Fluent.Focus { - class FocusMethodChainNode : BaseMouseTargetMethodChainNode + class FocusMethodChainNode : BaseDomElementTargetMethodChainNode { public override IBaseMethodChainNode Clone() { diff --git a/src/FluffySpoon.Automation.Web/Fluent/Focus/FocusOnTargetMethodChainNode.cs b/src/FluffySpoon.Automation.Web/Fluent/Focus/FocusOnTargetMethodChainNode.cs index 1c9caf2..598794c 100644 --- a/src/FluffySpoon.Automation.Web/Fluent/Focus/FocusOnTargetMethodChainNode.cs +++ b/src/FluffySpoon.Automation.Web/Fluent/Focus/FocusOnTargetMethodChainNode.cs @@ -14,7 +14,7 @@ public override IReadOnlyList Elements { protected override async Task OnExecuteAsync(IWebAutomationFrameworkInstance framework) { - await framework.FocusAsync(Elements.First(), Parent.OffsetX, Parent.OffsetY); + await framework.FocusAsync(Elements.First()); await base.OnExecuteAsync(framework); } diff --git a/src/FluffySpoon.Automation.Web/Fluent/Root/IMethodChainRoot.cs b/src/FluffySpoon.Automation.Web/Fluent/Root/IMethodChainRoot.cs index b52c1ca..6e20576 100644 --- a/src/FluffySpoon.Automation.Web/Fluent/Root/IMethodChainRoot.cs +++ b/src/FluffySpoon.Automation.Web/Fluent/Root/IMethodChainRoot.cs @@ -31,7 +31,7 @@ public interface IMethodChainRoot IMouseOnTargetMethodChainNode Hover { get; } IMouseFromTargetMethodChainNode> Drag { get; } - IMouseOnTargetMethodChainNode Focus { get; } + IDomElementOnTargetMethodChainNode Focus { get; } ISelectMethodChainNode Select { get; } IExpectMethodChainRoot Expect { get; } diff --git a/src/FluffySpoon.Automation.Web/Fluent/Root/MethodChainRoot.cs b/src/FluffySpoon.Automation.Web/Fluent/Root/MethodChainRoot.cs index b13cac4..0582a48 100644 --- a/src/FluffySpoon.Automation.Web/Fluent/Root/MethodChainRoot.cs +++ b/src/FluffySpoon.Automation.Web/Fluent/Root/MethodChainRoot.cs @@ -50,7 +50,7 @@ abstract class MethodChainRoot : public IMouseFromTargetMethodChainNode> Drag => MethodChainContext.Enqueue(new DragMethodChainNode()); - public IMouseOnTargetMethodChainNode Focus => + public IDomElementOnTargetMethodChainNode Focus => MethodChainContext.Enqueue(new FocusMethodChainNode()); public ISelectMethodChainNode Select => diff --git a/src/FluffySpoon.Automation.Web/FluffySpoon.Automation.Web.csproj b/src/FluffySpoon.Automation.Web/FluffySpoon.Automation.Web.csproj index ab54a58..3f905bb 100644 --- a/src/FluffySpoon.Automation.Web/FluffySpoon.Automation.Web.csproj +++ b/src/FluffySpoon.Automation.Web/FluffySpoon.Automation.Web.csproj @@ -20,6 +20,7 @@ + diff --git a/src/FluffySpoon.Automation.Web/IWebAutomationFrameworkInstance.cs b/src/FluffySpoon.Automation.Web/IWebAutomationFrameworkInstance.cs index 3d69aa7..228db14 100644 --- a/src/FluffySpoon.Automation.Web/IWebAutomationFrameworkInstance.cs +++ b/src/FluffySpoon.Automation.Web/IWebAutomationFrameworkInstance.cs @@ -12,12 +12,11 @@ public interface IWebAutomationFrameworkInstance: IDisposable Task> FindDomElementsBySelectorAsync(int methodChainOffset, string selector); Task> FindDomElementsByCssSelectorsAsync(int methodChainOffset, string[] selectors); - Task> EvaluateJavaScriptAsDomElementsAsync(int methodChainOffset, string code); Task EvaluateJavaScriptAsync(string code); Task OpenAsync(string uri); Task DragDropAsync(IDomElement from, int fromOffsetX, int fromOffsetY, IDomElement to, int toOffsetX, int toOffsetY); - Task FocusAsync(IDomElement domElement, int offsetX, int offsetY); + Task FocusAsync(IDomElement domElement); Task EnterTextInAsync(IReadOnlyList elements, string text); Task HoverAsync(IDomElement domElement, int offsetX, int offsetY); Task ClickAsync(IReadOnlyList elements, int offsetX, int offsetY); diff --git a/src/FluffySpoon.Automation.Web/WebAutomationEngine.cs b/src/FluffySpoon.Automation.Web/WebAutomationEngine.cs index c42afee..488e607 100644 --- a/src/FluffySpoon.Automation.Web/WebAutomationEngine.cs +++ b/src/FluffySpoon.Automation.Web/WebAutomationEngine.cs @@ -72,7 +72,7 @@ public async Task InitializeAsync() public IMouseOnTargetMethodChainNode Hover => StartNewSession().Hover; public IMouseFromTargetMethodChainNode> Drag => StartNewSession().Drag; - public IMouseOnTargetMethodChainNode Focus => StartNewSession().Focus; + public IDomElementOnTargetMethodChainNode Focus => StartNewSession().Focus; public ISelectMethodChainNode Select => StartNewSession().Select; public IWaitMethodChainNode Wait(TimeSpan time) => StartNewSession().Wait(time);