<repo_name>iamcucusa/e2e<file_sep>/iDareUI/PageInteractions/LoginPage.cs
﻿using System;
using iDareUI.Common;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;

namespace iDareUI.PageInteractions
{
    public class LoginPage
    {
        private readonly RemoteWebDriver driver;
        private readonly ILog log;

        public LoginPage(RemoteWebDriver driver, ILog log)
        {
            this.driver = driver;
            this.log = log;
        }
        public void NavigateTo()
        {
            driver.Manage().Window.Maximize();

            var targetUrl = Constants.PageUri;
            this.log.Info($"Navigating to {targetUrl}");

            driver.Navigate().GoToUrl(targetUrl);
            FlowUtilities.WaitUntil(
            () =>
            {
                try
                {
                    IWebElement rocheLogo = driver.FindElement(By.CssSelector("svg.prv-roche-icon"));
                    return true;
                }
                catch (NoSuchElementException ex)
                {
                    log.Error("The URL specified could not be found" + ex);
                    return false;
                }
            }, TimeSpan.FromSeconds(5), TimeSpan.FromMilliseconds(100), "The URL specified could not be found");
        }

        private IWebElement userName => driver.FindElements(By.XPath("//input[@id='undefinedInput']"))[0];
        private IWebElement password => driver.FindElements(By.XPath("//input[@id='undefinedInput']"))[1];
        private IWebElement loginButton => driver.FindElement(By.XPath("//button[@type='submit']"));
        private IWebElement errorMessage => driver.FindElement(By.XPath("//span[contains(.,' Authentication failed: Wrong credentials.')]"));
     

        public string UserName
        {
            set
            {
                userName.SendKeys(value);
            }
        }
        public string Password
        {
            set
            {
                password.SendKeys(value);
            }
        }

        public CaseMainPage LoginApplication()
        {
            loginButton.Click();
            return new CaseMainPage(driver);
        }

        public string ErrorMessageText => errorMessage.Text;
    }
}
<file_sep>/iDareUI/Common/InteractionUtilities.cs
﻿using System;
using OpenQA.Selenium;

namespace iDareUI.Common
{
    public static class InteractionUtilities
    {
        public static void SendKeysCharByChar(IWebElement element, string keys)
        {
            for (int i = 0; i < keys.Length; i++)
            {
                element.SendKeys(Char.ToString(keys[i]));
            }
        }

        public static bool IsVisible(string id, IWebDriver webDriver)
        {
            bool displayed;
            try
            {
                displayed = webDriver.FindElement(By.XPath("//*[@attr.data-idare-id='" + id + "']")).Displayed;
            }
            catch (NoSuchElementException)
            {
                // As the element is not present in DOM, it returns true.
                displayed = false;
            }
            catch (StaleElementReferenceException)
            {
                // The stale element reference implies that element is no longer visible, hence returns true.
                displayed = false;
            }
            return displayed;
        }
    }
}
<file_sep>/iDareUI/Common/TestingEnvironment.cs
﻿using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Remote;
using System;
using System.IO;
using System.Reflection;
using Xunit.Abstractions;

namespace iDareUI.Common
{
   public class TestingEnvironment:IDisposable
    {
        public bool IsIDE 
        {
            get { return System.Diagnostics.Debugger.IsAttached; }
        }
        private RemoteWebDriver driver = null;
        public RemoteWebDriver Driver
        {
            get
            {
                ChromeOptions chromeOptions = new ChromeOptions();
                if (this.driver == null)
                {
                    if (!IsIDE)
                    {
                        chromeOptions.AddArgument("headless");
                    }

                    this.driver = new ChromeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),chromeOptions);
                    this.driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
                }
                return driver;
            }
        }
        public TestingEnvironment(ITestOutputHelper helper)
        {
            this.Log = new Log(helper);
        }

        public ILog Log;

        public void Dispose()
        {
            if (this.driver != null)
            {
                this.driver.Dispose();
                this.driver = null;
            }
        }
    }
}
<file_sep>/iDareUI/PageInteractions/CaseInvestigationPage.cs
﻿using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using System.Collections.Generic;

namespace iDareUI.PageInteractions
{
    public class CaseInvestigationPage
    {
        private RemoteWebDriver driver;
        public CaseInvestigationPage(RemoteWebDriver driver)
        {
            this.driver = driver;
        }

        private IWebElement instrumentInformationCard => driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfo']"));
        private IWebElement instrumentInformationHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoHeader']")); 
        private IWebElement countersCard => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseDetailHardwareCounters']"));
        private IWebElement countersHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseDetailHardwareCountersHeader']"));
        private IWebElement instrumentStatesCard => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseDetailInvestigateTimelineBox']"));
        private IWebElement instrumentStatesHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseDetailInvestigateTimelineTitle']")); 
        private IWebElement recordedRunsCard => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseDetailInvestigateRunBox']"));
        private IWebElement recordedRunsHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseDetailInvestigateRunsTitle']")); 
        private IWebElement flagsCard => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseDetailInvestigateFlagsBox']")); 
        private IWebElement flagsHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseDetailInvestigateFlagsTitle']"));
        private IWebElement flagsTabsContainer => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseDetailFlagsTabs']"));
        private IList<IWebElement> flagsTabs => flagsTabsContainer.FindElements(By.CssSelector("div.mat-tab-label"));
        private IWebElement flagsProcessingModuleA => flagsTabs[0];
        private IWebElement flagsProcessingModuleB => flagsTabs[1];
        private IWebElement InvestigateTab => driver.FindElement(By.XPath("/html/body/prv-root/prv-case-details/div/section/mat-tab-group/mat-tab-header/div[2]/div/div/div[2]"));



        public void PressInvestigateTab() { InvestigateTab.Click(); }
        public void PressMatExpansionPanelInstrumentInformation() { instrumentInformationHeader.Click(); }
        public void PressMatExpansionPanelCounters() { countersHeader.Click(); }
        public void PressFlagProcessingModuleATab() { flagsProcessingModuleA.Click(); }
        public void PressFlagProcessingModuleBTab() { flagsProcessingModuleB.Click(); }




    }
}
<file_sep>/iDareUI/PageInteractions/TeachingMainPage.cs
﻿using iDareUI.Common;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using System;
using System.Collections.Generic;
using System.Text;

namespace iDareUI.PageInteractions
{
    class TeachingMainPage
    {
        private IWebElement teachingUserInfo => driver.FindElement(By.XPath("//*[@attr.data-idare-id='TeachingUserInfo']"));   
        private IWebElement teachingHeadlineComponentGreeting => driver.FindElement(By.XPath("//*[@attr.data-idare-id='TeachingHeadlineComponentGreeting']"));
        private IWebElement teachingHeadlineComponentName => driver.FindElement(By.XPath("//*[@attr.data-idare-id='TeachingHeadlineComponentName']"));
        private IWebElement teachingHeadlineComponentRole => driver.FindElement(By.XPath("//*[@attr.data-idare-id='TeachingHeadlineComponentRole']"));

        public IssuesRulesPage issuesRulesPage;
        private RemoteWebDriver driver;
        public TeachingMainPage(RemoteWebDriver driver)
        {
            this.driver = driver;
            issuesRulesPage = new IssuesRulesPage(driver);
        }

        public void NavigateToTeachingModule()
        {
            driver.Manage().Window.Maximize();

            var targetUrl = Constants.PageTeachingUri;

            driver.Navigate().GoToUrl(targetUrl);
            FlowUtilities.WaitUntil(
            () =>
            {
                try
                {
                    IWebElement teachingRocheIconHeader = driver.FindElement(By.XPath("//*[@attr.data-idare-id='TeachingRocheIcon']"));
                    return true;
                }
                catch (NoSuchElementException ex)
                {
                    return false;
                }
            }, TimeSpan.FromSeconds(5), TimeSpan.FromMilliseconds(100), "The URL specified could not be found");
        }

        public bool userIsLoggedInAs(string role, string username) {

            return teachingUserInfo != null &&
                teachingHeadlineComponentName != null &&
                teachingHeadlineComponentName != null &&
                teachingHeadlineComponentRole != null &&
                teachingHeadlineComponentRole.Text == role &&
                teachingHeadlineComponentName.Text == username;

        }
        

    }
}
<file_sep>/iDareUI/LoginSteps.cs
﻿using iDareUI.Common;
using iDareUI.Models;
using iDareUI.PageInteractions;
using TechTalk.SpecFlow;
using Xunit;

namespace iDareUI
{
    [Binding]
    public class LoginSteps
    {
        private TestingEnvironment environment;
        private CaseMainPage mainCasesPage;
        private LoginPage loginPage;
        public LoginSteps(TestingEnvironment environment)
        {
            this.environment = environment;
            this.loginPage = new LoginPage(environment.Driver, environment.Log);
            this.mainCasesPage = new CaseMainPage(environment.Driver);
        }

        [Given(@"I am in the Overview screen")]
        public void GivenIAmInTheOverviewScreen()
        {
            this.environment.Driver.Manage().Window.Maximize();
            this.loginPage.NavigateTo();
        }

        [Then(@"I should see the Cases screen for (.*)")]
        public void ThenIShouldSeeTheCasesScreenfor(string userName)
        {
            string userWebName = mainCasesPage.UserRole;
            Assert.Equal(userName, userWebName);
        }
    }
}
<file_sep>/iDareUI/Common/FlowUtilities.cs
﻿using System;
using System.Diagnostics;
using System.Threading;

namespace iDareUI.Common
{
    public static class FlowUtilities
    {
        public static WaitResponse WaitUntil(Func<bool> waitUntilResult, TimeSpan timeout, TimeSpan period, string errorMessage = "", bool throwException=true, bool ignoreErrors = true)
        {
            Stopwatch watch = Stopwatch.StartNew();
            while (watch.Elapsed < timeout)
            {
                try
                {
                    if (waitUntilResult())
                    {
                        return new WaitResponse {Success = true};
                    }
                }
                catch (Exception e)
                {
                    if (ignoreErrors == true)
                    {
                        Console.WriteLine("Error Ignored:\r\n" + e);
                        continue;
                    }

                    return new WaitResponse { Exception = e, Reason = e.Message, TimedOut = false  };
                }
               
                Thread.Sleep(period);
            }
            if (!waitUntilResult() && throwException)
            {
                return new WaitResponse{Exception = new TimeoutException(errorMessage), TimedOut  =  true, Reason = "TimedOut"} ;
            }

            return new WaitResponse{Success = true};
        }
        public static WaitResponse WaitUntilWithoutException(Func<bool> waitUntilResult, TimeSpan timeout, TimeSpan period)
        {
            return WaitUntil(waitUntilResult, timeout, period, "", false);
        }

    }
}
<file_sep>/iDareUI/CasesOverviewSteps.cs
﻿using iDareUI.Common;
using iDareUI.Models;
using OpenQA.Selenium;
using System;
using System.Collections.Generic;
using System.Linq;
using iDareUI.PageInteractions;
using TechTalk.SpecFlow;
using Xunit;

