I'm new-ish to C# and SO, please let me know if I can improve anything.
We're following the page object model and I have a page that I need to use inside and out of an iframe.
It looks like this at the moment:
public class MyPage {
protected IPage Page;
public MyPage (IPage page) {
Page = page;
}
public ILocator MyButton => Page.Locator("#myButton");
}
public class MyPageIframe {
protected IFrameLocator MyIframe;
public MyPageIframe (IPage page) {
MyIframe = page.FrameLocator("#myIframe");
}
public MyButton => MyIframe.Locator("#myButton");
}
The locators for both are exactly the same, except the context the Locator()
method is called on. Is there a way to make these the same class, with one MyButton
that works with or without the iframe?
In my head, the magic solution would be something like this:
public class MyPage {
// where someType can be either IPage or IFrameLocator
protected someType context;
public MyPage(IPage page, IFrameLocator locator) {
// do something to set context?
}
public MyButton => context.Locator("#myButton");
}
The first solution that came to my mind for your problem is this:
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
var home = new HomePage(page);
ILocator myButton = home.MyButton;
ILocator myOtherButton = home.MyOtherButton;
public abstract class BasePage
{
protected BasePage(IPage page)
{
Page = page;
}
protected IPage Page { get; }
public virtual ILocator Locate(string frameLocator, string locator) => Page.FrameLocator(frameLocator).Locator(locator);
public virtual ILocator Locate(string locator) => Page.Locator(locator);
}
public class HomePage : BasePage
{
public HomePage(IPage page)
: base(page)
{
}
public ILocator MyButton => Locate("#myButton");
public ILocator MyOtherButton => Locate("#myIframe", "#myOtherButton");
}