Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
hyva-themes avatar

Hyva Playwright Test

  • 780 installs
  • 78 repo stars
  • Updated July 31, 2026
  • hyva-themes/hyva-ai-tools

hyva-playwright-test is a Claude Code skill that writes Playwright end-to-end tests for Hyvä Magento themes with Alpine.js-aware selectors for developers testing storefront UI behavior.

About

hyva-playwright-test is a Playwright testing skill tailored to Hyvä Magento storefronts that replaced Luma KnockoutJS, RequireJS, and jQuery with Alpine.js and Tailwind CSS. Playwright strict mode rejects ambiguous locators, which clashes with Alpine.js DOM patterns where hidden elements persist on the page. The skill triggers on phrases like write playwright test, playwright alpine, test hyva page, e2e test, and playwright selector. Developers use it when creating page objects, debugging flaky locators, or adding E2E coverage for Hyvä checkout and component flows.

  • Handles Alpine.js hidden x-show elements that trigger Playwright strict mode failures
  • Provides scoped selectors targeting the #messages container for success and error messages
  • Documents common selector pitfalls specific to Hyvä + Tailwind storefronts
  • Includes patterns for writing page objects and debugging flaky Alpine tests
  • Trigger phrases: "write playwright test", "playwright alpine", "test hyva page"

Hyva Playwright Test by the numbers

  • 780 all-time installs (skills.sh)
  • +31 installs in the week ending Aug 2, 2026 (Skillselion tracking)
  • Ranked #561 of 2,153 Testing & QA skills by installs in the Skillselion catalog
  • Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/hyva-themes/hyva-ai-tools --skill hyva-playwright-test

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs780
repo stars78
Last updatedJuly 31, 2026
Repositoryhyva-themes/hyva-ai-tools

How do you write Playwright tests for Hyvä Alpine.js themes?

Generate reliable Playwright end-to-end tests for Hyvä Magento themes that correctly handle Alpine.js component behavior.

Who is it for?

Magento developers on Hyvä themes who need Playwright E2E tests that handle Alpine.js DOM and strict-mode locator rules.

Skip if: Luma-only Magento shops, non-Magento React apps, or teams not using Playwright for browser testing.

When should I use this skill?

User asks to write Playwright tests, debug Hyvä selectors, or mentions Alpine.js locators on a Hyvä Magento storefront.

What you get

Playwright spec files, Hyvä page objects, and Alpine.js-safe locator strategies for Magento storefronts.

  • Playwright spec files
  • Page object definitions
  • Alpine.js-safe locator recipes

Files

SKILL.mdMarkdownGitHub ↗

Writing Playwright Tests for Hyvä + Alpine.js

Overview

Hyvä replaces Luma's KnockoutJS/RequireJS/jQuery with Alpine.js + Tailwind CSS. Playwright's strict mode (rejects locators matching multiple elements) conflicts with Alpine.js DOM patterns where hidden elements exist throughout the page. This skill documents pitfalls and solutions discovered while writing Playwright tests for Hyvä storefronts.

The #1 Rule: Hidden Alpine Elements

Hyvä templates scatter elements like <div x-show="displayErrorMessage" class="message error"> throughout the DOM. These are invisible but present, so a bare selector like .message.error matches both hidden and visible instances, causing Playwright strict mode violations.

Always scope page-level messages to the `#messages` container:

// WRONG — matches hidden Alpine x-show elements throughout DOM
await expect(page.locator('.message.success')).toContainText('Added to cart');
await expect(page.locator('.message-error')).toContainText('Error');

// RIGHT — scoped to the visible messages container
await expect(page.locator('#messages .message.success')).toContainText('Added to cart');
await expect(page.locator('#messages .message-error, #messages .message.error')).toContainText('Error');

Never use: bare .message, .message.error, .message.success, or div.message as selectors.

Exception — inline page messages: Not all .message elements are flash messages. The search results "no results" notice (.message.notice) renders as static inline content inside #maincontent, not inside the #messages container. For these inline messages, the bare class selector is correct.

Selector Strategy

Follow Playwright's recommended locator priority:

1. `getByRole()` — always prefer — closest to how users perceive the page. Avoids text ambiguity where the same text appears in headings, links, breadcrumbs, and sr-only spans. 2. `getByLabel()` — for form controls (checkboxes, inputs with associated labels). 3. `getByText()` — for non-interactive elements, scoped to a container (e.g., page.locator('#maincontent').getByText(...)). 4. `getByPlaceholder()`, `getByAltText()` — for inputs and images respectively. 5. `getByTestId()` — when Hyvä provides data-testid attributes or when adding custom test IDs. 6. CSS selectors — last resort, only when user-facing locators aren't available. Prefer aria-* attribute selectors (e.g., [aria-label="pagination"], [aria-current="page"]) over class-based selectors. When CSS is necessary, scope to a unique container (e.g., #messages .message.success).

