Шаблон об'єкта сторінки
Версія 5 WebdriverIO розроблена з урахуванням підтримки шаблону об'єкта сторінки. Впровадивши принцип "елементів як першокласних громадян", тепер можливо створювати великі тестові набори за допомогою цього шаблону.
Для створення об'єктів сторінки не потрібні додаткові пакети. Виявляється, що чисті, сучасні класи надають усі необхідні функції:
- успадкування між об'єктами сторінки
- ліниве завантаження елементів
- інкапсуляція методів та дій
Мета використання об'єктів сторінки - абстрагувати будь-яку інформацію про сторінку від самих тестів. В ідеалі, ви повинні зберігати всі селектори або особливі інструкції, які є унікальними для певної сторінки, в об'єкті сторінки, щоб ви все ще могли запускати свій тест після повного редизайну вашої сторінки.
Створення об'єкта сторінки
Спочатку нам потрібен головний об'єкт сторінки, який ми назвемо Page.js
. Він міститиме загальні селектори або методи, які успадковуватимуть усі об'єкти сторінки.
// Page.js
export default class Page {
constructor() {
this.title = 'My Page'
}
async open (path) {
await browser.url(path)
}
}
Ми завжди export
екземпляр об'єкта сторінки та ніколи не створюємо цей екземпляр у тесті. Оскільки ми пишемо наскрізні тести, ми завжди розглядаємо сторінку як конструкцію без стану - так само, як кожен HTTP-запит є конструкцією без стану.
Звичайно, браузер може зберігати інформацію про сесії і тому може відображати різні сторінки на основі різних сесій, але це не повинно відображатися в об'єкті сторінки. Такі зміни стану повинні бути у ваших фактичних тестах.
Давайте почнемо тестувати першу сторінку. Для демонстраційних цілей ми використовуємо веб-сайт The Internet від Elemental Selenium як піддослідного. Спробуємо створити приклад об'єкта сторінки для сторінки входу.
Отримання селекторів через Get
Перший крок - написати всі важливі селектори, необхідні в нашому об'єкті login.page
, як функції getter:
// 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()
Визначення селекторів у функціях getter може виглядати дивно, але це дуже корисно. Ці функції оцінюються коли ви отримуєте доступ до властивості, а не коли ви створюєте об'єкт. Таким чином, ви завжди запитуєте елемент перед тим, як виконувати над ним дію.
Ланцюжкові команди
WebdriverIO внутрішньо запам'ятовує останній результат команди. Якщо ви поєднуєте команду елемента з командою дії, він знаходить елемент з попередньої команди і використовує результат для виконання дії. Таким чином, ви можете видалити селектор (перший параметр), і команда виглядає так просто:
await LoginPage.username.setValue('Max Mustermann')
Що по суті те саме, що й:
let elem = await $('#username')
await elem.setValue('Max Mustermann')
або
await $('#username').setValue('Max Mustermann')
Використання об'єктів сторінки у ваших тестах
Після того, як ви визначили необхідні елементи та методи для сторінки, ви можете розпочати написання тесту для неї. Все, що вам потрібно зробити для використання об'єкта сторінки, це import
(або require
) його. От і все!
Оскільки ви експортували вже створений екземпляр об'єкта сторінки, імпортуючи його, ви можете одразу почати його використовувати.
Якщо ви використовуєте фреймворк для тверджень, ваші тести можуть бути ще більш виразними:
// 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!')
})
})
З структурної точки зору має сенс розділяти файли специфікацій та об'єкти сторінки на різні каталоги. Крім того, ви можете дати кожному об'єкту сторінки закінчення: .page.js
. Це робить більш зрозумілим, що ви імпортуєте об'єкт сторінки.
Рухаючись далі
Це основний принцип написання об'єктів сторінки з WebdriverIO. Але ви можете створювати набагато складніші структури об'єктів сторінки, ніж це! Наприклад, у вас можуть бути спеціальні об'єкти сторінки для модальних вікон, або ви можете розділити величезний об'єкт сторінки на різні класи (кожен представляє різну частину загальної веб-сторінки), які успадковуються від головного об'єкта сторінки. Цей шаблон дійсно надає багато можливостей для відокремлення інформації про сторінку від ваших тестів, що важливо для збереження структури та ясності вашого тестового набору в часи, коли проект і кількість тестів зростають.
Ви можете знайти цей приклад (і ще більше прикладів об'єктів сторінки) у папці прикладів
на GitHub.