0

I'm developing .NET core app that using selenium, so I've designed the logic using fluent interface that make the code more readable and maintained.

I have a problem which is how to make a conditional logic in pipeline I followed this link of conditional builder.

the error here

enter image description here

here the source code

BasePage.cs

public class BasePage
{
    public IWebDriver WebDriver { get; set; }
    public WebDriverWait DefaultWait { get; }

    public BasePage(IWebDriver webDriver)
    {
        WebDriver = webDriver;
        DefaultWait = new WebDriverWait(WebDriver, TimeSpan.FromSeconds(1));
    }
}

HomePage.cs

public class HomePage: BasePage
{
    
    private Select2 Driver => new Select2(WebDriver, WebDriver.FindElementIfExists(By.XPath("xpath")));

    private TextBox FirstName => new TextBox(WebDriver, WebDriver.FindElementIfExists(By.XPath("xpath")));

    private TextBox LastName => new TextBox(WebDriver, WebDriver.FindElementIfExists(By.XPath("xpath")));

    

    public HomePage(IWebDriver webDriver) : base(webDriver)
    {
    }
    
    public HomePage FillPostingInformationForm(Company company)
    {
        
        FirstName.SetText(company.ContactPerson.FirstName);
        LastName.SetText(company.ContactPerson.LastName);
        return new HomePage(WebDriver)
    }
    public HomePage IsDriverFound(Company company)
    {
        Driver.IsItemSelected(company.Drivers.First().FirstName + " " + company.Drivers.First().LastName);
        return new HomePage(WebDriver)
    }
    
}

Select2.cs

public class BaseElement
{
    public IWebDriver WebDriver { get; set; }
    public BaseElement(IWebDriver webDriver)
    {
        WebDriver = webDriver;
    }
}
public class Select2 : BaseElement
{
    public IWebElement _element;

    public Select2(IWebDriver webDriver, IWebElement element) : base(webDriver)
    {
        _element = element;
    }
    public bool IsItemSelected(string keyWord)
    {
        try
        {
            _element.Click();
            _element.SendKeys(keyWord);
            var option = WebDriver.FindElement(By.XPath(string.Format("//*[@{0} = '{1}']",
                                            "role", "option")));
            option.Click();
            _element.BodyClick();
            return true;
        }
        catch (NoSuchElementException ex)
        {
            Console.WriteLine(ex.Message);
           return false;
        }
    }
}

BuilderExtensions.cs

public static class BuilderExtensions
{
    public static T If<T>(this T t,bool cond, Func<T, T> builder)
      where T : HomePage
    {
        if (cond)
            return builder(t);
        return t;
    }
}

and the call as following

public void Build()
{
    HomePage HomePage => new HomePage(InitializeBrowser());
       
    var x = HomePage
        .If(IsDriverFound(company), b => b.FillPostingInformationForm(company))
        .If(!IsDriverFound(company), b => b.GoToDriversPage());
}

IsDriverFound(company) shown error, so what I did wrong here? and how to call this method inside if extension in the pipeline

Greg Burghardt
  • 17,900
  • 9
  • 49
  • 92
Karim Fahmy
  • 215
  • 1
  • 11
  • Please post real code. It's very unlikely that `HomePage` inherits from `HomePage`. Please make sure that you give us full instructions on how to run this code ourselves. We need a [mcve]. – Enigmativity Jan 05 '23 at 11:17
  • Also a `return this` is a bad sign in a fluent interface. It should be something like `return new HomePage(/* this plus the stuff passed to the call*/);`. – Enigmativity Jan 05 '23 at 11:19
  • _"IsDriverFound(company) shown error,"_ - what error? Also what is `company` in `Build`, there is no such parameter in the method and I don't see a property/field with this name. – Guru Stron Jan 05 '23 at 12:39
  • @GuruStron the error is "this method not defined it's cannot be accessed in the pipeline ", company it's a model containing data – Karim Fahmy Jan 05 '23 at 12:50
  • Can you please provide a full [mre]? – Guru Stron Jan 05 '23 at 12:52
  • @GuruStron *I've updated the question with online code snipped and screen shot of error* – Karim Fahmy Jan 05 '23 at 13:25
  • @KarimFahmy - `return new HomePage(WebDriver)` is worse than `return this`. You need to make it that the current instance is unchanged and you create a new instance that incorporates the data from the new call. – Enigmativity Jan 05 '23 at 21:30

