Аутентификация
Сохранение и восстановление сессии, куки, HTTP Basic Auth, localStorage
Обзор
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 ....
Полный пример аутентификации
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"