<file_sep>﻿//This code is from TechTalk.SpecFlow/StringExtensions.cs
//The pre-release version of specflow 3 had these as public and we started using them in our testing.
//They were set to internal in Specflow commit #1408

using System;

namespace SeleniumSpecFlow.Classes
{
	public static class StringExtensions
	{
		public static bool IsNullOrEmpty(this string value)
		{
			return string.IsNullOrEmpty(value);
		}

		public static bool IsNotNullOrEmpty(this string value)
		{
			return !string.IsNullOrEmpty(value);
		}

		public static bool IsNullOrWhiteSpace(this string value)
		{
			if (value == null) return true;

			for (int i = 0; i < value.Length; i++)
			{
				if (!char.IsWhiteSpace(value[i])) return false;
			}

			return true;
		}

		public static bool IsNotNullOrWhiteSpace(this string value)
		{
			return !value.IsNullOrWhiteSpace();
		}

		public static string StripWhitespaces(this string value)
		{
			return value.Replace(" ", "").Replace("\n", "").Replace("\r", "");
		}

		/// <summary>
		/// Returns empty string if the value is null, othervise the original value.
		/// </summary>
		/// <param name="value">The value to convert.</param>
		/// <returns>Empty string or the orinal value.</returns>
		public static string AsEmpty(this string value)
		{
			return string.IsNullOrEmpty(value) ? string.Empty : value;
		}

		/// <summary>
		/// Returns null if the value is empty, othervise the original value.
		/// </summary>
		/// <param name="value">The value to convert.</param>
		/// <returns>Null or the orinal value.</returns>
		public static string AsNull(this string value)
		{
			return string.IsNullOrEmpty(value) ? null : value;
		}
	}
}
<file_sep>﻿using OpenQA.Selenium;
using System;

namespace PageObjects
{
    public class AukroHomePage : BasePage
    {
        private bool aukroOfferPopUpClosed;
        private IWebDriver _webDriver;
        private string _baseUrl;
        private const string PageUrl = "http://www.aukro.cz/";

        public AukroHomePage(IWebDriver webDriver, string baseUrl)
        {
            _baseUrl = baseUrl;
            _webDriver = webDriver;            
            webDriver.Url = baseUrl + PageUrl;
            webDriver.Navigate();
            _webDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(3);
            if (!this.IsVisible())
            {
                throw new InvalidOperationException(String.Format("The current browser window is not on the expected page."));
            }
        }

        #region Constructors
        #endregion

        #region Public Methods
        public bool IsVisible()
        {
            return _webDriver.Url.Contains("aukro.cz");
        }

        public bool VerifyReturnMoneyAllOffers()
        {
            var allOffers = _webDriver.FindElement(By.TagName("list-view")).FindElements(By.TagName("list-card"));
            bool result = true;

            for (int i = 1; i <= allOffers.Count; i++)
            {
                if ((i == 5)||(i==45))
                    i++;
                try
                {
                    if(!aukroOfferPopUpClosed) 
                        this.CloseAukroOfferPopUpWindow();
                    if (!_webDriver.FindElement(By.CssSelector($"list-card.propagation-bold-title:nth-child({i}) > div:nth-child(1) > div:nth-child(2) > div:nth-child(6) > div:nth-child(1) > div:nth-child(4) > span:nth-child(1) > svg-icon:nth-child(1) > div:nth-child(1) > svg:nth-child(1) > circle:nth-child(2)")).Displayed)
                        throw new Exception($"Offer with index {i} does not contain money back guarantee.");
                }
                catch (Exception)
                {
                    try
                    {
                        this.CloseAukroOfferPopUpWindow();
                        if (!_webDriver.FindElement(By.CssSelector($"list-card.hot-auction:nth-child({i}) > div:nth-child(1) > div:nth-child(2) > div:nth-child(6) > div:nth-child(1) > div:nth-child(4) > span:nth-child(1) > svg-icon:nth-child(1) > div:nth-child(1) > svg:nth-child(1) > circle:nth-child(2)")).Displayed)
                            throw new Exception($"Offer with index {i} does not contain money back guarantee.");
                    }
                    catch (Exception)
                    {

                        if (!aukroOfferPopUpClosed)
                            this.CloseAukroOfferPopUpWindow();
                        if (!_webDriver.FindElement(By.CssSelector($".product-sorting > list-view:nth-child(4) > list-card:nth-child({i}) > div:nth-child(1) > div:nth-child(2) > div:nth-child(6) > div:nth-child(1) > div:nth-child(4) > span:nth-child(1) > svg-icon:nth-child(1) > div:nth-child(1) > svg:nth-child(1) > circle:nth-child(2)")).Displayed)
                            throw new Exception($"Offer with index {i} does not contain money back guarantee.");
                    }
                }
            }
            return result;
        }

