|
| 1 | +--- |
| 2 | +title: 'Page object model' |
| 3 | +heading: 'Page object model with k6 browser' |
| 4 | +head_title: 'Page object model with k6 browser' |
| 5 | +excerpt: 'An example on how to implement page object model design pattern with k6 browser' |
| 6 | +--- |
| 7 | + |
| 8 | +When working with large test suites, a popular design pattern to improve your code’s maintainability and readability is the [page object model](https://martinfowler.com/bliki/PageObject.html). |
| 9 | + |
| 10 | +A page object commonly represents an HTML page or significant elements/components within a page, such as a header or a footer. It is a form of encapsulation that hides the details of the UI structure from other places, such as your test files. Through page object models, any changes you need to make on a specific page or element within a page are constrained into a single place, resulting in ease of maintenance and avoiding code duplication. |
| 11 | + |
| 12 | +Since k6 browser aims to provide rough compatibility with the Playwright API, you can leverage any existing page objects you have and easily re-use them with your k6 browser tests. |
| 13 | + |
| 14 | +## Implementation |
| 15 | + |
| 16 | +Let's take an example of a website with a booking form added to the homepage. Imagine you want to write a test that checks that a user can fill out the booking form successfully. |
| 17 | + |
| 18 | +To model a page object for the homepage, we've created a page object class called `homepage.js`. Different locators are created inside the constructor so that when the homepage class is instantiated, the page locator elements are ready to be used. |
| 19 | + |
| 20 | +There are also different methods for: |
| 21 | +- Navigating to the homepage |
| 22 | +- Submitting the form |
| 23 | +- Getting the verification message |
| 24 | + |
| 25 | +When locators need to be updated or other specific changes related to the homepage are made, you only need to update the `homepage.js` class. |
| 26 | + |
| 27 | +<CodeGroup labels={["homepage.js"]} lineNumbers={[true]}> |
| 28 | + |
| 29 | +```javascript |
| 30 | +import { bookingData } from '../data/booking-data.js' |
| 31 | + |
| 32 | +export class Homepage { |
| 33 | + constructor(page) { |
| 34 | + this.page = page |
| 35 | + this.nameField = page.locator('[data-testid="ContactName"]') |
| 36 | + this.emailField = page.locator('[data-testid="ContactEmail"]') |
| 37 | + this.phoneField = page.locator('[data-testid="ContactPhone"]'); |
| 38 | + this.subjectField = page.locator('[data-testid="ContactSubject"]'); |
| 39 | + this.descField = page.locator('[data-testid="ContactDescription"]'); |
| 40 | + this.submitButton = page.locator('#submitContact'); |
| 41 | + this.verificationMessage = page.locator('.row.contact h2') |
| 42 | + } |
| 43 | + |
| 44 | + async goto() { |
| 45 | + await this.page.goto('https://myexamplewebsite/') |
| 46 | + } |
| 47 | + |
| 48 | + async submitForm() { |
| 49 | + const { name, email, phone, subject, description } = bookingData |
| 50 | + |
| 51 | + this.nameField.type(name) |
| 52 | + this.emailField.type(email) |
| 53 | + this.phoneField.type(phone) |
| 54 | + this.subjectField.type(subject) |
| 55 | + this.descField.type(description) |
| 56 | + await this.submitButton.click() |
| 57 | + } |
| 58 | + |
| 59 | + getVerificationMessage() { |
| 60 | + return this.verificationMessage.innerText() |
| 61 | + } |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +</CodeGroup> |
| 66 | + |
| 67 | +You can import the `Homepage` class within your test class and invoke the methods you need. This makes the code easier to understand and enforces the separation between your test and business logic. |
| 68 | + |
| 69 | +<CodeGroup labels={["booking-test.js"]} lineNumbers={[true]}> |
| 70 | + |
| 71 | +```javascript |
| 72 | +import { chromium } from 'k6/experimental/browser' |
| 73 | +import { expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.0/index.js' |
| 74 | + |
| 75 | +import { Homepage } from '../pages/homepage.js' |
| 76 | +import { bookingData } from '../data/booking-data.js' |
| 77 | + |
| 78 | +export default async function () { |
| 79 | + const browser = chromium.launch() |
| 80 | + const page = browser.newPage() |
| 81 | + |
| 82 | + const { name } = bookingData |
| 83 | + |
| 84 | + const homepage = new Homepage(page) |
| 85 | + await homepage.goto() |
| 86 | + await homepage.submitForm() |
| 87 | + |
| 88 | + expect(homepage.getVerificationMessage()).to.contain(name) |
| 89 | + |
| 90 | + page.close() |
| 91 | + browser.close() |
| 92 | +} |
| 93 | +``` |
| 94 | + |
| 95 | +</CodeGroup> |
0 commit comments