webdriverio/website/i18n/ar/docusaurus-plugin-content-docs/current/PageObjects.md
Christian Bromann 11242e8f15
New Crowdin updates (#10370)
* New translations GettingStarted.md (Polish)

* New translations GettingStarted.md (Tamil)

* New translations GettingStarted.md (French)

* New translations GettingStarted.md (Spanish)

* New translations GettingStarted.md (German)

* New translations GettingStarted.md (Russian)

* New translations GettingStarted.md (Ukrainian)

* New translations GettingStarted.md (Chinese Simplified)

* New translations GettingStarted.md (Persian)

* New translations GettingStarted.md (Hindi)

* New translations Browser.md (Chinese Simplified)

* New translations BoilerplateProjects.md (Chinese Simplified)

* New translations Capabilities.md (Chinese Simplified)

* New translations Configuration.md (Chinese Simplified)

* New translations Protocols.md (Chinese Simplified)

* New translations GettingStarted.md (Chinese Simplified)

* New translations API.md (Chinese Simplified)

* New translations Accessibility.md (Chinese Simplified)

* New translations Assertion.md (Chinese Simplified)

* New translations AutoWait.md (Chinese Simplified)

* New translations Autocompletion.md (Chinese Simplified)

* New translations AutomationProtocols.md (Chinese Simplified)

* New translations BambooIntegration.md (Chinese Simplified)

* New translations CloudServices.md (Chinese Simplified)

* New translations ComponentTesting.md (Chinese Simplified)

* New translations ConfigurationFile.md (Chinese Simplified)

* New translations CustomCommands.md (Chinese Simplified)

* New translations CustomReporter.md (Chinese Simplified)

* New translations CustomServices.md (Chinese Simplified)

* New translations Debugging.md (Chinese Simplified)

* New translations Docker.md (Chinese Simplified)

* New translations DriverBinaries.md (Chinese Simplified)

* New translations Enterprise.md (Chinese Simplified)

* New translations GithubActions.md (Chinese Simplified)

* New translations JenkinsIntegration.md (Chinese Simplified)

* New translations MocksAndSpies.md (Chinese Simplified)

* New translations Multiremote.md (Chinese Simplified)

* New translations OrganizingTestSuites.md (Chinese Simplified)

* New translations PageObjects.md (Chinese Simplified)

* New translations ProtractorMigration.md (Chinese Simplified)

* New translations Record.md (Chinese Simplified)

* New translations Retry.md (Chinese Simplified)

* New translations Runner.md (Chinese Simplified)

* New translations Selectors.md (Chinese Simplified)

* New translations SetupTypes.md (Chinese Simplified)

* New translations SyncAsyncMigration.md (Chinese Simplified)

* New translations Testrunner.md (Chinese Simplified)

* New translations Timeouts.md (Chinese Simplified)

* New translations TypeScript.md (Chinese Simplified)

* New translations WatchFiles.md (Chinese Simplified)

* New translations WhyWebdriverIO.md (Chinese Simplified)

* New translations Element.md (Chinese Simplified)

* New translations Environment.md (Chinese Simplified)

* New translations Globals.md (Chinese Simplified)

* New translations Mock.md (Chinese Simplified)

* New translations Modules.md (Chinese Simplified)

* New translations Lit.md (Chinese Simplified)

* New translations Preact.md (Chinese Simplified)

* New translations React.md (Chinese Simplified)

* New translations Solid.md (Chinese Simplified)

* New translations Svelte.md (Chinese Simplified)

* New translations Vue.md (Chinese Simplified)

* New translations mocking.md (Chinese Simplified)

* New translations repl.md (Chinese Simplified)

* New translations v6Migration.md (Chinese Simplified)

* New translations v7Migration.md (Chinese Simplified)

* New translations Donate.md (Chinese Simplified)

* New translations Materials.md (Chinese Simplified)

* New translations OpenOfficeHours.md (Chinese Simplified)

* New translations Support.md (Chinese Simplified)

* New translations WebExtensionTesting.md (Chinese Simplified)

* New translations TipsAndTricks.md (Chinese Simplified)

* New translations Donate.md (Tamil)

* New translations Donate.md (Tamil)

* New translations Donate.md (Tamil)

* New translations Materials.md (Tamil)

* New translations OpenOfficeHours.md (Tamil)

* New translations CreateLocalWorkerProcess.md (Tamil)

* New translations HighLevelOverview.md (Tamil)

* New translations TestExecution.md (Tamil)

* New translations Support.md (Tamil)

* New translations Team.md (Tamil)

* New translations TestExecution.md (Tamil)

* New translations WDIOCommands.md (Tamil)

* New translations TipsAndTricks.md (Tamil)

* New translations Appium.md (Tamil)

* New translations code.json (Arabic)

* New translations options.json (Arabic)

* New translations current.json (Arabic)

* New translations current.json (Arabic)

* New translations footer.json (Arabic)

* New translations navbar.json (Arabic)

* New translations API.md (Arabic)

* New translations Accessibility.md (Arabic)

* New translations Assertion.md (Arabic)

* New translations AutoWait.md (Arabic)

* New translations Autocompletion.md (Arabic)

* New translations AutomationProtocols.md (Arabic)

* New translations Babel.md (Arabic)

* New translations BambooIntegration.md (Arabic)

* New translations BoilerplateProjects.md (Arabic)

* New translations Capabilities.md (Arabic)

* New translations CloudServices.md (Arabic)

* New translations ComponentTesting.md (Arabic)

* New translations Configuration.md (Arabic)

* New translations ConfigurationFile.md (Arabic)

* New translations CustomCommands.md (Arabic)

* New translations CustomReporter.md (Arabic)

* New translations CustomServices.md (Arabic)

* New translations Debugging.md (Arabic)

* New translations Docker.md (Arabic)

* New translations DriverBinaries.md (Arabic)

* New translations Enterprise.md (Arabic)

* New translations Flowcharts.md (Arabic)

* New translations Frameworks.md (Arabic)

* New translations GettingStarted.md (Arabic)

* New translations GithubActions.md (Arabic)

* New translations JenkinsIntegration.md (Arabic)

* New translations MocksAndSpies.md (Arabic)

* New translations Multiremote.md (Arabic)

* New translations OrganizingTestSuites.md (Arabic)

* New translations PageObjects.md (Arabic)

* New translations ProtractorMigration.md (Arabic)

* New translations Proxy.md (Arabic)

* New translations Record.md (Arabic)

* New translations Retry.md (Arabic)

* New translations Runner.md (Arabic)

* New translations Selectors.md (Arabic)

* New translations SetupTypes.md (Arabic)

* New translations SyncAsyncMigration.md (Arabic)

* New translations Testrunner.md (Arabic)

* New translations Timeouts.md (Arabic)

* New translations TypeScript.md (Arabic)

* New translations WatchFiles.md (Arabic)

* New translations WhyWebdriverIO.md (Arabic)

* New translations Browser.md (Arabic)

* New translations Element.md (Arabic)

* New translations Environment.md (Arabic)

* New translations Globals.md (Arabic)

* New translations Mock.md (Arabic)

* New translations Modules.md (Arabic)

* New translations Protocols.md (Arabic)

* New translations Lit.md (Arabic)

* New translations Preact.md (Arabic)

* New translations React.md (Arabic)

* New translations Solid.md (Arabic)

* New translations Svelte.md (Arabic)

* New translations Vue.md (Arabic)

* New translations coverage.md (Arabic)

* New translations mocking.md (Arabic)

* New translations CreateLocalWorkerProcess.md (Arabic)

* New translations HighLevelOverview.md (Arabic)

* New translations TestExecution.md (Arabic)

* New translations WDIOCommands.md (Arabic)

* New translations repl.md (Arabic)

* New translations v6Migration.md (Arabic)

* New translations v7Migration.md (Arabic)

* New translations Donate.md (Arabic)

* New translations Materials.md (Arabic)

* New translations OpenOfficeHours.md (Arabic)

* New translations Support.md (Arabic)

* New translations Team.md (Arabic)

* New translations WebExtensionTesting.md (Arabic)

* New translations TipsAndTricks.md (Arabic)

* New translations Appium.md (Arabic)

* New translations Support.md (Polish)

* New translations Browser.md (Polish)

* New translations Support.md (Polish)

* New translations Team.md (Polish)

* New translations Globals.md (Tamil)

* New translations Browser.md (Polish)

* New translations coverage.md (Tamil)

* New translations Browser.md (Polish)

* New translations API.md (Tamil)

* New translations API.md (Tamil)

* New translations Browser.md (Tamil)

* New translations Browser.md (Tamil)

* New translations Browser.md (Tamil)

* New translations Element.md (Tamil)

* New translations Lit.md (Tamil)

* New translations React.md (Tamil)

* New translations React.md (Tamil)

* New translations Solid.md (Tamil)

* New translations Svelte.md (Tamil)

* New translations Preact.md (Tamil)

* New translations Solid.md (Tamil)

* New translations Svelte.md (Tamil)

* New translations Vue.md (Tamil)

* New translations coverage.md (Tamil)

* New translations Autocompletion.md (Tamil)

* New translations Preact.md (Tamil)

* New translations coverage.md (Tamil)

* New translations mocking.md (Tamil)

* New translations JenkinsIntegration.md (Tamil)

* New translations Vue.md (Tamil)

* New translations mocking.md (Tamil)

* New translations TipsAndTricks.md (Tamil)

* New translations JenkinsIntegration.md (Tamil)

* New translations repl.md (Tamil)

* New translations repl.md (Tamil)

* New translations Configuration.md (Persian)

* New translations Babel.md (Tamil)

* New translations BambooIntegration.md (Tamil)

* New translations repl.md (Tamil)

* New translations Configuration.md (Persian)

* New translations BambooIntegration.md (Tamil)

* New translations BambooIntegration.md (Tamil)

* New translations MocksAndSpies.md (Tamil)

* New translations MocksAndSpies.md (Tamil)

* New translations DriverBinaries.md (Tamil)

* New translations Flowcharts.md (Tamil)

* New translations MocksAndSpies.md (Tamil)
2023-05-15 09:01:21 +02:00

5.5 KiB
Raw Blame History

id title
pageobjects Page Object Pattern

Version 5 of WebdriverIO was designed with Page Object Pattern support in mind. By introducing the "elements as first class citizens" principle, it is now possible to build up large test suites using this pattern.

There are no additional packages required to create page objects. It turns out that clean, modern classes provide all necessary features we need:

  • inheritance between page objects
  • lazy loading of elements
  • encapsulation of methods and actions

The goal of using page objects is to abstract any page information away from the actual tests. Ideally, you should store all selectors or specific instructions that are unique for a certain page in a page object, so that you still can run your test after you've completely redesigned your page.

Making A Page Object

First off, we need a main page object that we call Page.js. It will contain general selectors or methods which all page objects will inherit from.

// Page.js
export default class Page {
    constructor() {
        this.title = 'My Page'
    }

    async open (path) {
        await browser.url(path)
    }
}

We will always export an instance of a page object, and never create that instance in the test. Since we are writing end-to-end tests, we always consider the page as a stateless construct—just as each HTTP request is a stateless construct.

Sure, the browser can carry session information and therefore can display different pages based on different sessions, but this shouldn't be reflected within a page object. These sorts of state changes should live in your actual tests.

Let's start testing the first page. For demo purposes, we use The Internet website by Elemental Selenium as guinea pig. Let's try to build a page object example for the login page.

Get -ing Your Selectors

The first step is to write all important selectors that are required in our login.page object as getter functions:

// login.page.js
import Page from './page'

class LoginPage extends Page {

    get username () { return $('#username') }
    get password () { return $('#password') }
    get submitBtn () { return $('form button[type="submit"]') }
    get flash () { return $('#flash') }
    get headerLinks () { return $$('#header a') }

    async open () {
        await super.open('login')
    }

    async submit () {
        await this.submitBtn.click()
    }

}

export default new LoginPage()

Defining selectors in getter functions might look a little weird, but it’s really useful. These functions are evaluated when you access the property, not when you generate the object. With that you always request the element before you do an action on it.

Chaining Commands

WebdriverIO internally remembers the last result of a command. If you chain an element command with an action command, it finds the element from the previous command and uses the result to execute the action. With that you can remove the selector (first parameter) and the command looks as simple as:

await LoginPage.username.setValue('Max Mustermann')

Which is basically the same thing as:

let elem = await $('#username')
await elem.setValue('Max Mustermann')

or

await $('#username').setValue('Max Mustermann')

Using Page Objects In Your Tests

After you've defined the necessary elements and methods for the page, you can start to write the test for it. All you need to do to use the page object is to import (or require) it. That's it!

Since you exported an already-created instance of the page object, importing it lets you start using it right away.

If you use an assertion framework, your tests can be even more expressive:

// login.spec.js
import LoginPage from '../pageobjects/login.page'

describe('login form', () => {
    it('should deny access with wrong creds', async () => {
        await LoginPage.open()
        await LoginPage.username.setValue('foo')
        await LoginPage.password.setValue('bar')
        await LoginPage.submit()

        await expect(LoginPage.flash).toHaveText('Your username is invalid!')
    })

    it('should allow access with correct creds', async () => {
        await LoginPage.open()
        await LoginPage.username.setValue('tomsmith')
        await LoginPage.password.setValue('SuperSecretPassword!')
        await LoginPage.submit()

        await expect(LoginPage.flash).toHaveText('You logged into a secure area!')
    })
})

From the structural side, it makes sense to separate spec files and page objects into different directories. Additionally you can give each page object the ending: .page.js. This makes it more clear that you import a page object.

Going Further

This is the basic principle of how to write page objects with WebdriverIO. But you can build up way more complex page object structures than this! For example, you might have specific page objects for modals, or split up a huge page object into different classes (each representing a different part of the overall web page) that inherit from the main page object. The pattern really provides a lot of opportunities to separate page information from your tests, which is important to keep your test suite structured and clear in times where the project and number of tests grows.

You can find this example (and even more page object examples) in the example folder on GitHub.