3 Answers3

1

Probably you missed lambda parameter. The error says The name 'IsDriverFound' does not exist in the current context so there is no method in the context of Main, but it exists in HomePage object which is passed as lambda parameter into a method.

Check the second parameter - it's exactly the same. The lambda parameter is passed.

Just add x => x.IsDriverFound(company)

Xeo
  • 110
  • 1
  • 6
1

Yo have a couple of issues here:

Return Type:

IsDriverFound() return a HomePage while if is expecting a bool.

you can either change it or create a new method:

public HomePage IsDriverFound(Company company) => 
Driver.IsItemSelected(company.Drivers.First().FirstName + " " + company.Drivers.First().LastName);

Class membership:

IsDriverFound() is a method of HomePage, so it can´t be called from outside of this class if it´s not referencing a HomePage instance. It should be:

HomePage.IsDriverFound(company);

That said, you can try this:

public void Build()
        {
            HomePage homePage => new HomePage(InitializeBrowser());
       
            var x = homePage
                 .If(homePage.IsDriverFound(company), b => b.FillPostingInformationForm(company))
                 .If(!homePage.IsDriverFound(company), b => b
                 .GoToDriversPage());
       }

Where IsDriverFound() return a bool or the method If expects a HomePage.

Yusef Ham
  • 55
  • 1
  • 7
  • I can't use `homePage.IsDriverFound(company)` because it will create another instance of selenium – Karim Fahmy Jan 05 '23 at 14:11
  • you can modify it or create a new method that returns a `bool` and doesn't create a new instance. ```public HomePage IsDriverFound2(Company company) => Driver.IsItemSelected(company.Drivers.First().FirstName + " " + company.Drivers.First().LastName); ``` – Yusef Ham Jan 05 '23 at 14:35
-1

Here's an example of a what a fluent interface should look like if you're trying to build a HomePage object.

HomePage HomePage =
    HomePageBuilder
        .Initialize()
        .If(hp => hp.IsDriverFound(company), hp => hp.FillPostingInformationForm(company))
        .If(hp => hp.IsDriverFound(company), hp => hp.GoToDriversPage())
        .Do(hp => hp.SomeOtherMethod())
        .Build();

The builder and the object you are building are two different types.

The HomePage object is then rather simple:

public class HomePage
{
    public bool IsDriverFound(Company company) { /* ... */ }
    public void FillPostingInformationForm(Company company) { /* ... */ }
    public void GoToDriversPage() { /* ... */ }
    public void SomeOtherMethod() { /* ... */ }
}

It's just a plain object with normal methods.

The builder itself does the heavy lifting of building the object, obviously!

public class HomePageBuilder
{
    private HomePageBuilder()
    {
        actions = new List<Action<HomePage>>();
    }

    private HomePageBuilder(HomePageBuilder previous, Action<HomePage> action)
    {
        actions = previous.actions.Append(action).ToList();
    }

    public static HomePageBuilder Initialize(/* add any mandatory init stuff here */) =>
        new HomePageBuilder();

    private List<Action<HomePage>> actions = new List<Action<HomePage>>();

    public HomePage Build() =>
        actions
            .Aggregate(
                new HomePage(),
                (hp, a) => { a(hp); return hp; });

    public HomePageBuilder Do(Action<HomePage> action) =>
        new HomePageBuilder(this, action);

    public HomePageBuilder If(Func<HomePage, bool> cond, Action<HomePage> action) =>
        new HomePageBuilder(this, hp => { if (cond(hp)) action(hp); });
}

Note that the list of actions is extended for each step in the building process without changing the list from the previous step.

Also, the final Build call creates a new HomePage and then plays the list of actions against it before returning it.

Clearly this is a simple implementation and I haven't added any error handling, but it should be a good start.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172