New projct BrowserDriver infered to help with webscraping

This commit is contained in:
2022-02-01 21:15:31 +01:00
parent 5e42d91c1e
commit 5f0c4ef990
17 changed files with 472 additions and 649 deletions

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Selenium.Support" Version="4.1.0" />
<PackageReference Include="Selenium.WebDriver" Version="4.1.0" />
<PackageReference Include="WebDriverManager" Version="2.12.3" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,33 @@
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;
using WebDriverManager;
using WebDriverManager.DriverConfigs.Impl;
namespace BrowserHelper.Driver;
public class BrowserDriver : IBrowserDriver
{
public IWebDriver GetChromeDriver(bool headless = true)
{
new DriverManager().SetUpDriver(new ChromeConfig());
ChromeOptions options = new ChromeOptions();
if (headless)
options.AddArguments("--headless");
return new ChromeDriver(options);
}
public IWebDriver GetFirefoxDriver(bool headless = true)
{
new DriverManager().SetUpDriver(new FirefoxConfig());
FirefoxOptions options = new FirefoxOptions();
if (headless)
options.AddArguments("--headless");
return new FirefoxDriver(options);
}
}
public enum BrowserType
{
Chrome,
Firefox
}

View File

@ -0,0 +1,40 @@
using BrowserHelper.Settings;
using OpenQA.Selenium;
using System;
namespace BrowserHelper.Driver
{
public class DriverFixture : IDriverFixture, IDisposable
{
IWebDriver driver;
private readonly TestSettings _testSettings;
private readonly IBrowserDriver _browserDriver;
public DriverFixture(TestSettings testSettings, IBrowserDriver browserDriver)
{
_testSettings = testSettings;
_browserDriver = browserDriver;
driver = GetWebDriver();
driver.Navigate().GoToUrl(_testSettings.ApplicationUrl);
}
public IWebDriver Driver => driver;
public IWebDriver GetWebDriver()
{
return _testSettings.BrowserType switch
{
BrowserType.Chrome => _browserDriver.GetChromeDriver(_testSettings.Headless),
BrowserType.Firefox => _browserDriver.GetFirefoxDriver(_testSettings.Headless),
_ => _browserDriver.GetChromeDriver()
};
}
public void Dispose()
{
driver.Quit();
}
}
}

View File

@ -0,0 +1,9 @@
using OpenQA.Selenium;
namespace BrowserHelper.Driver;
public interface IBrowserDriver
{
IWebDriver GetChromeDriver(bool headless = true);
IWebDriver GetFirefoxDriver(bool headless = true);
}

View File

@ -0,0 +1,10 @@
using OpenQA.Selenium;
namespace BrowserHelper.Driver
{
public interface IDriverFixture
{
IWebDriver Driver { get; }
}
}

View File