namespace iDareUI
{
    [Binding]
    public class CasesOverviewSteps
    {
        private TestingEnvironment environment;
        private CaseMainPage mainCasesPage;
        private CaseDetailsPage casesDetailsPage;
        private CaseCreationSteps caseCreationSteps;
        private ScenarioContext scenarioContext;
        private FeatureContext featureContext;
        private Case caseCreatedForSearch;
        public enum CaseSearchProperty
        {
            CaseId,
            SerialNumber,
            Customer,
            Country
        }

        public CasesOverviewSteps(TestingEnvironment environment, ScenarioContext scenarioContext, FeatureContext featureContext)
        {
            this.environment = environment;
            this.mainCasesPage = new CaseMainPage(environment.Driver);
            this.casesDetailsPage = new CaseDetailsPage(environment.Driver);
            this.caseCreationSteps = new CaseCreationSteps(environment, featureContext);
            this.scenarioContext = scenarioContext;
            this.featureContext = featureContext;
        }

        [When(@"I go to the Cases overview screen")]
        public void WhenIGoToTheCasesOverviewScreen()
        {
            mainCasesPage.PressCasesButton();
        }
        [When(@"I enter to the details of a case")]
        public void WhenIEnterToTheDetailsOfACase()
        {
            FlowUtilities.WaitUntil(
                () => (mainCasesPage.firstIdRowText.Contains("CAS-0123")), TimeSpan.FromSeconds(20), TimeSpan.FromMilliseconds(100),
                "The created case is not located in the first position of the Cases Overview grid");

            FlowUtilities.WaitUntil(
                () =>
                {
                    try
                    {
                        mainCasesPage.PressDetailsButton();
                        casesDetailsPage.PressCloseCaseDetailsButton();
                        return mainCasesPage.firstCaseSWVersionText.Contains("01.");
                    }
                    catch
                    {
                        return false;
                    }
                }, TimeSpan.FromSeconds(20), TimeSpan.FromMilliseconds(1000));

            mainCasesPage.PressDetailsButton();
            Assert.True(casesDetailsPage.closeCaseDetailsButton.Enabled, "The case details page was not opened.");
        }

        [Then(@"the cases grid with the correct columns is displayed")]
        public void ThenTheCasesGridWithTheCorrectColumnsIsDisplayed()
        {
            string[] casesGridColumns = new string[] { "Case ID", "System", "Serial No.", "SW Version", "Created (UTC)", "Customer", "Country", "Created by", "Issues" };
            var obtainColumns = mainCasesPage.GetGridHeaderNames();
            Assert.True(casesGridColumns.SequenceEqual(obtainColumns),
                $"The grid headers are not the expected ones. \nExpected: {string.Join(", ", casesGridColumns)}, \nActual: {string.Join(", ", obtainColumns)}");
        }

        [Then(@"cases are sorted by creation time")]
        public void ThenCasesAreSortedByCreationTime()
        {
            IEnumerable<DateTime> obtainedCreationDateTime = null;
            IEnumerable<DateTime> orderedCreationDateTime = null;

            FlowUtilities.WaitUntil(
                () =>
                {
                    try
                    {
                        obtainedCreationDateTime = mainCasesPage.GetCreationDateTime();
                        orderedCreationDateTime = mainCasesPage.GetSortedDates();

                        return orderedCreationDateTime.SequenceEqual(obtainedCreationDateTime);
                    }
                    catch (StaleElementReferenceException ex)
                    {
                        environment.Log.Error("Error getting data: " + ex.Message);
                        return false;
                    }

                }, TimeSpan.FromSeconds(5), TimeSpan.FromMilliseconds(100));
        }

        [Given(@"I create two duplicate cases and a different case")]
        public void GivenICreateTwoDuplicateCasesAndADifferentCase()
        {
            caseCreatedForSearch = Case.GetRandomCase();
            this.CreateCase(caseCreatedForSearch);
            this.CreateCase(caseCreatedForSearch);
            var myCase2 = Case.GetRandomCase();
            this.CreateCase(myCase2);
            mainCasesPage.WaitUntilCasesAreUpdated(myCase2.CaseID, myCase2.CaseID);
        }

        private void CreateCase(Case c)
        {
            caseCreationSteps.GivenIEnterToCreateANewCase();
            caseCreationSteps.WhenIEnterAsRexisID(c.CaseID);
            caseCreationSteps.WhenIEnterAsSerialNumber(c.SerialNo);
            caseCreationSteps.WhenIEnterAsCountry(c.Country);
            caseCreationSteps.WhenIEnterAsCustomer(c.Customer);
            caseCreationSteps.WhenIEnterTheOptionOfTheDropdownAsTimezone(2);
            caseCreationSteps.WhenIPressTheSaveButton();
        }


        [When(@"I search by (.*) of the duplicate cases")]
        public void WhenISearchByOfTheDuplicateCases(CaseSearchProperty property)
        {
            switch (property)
            {
                case CaseSearchProperty.CaseId:
                    mainCasesPage.SearchFilterCases(caseCreatedForSearch.CaseID);
                    break;
                case CaseSearchProperty.Country:
                    mainCasesPage.SearchFilterCases(caseCreatedForSearch.Country);
                    break;
                case CaseSearchProperty.Customer:
                    mainCasesPage.SearchFilterCases(caseCreatedForSearch.Customer);
                    break;
                case CaseSearchProperty.SerialNumber:
                    mainCasesPage.SearchFilterCases(caseCreatedForSearch.SerialNo);
                    break;
                default:
                    throw new InvalidOperationException("The search property is wrong.");
            }
            
            mainCasesPage.PressEnterToFilter();
        }


        [Then(@"the only two cases with the same (.*) I created are displayed")]
        public void ThenTheOnlyTwoCasesWithTheSameICreatedAreDisplayed(CaseSearchProperty property)
        {
            FlowUtilities.WaitUntil(
                () => (mainCasesPage.SelectCases(caseCreatedForSearch, property)), TimeSpan.FromSeconds(2000), TimeSpan.FromMilliseconds(25));

            Assert.True(mainCasesPage.SelectCases(caseCreatedForSearch, property), "The searching filter is not working");
        }
    }
}
<file_sep>/iDareUI/Common/Log.cs
﻿using System;
using TechTalk.SpecFlow;
using Xunit.Abstractions;

namespace iDareUI.Common
{
    internal class Log : ILog
    {
        private readonly ITestOutputHelper helper;

        public Log(ITestOutputHelper helper)
        {
            this.helper = helper;
        }

        public void Info(string s)
        {
            this.LogLine("INFO", s);
        }

        public void Debug(string s)
        {
            this.LogLine("DEBUG", s);
        }

        public void Trace(string s)
        {
            this.LogLine("TRACE", s);
        }

        public void Error(string s)
        {
            this.LogLine("ERROR", s);
        } 

        public void Fatal(string s)
        {
            this.LogLine("FATAL", s);
        } 

        private void LogLine(string level, string s)
        {
            var line = $"{DateTime.Now.ToString("yyyyMMdd - HH:mm:ss.fff")} {level} - {s}";
            this.helper.WriteLine(line);
        }
    }
}
<file_sep>/iDareUI/Common/DataLocation.cs
﻿using System;
using System.Collections.Generic;
using System.IO;

namespace iDareUI.Common
{
    public static class DataLocation
    {
        public static string GetProblemReportsDirectory(List<string> fileNamesList)
        {

            string fileNameConcat = GetProblemReportFilePath(fileNamesList[0]);
            fileNamesList.RemoveAt(0);

            foreach (string name in fileNamesList)
            {
                string nextFileName = GetProblemReportFilePath(name);
                fileNameConcat = fileNameConcat + "\r\n" + nextFileName;
            }
            return fileNameConcat;
        }

        public static string GetProblemReportFilePath(string fileName)
        {
            string filePath = Path.GetDirectoryName(typeof(DataLocation).Assembly.Location) + "\\TestData\\ProblemReport\\" + fileName;
            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException("Could not find the path: " + filePath);
            }
            return filePath;
        }
    }
}
<file_sep>/iDareUI/Common/WindowsApi.cs
﻿using System;
using System.Runtime.InteropServices;

namespace iDareUI.Common
{
    public static class WindowsApi
    {
        [DllImport("user32.dll", EntryPoint = "FindWindow")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetForegroundWindow(IntPtr hWnd);
    }
}
<file_sep>/iDareUI/PageInteractions/CaseUpdatePage.cs
﻿using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using System.Collections.Generic;
using System.Linq;
using Xunit;

namespace iDareUI.PageInteractions
{
    class CaseUpdatePage
    {
        private readonly RemoteWebDriver driver;
        public CaseUpdatePage(RemoteWebDriver driver)
        {
            this.driver = driver;
        }

        private IWebElement editCaseButton => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseListComponentEditCaseButton']"));
        private IList<IWebElement> fileUploadedRow => driver.FindElements(By.XPath("//*[@attr.data-idare-id='CaseFileListTableHeaderRows']"));

        public void OpenCaseUpdate() { editCaseButton.Click(); }
        public IEnumerable<string> GetFileUploadedNameListText()
        {
            var filesUploadedText = this.GetFileUploadedNameList();
            return filesUploadedText.Select(element => element.Text);
        }
        public IList<IWebElement> GetFileUploadedNameList()
        {
            IList<IWebElement> allFilesUploaded = driver.FindElements(By.XPath("//*[@attr.data-idare-id='CaseFileListTableHeaderRows']"));
            return allFilesUploaded;
        }

