2025-09-02 15:32:24 +01:00
using OpenQA.Selenium ;
using OpenQA.Selenium.Chrome ;
using OpenQA.Selenium.Support.UI ;
namespace AiQ_GUI
{
internal class Selenium
{
// Directs to url using chrome drive and waits for the page to fully load
public static void GoToUrl ( string url , ChromeDriver driver )
{
try
{
driver . Navigate ( ) . GoToUrl ( url ) ;
// Wait until the document is fully loaded
WebDriverWait wait = new ( driver , TimeSpan . FromSeconds ( 10 ) ) ;
wait . Until ( d = > ( ( IJavaScriptExecutor ) d ) . ExecuteScript ( "return document.readyState" ) . Equals ( "complete" ) ) ;
}
catch ( WebDriverTimeoutException )
{
MainForm . Instance . AddToActionsList ( "Could not load web page " + url + "1. Check camera has no password set. " + Environment . NewLine + "2. If unable to fix speak to supervisor." ) ;
}
}
// Retrieves lates element ID for Shutter,iris, gain and IR
public static ElementID GetElementIds ( ChromeDriver driver )
{
ElementID elementID = new ( )
{
modeId = GetLatestElementIdContaining ( "Mode_" , driver ) ,
shutterId = GetLatestElementIdContaining ( "FixShutter_" , driver ) ,
irisId = GetLatestElementIdContaining ( "FixIris_" , driver ) ,
gainId = GetLatestElementIdContaining ( "FixGain_" , driver ) ,
irLevelId = GetLatestElementIdContaining ( "CameraControls_" , driver ) ,
CamAct = GetLatestElementIdContaining ( "CameraActivity_" , driver )
} ;
return elementID ;
}
2025-11-11 13:18:02 +00:00
public static void SwitchUser ( ChromeDriver driver )
{
try
{
WebDriverWait wait = new ( driver , TimeSpan . FromSeconds ( 10 ) ) ;
// Click "Switch User"
IWebElement switchBtn = wait . Until ( d = >
d . FindElement ( By . XPath ( "//*[contains(text(),'Switch User')]" ) )
) ;
switchBtn . Click ( ) ;
// Username
IWebElement userBox = wait . Until ( d = > d . FindElement ( By . Id ( "username" ) ) ) ;
userBox . Clear ( ) ;
userBox . SendKeys ( "admin" ) ;
// Password
IWebElement passBox = wait . Until ( d = > d . FindElement ( By . Id ( "password" ) ) ) ;
passBox . Clear ( ) ;
passBox . SendKeys ( "admin" ) ;
// Login button
IWebElement loginBtn = wait . Until ( d = >
d . FindElement ( By . XPath ( "//button[contains(normalize-space(text()), 'Login')]" ) )
) ;
// Wait until it's clickable manually (no SeleniumExtras)
wait . Until ( d = > loginBtn . Displayed & & loginBtn . Enabled ) ;
loginBtn . Click ( ) ;
MainForm . Instance . AddToActionsList ( "Switched user and logged in." ) ;
}
catch ( Exception ex )
{
MainForm . Instance . AddToActionsList ( "SwitchUser failed: " + ex . Message ) ;
}
}
2025-09-02 15:32:24 +01:00
// Attempts to click the web element with the specified ID; refreshes the page and retries once if the initial attempt fails
2025-10-21 14:01:27 +01:00
public static void ClickElementByID ( string elementID , ChromeDriver driver , bool tryagain = true )
2025-09-02 15:32:24 +01:00
{
try
{
WebDriverWait wait = new ( driver , TimeSpan . FromSeconds ( 10 ) ) ;
IWebElement element = wait . Until ( driver = > driver . FindElement ( By . Id ( elementID ) ) ) ;
element . Click ( ) ;
}
catch
{
if ( tryagain )
{
driver . Navigate ( ) . Refresh ( ) ;
WebDriverWait wait = new ( driver , TimeSpan . FromSeconds ( 10 ) ) ;
wait . Until ( d = > ( ( IJavaScriptExecutor ) d ) . ExecuteScript ( "return document.readyState" ) . Equals ( "complete" ) ) ;
2025-10-21 14:01:27 +01:00
ClickElementByID ( elementID , driver , false ) ;
2025-09-02 15:32:24 +01:00
}
MainForm . Instance . AddToActionsList ( "Could not click " + elementID ) ;
}
}
// Initialises and opens a ChromeDriver with specific options
public static ChromeDriver OpenDriver ( )
{
2025-11-11 13:18:02 +00:00
string tempProfile = null ;
try
{
ChromeOptions options = new ( ) ;
options . AddArguments ( "--app=data:," ,
"--window-size=960,1040" ,
"--window-position=0,0" ,
"--no-sandbox" ,
"--incognito" ,
"--no-first-run" ,
"--no-default-browser-check" ,
"--disable-features=BrowserAddPersonFeature,InterestFeedContentSuggestions" ) ;
// Use a unique temporary profile to avoid conflicts
tempProfile = Path . Combine ( Path . GetTempPath ( ) , Guid . NewGuid ( ) . ToString ( ) ) ;
options . AddArguments ( $"--user-data-dir={tempProfile}" ) ;
// manual driver path
string driverPath = @"C:\ProgramData\MAV\AiQ_GUI" ;
ChromeDriverService service = ChromeDriverService . CreateDefaultService ( driverPath ) ;
service . HideCommandPromptWindow = true ;
ChromeDriver driver = new ( service , options ) ;
driver . Manage ( ) . Timeouts ( ) . PageLoad = TimeSpan . FromSeconds ( 5 ) ;
return driver ;
}
catch ( Exception ex )
{
MainForm . Instance . AddToActionsList ( "Failed to create ChromeDriver: " + ex . Message ) ;
throw ;
}
2025-09-02 15:32:24 +01:00
}
// Changes the value of a dropdown element by ID, logs the action, and verifies the result using flashline feedback
public static async Task Dropdown_Change ( string fullId , string value , ChromeDriver driver , string SoakLogFile , string CamAct )
{
WebDriverWait wait = new ( driver , TimeSpan . FromSeconds ( 10 ) ) ;
IWebElement element = wait . Until ( driver = > driver . FindElement ( By . Id ( fullId ) ) ) ;
await Logging . LogMessage ( $"Changing dropdown {fullId} to value: {value}" , SoakLogFile ) ;
await Task . Delay ( fullId . Contains ( "Mode_" ) ? 4000 : 200 ) ;
if ( value = = element . GetAttribute ( "value" ) )
return ; // No change needed setting is already correct
SelectElement select = new ( element ) ;
select . SelectByValue ( value ) ;
await Task . Delay ( 500 ) ; // Wait for the change to take effect
if ( ! await Checkflashline ( driver , CamAct ) )
{
Logging . LogWarningMessage ( "Bad flashline after changing: " + fullId , SoakLogFile ) ;
MainForm . Instance . AddToActionsList ( "Bad flashline after changing: " + fullId ) ;
}
}
// Monitors the flashline element's color to determine success (green) or failure (red) of a camera
public static async Task < bool > Checkflashline ( ChromeDriver driver , string CamAct )
{
IWebElement flashline = driver . FindElement ( By . Id ( CamAct ) ) ;
string flashlinecolor = flashline . GetCssValue ( "color" ) ;
Task FlashWait = Task . Delay ( 8000 ) ;
while ( ! FlashWait . IsCompleted )
{
if ( flashlinecolor . Contains ( "0, 255, 127" ) )
return true ;
else if ( flashlinecolor . Contains ( "255, 69, 0" ) )
return false ;
await Task . Delay ( 500 ) ;
flashlinecolor = flashline . GetCssValue ( "color" ) ;
}
return false ;
}
// Retrieves the ID of the last <select> element whose ID starts with the specified partial ID
public static string GetLatestElementIdContaining ( string partialId , ChromeDriver driver )
{
System . Collections . ObjectModel . ReadOnlyCollection < IWebElement > elements = driver . FindElements ( By . XPath ( $"//*[@id][starts-with(@id, '{partialId}')]" ) ) ;
List < string? > matchingIds = elements
. Select ( el = > el . GetAttribute ( "id" ) )
. Where ( id = > ! string . IsNullOrEmpty ( id ) )
. ToList ( ) ;
return matchingIds . LastOrDefault ( ) ;
}
}
}