@ -0,0 +1,248 @@
using OpenQA.Selenium;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BrowserHelper.Extensions
{
public static class HtmlTableExtension
{
//Read of Table
private static List<TableDataCollection> ReadTable(IWebElement table)
{
var tableDataCollection = new List<TableDataCollection>();
var columns = table.FindElements(By.TagName("th"));
var rows = table.FindElements(By.TagName("tr"));
int rowIndex = 0;
foreach (var row in rows)
{
int colIndex = 0;
var colDatas = row.FindElements(By.TagName("td"));
if (colDatas.Count != 0)
foreach (var colValue in colDatas)
{
tableDataCollection.Add(new TableDataCollection
{
RowNumber = rowIndex,
ColumnName = columns[colIndex].Text != "" ?
columns[colIndex].Text : colIndex.ToString(),
ColumnValue = colValue.Text,
ColumnSpecialValue = GetControl(colValue)
});
colIndex++;
}
rowIndex++;
}
return tableDataCollection;
}
private static List<TableDataCollection> ReadTablePartly(IWebElement table, string[] shares, string[] shareHeaders)
{
var tableDataCollection = new List<TableDataCollection>();
var columns = table.FindElements(By.TagName("th"));
var rows = table.FindElements(By.TagName("tr"));
var antal = shares.Length;
int rowIndex = 0;
foreach (var row in rows)
{
int colIndex = 0;
var colDatas = row.FindElements(By.TagName("td"));
if (colDatas.Count != 0 && shares.Contains(colDatas[0].Text))
{
if (colDatas.Count != 0)
foreach (var colValue in colDatas)
{
if (shareHeaders.Contains(columns[colIndex].Text))
{
tableDataCollection.Add(new TableDataCollection
{
RowNumber = rowIndex,
ColumnName = columns[colIndex].Text != "" ?
columns[colIndex].Text : colIndex.ToString(),
ColumnValue = colValue.Text,
ColumnSpecialValue = GetControl(colValue)
});
}
colIndex++;
}
rowIndex++;
antal--;
}
if (antal < 1) break;
}
return tableDataCollection;
}
private static ColumnSpecialValue GetControl(IWebElement columnValue)
{
ColumnSpecialValue? columnSpecialValue = null;
if (columnValue.FindElements(By.TagName("a")).Count > 0)
{
columnSpecialValue = new ColumnSpecialValue
{
ElementCollection = columnValue.FindElements(By.TagName("a")),
ControlType = ControlType.hyperlink
};
}
if (columnValue.FindElements(By.TagName("input")).Count > 0)
{
columnSpecialValue = new ColumnSpecialValue
{
ElementCollection = columnValue.FindElements(By.TagName("input")),
ControlType = ControlType.input
};
}
return columnSpecialValue;
}
public static List<TableDataCollection> ReadHandledStock(this IWebElement table)
{
var tableDataCollection = new List<TableDataCollection>();
var columns = table.FindElements(By.TagName("th"));
var rows = table.FindElements(By.TagName("tr"));
var antal = rows.Count;
int rowIndex = 0;
foreach (var row in rows)
{
var colDatas = row.FindElements(By.TagName("td"));
if (colDatas.Count != 0)
{
if (colDatas.Count != 0)
tableDataCollection.Add(new TableDataCollection
{
RowNumber = rowIndex,
ColumnName = columns[0].Text,
ColumnValue = colDatas[0].Text,
ColumnSpecialValue = null
});
}
rowIndex++;
antal--;
if (antal < 0) break;
}
return tableDataCollection;
}
public static List<Share> GetCertainStocks(this IWebElement element, string[] shares, string[] shareHeaders)
{
List<Share> shareList = new List<Share>();
var reducedList = ReadTablePartly(element, shares, shareHeaders);
int rNr = -1;
Share Aktie = null;
foreach (var shareRow in reducedList)
{
if (shareRow.RowNumber != rNr)
{
if (Aktie != null)
{
shareList.Add(Aktie);
}
Aktie = new();
rNr = shareRow.RowNumber;
}
switch (shareRow.ColumnName)
{
case "Aktie":
{
Aktie.AktieNamn = shareRow.ColumnValue;
break;
}
case "Senast":
{
Aktie.SenastePris = Convert.ToDecimal(shareRow.ColumnValue);
break;
}
case "Tid":
{
Aktie.RegTime = TimeOnly.Parse(shareRow.ColumnValue);
break;
}
}
}
shareList.Add(Aktie);
return shareList;
}
public static void PerformActionOnCell(this IWebElement element, string targetColumnIndex, string refColumnName, string refColumnValue, string controlToOperate = null)
{
var table = ReadTable(element);
foreach (int rowNumber in GetDynamicRowNumber(table, refColumnName, refColumnValue))
{
var cell = (from e in table
where e.ColumnName == targetColumnIndex && e.RowNumber == rowNumber
select e.ColumnSpecialValue).SingleOrDefault();
if (controlToOperate != null && cell != null)
{
IWebElement elementToClick = null;
if (cell.ControlType == ControlType.hyperlink)
{
elementToClick = (from c in cell.ElementCollection
where c.Text == controlToOperate.ToString()
select c).SingleOrDefault();
}
if (cell.ControlType == ControlType.input)
{
elementToClick = (from c in cell.ElementCollection
where c.GetAttribute("value") == controlToOperate.ToString()
select c).SingleOrDefault();
}
elementToClick?.Click();
}
else
{
cell.ElementCollection?.First().Click();
}
}
}
private static IEnumerable GetDynamicRowNumber(List<TableDataCollection> tableCollection, string columnName, string columnValue)
{
foreach (var table in tableCollection)
{
if (table.ColumnName == columnName && table.ColumnValue == columnValue)
yield return table.RowNumber;
}
}
}
public class TableDataCollection
{
public int RowNumber { get; set; }
public string? ColumnName { get; set; }
public string? ColumnValue { get; set; }
public ColumnSpecialValue? ColumnSpecialValue { get; set; }
}
public class ColumnSpecialValue
{
public IEnumerable<IWebElement>? ElementCollection { get; set; }
public ControlType? ControlType { get; set; }
}
public enum ControlType
{
hyperlink,
input,
option,
select
}
public class Share
{
public string AktieNamn { get; set; }
public decimal SenastePris { get; set; }
public TimeOnly RegTime { get; set; }
}
}

View File

@ -0,0 +1,39 @@
using BrowserHelper.Driver;
using Microsoft.Extensions.DependencyInjection;
using System.IO;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using BrowserHelper.Settings;
namespace BrowserHelper.Extensions;
public static class WebDriverInitializerExtension
{
public static IServiceCollection UseWebDriverInitializer(
this IServiceCollection services)
{
services.AddSingleton(ReadConfig());
return services;
}
private static TestSettings ReadConfig()
{
var configFile = File
.ReadAllText(Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location)
+ "/appsettings.json");
var jsonSerializeOptions = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
};
jsonSerializeOptions.Converters.Add(new JsonStringEnumConverter());
var testSettings = JsonSerializer.Deserialize<TestSettings>(configFile, jsonSerializeOptions);
return testSettings;
}
}

View File

@ -0,0 +1,35 @@
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
namespace BrowserHelper.Extensions
{
public static class WebElementExtension
{
public static void SelectDropDownByText(this IWebElement element, string text)
{
var select = new SelectElement(element);
select.SelectByText(text);
}
public static void SelectDropDownByValue(this IWebElement element, string value)
{
var select = new SelectElement(element);
select.SelectByValue(value);
}
public static void SelectDropDownByIndex(this IWebElement element, int index)
{
var select = new SelectElement(element);
select.SelectByIndex(index);
}
public static void ClearAndEnterText(this IWebElement element, string value)
{
element.Clear();
element.SendKeys(value);
}
public static string GetSelectedDropDownValue(this IWebElement element)
{
return new SelectElement(element).SelectedOption.Text;
}
}
}

View File

@ -0,0 +1,8 @@
namespace BrowserHelper
{
public interface IMessages
{
string SayGoodBye();
string SayHello();
}
}

14
BrowserHelper/Messages.cs Normal file
View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BrowserHelper
{
public class Messages : IMessages
{
public string SayHello() => "Hello Viewer";
public string SayGoodBye() => "GoddBye, farewell, and good day!";
}
}

View File

@ -0,0 +1,15 @@
using System;
using BrowserHelper.Driver;
namespace BrowserHelper.Settings
{
public class TestSettings
{
public BrowserType BrowserType { get; set; }
public bool Headless { get; set; }
public Uri ApplicationUrl { get; set; }
public int TimeoutInterval { get; set; }
public string[] StockWishes { get; set; }
public string[] StocWishCols { get; set; }
}
}