        public string GetFileUploadedStatus (string fileName)
        {
            string status = null;
            foreach (IWebElement row in fileUploadedRow)
            {
                if (row.Text.Contains(fileName))
                {
                    IWebElement currentStatusFileUploaded = row.FindElement(By.XPath("//*[@attr.data-idare-id='CaseFileListTableStatus']"));
                    status = currentStatusFileUploaded.Text;
                }
            }
            Assert.NotNull(status);
            return status;
        }
        public void PressFileUploadedDeleteButton(string fileName)
        {
            IWebElement deleteButton = null;
            foreach (IWebElement row in fileUploadedRow)
            {
                if (row.Text.Contains(fileName))
                {
                    deleteButton = row.FindElement(By.XPath("//*[@attr.data-idare-id='CaseFileListTableDeleteButton']"));
                }
            }
            Assert.NotNull(deleteButton);
            deleteButton.Click();
        }
    }
}
<file_sep>/iDareUI/PageInteractions/CasesMainPage.cs
﻿using iDareUI.Common;
using iDareUI.Models;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Xunit;
using static iDareUI.CasesOverviewSteps;

namespace iDareUI.PageInteractions
{
    public class CaseMainPage
    {
        private RemoteWebDriver driver;
        public CaseMainPage(RemoteWebDriver driver)
        {
            this.driver = driver;
        }

        private IWebElement userLabel => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IDareUserInfoUserName']"));
        private IWebElement newCaseButton => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseListComponentAddCaseButton']"));
        private IWebElement rangeLabel => driver.FindElement(By.ClassName("mat-paginator-range-label"));
        private IWebElement firstIdRow => driver.FindElements(By.XPath("//*[@attr.data-idare-id='CaseListComponentCaseRow']"))[0];
        private IWebElement casesButton => driver.FindElements(By.CssSelector("span.prv-sidebar__title"))[0];

        private IWebElement caseEditFirstButton => driver.FindElements(By.XPath("//*[@attr.data-idare-id='CaseListComponentEditCaseIcon']"))[0];

        private IWebElement detailsButton => driver.FindElement(By.XPath("//*[@attr.data-idare-id='DetectedIssuesContainerViewButton']"));
        private IWebElement firstCaseSWVersion => driver.FindElement(By.XPath("/html/body/prv-root/prv-layout/prv-template/div/section[2]/mat-drawer-container/mat-drawer-content/prv-list-cases/div/div[2]/section/div[1]/mat-table/mat-row[1]/mat-cell[4]"));
        public IWebElement nextPageClickableButton => driver.FindElement(By.CssSelector("button.mat-paginator-navigation-next.mat-icon-button"));
        private IWebElement searchFilter => driver.FindElement(By.XPath("/html/body/prv-root/prv-layout/prv-template/div/section[2]/mat-drawer-container/mat-drawer-content/prv-case-detected-issue/div/div[1]/div/mat-form-field/div/div[1]/div/input"));
        private IEnumerable<IWebElement> caseRows => driver.FindElements(By.XPath("//*[@attr.data-idare-id='CaseListComponentCaseRow']"));

        public string[] caseCreationValues = new string[] { "CAS-0123", "1234", "Spain", "Customer" };

        private IWebElement searchButton => driver.FindElements(By.CssSelector("button.mat-icon-button"))[1];

        public IEnumerable<string> GetGridHeaderNames()
        {
            var headers = this.GetGridHeaderElements();
            return headers.Select(element => element.Text);
        }

        public IList<IWebElement> GetGridHeaderElements()
        {
            IList<IWebElement> allHeaders = driver.FindElements(By.CssSelector("button.mat-sort-header-button"));
            return allHeaders;
        }
        public IList<IWebElement> GetRowsElements()
        {
            IList<IWebElement> rows = driver.FindElements(By.XPath("//*[@attr.data-idare-id='CaseListComponentCaseRow']"));
            return rows;
        }
        public IEnumerable<Case> GetRowsElementsCases()
        {
            var ret = new List<Case>();
            var rows = this.GetRowsElements();

            foreach (var row in rows)
            {
                IWebElement rowCaseID = row.FindElement(By.CssSelector("td.mat-cell.cdk-cell.cdk-column-caseReference.mat-column-caseReference.ng-star-inserted"));
                IWebElement rowSerialNo = row.FindElement(By.CssSelector("td.mat-cell.cdk-cell.cdk-column-serialNumber.mat-column-serialNumber.ng-star-inserted"));
                IWebElement rowCustomer = row.FindElement(By.CssSelector("td.mat-cell.cdk-cell.cdk-column-customer.mat-column-customer.ng-star-inserted"));
                IWebElement rowCountry = row.FindElement(By.CssSelector("td.mat-cell.cdk-cell.cdk-column-country.mat-column-country.ng-star-inserted"));
                IWebElement rowSWV = row.FindElement(By.CssSelector("td.mat-cell.cdk-cell.cdk-column-softwareVersion.mat-column-softwareVersion.ng-star-inserted"));

                var myCase = new Case();
                myCase.CaseID = rowCaseID.Text;
                myCase.SerialNo = rowSerialNo.Text;
                myCase.Customer = rowCustomer.Text;
                myCase.Country = rowCountry.Text;
                myCase.SWVersion = rowSWV.Text;

                ret.Add(myCase);
            }
            return ret;
        }

        public IList<IWebElement> GetRowsIds()
        {
            IList<IWebElement> caseIds = driver.FindElements(By.XPath("//*[@attr.data-idare-id='CaseListComponentCaseIDValue']"));
            return caseIds;
        }

        public IEnumerable<DateTime> GetCreationDateTime()
        {
            var dateTimes = this.GetCreationTimeText();
            return dateTimes.Select(element => DateTime.ParseExact(element, "dd-MM-yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture));
        }

        public IEnumerable<DateTime> GetSortedDates()
        {
            return this.GetCreationDateTime().OrderByDescending(element => element.Ticks);
        }

        public IEnumerable<string> GetCreationTimeText()
        {
            var dateTimesText = this.GetCreationTimeElements();
            return dateTimesText.Select(element => element.Text);
        }

        public IList<IWebElement> GetCreationTimeElements()
        {
            IList<IWebElement> allCreationTimeElements =
                driver.FindElements(By.CssSelector("mat-cell.cdk-column-creation-time.mat-column-creation-time.ng-star-inserted")).ToList();
            return allCreationTimeElements;
        }

        public string UserRole => userLabel.Text;
        public string RangeLabelText => rangeLabel.Text;
        public string firstIdRowText => firstIdRow.Text;
        public string firstCaseSWVersionText => firstCaseSWVersion.Text;

        public void PressNextPageButton()
        {
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
            IWebElement nextPageClickableButton = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(By.CssSelector("button.mat-paginator-navigation-next.mat-icon-button")));
            nextPageClickableButton.Click();
        }
        public void PressPreviousPageButton()
        {
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
            IWebElement previousPageClickableButton = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(By.CssSelector("button.mat-paginator-navigation-previous.mat-icon-button.mat-button-base")));
            previousPageClickableButton.Click();
        }

        public void PressFirstCaseEditButton()
        {
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
            this.caseEditFirstButton.Click();
        }

        public void NewCase()
        {
            newCaseButton.Click();
        }
        public void PressCasesButton()
        {
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
            IWebElement nextPageClickableButton = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(By.CssSelector("span.prv-sidebar__title")));
            casesButton.Click();
        }

        public void PressDetailsButton()
        {
            detailsButton.Click();
        }

        public void SearchFilterCases(string value)
        {
            searchFilter.Click();
            searchFilter.SendKeys(value);
        }
        public void PressEnterToFilter()
        {
            searchFilter.SendKeys(Keys.Enter);
        }

        internal void WaitUntilRangeLabelChanges()
        {
            FlowUtilities.WaitUntil(() => RangeLabelText.StartsWith("1 -"), TimeSpan.FromSeconds(10), TimeSpan.FromMilliseconds(100));
        }
        public void WaitUntilCasesAreUpdated(string caseId, string fieldUpdated)
        {
            FlowUtilities.WaitUntil(
                () =>
                {
                    try
                    {
                        var caseRows = GetRowsElements();
                        var ret = caseRows.Where(row => row.Text.Contains(caseId));
                        return ret.Any(row => row.Text.Contains(fieldUpdated));
                    }
                    catch
                    {
                        return false;
                    }
                }, TimeSpan.FromSeconds(2000), TimeSpan.FromMilliseconds(25));
        }

        public bool SelectCases(Case caseCreatedForSearch, CaseSearchProperty property)
        {
            Thread.Sleep(TimeSpan.FromSeconds(5));
            var ret = GetRowsElementsCases();
            string caseProperty = null;
            bool value = false;

            switch (property)
            {
                case CaseSearchProperty.CaseId:
                    caseProperty = caseCreatedForSearch.CaseID;
                    value = ret.All(myCase => myCase.CaseID.Contains(caseProperty));
                    break;
                case CaseSearchProperty.Country:
                    caseProperty = caseCreatedForSearch.Country;
                    value = ret.All(myCase => myCase.Country.Contains(caseProperty));
                    break;
                case CaseSearchProperty.Customer:
                    caseProperty = caseCreatedForSearch.Customer;
                    value = ret.All(myCase => myCase.Customer.Contains(caseProperty));
                    break;
                case CaseSearchProperty.SerialNumber:
                    caseProperty = caseCreatedForSearch.SerialNo;
                    value = ret.All(myCase => myCase.SerialNo.Contains(caseProperty));
                    break;
                default:
                    throw new InvalidOperationException("The search property is wrong.");
            }
            return value;
        }

        public int ReadPageLabel()
        {
            int numberOfCases = -1;
            var response = FlowUtilities.WaitUntilWithoutException(
                () =>
                {
                    IWebElement componentPaginator = driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseListComponentPaginator']"));
                    IWebElement inside1 = componentPaginator.FindElement(By.CssSelector("div.mat-paginator-range-label"));
                    string rangeLabel = inside1.Text;

                    int start = rangeLabel.LastIndexOf(" ");
                    if (start < 0)
                    {
                        return false;
                    }
                    string labelCut = rangeLabel.Substring(start);
                    numberOfCases = Int32.Parse(labelCut);
                    return numberOfCases > 0;
                }, TimeSpan.FromSeconds(5), TimeSpan.FromMilliseconds(25));

            Assert.True(response.Success, response.ToString());

            return numberOfCases;
        }

