Agent skill

E2E Testing

by Opentrons in Opentrons/opentrons

E2E testing conventions for Protocol Designer and Labware Library using Playwright + pytest in e2e-testing/.

Apache-2.0Auto-check: notesTesting & QA

Install E2E Testing

skills CLI
$ npx skills add Opentrons/opentrons --skill e2e-testing -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install Opentrons/opentrons e2e-testing --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/Opentrons/opentrons.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.cursor/skills/e2e-testing .claude/skills/e2e-testing && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
e2e-testing
GitHub stars
521
Token cost
~3k tokens
SKILL.md length
781 words
Files
1
Skills in repo
17
Repo updated
First seen
Licence
Apache-2.0

At a glance

E2E testing conventions for Protocol Designer and Labware Library using Playwright + pytest in e2e-testing/.

  • Works in 4 steps: get_by_role() — Semantic HTML roles → get_by_test_id() — Test IDs → get_by_text() — Visible text → …
  • Modifying end-to-end tests
  • SKILL.md covers Project Overview, Directory Layout, Architecture — Page Object Model and Environment Configuration, plus 6 more sections
  • Calls make, node and uv; reaches staging.designer.opentrons.com and staging.labware.opentrons.com; needs APPLITOOLS_API_KEY

What it does

E2E Testing is an agent skill from Opentrons/opentrons. E2E testing conventions for Protocol Designer and Labware Library using Playwright + pytest in e2e-testing/. Use when writing, running, or modifying end-to-end tests, page objects, or Playwright tests.

Its SKILL.md is about 3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Testing & QA, covering End-to-end testing, Unit testing and Browser testing. It works with Playwright and pytest. The repository describes itself as: Software for writing protocols and running them on the Opentrons Flex and Opentrons OT-2. The licence is Apache-2.0.

When your agent uses it

  • Modifying end-to-end tests
  • Playwright tests

Example prompts

  • “/e2e-testing”

Requirements

  • Python 3
  • Node.js
  • A credential in APPLITOOLS_API_KEY

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. get_by_role() — Semantic HTML roles
  2. get_by_test_id() — Test IDs
  3. get_by_text() — Visible text
  4. get_by_label() — Form labels

What it can do on your machine

Read from SKILL.md and the folder at commit a14fef9. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • make
    • node
    • uv

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • staging.designer.opentrons.com
    • staging.labware.opentrons.com
    • designer.opentrons.com
    • labware.opentrons.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • APPLITOOLS_API_KEY

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

E2E Testing loads about 3k tokens when it runs. Until then it costs about 53 tokens; SKILL.md has 781 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~53
When it runs · the whole SKILL.md, loaded when a task matches
~3k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NoteMentions a .env fileSKILL.md:261
    - `python-dotenv` loads `.env`. Set `APPLITOOLS_API_KEY` to enable

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from Opentrons/opentrons at commit a14fef9, republished under its Apache-2.0 licence (© Opentrons). 781 words, ~2,964 tokens.

