Page Component Object
Object для дискретної частини page, яку можна вкладати в Page Object і повторно використовувати в кількох pages.
Неймінг та структура automation-проєкту →Відеобібліотека
Пошук у нотатках курсу Java з переходом на потрібну секунду.
Object для дискретної частини page, яку можна вкладати в Page Object і повторно використовувати в кількох pages.
Неймінг та структура automation-проєкту →Уточнює Page Object, Page Component Object і допустиму readiness verification.
Неймінг та структура automation-проєкту → Першоджерело ↗Описати typed object з одним boundary field.
Створити валідний object у arrange.
Передати його у create action.
Звірити ті самі expected fields в API response і UI details.
Зберегти seed у failure output.
Один test відтворює data set і виявляє помилку mapping на конкретному checkpoint.
OpenAPI 3.1 Schema Object описує структуру payload через JSON Schema vocabulary. Список required визначає обов’язкові properties; оголошення property саме по собі не робить його обов’язковим.
Design pattern, який відділяє test code від page-specific locators і operations; UI change зазвичай локалізується в одному object.
Неймінг та структура automation-проєкту →Pinned приклад пов’язує API client і Page Object із переходом уроку від прямого UI-flow до reusable automation structure. Код не скопійовано через відсутність LICENSE у repository.
Практика курсу на YOY, домашні завдання та формат ПМП → Першоджерело ↗Коли `BaseTest` починає відповідати за login, конфігурацію та ініціалізацію всіх Page Objects, він перетворюється на надто широкий контейнер. Ініціалізація сторінок переноситься до окремого `Application`, а тест отримує один об'єкт `app` і звертається через нього до потрібної сторінки. У відео цей підхід порівнюється з агрегатором або facade і застерігається, що глобальний God Object погано масштабується на дуже великі паралельні набори тестів. Для невеликого навчального проєкту Application object спрощує сценарії. Якщо система має окремі домени, наприклад сайт і адмінку, їх можна розділити на `WebsiteApplication` та `AdminApplication` замість одного безмежного контейнера.
Login-сценарій переноситься до `LoginPage`: тест передає login і password, а Page Object виконує технічні дії з полями та кнопкою. Поширений варіант — передавати `WebDriver` у constructor кожного Page Object, але це повторює однакову залежність у тестах і сторінках. Для навчального врапера обирається централізований provider, з якого Page Objects отримуватимуть поточний драйвер без constructor plumbing. Водночас пакети розділяються за призначенням: web pages залишаються окремо від common-коду обгортки та від можливих API tests.
Показано, що Java-клас успадковує методи `Object`, зокрема `equals`, `hashCode`, `getClass`, `toString`, `notify`, `wait` та інші. Підказки IntelliJ IDEA відображають ці успадковані методи навіть тоді, коли вони не оголошені безпосередньо в Page Object. Новий метод можна спочатку викликати в тесті, а потім створити в цільовому Page Object через quick fix `Create method`. IDE переносить назву й параметри з місця виклику, після чого до згенерованого методу додається реальна реалізація. У контексті Java викладач уточнює, що такі функції класу коректно називаються методами.
Замість довгого `locator.waitFor` для очікуваного стану використовується динамічний Playwright assertion на `Locator`, наприклад перевірка видимості або тексту. Так очікування і причина падіння залишаються частиною перевірки, а не окремим технічним кроком. Для `HomePage`, `SignInPage`, `ProjectsPage` і сторінки окремого проєкту створюються Page Object-и. Кожен отримує спільний `Page` через constructor, зберігає дії на своїй сторінці та повертає наступний Page Object там, де сценарій переходить далі. Початковий лінійний тест рефакториться у послідовність доменних дій: відкрити home page, увійти, знайти проєкт, відкрити його й перевірити title. Це прибирає locator-и з тесту та залишає у ньому читабельний користувацький сценарій.
Щоб не створювати Page Object-и безпосередньо в кожному тесті, будується невеликий application facade. Він один раз приймає `Page`, створює `HomePage`, `SignInPage`, `ProjectsPage` та інші сторінки у правильному порядку й віддає їх тесту через короткі методи. Під час рефакторингу перевіряється момент ініціалізації: Page Object-и не можна створювати раніше, ніж JUnit integration надасть валідний `Page`. Після перенесення створення у constructor application object отримується стабільний lifecycle без повторюваних `new ...Page(page)` у тесті. У вбудованій Playwright JUnit implementation показано зберігання instances через `ThreadLocal`. Це дає окремі Playwright, Browser, BrowserContext і Page для кожного test thread; tracing lifecycle додатково враховує завершення, падіння або скасування тесту.
Page Object визначається як клас, що описує логічну частину сторінки: цілу сторінку або окремий повторно використовуваний компонент. Для початкового варіанта кожна сторінка отримує окремий клас із діями, доступними користувачеві на ній. У `src/main/java` створюється окрема структура пакетів для вебчастини та сторінок. Після перенесення методу авторизації Selenide стає недоступним у production-коді, бо залежність оголошена через `testImplementation`; її змінюють на `implementation`, тоді як test runner залишається лише в тестовій області. Після синхронізації Gradle IntelliJ IDEA може додати потрібні імпорти через quick fix; невикористані імпорти потрібно регулярно прибирати.
Щоб будувати виклики через крапку, метод Page Object замість `void` повертає поточний тип і завершується `return this`. Так `open()` може повернути `SignInPage`, після чого одразу викликається `loginUser(...)`. У відео цей стиль пов'язують із назвами fluent interface та chain of invocation; у заголовку уроку також використано Chain of responsibility. Повернення `this` зручне для послідовності дій у межах одного Page Object. Повертати з кожного методу наступну сторінку викладач не радить: довгі ланцюжки приховують переходи й ускладнюють code review. Допустимий локальний виняток — компонент або popup, який належить поточній сторінці й природно стає наступним об'єктом взаємодії. Спільні значення, потрібні кільком тестам, переносяться до наявного `BaseTest`, а не дублюються. Для них обирається найвужча достатня видимість, у прикладі — `protected` для класів-нащадків.
Дії та динамічні очікування переносяться в Page Object у порядку, в якому їх викликає сценарій. Перевірку точного тексту можна інкапсулювати методом, що приймає очікуване значення і використовує Selenide `shouldHave`. Це дозволяє Selenide чекати, доки елемент набуде потрібного стану. Якщо перевірка потребує довільної логіки, наприклад порівняння кількості тест-кейсів із порогом, Page Object повертає текст або оброблене значення, а assertion залишається в тесті. TestNG не переносять до `src/main/java`; production-частина отримує дані зі сторінки, тест явно формулює очікування. Викладач рекомендує динамічні очікування там, де це можливо, замість одноразового читання нестабільного UI.
Заняття підсумовує перехід від простого KISS-тесту, доповненого YAGNI, DRY і DAMP, до Page Object-структури з очікуваннями та двома способами перевірок: очікувати значення безпосередньо в об'єкті сторінки або повернути дані в тест для окремого порівняння. Для іменування класів, методів, змінних і тестів радять використовувати терміни, уже закладені розробниками: назви з URL, HTML та мережевих запитів, а також фактичні дії користувача. Наступні тести пропонується одразу писати через Page Object і вдосконалювати назви практикою.
Першим джерелом назви сторінки є route: кореневий шлях підказує home page, а змістовний path — конкретний екран. Якщо це SPA або URL не змінюється, наступним джерелом стає видима назва сторінки: `h1`, `h2`, title чи інший семантичний заголовок. Коли framework генерує сторінку переважно з `div`, треба орієнтуватися на мову продукту та стабільні атрибути DOM. Мета — щоб назва в automation-коді відповідала тому, як екран уже називають користувачі й розробники.