        public void AssertThatNoProgressBarIsShown()
        {
            //dont want a progress bar - if one appears we fail - so a timeout is good
            var response = FlowUtilities.WaitUntil(() => driver.FindElements(By.XPath("//*[@attr.data-idare-id='CaseUploadFileProgressBar']")).Count >= 1,
                TimeSpan.FromSeconds(5), TimeSpan.FromMilliseconds(100));

            Assert.True(response.TimedOut);
        }

        public void WaitUntilProgressBarIsShown(int numberOfUploads)
        {
            for (int i = 0; i < numberOfUploads; i++)
            {
                FlowUtilities.WaitUntil(
                    () => driver.FindElements(By.XPath("//*[@attr.data-idare-id='CaseUploadFileProgressBar']")).Count == numberOfUploads,
                    TimeSpan.FromSeconds(5), TimeSpan.FromMilliseconds(100));
            }
        }
        public void AssertThatAllProgressBarsAreRemoved()
        {
            bool elementHasDisappeared = false;

            var response = FlowUtilities.WaitUntil(() =>
            {
                elementHasDisappeared = !InteractionUtilities.IsVisible("CaseUploadFileProgressBar", this.driver);
                return elementHasDisappeared;
            },
                TimeSpan.FromSeconds(300), TimeSpan.FromMilliseconds(500));

            Assert.True(response.Success, "The progress bars were not removed at the end of the upload");
        }
        
        public void WaitUntilProgressBarShowsUpdatedStatusSuccess(int maxWaitSeconds)
        {
            FlowUtilities.WaitUntil(() =>
            {
                return driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseUploadFileSuccess']")) != null;
            }, TimeSpan.FromSeconds(maxWaitSeconds), TimeSpan.FromMilliseconds(100));
        }

        public void WaitUntilProgressBarShowsUpdatedStatusError(int maxWaitSeconds)
        {
            FlowUtilities.WaitUntil(() =>
            {
                return driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseUploadFileError']")) != null;
            }, TimeSpan.FromSeconds(maxWaitSeconds), TimeSpan.FromMilliseconds(100));
        }
    }
}
<file_sep>/iDareUI/Models/Case.cs
﻿using System;

namespace iDareUI.Models
{
    public class Case
    {
        public string CaseID {get;set;}
        public string System {get;set;}
        public string SerialNo {get;set;}
        public string SWVersion {get;set;}
        public string Created {get;set;}
        public string Customer {get;set;}
        public string Country { get; set;}
        public string CreatedBy { get; set;}
        public string Issues { get; set;}

        public static Case GetRandomCase()
        {
            return new Case()
            { 
                CaseID = Guid.NewGuid().ToString(),
                SerialNo = Guid.NewGuid().ToString(),
                Customer = Guid.NewGuid().ToString(),
                Country = Guid.NewGuid().ToString(),
            };
        }
    }
}
<file_sep>/iDareUI/PageInteractions/IssuesRulesPage.cs
﻿using System;
using System.Collections.Generic;
using iDareUI.Models;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;

namespace iDareUI.PageInteractions
{
    public class IssuesRulesPage
    {
        
        private RemoteWebDriver driver;
        public IssuesRulesPage(RemoteWebDriver driver)
        {
            this.driver = driver;
        }

        

        private IWebElement newIssueButton => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueRuleContainerActionsButton']"));
        private IWebElement newIssueButtonIcon => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueRuleContainerActionsIcon']"));

        private IWebElement issueListContainer => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueRuleContainerList']"));
        private IWebElement supportedIssuesList => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesList']"));
        private IWebElement supportedIssuesListFilter => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListFilter']"));
        private IWebElement supportedIssuesListFilterInput => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListFilterValue']"));
        private IWebElement supportedIssuesListTable => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListTable']"));
        private IWebElement supportedIssuesListPaginator => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListPaginator']"));

        private IWebElement supportedIssuesListHeaderRow => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListHeaderRow']"));
        private IWebElement supportedIssuesListRuleInWorkHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListRuleInWorkHeader']"));
        private IWebElement supportedIssuesListTitleHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListTitleHeader']"));
        private IWebElement supportedIssuesListCategoryHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListCategoryHeader']"));
        private IWebElement supportedIssuesListSystemHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListSystemHeader']"));
        private IWebElement supportedIssuesListFootprintsHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListFootprintsHeader']"));
        private IWebElement supportedIssuesListModifiedByHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListModifiedByHeader']"));
        private IWebElement supportedIssuesListModifiedHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListModifiedHeader']"));
        private IWebElement supportedIssuesListEditHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListEditHeader']"));

