Playwright Python — справочникНа главный сайт

Обзор

Playwright позволяет сохранять состояние аутентификации между тестами. Это избавляет от необходимости повторного входа в систему в каждом тесте. Состояние включает cookies, localStorage и sessionStorage.

Сохранение состояния — storage_state()

Метод context.storage_state() возвращает объект с куками и localStorage. Можно сохранить результат в файл для последующего использования:

from playwright.sync_api import sync_playwright

def save_auth():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        context = browser.new_context()
        page = context.new_page()
        page.goto("https://example.com/login")
        page.fill("#username", "admin")
        page.fill("#password", "secret")
        page.click("button[type='submit']")
        page.wait_for_url("**/dashboard")
        # Сохраняем состояние в файл
        context.storage_state(path="auth.json")
        browser.close()
Важно: Файл auth.json содержит сериализованные cookies и localStorage. Храните его в безопасности — он даёт доступ к аутентифицированной сессии.

Восстановление сессии — storage_state в new_context()

Передайте путь к сохранённому файлу в параметр storage_state при создании нового контекста:

with sync_playwright() as p:
    browser = p.chromium.launch()
    context = browser.new_context(storage_state="auth.json")
    page = context.new_page()
    page.goto("https://example.com/dashboard")
    # Уже аутентифицирован — страница загрузится без редиректа на логин

Получение состояния как dict

context.storage_state() без аргументов возвращает Python-словарь:

state = context.storage_state()
print(state["cookies"])       # список кук
print(state["origins"])      # localStorage по доменам

Словарь можно передать напрямую в new_context(storage_state=state) без сохранения в файл.

Экспорт в файл

# Прямое сохранение
context.storage_state(path="auth.json")

# Через страницу
page.context.storage_state(path="auth.json")

Аутентификация через UI — полный цикл

Типичный сценарий: один раз выполнить логин, сохранить состояние, затем использовать его во всех тестах.

# conftest.py
import pytest
from playwright.sync_api import sync_playwright

AUTH_FILE = "auth.json"

@pytest.fixture(scope="session")
def browser_context(playwright):
    browser = playwright.chromium.launch()
    context = browser.new_context(storage_state=AUTH_FILE)
    yield context
    browser.close()

@pytest.fixture(scope="session")
def auth_state(playwright):
    # Одноразовый логин
    browser = playwright.chromium.launch(headless=False)
    context = browser.new_context()
    page = context.new_page()
    page.goto("https://example.com/login")
    page.fill("#username", "admin")
    page.fill("#password", "secret")
    page.click("button[type='submit']")
    page.wait_for_url("**/dashboard")
    context.storage_state(path=AUTH_FILE)
    browser.close()
    return AUTH_FILE
Совет: Используйте scope="session" для фикстуры аутентификации. Состояние сохраняется один раз и используется во всех тестах. При необходимости перелогиниться — удалите файл auth.json.

Cookies — ручная установка

Метод context.add_cookies() добавляет куки в контекст:

context.add_cookies([{
    "name": "session_id",
    "value": "abc123",
    "domain": "example.com",
    "path": "/"
}])

Получение кук

cookies = context.cookies()
for cookie in cookies:
    print(cookie["name"], cookie["value"])

localStorage и токены через page.evaluate()

Установка:

page.evaluate("""() => {
    localStorage.setItem('token', 'my-jwt-token');
    localStorage.setItem('user', JSON.stringify({id: 1, role: 'admin'}));
}""")

Чтение:

token = page.evaluate("localStorage.getItem('token')")
user = page.evaluate("JSON.parse(localStorage.getItem('user'))")

HTTP Basic Auth

Playwright поддерживает HTTP Basic Authentication через параметр http_credentials:

context = browser.new_context(
    http_credentials={
        "username": "admin",
        "password": "password123"
    }
)

Теперь все запросы в этом контексте будут содержать заголовок Authorization: Basic ....

Внимание: HTTP Basic Auth передаёт учётные данные в открытом виде (base64). Используйте только через HTTPS в production.

Полный пример аутентификации

from playwright.sync_api import sync_playwright
import json

def auth_flow():
    with sync_playwright() as p:
        # Шаг 1: Логин через UI
        browser = p.chromium.launch(headless=False)
        context = browser.new_context()
        page = context.new_page()
        page.goto("https://example.com/login")
        page.fill("input[name='login']", "user")
        page.fill("input[name='password']", "pass")
        page.click("button[type='submit']")
        page.wait_for_selector(".avatar")

        # Шаг 2: Сохраняем состояние
        state = context.storage_state()
        with open("auth.json", "w") as f:
            json.dump(state, f, indent=2)
        browser.close()

        # Шаг 3: Используем состояние в новом контексте
        browser2 = p.chromium.launch()
        context2 = browser2.new_context(storage_state="auth.json")
        page2 = context2.new_page()
        page2.goto("https://example.com/dashboard")
        assert page2.locator(".avatar").is_visible()
        browser2.close()

auth_flow()

Хранение state между тестами — pytest фикстура

# conftest.py
import pytest
from playwright.sync_api import sync_playwright

@pytest.fixture(scope="session")
def authenticated_context(playwright):
    # Восстанавливаем сохранённое состояние
    browser = playwright.chromium.launch()
    context = browser.new_context(storage_state="auth.json")
    yield context
    browser.close()

# test_dashboard.py
def test_dashboard(authenticated_context):
    page = authenticated_context.new_page()
    page.goto("https://example.com/dashboard")
    assert page.locator("h1").text_content() == "Dashboard"