        public void CloseAukroOfferPopUpWindow()
        {
            try
            {
                if (_webDriver.FindElement(By.CssSelector("i.vertical-bottom")).Displayed)
                {
                    aukroOfferPopUpClosed = true;
                    _webDriver.FindElement(By.CssSelector("i.vertical-bottom")).Click();
                }
            }
            catch (Exception)
            {

            }
        }
        public void ClickToAgreementButton()
        {
            agreementButton.Click();
        }

        public void ClickToAukroIcon()
        {
            aukroIcon.Click();
        }
        public void ClickToCategoryButton()
        {
            categoryButton.Click();
        }

        public void ClickToCollectiblesOption()
        {
            collectiblesOption.Click();
        }

        public void ClickToAntiquesAndArtOption()
        {
            antiquesAndArtOption.Click();
        }

        public void SelectReturnMoneyGuaranteeCheckbox()
        {
            var elem = _webDriver.FindElement(By.CssSelector(".filter-sidebar-wrapper > filter:nth-child(1) > parameters:nth-child(2) > filter-parameter-attribute:nth-child(3) > span:nth-child(1)"));
            IJavaScriptExecutor js = (IJavaScriptExecutor)_webDriver;
            string title = (string)js.ExecuteScript("arguments[0].scrollIntoView(true);", elem);
            returnMoneyGuaranteeCheckbox.Click();
        }

        public void SelectFreeShippingCheckbox()
        {
            freeShippingCheckbox.Click();
        }

        #endregion

        #region Private
        private IWebElement agreementButton { get { return _webDriver.FindElement(By.CssSelector(".fc-cta-consent")); } }
        private IWebElement aukroIcon { get { return _webDriver.FindElement(By.CssSelector("#Layer_1")); } }
        private IWebElement categoryButton { get { return _webDriver.FindElement(By.CssSelector("#ssr-done > app-header > div:nth-child(3) > div > div.display-inline-block-min-tablet > button")); } }
        private IWebElement collectiblesOption { get { return _webDriver.FindElement(By.CssSelector("div.nav-section:nth-child(4) > top-level-category:nth-child(1) > div:nth-child(1) > a:nth-child(2)")); } }
        private IWebElement antiquesAndArtOption { get { return _webDriver.FindElement(By.CssSelector("div.nav-section:nth-child(4) > top-level-category:nth-child(2) > div:nth-child(1) > a:nth-child(2)")); } }
        private IWebElement returnMoneyGuaranteeCheckbox { get { return _webDriver.FindElement(By.CssSelector("#mat-checkbox-6 > label:nth-child(1) > span:nth-child(2) > span:nth-child(2)")); } }
        private IWebElement freeShippingCheckbox { get { return _webDriver.FindElement(By.CssSelector("#mat-checkbox-7 > label:nth-child(1) > span:nth-child(2) > span:nth-child(2)")); } }
        #endregion
    }
}
<file_sep>﻿using System;

namespace PageObjects
{
    public class BasePage
    {
    }
}
<file_sep>﻿using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;

namespace SeleniumSpecFlow
{
    /// <summary>
    /// Class to generate WebDriver
    /// </summary>
    public static class WebDriverFactory
    {
        private static IWebDriver _webDriver;

        public static IWebDriver WebDriver
        {
            get
            {
                return _webDriver;
            }
        }

        public static void Initialize(BrowserType browserType)
        {
            switch (browserType)
            {
                case BrowserType.Chrome:
                    ChromeOptions options = new ChromeOptions();
                    options.AddArgument("--start-maximized");
                    _webDriver = new ChromeDriver(options);
                    break;
                case BrowserType.Firefox:
                    FirefoxOptions firefoxBrowser = new FirefoxOptions();
                    firefoxBrowser.AddArgument("--start-maximized");
                    _webDriver = new FirefoxDriver(firefoxBrowser);
                    break;
                default: throw new Exception("Unknown browser type");
            }            
        }
        public static void CloseBrowser(BrowserType browserType)
        {
            switch (browserType)
            {
                case BrowserType.Chrome:
                    _webDriver.Quit();
                    break;
                case BrowserType.Firefox:
                    _webDriver.Quit();
                    break;
                default: throw new Exception("Unknown browser type");
            }
        }

    }

    public enum BrowserType
    {
        Chrome,
        Firefox
    }
}
<file_sep>﻿using PageObjects;
using TechTalk.SpecFlow;

namespace SeleniumSpecFlow.metadata
{
    [Binding]
    public class BaseSteps
    {
        public BasePage CurrentPage { get; set; }