Download SKILL.mdSave it as .claude/skills/e2e-testing/SKILL.md (or your agent's skills folder).
name
e2e-testing
description
E2E testing conventions for Protocol Designer and Labware Library using Playwright + pytest in e2e-testing/. Use when writing, running, or modifying end-to-end tests, page objects, or Playwright tests.

E2E Testing Instructions

Project Overview

The e2e-testing directory contains end-to-end tests for Protocol Designer (PD) and Labware Library (LL) using:

  • Playwright — Browser automation (Chromium)
  • pytest — Test framework
  • pytest-playwright — Pytest + Playwright integration
  • uv — Python package manager (lockfile: uv.lock)
  • Python 3.12

Directory Layout

  • automation/base_page.py — Shared BasePage class inherited by all page objects
  • automation/pd_pages/ — PD page objects (import from automation.pd_pages)
  • automation/ll_pages/ — LL page objects (import from automation.ll_pages)
  • tests/pd/ — PD E2E tests (marked @pytest.mark.pdE2E)
  • tests/ll/ — LL E2E tests (marked @pytest.mark.llE2E)
  • fixtures/ — Protocol JSON files, labware definitions, and test data

Architecture — Page Object Model

ALWAYS use Page Object Model and/or Screenplay Pattern when writing or modifying tests.

Shared Base (automation/base_page.py)

BasePage provides: click_button, click_test_id, fill_input, wait_for_visible, dismiss_release_notes_toast, highlight_element, goto. Exposes self.is_sandbox (True when TEST_ENV=sandbox). All page objects inherit from it.

PD Page Objects (automation/pd_pages/)

LandingPage, CreateProtocolWizard, PipetteModal, ModuleConfigPage, DeckConfigPage, ProtocolEditorPage, TransferPage, MixStepForm, ThermocyclerStepPage, ThermocyclerProfileModal, TemperatureStepPage, HeaterShakerStepPage, PlateReaderPage, FlexStackerPage, SettingsPage, Timeline.

LL Page Objects (automation/ll_pages/)

DesktopNavigation, LabwareCreator.

Tests (tests/pd/ and tests/ll/)
  • Import and use page objects — never write raw Playwright selectors in test files
  • Naming: test_<feature>_<scenario>
  • Mark PD tests with @pytest.mark.pdE2E, LL tests with @pytest.mark.llE2E
  • Add @pytest.mark.slow for tests taking >10 seconds
  • Add type annotations: def test_name(page: Page, pd_base_url: str) -> None:
Example — PD Page Object
python
"""Module for <page name> interactions."""

from playwright.sync_api import Page
from automation.base_page import BasePage


class MyPage(BasePage):
    """Page object for <page name>."""

    def __init__(self, page: Page) -> None:
        super().__init__(page)

    def click_submit_button(self) -> None:
        """Click the submit button."""
        self.click_button("Submit")

    def fill_protocol_name(self, name: str) -> None:
        """Fill in the protocol name field."""
        self.fill_input("protocolName", name)
Example — PD Test
python
import pytest
from playwright.sync_api import Page
from automation.pd_pages import LandingPage, MyPage


@pytest.mark.pdE2E
def test_my_feature(page: Page, pd_base_url: str) -> None:
    """Test description here."""
    landing = LandingPage(page)
    landing.wait_for_page_load()

    my_page = MyPage(page)
    my_page.fill_protocol_name("Test Protocol")
    my_page.click_submit_button()
Example — LL Test
python
import pytest
from playwright.sync_api import Page
from automation.ll_pages import DesktopNavigation


@pytest.mark.llE2E
def test_nav_loads(page: Page, ll_base_url: str) -> None:
    """Verify navigation renders."""
    page.goto(f"{ll_base_url}/")
    nav = DesktopNavigation(page)
    nav.wait_for_loaded()

Environment Configuration

Tests run against different environments via TEST_ENV:

  • local (default): Auto-builds and serves the app (PD on ports 4173-4175, LL on ports 4176-4178)
  • staging: PD → https://staging.designer.opentrons.com / LL → https://staging.labware.opentrons.com
  • prod: PD → https://designer.opentrons.com / LL → https://labware.opentrons.com
  • sandbox: TODO — Not implemented (requires branch-specific URLs)
conftest.py Fixtures
FixtureScopePurpose
pd_base_urlsessionResolves PD URL; starts local preview server when TEST_ENV=local
ll_base_urlsessionResolves LL URL; starts local preview server when TEST_ENV=local
pagefunctionCreates a Playwright page, navigates to the correct app URL based on test markers, saves video
browser_context_argssessionViewport 1280x720, video recording
browser_type_launch_argssessionHeadless/headed, slow_mo
eyesfunctionApplitools Eyes session (or None)
eyes_singletonsessionShared Applitools Eyes instance
Key Environment Variables
VariableDefaultNotes
TEST_ENVlocallocal, staging, prod, sandbox
HEADLESS(unset)true / false; overrides default
SKIP_SERVER_STARTfalseSkip automatic server build+serve
PD_SERVER_URLautoOverride PD URL
LL_SERVER_URLautoOverride LL URL
LL_SERVER_PORT4176Preferred port for LL local server
APPLITOOLS_API_KEY(unset)Enable Applitools visual checks

Development Commands

ALWAYS run before committing:

bash
make format       # Auto-format (ruff format + ruff check --fix)
make typecheck    # Run mypy
make check        # lint + typecheck combined
make prep         # format + typecheck

Running PD tests:

bash
make test-pd-local                               # Headless, chromium
make test-pd-local-headed                        # Headed, 250ms slow-mo
make test-pd-local PYTEST_ARGS="-k test_name"    # Run one test
make test-pd-staging                             # Against staging
make test-pd-prod                                # Against prod
make test-pd-debug                               # Headed, 1000ms slow-mo, verbose

Running LL tests:

bash
make test-ll-local                               # Headless, chromium
make test-ll-local-headed                        # Headed
make test-ll-staging                             # Against staging
make test-ll-prod                                # Against prod

Other targets:

bash
make test-unit      # Unit tests only
make troubleshoot   # Re-run last failures in headed mode
make codegen        # Playwright Inspector/recorder (default localhost:4173)
make codegen URL=<url>  # Record against custom URL

Code Quality Standards

Type Annotations (REQUIRED)

All functions must have type annotations:

python
# Good
def my_function(page: Page, name: str) -> None:
    """Docstring here."""
    pass

# Bad — Missing type annotations
def my_function(page, name):
    pass

Note: mypy is strict for automation/ but relaxed (disallow_untyped_defs = false) for tests/.

Imports

Import page objects from the package, not from internal modules:

python
# Good
from automation.pd_pages import LandingPage
from automation.ll_pages import LabwareCreator
from automation.base_page import BasePage

# Bad
from automation.pd_pages.landing_page import LandingPage
Docstrings

ALWAYS add docstrings to modules (top of file), classes, and public methods.

Testing Best Practices

Selectors (prefer in order)
  1. get_by_role() — Semantic HTML roles
  2. get_by_test_id() — Test IDs
  3. get_by_text() — Visible text
  4. get_by_label() — Form labels

Avoid CSS selectors (brittle) and XPath (hard to maintain).

Wait for Elements

ALWAYS wait before interacting:

python
# Good — Using BasePage helper
self.wait_for_visible(element, timeout=5000)

# Good — Using Playwright expect
from playwright.sync_api import expect
expect(element).to_be_visible()
element.click()

# Bad — No wait
self.page.get_by_role("button", name="Submit").click()
Show full SKILL.md (317 more words)Show less
Test Independence
  • Don't rely on test execution order
  • Don't share state between tests
  • Clean up handled by fixtures and fresh browser contexts
Test Markers

Every PD test must have @pytest.mark.pdE2E. Every LL test must have @pytest.mark.llE2E. A test cannot have both markers.

Visual Snapshots (Applitools Eyes)

  • Use the eyes pytest fixture (exposed via pytest_plugins = ["eyes"] in conftest.py)
  • python-dotenv loads .env. Set APPLITOOLS_API_KEY to enable
  • In headed mode, eyes yields None (no visual snapshots)
python
from eyes import Eyes

def test_my_feature(page: Page, pd_base_url: str, eyes: Eyes | None) -> None:
    # ... navigate ...
    if eyes is None:
        return
    eyes.check("After navigation")
    eyes.check_element("Timeline", page.get_by_test_id("TimelineToolbox_scrollContainer"))

Common Patterns

Adding a New PD Test
  1. Create/update page objects in automation/pd_pages/
  2. Write test in tests/pd/ using page objects, add @pytest.mark.pdE2E
  3. Add type annotations and docstrings
  4. Run locally: make test-pd-local PYTEST_ARGS="-k test_name"
  5. Check code quality: make check
Adding a New LL Test
  1. Create/update page objects in automation/ll_pages/
  2. Write test in tests/ll/ using page objects, add @pytest.mark.llE2E
  3. Add type annotations and docstrings
  4. Run locally: make test-ll-local PYTEST_ARGS="-k test_name"
  5. Check code quality: make check
Chaining Page Objects
python
def navigate_and_configure(self) -> "NextPage":
    """Navigate to next page and return its page object."""
    self.click_button("Next")
    from .next_page import NextPage
    return NextPage(self.page)

CI/CD Integration

  • .github/workflows/pd-e2e-test.yaml — PD E2E tests
  • .github/workflows/ll-e2e-test.yaml — LL E2E tests
  • .github/workflows/e2e-test-checks.yaml — Lint + typecheck

Troubleshooting

Local Server Issues
  1. Check Node.js version: node --version (should be >= 22.22.0)
  2. Build manually: cd ../protocol-designer && make build or cd ../labware-library && make build
  3. Check memory: PD Makefile sets NODE_OPTIONS=--max-old-space-size=8192
  4. Kill conflicting processes: pkill -9 node
Import Errors
  1. Run: make setup
  2. Verify: uv run python -c "from automation.base_page import BasePage; print('OK')"
Test Timeouts

Default: 300 seconds per test (set in pytest.ini). Per-test override: @pytest.mark.timeout(600). Use make test-pd-debug or make troubleshoot for step-by-step debugging.

DO NOT

  1. Write Playwright selectors directly in test files — USE page objects
  2. Use CSS selectors without justification — USE semantic selectors
  3. Commit without running make check
  4. Skip type annotations — REQUIRED by mypy
  5. Rely on test execution order — tests must be independent
  6. Use time.sleep() — use Playwright's waiting mechanisms
  7. Mark a test with both @pytest.mark.pdE2E and @pytest.mark.llE2E
  8. Import BasePage from automation.pd_pages.base_page — use automation.base_page

© Opentrons, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .cursor/skills/e2e-testing of Opentrons/opentrons.

Open the folder on GitHubat commit a14fef9

Compare with similar skills

E2E Testing next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

E2E Testing compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
E2E Testing this skillOpentrons/opentrons521—~3kAutomated safety check: NotesApache-2.0
Claude Code QAPramodDutta/qaskills232—~2.3kAutomated safety check: PassMIT
E2E Agent Browserjh941213/my-cc-harness126—~3.1kAutomated safety check: NotesNone
Python Testingmacalbert/envilder138—~3.1kAutomated safety check: PassMIT
Control UI E2Eopenclaw/openclaw392k—~2.9kAutomated safety check: PassMIT
VerifyGnathonic/mokuro-reader209—~724Automated safety check: PassGPL-3.0

Similar skills

  • Claude Code QA

    PramodDutta/qaskills

    The complete QA skill for Claude Code — turn Claude into an expert QA engineer that picks the right test type, writes reliable Playwright, Cypress, and pytest tests, eliminates flaky tests, enforces…

    232 GitHub stars~2.3k tokensUpdated 3 days ago
    Testing & QAAuto-check passed
  • E2E Agent Browser

    jh941213/my-cc-harness

    E2E test automation using agent-browser CLI. An agent skill from jh941213/my-cc-harness.

    126 GitHub stars~3.1k tokensUpdated 2 mo ago
    Testing & QAAuto-check: notes
  • Python Testing

    macalbert/envilder

    Mandatory testing conventions including AAA pattern, test naming, assertions, and mocks.

    138 GitHub stars~3.1k tokensUpdated 3 days ago
    Testing & QAAuto-check passed
  • Control UI E2E

    openclaw/openclaw

    A skill your agent uses when designing, testing, fixing, or extending the OpenClaw Control UI GUI, including UI stress-test galleries with feedback inputs, Vitest + Playwright end-to-end checks…

    392k GitHub stars~2.9k tokensUpdated today
    Testing & QAAuto-check passed
  • Verify

    Gnathonic/mokuro-reader

    Verify reader features end-to-end by importing a synthetic volume through the real upload modal and driving the reader with Playwright.

    209 GitHub stars~724 tokensUpdated today
    Testing & QAAuto-check passed
  • Svelte Testing

    spences10/sveltest

    Fix and create Svelte 5 tests with vitest-browser-svelte and Playwright.

    113 GitHub stars~579 tokensUpdated today
    Testing & QAAuto-check passed

More from Opentrons/opentrons

All 17 skills in this repo
  • AI Client

    Opentrons/opentrons

    Conventions for the opentrons-ai-client React/TypeScript frontend — project structure, API integration, state management (Jotai), feature flags, types, and testing.

    521 GitHub stars~1.6k tokensUpdated today
    Auto-check passed
  • AI Server

    Opentrons/opentrons

    Conventions for the opentrons-ai-server FastAPI service — project structure, uv dependency management, settings, testing, Docker, and deployment.

    521 GitHub stars~2.5k tokensUpdated today
    Auto-check: notes
  • Analyses Snapshot Testing

    Opentrons/opentrons

    Conventions for the analyses snapshot testing framework in analyses-snapshot-testing/.

    521 GitHub stars~1.7k tokensUpdated today
    Auto-check passed
  • CSS Modules

    Opentrons/opentrons

    CSS Modules conventions, Stylelint rules, design tokens (spacing, colors, typography, border-radius), and patterns for the Opentrons monorepo.

    521 GitHub stars~2.2k tokensUpdated today
    Auto-check passed
  • Docs

    Opentrons/opentrons

    Authoring and styling guidelines for the Opentrons /docs MkDocs project.

    521 GitHub stars~2.8k tokensUpdated today
    Auto-check passed
  • JS Package Testing

    Opentrons/opentrons

    Vite demo and Playwright + Applitools tests for packed @opentrons JS packages in js-package-testing/.

    521 GitHub stars~1.2k tokensUpdated today
    Auto-check: notes

Categories

Questions about E2E Testing

What does E2E Testing do?

E2E testing conventions for Protocol Designer and Labware Library using Playwright + pytest in e2e-testing/. E2E Testing is an agent skill from Opentrons/opentrons. E2E testing conventions for Protocol Designer and Labware Library using Playwright + pytest in e2e-testing/.

When should I use E2E Testing?

E2E Testing fits situations like: modifying end-to-end tests; playwright tests.

How do I install E2E Testing in Claude Code?

Run `npx skills add Opentrons/opentrons --skill e2e-testing -a claude-code`. Or copy the skill folder (.cursor/skills/e2e-testing in Opentrons/opentrons) into .claude/skills/e2e-testing in your project. Claude Code loads it when a task matches its description.

How do I install E2E Testing in Codex?

Run `npx skills add Opentrons/opentrons --skill e2e-testing -a codex`. Or copy the skill folder (.cursor/skills/e2e-testing in Opentrons/opentrons) into .agents/skills/e2e-testing in your project. Codex loads it when a task matches its description.

Can I use E2E Testing in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Opentrons/opentrons --skill e2e-testing -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/e2e-testing, .gemini/skills/e2e-testing, .github/skills/e2e-testing and .opencode/skills/e2e-testing in your project.

What does E2E Testing need to run?

Going by SKILL.md and its folder, E2E Testing needs the command-line tools its instructions call (make, node and uv) and credentials named APPLITOOLS_API_KEY. Our summary lists: Python 3; Node.js; A credential in APPLITOOLS_API_KEY.

Does E2E Testing access the network?

SKILL.md names 4 domains. In commands or code: staging.designer.opentrons.com, staging.labware.opentrons.com, designer.opentrons.com and labware.opentrons.com; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.

Is E2E Testing safe to install?

Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does E2E Testing use?

E2E Testing is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does E2E Testing use?

About 3k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to E2E Testing?

Skills that share tags, products or a category with E2E Testing: Claude Code QA (PramodDutta/qaskills, 232 stars), E2E Agent Browser (jh941213/my-cc-harness, 126 stars), Python Testing (macalbert/envilder, 138 stars) and Control UI E2E (openclaw/openclaw, 392k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains E2E Testing?

Opentrons (a GitHub organization) maintains it in Opentrons/opentrons, which has 521 GitHub stars. The repository holds 17 skills in this directory. The repository was last updated on October 7, 2026.

Source: Opentrons/opentrons on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.