Avoid: :visible pseudo-selector — per Playwright docs, "it's usually better to find a more reliable way to uniquely identify the element." Scope to a container or use role/attribute selectors instead. Only use :visible as an absolute last resort when the DOM provides no other way to distinguish elements.

Alpine.js Interaction Patterns

PatternProblemSolution
x-show hidden elementsStrict mode: multiple matchesScope to unique container (#messages), use role/attribute selectors
x-defer="intersect"Element not initialized until visiblescrollIntoViewIfNeeded() before interacting
x-if (template)Elements don't exist in DOM until condition trueClick the trigger first, then query children
x-model on inputsAlpine clears value after form submitDon't assert input value post-submit; verify via success message
x-text / x-html asyncCart badge updates asynchronouslyUse web-first assertions with timeout: not.toHaveText('0', { timeout: 15_000 })
x-show submenusHidden until hoverhover() on parent before clicking child
Alpine form revealFields hidden until checkbox checkedwaitFor({ state: 'visible' }) after checking the checkbox
press('Enter') on inputMay submit Alpine-bound form unexpectedlyPrefer explicit .click() on submit button

Assertions

Always use web-first assertions that auto-wait and retry:

// DO — auto-retries             // DON'T — no retry
await expect(loc).toBeVisible(); // expect(await loc.isVisible()).toBe(true);
await expect(loc).toContainText('X'); // expect(await loc.textContent()).toContain('X');

For async Alpine.js updates (cart counts, prices), use extended timeouts on the assertion — never waitForTimeout():

// Cart count updates asynchronously via Alpine x-text
await expect(page.locator('#menu-cart-icon span[x-text="summaryCount"]'))
  .not.toHaveText('0', { timeout: 15_000 });

Hyvä vs Luma Selector Differences

ElementHyvä SelectorLuma Selector
Pagination navgetByRole('navigation', { name: 'pagination' })ul.pages-items
Page linkgetByRole('link', { name: 'Page 2' }).pages-items li a
Active page[aria-current="page"]<strong> element
Filter buttongetByRole('button', { name: 'Color filter' }).filter-options-title
Cart icon badge#menu-cart-icon > span[x-text="summaryCount"].counter-number
Account menu#customer-menu + nav.customer-menu
Success message#messages .message.success.message-success
Error message#messages .message-error, #messages .message.error.message-error
Main menugetByRole('navigation', { name: 'Main menu' })nav.navigation
Footer navgetByRole('navigation', { name: 'Company Menu' }).getByRole('link', { name })nav ul li:nth-child(N) a
Product image#gallery img[itemprop="image"]#gallery img:visible
Add to Cart (card)getByRole('button', { name: /Add to Cart/ }).first()button.btn-primary:visible

References

See references/ for code examples. Load files relevant to the current task:

Always useful:

  • [page-object-patterns.md](references/page-object-patterns.md) — Page object structure, navigation, form submits, redirects
  • [selector-patterns.md](references/selector-patterns.md) — Before/after selector fixes (messages, text ambiguity, forms)

Page-specific (load when testing that page):

  • [cart-patterns.md](references/cart-patterns.md) — Cart spinner wait, quantity changes, mini cart
  • [product-patterns.md](references/product-patterns.md) — Bundle quantities, gallery images
  • [account-patterns.md](references/account-patterns.md) — Password change (Alpine checkbox reveal)
  • [category-patterns.md](references/category-patterns.md) — Filters (x-defer scroll), pagination (ARIA)

<!-- Copyright © Hyvä Themes https://hyva.io. All rights reserved. Licensed under OSL 3.0 -->

Related skills

How it compares

Pick hyva-playwright-test over generic Playwright skills when the storefront runs Hyvä with Alpine.js rather than Luma KnockoutJS patterns.

FAQ

Why do Hyvä storefronts break standard Playwright locators?

hyva-playwright-test addresses Hyvä's Alpine.js DOM, where hidden elements remain in the tree. Playwright strict mode then rejects locators matching multiple nodes—a pattern uncommon in Luma KnockoutJS storefronts.

What trigger phrases activate hyva-playwright-test?

hyva-playwright-test activates on write playwright test, playwright alpine, test hyva page, e2e test, and playwright selector requests while authoring or debugging Hyvä Magento Playwright coverage.

Testing & QAtestingintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.