        [BeforeTestRun]
        public static void BeforeTest()
        {
            //WebDriverFactory.Initialize(BrowserType.Chrome);
            WebDriverFactory.Initialize(BrowserType.Firefox);
        }
        [AfterScenario]
        public static void AfterScenario()
        {
            //WebDriverFactory.CloseBrowser(BrowserType.Chrome);
            WebDriverFactory.CloseBrowser(BrowserType.Firefox);
        }
    }
}<file_sep>﻿using PageObjects;
using TechTalk.SpecFlow;
using SeleniumSpecFlow.metadata;
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace SeleniumSpecFlow.Features
{
    [Binding]
    public class AukroHomePageTestSteps : BaseSteps
    {
        [Given(@"Load Current page")]
        public void GivenLoadCurrentPage()
        {
            CurrentPage = new AukroHomePage(WebDriverFactory.WebDriver, string.Empty);
        }

        [Given(@"Close pop up Agreement")]
        public void GivenClosePopUpAgreement()
        {
            if (!(CurrentPage is AukroHomePage)) throw new System.Exception("Bad page");
            ((AukroHomePage)this.CurrentPage).ClickToAgreementButton();
        }

        [Given(@"Close pop up Aukro Offer")]
        public void GivenClosePopUpAukroOffer()
        {
            if (!(CurrentPage is AukroHomePage)) throw new System.Exception("Bad page");
            ((AukroHomePage)this.CurrentPage).ClickToAukroIcon();
        }


        [When(@"I select Category Button")]
        public void WhenISelectCategoryButton()
        {
            if (!(CurrentPage is AukroHomePage)) throw new System.Exception("Bad page");
            ((AukroHomePage)this.CurrentPage).ClickToCategoryButton();
        }

        [When(@"I select ""(.*)"" Option")]
        public void WhenISelectOption(string aukroOption)
        {
            switch (aukroOption)
            {
                case "Collectibles":
                    if (!(CurrentPage is AukroHomePage)) throw new System.Exception("Bad page");
                    ((AukroHomePage)this.CurrentPage).ClickToCollectiblesOption();
                    break;
                case "AntiquesAndArt":
                    if (!(CurrentPage is AukroHomePage)) throw new System.Exception("Bad page");
                    ((AukroHomePage)this.CurrentPage).ClickToAntiquesAndArtOption();
                    break;
                default:
                    throw new Exception(string.Format("{0} not supported value.", aukroOption));
            }
        }

        [When(@"I select Parameter Options Checkboxes")]
        public void WhenISelectParameterOptionsCheckboxes(Table table)
        {
            if (table.ContainsColumn("ReturnMoneyGuarantee") && table.Rows[0]["ReturnMoneyGuarantee"].Contains("check"))
            {
                if (!(CurrentPage is AukroHomePage)) throw new System.Exception("Bad page");
                ((AukroHomePage)this.CurrentPage).SelectReturnMoneyGuaranteeCheckbox();
            }

            if (table.ContainsColumn("FreeShipping ") && table.Rows[0]["FreeShipping"].Contains("check"))
            {
                if (!(CurrentPage is AukroHomePage)) throw new System.Exception("Bad page");
                ((AukroHomePage)this.CurrentPage).SelectFreeShippingCheckbox();
            }

            if (table.ContainsColumn("PersonalTakeover ") && table.Rows[0]["PersonalTakeover"].Contains("check"))
            {
                if (!(CurrentPage is AukroHomePage)) throw new System.Exception("Bad page");
                // ToDO PersonalTakeover
            }

            if (table.ContainsColumn("TransportWithCashOnDelivery ") && table.Rows[0]["TransportWithCashOnDelivery"].Contains("check"))
            {
                if (!(CurrentPage is AukroHomePage)) throw new System.Exception("Bad page");
                // ToDO TransportWithCashOnDelivery
            }

            if (table.ContainsColumn("AukroPlus") && table.Rows[0]["AukroPlus"].Contains("check"))
            {
                if (!(CurrentPage is AukroHomePage)) throw new System.Exception("Bad page");
                // ToDO AukroPlus
            }
        }

        [Then(@"Verify that all offers include Aukro Return Money Guarantee")]
        public void ThenVerifyThatAllOffersIncludeAukroReturnMoneyGuarantee()
        {
            if (!(CurrentPage is AukroHomePage)) throw new System.Exception("Bad page");
            Assert.IsTrue(((AukroHomePage)this.CurrentPage).VerifyReturnMoneyAllOffers(), "Aukro money return guarantee is not present for all offers.");
        }
    }
}
<file_sep>﻿using System.Collections.Generic;
using System.Linq;
using TechTalk.SpecFlow;

namespace SeleniumSpecFlow.Classes
{
    public static class TableRowExtensions
    {
        public static bool ContainsNonEmptyKey(this TableRow row, string key)
        {
            return row.ContainsKey(key) && !string.IsNullOrEmpty(row[key]);
        }

        public static bool IsEmpty(this TableRow row)
        {
            return row.Values.All(x => x.IsNullOrEmpty());
        }
    }
}
