POM is asked in every single automation interview. Whether it is a startup or a Fortune 500, the interviewer will ask you about page objects. These questions come from real interviews at top companies. Know them cold.
Q: What is the Page Object Model and why do you use it?
A: Page Object Model is a design pattern that creates a class for each page or major section of a web application. Each class contains locators for elements on that page and methods for user interactions. The main benefit is maintainability -- when the UI changes, I update one class instead of every test. It also improves readability -- tests call loginPage.login() instead of filling fields and clicking buttons manually. In Playwright with TypeScript, POM is especially clean because of readonly locators, type safety, and IDE autocomplete.
Q: How is POM in Playwright different from POM in Selenium?
A: Three key differences. First, no PageFactory -- Selenium needs @FindBy annotations and initElements() to initialize locators. Playwright locators are lazy by default, so defining them in the constructor is enough. Second, TypeScript readonly vs Java final -- TypeScript readonly is cleaner and the IDE provides better autocomplete. Third, custom fixtures -- Playwright lets you extend the test function with page objects as parameters. Selenium has no equivalent. You either use dependency injection frameworks or create page objects manually in every test.
Q: Should page objects contain assertions?
A: The general rule is no -- page objects perform actions, tests verify results. However, I make an exception for state-verification methods like expectLoaded() that check if a page is ready. These are not testing business logic; they are confirming navigation worked. The key principle: action methods like login() should never assert because they would become unusable for negative tests. If login() asserts the dashboard appeared, I cannot use it to test invalid credentials.
Q: What is the BasePage pattern?
A: BasePage is an abstract class that holds methods shared by all pages -- goto(), waitForLoad(), getTitle(), takeScreenshot(). Every page object extends BasePage and inherits these common methods. I keep BasePage thin -- only truly universal methods go there. Page-specific locators and actions stay in the concrete page classes. It reduces code duplication and enforces a consistent structure across all page objects.
Q: Explain Playwright fixtures and how you use them with POM.
A: Playwright fixtures extend the base test with custom parameters. For POM, I create a fixture file that defines each page object as a fixture. Instead of writing new LoginPage(page) in every test, tests receive { loginPage } as a parameter. I extend base.test with a type that lists all page object fixtures. Each fixture uses the async ({ page }, use) pattern -- it creates the page object and passes it to the test via use(). Fixtures are lazy, so unused page objects are never created. I also create composite fixtures like authenticatedPage that logs in before the test starts.
Q: How do you handle reusable UI components like headers, modals, and sidebars?
A: I extract them into component classes -- HeaderComponent, ModalComponent, SidebarComponent. Each component scopes its locators to the container element. For example, HeaderComponent scopes all locators to page.getByRole('banner'). Page objects compose these components as properties: this.header = new HeaderComponent(page). Tests access them through the page object: dashboardPage.header.logout(). This way, the header is defined once and reused across every page that has it.
Q: What is fluent navigation in POM?
A: Fluent navigation means action methods return the page object of the destination page. loginPage.loginAs() returns a DashboardPage because successful login takes you to the dashboard. dashboardPage.goToTransfer() returns TransferPage. This documents the navigation flow in the code itself. The return type tells the developer which page they will be on next. It also enables IDE autocomplete -- after calling loginAs(), the IDE suggests only DashboardPage methods. I use different method names for different outcomes: loginAs() returns DashboardPage, loginExpectingError() returns nothing because you stay on the login page.
| Question | One-Line Answer |
|---|---|
| Where do locators go? | In the constructor as readonly Locator properties |
| Where do assertions go? | In test files, not in page objects |
| What is a God Object? | A page object with too many responsibilities -- split it up |
| Should I use PageFactory in Playwright? | No. Playwright locators are lazy. No PageFactory needed. |
| How many methods per page object? | Aim for 5-15. More than 15 means your class is doing too much. |
| What naming convention for files? | <name>.page.ts for page objects, <name>.component.ts for components |
| Can page objects inherit from each other? | Only from BasePage. Page-to-page inheritance creates tight coupling. |
| What is the biggest POM mistake? | Putting expect() in action methods like login() or addToCart() |
Key Point: POM is a guaranteed interview topic. Know the pattern, know fixtures, know components, know common mistakes. Practice explaining each concept in 2-3 sentences.
Answer all 5 questions, then submit to see your score.
1. Where should locators be defined in a Playwright page object?
2. What is wrong with putting expect() assertions inside page object action methods like login()?
3. How do Playwright custom fixtures help with POM?
4. What does fluent navigation mean in POM?
5. When should you extract a UI section into a separate component class?