        private IList<IWebElement> supportedIssuesListCellRows => driver.FindElements(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListCellRows']"));
        private IList<IWebElement> supportedIssuesListRuleInWorkCells => driver.FindElements(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListRuleInWorkCell']"));
        private IList<IWebElement> supportedIssuesListTitleCells => driver.FindElements(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListTitleCell']"));
        private IList<IWebElement> supportedIssuesListCategoryCells => driver.FindElements(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListCategoryCell']"));
        private IList<IWebElement> supportedIssuesListSystemCells => driver.FindElements(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListSystemCell']"));
        private IList<IWebElement> supportedIssuesListFootprintsCells => driver.FindElements(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListFootprintsCell']"));
        private IList<IWebElement> supportedIssuesListModifiedByCells => driver.FindElements(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListModifiedByCell']"));
        private IList<IWebElement> supportedIssuesListModifiedCells => driver.FindElements(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListModifiedCell']"));
        private IList<IWebElement> supportedIssuesListEditCells => driver.FindElements(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListEditCell']"));
        private IList<IWebElement> supportedIssuesListEditCellButtons => driver.FindElements(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListEditCellButton']"));
        private IList<IWebElement> supportedIssuesListEditCellIcons => driver.FindElements(By.XPath("//*[@attr.data-idare-id='SupportedIssuesListEditCellIcon']"));

        public bool NewIssue()
        {

            var NewIssueButtonLoaded = true;
            NewIssueButtonLoaded = this.newIssueButton != null && NewIssueButtonLoaded;
            NewIssueButtonLoaded = this.newIssueButtonIcon != null && NewIssueButtonLoaded;

            newIssueButton.Click();

            return NewIssueButtonLoaded;
        }

        public bool IssueListIsLoaded()
        {
            var IssueListElementsLoaded = true;

            IssueListElementsLoaded = this.issueListContainer != null && IssueListElementsLoaded;
            IssueListElementsLoaded = this.supportedIssuesList != null && IssueListElementsLoaded;
            IssueListElementsLoaded = this.supportedIssuesListFilter != null && IssueListElementsLoaded;
            IssueListElementsLoaded = this.supportedIssuesListFilterInput != null && IssueListElementsLoaded;
            IssueListElementsLoaded = this.supportedIssuesListTable != null && IssueListElementsLoaded;
            IssueListElementsLoaded = this.supportedIssuesListPaginator != null && IssueListElementsLoaded;
            return IssueListElementsLoaded;
        }

        public bool IssueListTableHeaderIsCorrect() {

            return supportedIssuesListHeaderRow != null &&
                supportedIssuesListRuleInWorkHeader != null &&
                supportedIssuesListTitleHeader != null &&
                supportedIssuesListCategoryHeader != null &&
                supportedIssuesListSystemHeader != null &&
                supportedIssuesListFootprintsHeader != null &&
                supportedIssuesListModifiedByHeader != null &&
                supportedIssuesListModifiedHeader != null &&
                supportedIssuesListEditHeader != null &&
                supportedIssuesListCellRows.Count > 0;

            
       }

        public bool IssueListTableIsPopulatedWithAtLeastOneRow()
        {

            return supportedIssuesListRuleInWorkCells.Count > 0 &&
                supportedIssuesListTitleCells.Count > 0 &&
                supportedIssuesListCategoryCells.Count > 0 &&
                supportedIssuesListSystemCells.Count > 0 &&
                supportedIssuesListFootprintsCells.Count > 0 &&
                supportedIssuesListModifiedByCells.Count > 0 &&
                supportedIssuesListEditCells.Count > 0 && 
                supportedIssuesListModifiedCells.Count > 0;



        }

        public bool IssueIsAddedOnTopOfTheList(IssueRow issueRow) {
            return supportedIssuesListTitleCells[0].Text == issueRow.Title &&
                supportedIssuesListCategoryCells[0].Text == issueRow.Category &&
                supportedIssuesListSystemCells[0].Text == issueRow.System &&
                supportedIssuesListFootprintsCells[0].Text == issueRow.Footprints &&
                supportedIssuesListModifiedByCells[0].Text == issueRow.ModifiedBy;

        }

        public bool IssueEditButtonIsCorrect(int index) {

            return supportedIssuesListEditCells[index] != null &&
                supportedIssuesListEditCellButtons[index] != null &&
                supportedIssuesListEditCellButtons[index].TagName == "button" &&
                supportedIssuesListEditCellIcons[index] != null;
        }

        public int numberOfIssuesInTheList() {
            return supportedIssuesListCellRows.Count;
        }
    }


}
<file_sep>/iDareUI/CaseCreationSteps.cs
﻿using iDareUI.Common;
using System;
using System.Collections.Generic;
using System.Threading;
using iDareUI.Models;
using iDareUI.PageInteractions;
using TechTalk.SpecFlow;
using Xunit;

namespace iDareUI
{
    [Binding]
    public class CaseCreationSteps
    {
        private TestingEnvironment environment;
        private CaseMainPage mainCasesPage;
        private CaseCreationPage caseCreationPage;
        private FeatureContext featureContext;

        private string rexisId;

        public CaseCreationSteps(TestingEnvironment environment, FeatureContext featureContext)
        {
            this.environment = environment;
            this.mainCasesPage = new CaseMainPage(environment.Driver);
            this.caseCreationPage = new CaseCreationPage(environment.Driver);
            this.featureContext = featureContext;
        }

        [Given(@"I navigate to the next case page")]
        public void GivenINavigateToTheNextCasePage()
        {
            mainCasesPage.PressNextPageButton();
        }

        [Given(@"I enter to create a new case")]
        public void GivenIEnterToCreateANewCase()
        {
            mainCasesPage.NewCase();
            Assert.True(caseCreationPage.CaseCreationDialog.Displayed, "The dialog to create a new case was not displayed");
        }

        [When(@"I enter a Rexis ID with a unique ID")]
        public void WhenIEnterARexisIDWithAUniqueID()
        {
            rexisId = caseCreationPage.SetUniqueRexisId();
        }

        [When(@"I enter (.*) as Rexis ID")]
        public void WhenIEnterAsRexisID(string value)
        {
            caseCreationPage.SetRexisId(value);
        }
        [When(@"I enter (.*) as Serial number")]
        public void WhenIEnterAsSerialNumber(string value)
        {
            caseCreationPage.SetSerialNo(value);
        }

        [When(@"I enter (.*) as Customer")]
        public void WhenIEnterAsCustomer(string value)
        {
            caseCreationPage.SetCustomer(value);
        }

        [When(@"I enter (.*) as Country")]
        public void WhenIEnterAsCountry(string value)
        {
            caseCreationPage.SetCountry(value);
        }

        [When(@"I enter the option (.*) of the dropdown as Timezone")]
        public void WhenIEnterTheOptionOfTheDropdownAsTimezone(int optionNumber)
        {
            caseCreationPage.SelectOptionInTimezoneDropdown(optionNumber);
        }

        [When(@"I leave the ID field empty")]
        public void WhenILeaveTheIDFieldEmpty()
        {
            caseCreationPage.SetRexisId("");
        }
       
        [Then(@"The files list shows the files I have added (.*)")]
        public void ThenTheFilesListShowsTheFilesIHaveAdded(List<string> fileNameList)
        {
            foreach (var fileName in fileNameList)
            {
                caseCreationPage.AssertFileUploadListFileIsDisplayed(fileName);
            }
        }

        [When(@"I upload a Problem Report with name (.*)")]
        public void WhenIUploadAProblemReportWithName(List<string> fileNameList)
        {
            List<string> uploadingFilesList = fileNameList;
            string filePath = DataLocation.GetProblemReportsDirectory(fileNameList);
            caseCreationPage.SimulateFileUploading(filePath);
            foreach (string fileName in uploadingFilesList)
            {
                caseCreationPage.AssertFileUploadListFileIsDisplayed(fileName);
            }
        }

        [Then(@"The case creation dialog is closed")]
        public void ThenTheCaseCreationDialogIsClosed()
        {
            var response =
                FlowUtilities.WaitUntil(() => !InteractionUtilities.IsVisible("CaseDialog", this.environment.Driver),
                    TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(1));
            Assert.True(response.Success, "The case creation page should not be displayed.");
        }

        [When(@"I press the Save button")]
        public void WhenIPressTheSaveButton()
        {
            caseCreationPage.PressSaveButton();
        }

        [When(@"I enter the RexisId in the filter")]
        public void ThenIEnterTheRexisIdInTheFilter()
        {
            mainCasesPage.SearchFilterCases(this.rexisId);
            mainCasesPage.PressEnterToFilter();
            //Not nice - but need to wait for the results to be updated.
            Thread.Sleep(1000);
        }

        [Then(@"The case is displayed in the list with the RexisId")]
        public void ThenTheCaseIsDisplayedInTheListWithTheRexisId()
        {
            mainCasesPage.SelectCases(new Case { CaseID = rexisId}, CasesOverviewSteps.CaseSearchProperty.CaseId);
        }

        [Then(@"I click the edit case button for the first case")]
        public void ThenIClickTheEditCaseButtonForTheFirstCase()
        {
            mainCasesPage.PressFirstCaseEditButton();
        }

        [When(@"I press the Cancel button")]
        public void WhenIPressTheCancelButton()
        {
            caseCreationPage.PressCancelButton();
        }

        [Then(@"the Save button is disabled")]
        public void ThenTheSaveButtonIsDisabled()
        {
            Assert.False(caseCreationPage.SaveButton.Enabled, "The Save button is enabled");
        }

        [Then(@"the first page of the cases overview is shown")]
        public void ThenTheFirstPageOfTheCasesOverviewIsShown()
        {
            mainCasesPage.PressPreviousPageButton();
            mainCasesPage.WaitUntilRangeLabelChanges();
            Assert.StartsWith("1 -", mainCasesPage.RangeLabelText);
        }

        [Then(@"the case with the unique ID as Rexis ID is on the top of the list")]
        public void ThenTheCaseWithTheUniqueIdAsRexisIDIsOnTheTopOfTheList()
        {
            var response = FlowUtilities.WaitUntil(() => mainCasesPage.firstIdRowText.Contains(rexisId), 
                TimeSpan.FromSeconds(10), TimeSpan.FromMilliseconds(100));

            Assert.True(response.Success, "The case is not displayed.");
        }

        [When(@"I create a new Case for details")]
        public void WhenICreateANewCaseForDetails()
        {
            Case caseDetails = Case.GetRandomCase();
            this.featureContext["caseDetails"] = caseDetails;
            this.GivenIEnterToCreateANewCase();
            this.WhenIEnterAsRexisID(caseDetails.CaseID);
            this.WhenIEnterTheOptionOfTheDropdownAsTimezone(2);
            List<string> fileName = new List<string>();
            fileName.Add(Constants.ProblemReportOnlySummary);
            this.WhenIUploadAProblemReportWithName(fileName);
            this.WhenIPressTheSaveButton();
        }

        [Given(@"there are at least (.*) cases created")]
        public void ThereAreAtLeastCasesCreated(int cases)
        {
            FlowUtilities.WaitUntil(() =>
            {
                if (!(mainCasesPage.ReadPageLabel() > cases))
                {
                    this.GivenICreateANewCaseWithoutProblemReport();
                }
                return mainCasesPage.ReadPageLabel() > cases;
            }, TimeSpan.FromSeconds(10), TimeSpan.FromMilliseconds(100));
        }
        [Given(@"I create a new case without problem report")]
        public void GivenICreateANewCaseWithoutProblemReport()
        {
            this.GivenIEnterToCreateANewCase();
            this.WhenIEnterARexisIDWithAUniqueID();
            this.WhenIEnterAsSerialNumber("12345");
            this.WhenIEnterAsCountry("Spain");
            this.WhenIEnterAsCustomer("Customer");
            this.WhenIEnterTheOptionOfTheDropdownAsTimezone(2);
            this.WhenIPressTheSaveButton();
        }

        [Then(@"I should see the progress of the (.*) uploads")]
        public void ThenIShouldSeeTheProgressOfTheUpload(int numberOfUploads)
        {
            mainCasesPage.WaitUntilProgressBarIsShown(numberOfUploads);
        }

        [Then(@"The progress of the uploads should disappear")]
        public void ThenTheProgressOfTheUploadsShouldDisappear()
        {
            mainCasesPage.AssertThatAllProgressBarsAreRemoved();
        }

        [Then(@"I should not see any upload progress bars")]
        public void ThenIShouldNotSeeAnyProgressBars()
        {
            mainCasesPage.AssertThatNoProgressBarIsShown();
        }

        [Then(@"the status gets updated as successful")]
        public void ThenTheStatusGetsUpdatedAsSuccessful()
        {
            FlowUtilities.WaitUntil(() => rexisId.Contains(mainCasesPage.firstIdRowText), TimeSpan.FromSeconds(10), TimeSpan.FromMilliseconds(100));
        }

        [Then(@"the status gets updated as error")]
        public void ThenTheStatusGetsUpdatedAsError()
        {
            mainCasesPage.WaitUntilProgressBarShowsUpdatedStatusError(300);
        }

        [Then(@"I remove a file (.*)")]
        public void ThenIRemoveAFile(string fileName)
        {
            caseCreationPage.PressFirstFileSelectComponentDeleteButton();
            caseCreationPage.AssertFileUploadListFileIsRemoved(fileName);
        }

        [Then(@"The Progress Shows Updated Status Success")]
        public void ThenTheProgressShowsUpdatedStatusSuccess()
        {
            mainCasesPage.WaitUntilProgressBarShowsUpdatedStatusSuccess(10);
        }


    }
}
<file_sep>/iDareUI/Common/Constants.cs
﻿using System;

namespace iDareUI.Common
{
    public class Constants
    {
        private const string pageUri = @"https://idare-qa-webapp.azurewebsites.net/cases";
        public static string PageUri
        {
            get
            {
                var environmentUrl = Environment.GetEnvironmentVariable("testUrl", EnvironmentVariableTarget.Process);
                if(environmentUrl != null && environmentUrl.Length != 0)
                {
                    return environmentUrl;
                }

                return pageUri;
            }
        }

        private const string pageTeachingUri = @"https://idare-qa-teaching-webapp.azurewebsites.net";
        public static string PageTeachingUri
        {
            get
            {
                return pageTeachingUri;
            }
        }

        public const string TeacherUserName = "teacher";
        public const string TeacherPassword = "<PASSWORD>";

        public const string InvestigatorName = "investigator";
        public const string InvestigatorPassword = "<PASSWORD>";

        public const string ProblemReportOnlySummary = "ProblemReport_OnlySummary.zip";
    }
}
<file_sep>/iDareUI/IssueCreationSteps.cs
﻿using iDareUI.Common;
using iDareUI.Models;
using System;
using System.Collections.Generic;
using iDareUI.PageInteractions;
using TechTalk.SpecFlow;
using TechTalk.SpecFlow.Assist;
using Xunit;

namespace iDareUI
{
    [Binding]
    public class IssueCreationSteps
    {
        private TestingEnvironment environment;
        private TeachingMainPage mainTeachingPage;
        private IssueCreationPage issueCreationPage;

        public IssueCreationSteps(TestingEnvironment environment)
        {
            this.environment = environment;
            this.mainTeachingPage = new TeachingMainPage(environment.Driver);
            this.issueCreationPage = new IssueCreationPage(environment.Driver);
        }

        [Given(@"I navigate successfully to the teaching module")]
        public void GivenINavigateSuccessfullyToTheTeachingModule()
        {
            environment.Driver.Manage().Window.Maximize();
            mainTeachingPage.NavigateToTeachingModule();
        }
        
        [Given(@"I am in the issue list in teaching module")]
        public void GivenIAmInTheIssueListInTeachingModule()
        {
            Assert.True(mainTeachingPage.issuesRulesPage.IssueListIsLoaded());
            Assert.True(mainTeachingPage.issuesRulesPage.IssueListTableHeaderIsCorrect());
            Assert.True(mainTeachingPage.issuesRulesPage.IssueListTableIsPopulatedWithAtLeastOneRow());
        }

        [Given(@"I am logged in as teacher user")]
        public void IAmLoggedInAsTeacherUser()
        {
            Assert.True(mainTeachingPage.userIsLoggedInAs("Teacher", "DebugUser"));
            
        }

        [Given(@"I click add issue button")]
        public void GivenIClickAddIssueButton()
        {
            Assert.True(this.mainTeachingPage.issuesRulesPage.NewIssue());
           
        }
        
        [Given(@"Issue Dialog is open")]
        public void GivenIssueDialogIsOpen()
        {
            Assert.True(this.issueCreationPage.NewIssueDialogIsOpen());
        }
        
        [Given(@"I enter the following fields")]
        public void GivenIEnterTheFollowingFields(Table table)
        {
            var issueFormFields = table.CreateInstance<IssueForm>();

            issueCreationPage.issueFormPage.populateIssueForm(issueFormFields);

            Assert.True(issueCreationPage.issueFormPage.validateIssueFormFields(issueFormFields));
        }
        
        [When(@"I enter '(.*)' as Category")]
        public void WhenIEnterAsCategory(string category)
        {
            issueCreationPage.issueFormPage.SetCategory(category);
      
            Assert.True(issueCreationPage.issueFormPage.validateIssueCategoryField(category));
        }
        
        [When(@"I enter '(.*)' as System")]
        public void WhenIEnterAsSystem(string system)
        {
            issueCreationPage.issueFormPage.SetSystem(system);

            Assert.True(issueCreationPage.issueFormPage.validateIssueSystemField(system));
        }
        
        
        [When(@"I enter '(.*)' as Title")]
        public void WhenIEnterAsTitle(string title)
        {
            issueCreationPage.issueFormPage.SetTitle(title);

            Assert.True(issueCreationPage.issueFormPage.validateIssueTitleField(title));
        }
        
        [When(@"I click save button is enabled")]
        public void WhenIClickSaveButtonIsEnabled()
        {
            Assert.True(issueCreationPage.SaveIssueButtonIsEnabled());
            issueCreationPage.SaveNewIssue();

        }
        
        [Then(@"the save button must be disabled")]
        public void ThenTheSaveButtonMustBeDisabled()
        {
            Assert.True(issueCreationPage.SaveIssueButtonIsDisabled());
        }
        
        [Then(@"the save button must be enabled")]
        public void ThenTheSaveButtonMustBeEnabled()
        {
            Assert.True(issueCreationPage.SaveIssueButtonIsEnabled());
        }
        
        [Then(@"the issue list is updated successfully and includes the new created issue")]
        public void ThenTheIssueListIsUpdatedSuccessfullyAndIncludesTheNewCreatedIssue(Table table)
        {
            var issueRowFields = table.CreateInstance<IssueRow>();

            Assert.True(mainTeachingPage.issuesRulesPage.IssueListIsLoaded());
            Assert.True(mainTeachingPage.issuesRulesPage.IssueListTableHeaderIsCorrect());
            Assert.True(mainTeachingPage.issuesRulesPage.IssueListTableIsPopulatedWithAtLeastOneRow());
            Assert.True(mainTeachingPage.issuesRulesPage.IssueIsAddedOnTopOfTheList(issueRowFields));
        }
        
        [Then(@"the first issue edit button must be the last cell with the defined icon")]
        public void ThenTheFirstIssueEditButtonMustBeTheLastCellWithTheDefinedIcon()
        {
            Assert.True(mainTeachingPage.issuesRulesPage.IssueEditButtonIsCorrect(0));
        }

        [Then(@"I cancel the issue creation and no new issue is created in the list")]
        public void ICancelTheIssueCreationAndNoNewIssueIsCreatedInTheList()
        {
            var issueListTotal = mainTeachingPage.issuesRulesPage.numberOfIssuesInTheList();

            issueCreationPage.CancelNewIssue();

            Assert.Equal(issueListTotal, mainTeachingPage.issuesRulesPage.numberOfIssuesInTheList());
        }
    }
}
<file_sep>/iDareUI/TestData/CustomConversions.cs
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TechTalk.SpecFlow;

namespace iDareUI.TestData
{
    [Binding]
    class CustomConversions
    {
        [StepArgumentTransformation]
        [Scope(Tag = "FileUploadingCases")]
        public List<string> GetFileNameList(string fileNameDelimited)
        {
            List<string> fileNameList = new List<string>();
            if (!fileNameDelimited.Contains(','))
            {
                fileNameList.Add(fileNameDelimited);
                return fileNameList;
            }
            else
            {
                var fileNames = fileNameDelimited.Split(",", StringSplitOptions.RemoveEmptyEntries);
                for (var index = 0; index < fileNames.Length; index++)
                {
                    fileNames[index] = fileNames[index].Trim();
                }
                return fileNames.ToList();
            }
        }
    }
}
<file_sep>/iDareUI/Models/IssueForm.cs
﻿using System;
namespace iDareUI.Models
{
    public class IssueForm
    {
        public IssueForm()
        {
        }

        public string Title { get; set; }
        public string Description { get; set; }
        public string ObservedInInstrument { get; set; }
        public string System { get; set; }
        public string Category { get; set; }
        public string ExcludedSoftwareVersions { get; set; }
    }
}
<file_sep>/iDareUI/Common/DisposeDriverService.cs
﻿using System;
using System.Diagnostics;

namespace iDareUI.Common
{
    public static class DisposeDriverService
    {
        public static void KillChromeDriver(DateTime testRunStartTime)
        {
            Process[] chromeDriverProcesses = Process.GetProcessesByName("chromedriver");

            foreach (var chromeDriverProcess in chromeDriverProcesses)
            {
                if (chromeDriverProcess.StartTime < testRunStartTime)
                {
                    chromeDriverProcess.Kill();
                }
            }
        }
    }
}
<file_sep>/iDareUI/Common/Ilog.cs
namespace iDareUI.Common
{
    public interface ILog
    {
        void Info(string s);
        void Debug(string s);
        void Trace(string s);
        void Error(string s);
        void Fatal(string s);
    }
}
<file_sep>/iDareUI/PageInteractions/IssueCreationPage.cs
﻿using System;
using System.Collections.Generic;
using iDareUI.Common;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Support.UI;

namespace iDareUI.PageInteractions
{
    public class IssueCreationPage
    {
        private IWebElement supportedIssuesNewContainer => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesNew']"));
        private IWebElement supportedIssuesNewHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesNewHeader']"));
        private IWebElement supportedIssuesNewHeaderTitle => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesNewHeaderTitle']"));
        private IWebElement supportedIssuesNewHeaderButton => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesNewHeaderButton']"));
        private IWebElement supportedIssuesNewHeaderIcon => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesNewHeaderIcon']"));
        private IWebElement supportedIssuesNewCancelButton => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesNewCancelButton']"));
        private IWebElement supportedIssuesNewSaveButton => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesNewSaveButton']"));
        private IWebElement supportedIssuesNewNote => driver.FindElement(By.XPath("//*[@attr.data-idare-id='SupportedIssuesNewNote']"));

        public IssueFormPage issueFormPage;


        private RemoteWebDriver driver;
        public IssueCreationPage(RemoteWebDriver driver)
        {
            this.driver = driver;
            this.issueFormPage = new IssueFormPage(driver);

        }

        public bool NewIssueDialogIsOpen()
        {
            var NewIssueDialogIsOpen = true;

            NewIssueDialogIsOpen = this.supportedIssuesNewContainer != null && NewIssueDialogIsOpen;
            NewIssueDialogIsOpen = this.supportedIssuesNewHeader != null && NewIssueDialogIsOpen;
            NewIssueDialogIsOpen = this.supportedIssuesNewHeaderTitle != null && NewIssueDialogIsOpen;
            NewIssueDialogIsOpen = this.supportedIssuesNewHeaderButton != null && NewIssueDialogIsOpen;
            NewIssueDialogIsOpen = this.supportedIssuesNewHeaderIcon != null && NewIssueDialogIsOpen;
            NewIssueDialogIsOpen = this.supportedIssuesNewCancelButton != null && NewIssueDialogIsOpen;
            NewIssueDialogIsOpen = this.supportedIssuesNewSaveButton != null && NewIssueDialogIsOpen;
            NewIssueDialogIsOpen = this.supportedIssuesNewNote != null && NewIssueDialogIsOpen;


            return NewIssueDialogIsOpen && this.issueFormPage.AreIssueFormElementsLoaded();
        }

        public bool SaveIssueButtonIsEnabled() {

            SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(supportedIssuesNewSaveButton);

            return supportedIssuesNewSaveButton.GetAttribute("disabled") == null;
        }

        public bool SaveIssueButtonIsDisabled()
        {
           
            return supportedIssuesNewSaveButton.GetAttribute("disabled") == "true";
        }

        public void SaveNewIssue()
        {

            supportedIssuesNewSaveButton.Click();
        }

        public void CancelNewIssue() {
            supportedIssuesNewCancelButton.Click();
        }
    }

    
}
<file_sep>/iDareUI/PageInteractions/CaseCreationPage.cs
﻿using System;
using System.Collections.Generic;
using System.Linq;
using iDareUI.Common;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using Xunit;

namespace iDareUI.PageInteractions
{
    public class CaseCreationPage
    {
        private readonly RemoteWebDriver driver;
        public CaseCreationPage(RemoteWebDriver driver)
        {
            this.driver = driver;
        }

        private IWebElement RexisId => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseComponentCaseIDInput']"));
        private IWebElement SerialNo => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseComponentSerialNoInput']"));
        private IWebElement Customer => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseComponentCustomerInput']"));
        private IWebElement Country => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseComponentCountryInput']"));
        private IWebElement CancelButton => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseComponentCancelButton']"));
        private IWebElement CloseButton => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseComponentCloseButton']"));
        private IWebElement CaseFilesUploadList => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseFilesToUploadList']"));
        private IWebElement FileUploadInput => driver.FindElement(By.XPath("//*[@attr.data-idare-id='FileUploadInput']"));
        public IWebElement SaveButton => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseComponentSaveButton']"));
        public IWebElement UploadFileButton => driver.FindElement(By.XPath("//*[@attr.data-idare-id='FileUploadSubmitButton']"));
        public IWebElement CaseFilesToUploadList => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseFilesToUploadList']"));
        public IWebElement TimezoneElement => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseComponentTimezoneLabel']")); 
        public IWebElement CaseCreationDialog => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseDialog']"));

        public IList<IWebElement> FileSelectComponentDeleteButtons =>
            driver.FindElements(By.XPath("//*[@attr.data-idare-id='FileSelectComponentDeleteIcon']")).ToList();

        public IList<IWebElement> GetTimezoneOptions()
        {
            IList<IWebElement> timezoneOptions = driver.FindElements(By.XPath("//*[@attr.data-idare-id='CaseComponentTimezoneOption']"));
            return timezoneOptions;
        }

        public void SetRexisId(string value)
        {
            InteractionUtilities.SendKeysCharByChar(RexisId, value);
        }
        public void SetSerialNo(string value) { SerialNo.SendKeys(value); }
        public void SetCustomer(string value) { Customer.SendKeys(value); }
        public void SetCountry(string value) { Country.SendKeys(value); }

        public string SetUniqueRexisId()
        {
            Guid guid = Guid.NewGuid();
            string unicId = guid.ToString();
            InteractionUtilities.SendKeysCharByChar(RexisId, unicId);
            return unicId;
        }
        
        public void PressCancelButton() { CancelButton.Click(); }
        public void PressSaveButton() { SaveButton.Click(); }
        public void PressUploadFileButton() { UploadFileButton.Click(); }
        public void SimulateFileUploading(string filePath)
        {
            IWebElement inputFile = this.FileUploadInput;
            inputFile.SendKeys(filePath);
        }
        public void AssertFileUploadListFileIsDisplayed(string fileName)
        {
            var response = FlowUtilities.WaitUntil(() =>
            {
                IWebElement caseFileUploaded = this.CaseFilesToUploadList;
                return caseFileUploaded.Text.Contains(fileName);
            }, TimeSpan.FromSeconds(60), TimeSpan.FromMilliseconds(100));
            
            Assert.True(response.Success, response.ToString());
        }

        public void AssertFileUploadListFileIsRemoved(string fileName)
        {
            var response = FlowUtilities.WaitUntil(() =>
            {
                IWebElement caseFileUploaded = this.CaseFilesToUploadList;
                return !caseFileUploaded.Text.Contains(fileName);
            }, TimeSpan.FromSeconds(60), TimeSpan.FromMilliseconds(100));

            Assert.True(response.Success, response.ToString());
        }

        public void SelectOptionInTimezoneDropdown(int optionIndex)
        {
            TimezoneElement.Click();
            TimezoneElement.SendKeys("U");
            var response = FlowUtilities.WaitUntil(() =>
            {
                var optionsLoaded = GetTimezoneOptions().Count >= optionIndex - 1;

                if (!optionsLoaded)
                {
                    TimezoneElement.Click();
                }

                return optionsLoaded;
            }, TimeSpan.FromSeconds(4), TimeSpan.FromMilliseconds(100));

            Assert.True(response.Success, response.ToString());

            IWebElement timezoneOption = GetTimezoneOptions().ToArray()[optionIndex - 1];
            timezoneOption.Click();
        }

        public void PressFirstFileSelectComponentDeleteButton()
        {
            FileSelectComponentDeleteButtons[0].Click();
        }

    }
}
<file_sep>/iDareUI/Common/WaitResponse.cs
﻿using System;
using System.Text;

namespace iDareUI.Common
{
    public class WaitResponse
    {
        public bool Success;
        public string Reason { get; set; }
        public bool TimedOut { get; set; }
        public Exception Exception { get; set; }
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            if (this.TimedOut)
                sb.Append("TimedOut=True");

            if (!string.IsNullOrEmpty(this.Reason))
                sb.Append($"Reason={this.Reason}");

            if (this.Exception != null)
                sb.Append($"Exception={this.Exception}");

            return sb.ToString();
        }
    }
}<file_sep>/iDareUI/KillChromeDriver.cs
﻿using iDareUI.Common;
using System;
using TechTalk.SpecFlow;

namespace iDareUI
{
    [Binding]
    public sealed class KillChromeDriver
    {
        [BeforeTestRun]
        public static void BeforeTestRun()
        {
            DisposeDriverService.KillChromeDriver(DateTime.Now);
        }
    }
}
<file_sep>/iDareUI/Models/IssueRow.cs
﻿using System;
namespace iDareUI.Models
{
    public class IssueRow
    {
        public bool RuleInWork { get; set; }
        public string Title { get; set; }
        public string Category { get; set; }
        public string System { get; set; }
        public string Footprints { get; set; }
        public string ModifiedBy { get; set; }
        public string Modified { get; set; }

        public IssueRow()
        {
        }
    }
}
<file_sep>/iDareUI/PageInteractions/IssueFormPage.cs
﻿using System;
using System.Collections.Generic;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using iDareUI.Models;
using OpenQA.Selenium.Support.UI;

namespace iDareUI.PageInteractions
{
    public class IssueFormPage
    {
        private RemoteWebDriver driver;
        public IssueFormPage(RemoteWebDriver driver)
        {
            this.driver = driver;
        }

        private IWebElement supportedIssueForm => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueForm']"));
        private IWebElement supportedIssueFormFieldTitle => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldTitle']"));
        private IWebElement supportedIssueFormFieldTitleLabel => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldTitleLable']"));
        private IWebElement supportedIssueFormFieldTitleValue => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldValue']"));
        private IWebElement supportedIssueFormFieldDescription => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldDescription']"));
        private IWebElement supportedIssueFormFieldDescriptionLabel => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldDescriptionLabel']"));
        private IWebElement supportedIssueFormFieldDescriptionValue => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldDescriptionValue']"));
        private IWebElement supportedIssueFormFieldInstrument => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldInstrument']"));
        private IWebElement supportedIssueFormFieldInstrumentLabel => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldInstrumentLabel']"));
        private IWebElement supportedIssueFormFieldInstrumentValue => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldInstrumentValue']"));
        private IWebElement supportedIssueFormFieldSystem => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldSystem']"));
        private IWebElement supportedIssueFormFieldSystemLabel => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldSystemLabel']"));
        private IWebElement supportedIssueFormSystemsSelect => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldSystemSelect']"));
        private IList<IWebElement> supportedIssueFormSystems => driver.FindElements(By.XPath("//*[@attr.data-idare-id='IssueFormFieldSystemSelectOption']"));
        private IWebElement supportedIssueFormFieldCategory => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldCategory']"));
        private IWebElement supportedIssueFormFieldCategoryLabel => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldCategoryLabel']"));
        private IWebElement supportedIssueFormFieldCategoryValue => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldCategoryValue']"));

        private IWebElement supportedIssueFormFieldSWVersions => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldSWVersions']"));
        private IWebElement supportedIssueFormFieldSWVersionsLabel => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldSWVersionsLabel']"));
        private IWebElement supportedIssueFormFieldSWVersionsValue => driver.FindElement(By.XPath("//*[@attr.data-idare-id='IssueFormFieldSWVersionsValue']"));

        public void SetTitle(string value) { supportedIssueFormFieldTitleValue.SendKeys(value); }
        public void SetDescription(string value) { supportedIssueFormFieldDescriptionValue.SendKeys(value); }
        public void SetInstrument(string value) { supportedIssueFormFieldInstrumentValue.SendKeys(value); }
        public void SetSystem(string value) {

            if (value != "")
            {
                supportedIssueFormSystemsSelect.Click();
                var SystemOption = driver.FindElement(By.XPath("//mat-option/span[contains(.,'" + " " + value + " " + "')]"));
                WebDriverWait Wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
                Wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(SystemOption));
                SystemOption.Click();
            }
            
        }
        public void SetCategory(string value) { supportedIssueFormFieldCategoryValue.SendKeys(value); }
        public void SetSWVersions(string value) { supportedIssueFormFieldSWVersionsValue.SendKeys(value); }

        public IList<IWebElement> GetSystemOptions()
        {
            return supportedIssueFormSystems;
        }

        public bool AreIssueFormElementsLoaded() {

            var IssueFormElementsLoaded = true;

            IssueFormElementsLoaded = supportedIssueFormFieldTitle != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldTitleLabel != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldDescription != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldDescriptionLabel != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldDescriptionValue != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldInstrument != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldInstrumentLabel != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldInstrumentValue != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldSystem != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldSystemLabel != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormSystemsSelect != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldCategory != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldCategoryLabel != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldCategoryValue != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldSWVersions != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldSWVersionsLabel != null && IssueFormElementsLoaded;
            IssueFormElementsLoaded = supportedIssueFormFieldSWVersionsValue != null && IssueFormElementsLoaded;

            return IssueFormElementsLoaded;
        }

        public void populateIssueForm(IssueForm issueFormFields) {
            SetTitle(issueFormFields.Title);
            SetCategory(issueFormFields.Category);
            SetInstrument(issueFormFields.ObservedInInstrument);
            SetSWVersions(issueFormFields.ExcludedSoftwareVersions);
            SetSystem(issueFormFields.System);
            SetDescription(issueFormFields.Description);
        }

        public bool validateIssueTitleField(string title)
        {

            return supportedIssueFormFieldTitleValue.GetAttribute("value") == title; ;
        }

        public bool validateIssueDescriptionField(string description)
        {

            return supportedIssueFormFieldDescriptionValue.GetAttribute("value") == description;
        }

        public bool validateIssueInstrumentField(string instrument)
        {

            return supportedIssueFormFieldInstrumentValue.GetAttribute("value") == instrument;
        }

        public bool validateIssueSWVersionField(string swVersion)
        {

            return supportedIssueFormFieldSWVersionsValue.GetAttribute("value") == swVersion;
        }

        public bool validateIssueSystemField(string system)
        {
            if (system != "")
            {
                var SystemOptionValueSpan = driver.FindElement(By.XPath("//*[@id='mat-select-1']/div/div[1]/span/span"));

                return SystemOptionValueSpan.Text == system;
            }
            return true;
            
        }

        public bool validateIssueCategoryField(string category)
        {

            return supportedIssueFormFieldCategoryValue.GetAttribute("value") == category;
        }

        public bool validateIssueFormFields(IssueForm issueFormFields)
        {
            var issueFormValid = true;

            issueFormValid = issueFormValid && validateIssueTitleField(issueFormFields.Title);
            issueFormValid = issueFormValid && validateIssueDescriptionField(issueFormFields.Description);
            issueFormValid = issueFormValid && validateIssueInstrumentField(issueFormFields.ObservedInInstrument);
            issueFormValid = issueFormValid && validateIssueSWVersionField(issueFormFields.ExcludedSoftwareVersions);
            issueFormValid = issueFormValid && validateIssueSystemField(issueFormFields.System);
            issueFormValid = issueFormValid && validateIssueCategoryField(issueFormFields.Category);

            return issueFormValid;
        }
    }
}
<file_sep>/iDareUI/CaseDetailsSteps.cs
﻿using iDareUI.Common;
using iDareUI.Models;
using OpenQA.Selenium;
using System;
using System.Collections.Generic;
using System.Linq;
using iDareUI.PageInteractions;
using TechTalk.SpecFlow;
using Xunit;

namespace iDareUI
{
    [Binding]
    public class CaseDetailsSteps
    {
        private TestingEnvironment environment;
        private CaseDetailsPage caseDetailsPage;
        private CaseCreationSteps caseCreationSteps;
        private FeatureContext featureContext;
        private CaseMainPage caseMainPage;
        private CaseInvestigationPage caseInvestigationPage;

        public CaseDetailsSteps(TestingEnvironment environment, FeatureContext featureContext)
        {
            this.environment = environment;
            this.caseInvestigationPage = new CaseInvestigationPage(environment.Driver);
            this.caseDetailsPage = new CaseDetailsPage(environment.Driver);
            this.caseMainPage = new CaseMainPage(environment.Driver);
            this.caseCreationSteps = new CaseCreationSteps(environment, featureContext);
            this.featureContext = featureContext;
        }

        [Then(@"I enter to the details of a case")]
        public void ThenIEnterToTheDetailsOfACase()
        {
            caseMainPage.PressDetailsButton();
        }

        [When(@"all files of the (.*) case have been processed")]
        public void WhenAllFilesOfTheCASCaseHaveBeenProcessed(string caseId)
        {
            caseMainPage.WaitUntilCasesAreUpdated(caseId, "01.");
        }

        [Then(@"the Instrument Information should be shown under the Instrument Information section")]
        public void ThenTheInstrumentInformationShouldBeShownUnderTheInstrumentInformationSection()
        {
            string[] expectedInstrumentInformationTitles = new string[]{ "Lab name", "Lab address", "Instrument type", "Instrument serial number", "Software version", "Instrument time zone" };
            string[] expectedInstrumentInformationData = new string[] { "ศูนย์บริการโลหิตแห่งชาติ สภากาชาดไทย", "Forrenstrasse 2, 6343 Rotkreuz", "cobas 6800 movable", "WSIM001234", "01.03.08.1011", "(UTC-11:00) Coordinated Universal Time-11" };
            var obtainedTitles = caseDetailsPage.GetInstrumentInformationTitles();
            var obtainedData = caseDetailsPage.GetInstrumentInformationData();
            Assert.True(expectedInstrumentInformationTitles.SequenceEqual(obtainedTitles),
                $"The Information Titles are not the expected ones. \nExpected: {string.Join(", ", expectedInstrumentInformationTitles)}, \nActual: {string.Join(", ", obtainedTitles)}");
            Assert.True(expectedInstrumentInformationData.SequenceEqual(obtainedData),
                $"The Information Titles are not the expected ones. \nExpected: {string.Join(", ", expectedInstrumentInformationData)}, \nActual: {string.Join(", ", obtainedData)}");
        }

        [Then(@"the titles shown in the Details of the case are correct")]
        public void ThenTheTitlesShownInTheDetailsOfTheCaseAreCorrect()
        {
            string[] expectedDetailsHeaders = new string[] { "Instrument states", "Detected issues", "Footprint", "Instrument information", "Recorded runs" };
            var obtainedTitles = caseDetailsPage.GetDetailsCardHeaders();
            Assert.True(expectedDetailsHeaders.SequenceEqual(obtainedTitles),
               $"The Detail titles are not the expected ones. \nExpected: {string.Join(", ", expectedDetailsHeaders)}, \nActual: {string.Join(", ", obtainedTitles)}");
        }

        [Then(@"the system shall fill the case fields automatically")]
        public void ThenTheSystemShallFillTheCaseFieldsAutomatically()
        {
            caseCreationSteps.ThenTheProgressOfTheUploadsShouldDisappear();
            Case currentCaseCreated = new Case();
            Case caseDetails = (Case)this.featureContext["caseDetails"];
            caseMainPage.WaitUntilCasesAreUpdated(caseDetails.CaseID, "01.");
            IEnumerable<Case> caseListComponent = caseMainPage.GetRowsElementsCases();
            IEnumerable<Case> caseDetailsCreated = caseListComponent.Where(myCase => myCase.CaseID.Contains(caseDetails.CaseID));
            if (caseDetailsCreated.Count() == 1)
            {
                currentCaseCreated.SWVersion = caseDetailsCreated.ElementAt(0).SWVersion;
                currentCaseCreated.SerialNo = caseDetailsCreated.ElementAt(0).SerialNo;
                currentCaseCreated.Customer = caseDetailsCreated.ElementAt(0).Customer;
                currentCaseCreated.Country = caseDetailsCreated.ElementAt(0).Country;
            }
            Assert.False(String.IsNullOrEmpty(currentCaseCreated.SWVersion), "The fields were not automatically filled");
            Assert.False(String.IsNullOrEmpty(currentCaseCreated.SerialNo), "The fields were not automatically filled");
            Assert.False(String.IsNullOrEmpty(currentCaseCreated.Customer), "The fields were not automatically filled");
            Assert.False(String.IsNullOrEmpty(currentCaseCreated.Country), "The fields were not automatically filled");
        }
        [Then(@"The user navigates to the investigation view")]
        public void ThenTheUserNavigatesToTheInvestigationView()
        {
            caseInvestigationPage.PressInvestigateTab();
        }
    }
}
<file_sep>/iDareUI/PageInteractions/CaseDetailsPage.cs
﻿using System;
using System.Collections.Generic;
using System.Linq;
using iDareUI.Common;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;

namespace iDareUI.PageInteractions
{
    public class CaseDetailsPage
    {
        private RemoteWebDriver driver;
        public CaseDetailsPage(RemoteWebDriver driver)
        {
            this.driver = driver;
        }
        public IWebElement closeCaseDetailsButton => driver.FindElement(By.CssSelector("button.prv-context-info__close.mat-icon-button")); 
        private IWebElement DetailsTitleCaseId => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CasedDetailHeaderHeading1']"));
        private IWebElement instrumentInformationCard => driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfo']"));
        private IWebElement instrumentInformationHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoHeader']")); 
        private IWebElement recordedRunsCard => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseDetailRecordedRunsInfoContainer']"));
        private IWebElement recordedRunsHeader => driver.FindElement(By.XPath("//*[@attr.data-idare-id='CaseDetailRecordedRunsInfoContainerTitle']"));
       
        public void PressMatExpansionPanelInstrumentInformation() { instrumentInformationHeader.Click(); }
        public void PressMatExpansionPanelRecordedRuns() { recordedRunsHeader.Click(); }
        public IEnumerable<string> GetDetailsCardHeaders()
        {
            IList<IWebElement> detailsHeaders = driver.FindElements(By.CssSelector("span.section-title"));
            List<string> detailsHeadersText = new List<string> (detailsHeaders.Select(element => element.Text));

            detailsHeadersText.Add(instrumentInformationHeader.Text);
            detailsHeadersText.Add(recordedRunsHeader.Text);

            return detailsHeadersText;
        }

        public IEnumerable<string> GetInstrumentInformationTitles()
        {
            IList<IWebElement> instrumentInformationFieldsElements = new List<IWebElement>();
            instrumentInformationFieldsElements.Add(driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoLabNameLabel']")));
            instrumentInformationFieldsElements.Add(driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoLabAddressLabel']")));
            instrumentInformationFieldsElements.Add(driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoInstrumentTypeLabel']")));
            instrumentInformationFieldsElements.Add(driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoSerialNumberLabel']")));
            instrumentInformationFieldsElements.Add(driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoSfVersionLabel']")));
            instrumentInformationFieldsElements.Add(driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoTimeZoneLabel']")));
            var instrumentInformationFieldsText = instrumentInformationFieldsElements.Select(element => element.Text);
            return instrumentInformationFieldsText;
        }

        public IEnumerable<string> GetInstrumentInformationData()
        {
            IList<IWebElement> instrumentInformationDataElements = new List<IWebElement>();
            instrumentInformationDataElements.Add(driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoLabNameValue']")));
            instrumentInformationDataElements.Add(driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoLabAddressValue']")));
            instrumentInformationDataElements.Add(driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoInstrumentTypeValue']")));
            instrumentInformationDataElements.Add(driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoSerialNumberValue']")));
            instrumentInformationDataElements.Add(driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoSfVersionValue']")));
            instrumentInformationDataElements.Add(driver.FindElement(By.XPath("//*[@attr.data-idare-id='InstrumentInfoTimeZoneValue']")));
            var instrumentInformationDataText = instrumentInformationDataElements.Select(element => element.Text);
            return instrumentInformationDataText;
        }

        public void PressCloseCaseDetailsButton()
        {
            FlowUtilities.WaitUntil(() => closeCaseDetailsButton.Enabled, TimeSpan.FromSeconds(2), TimeSpan.FromMilliseconds(100));
            closeCaseDetailsButton.Click();
        }
    }
}
