149 lines
8.7 KiB
Python
149 lines
8.7 KiB
Python
"""Offline editor UX check: python tests/browser_council_editor.py."""
|
|
import os
|
|
from pathlib import Path
|
|
import sys
|
|
from urllib.parse import urlsplit
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
|
|
from fastapi.testclient import TestClient
|
|
from playwright.sync_api import expect, sync_playwright
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import sessionmaker
|
|
from sqlalchemy.pool import StaticPool
|
|
|
|
from app.config import Settings, get_settings
|
|
from app.db import Base, get_db
|
|
from app.main import app
|
|
from app.models import Employee, EmployeePublication
|
|
from app.security import SESSION_COOKIE, sign_session
|
|
from app.services import council
|
|
|
|
|
|
def main():
|
|
engine = create_engine('sqlite://', connect_args={'check_same_thread': False}, poolclass=StaticPool)
|
|
Base.metadata.create_all(engine)
|
|
factory = sessionmaker(bind=engine)
|
|
with factory() as db:
|
|
person = Employee(profile_key='editor', full_name='Иванов Иван Иванович',
|
|
canonical_url='https://www.hse.ru/staff/test',
|
|
current_data={'sections': [{'title': 'Учёные степени', 'items': ['Доктор технических наук']}]})
|
|
db.add(person)
|
|
db.flush()
|
|
db.add(EmployeePublication(employee_id=person.id, title='Исследование передачи данных',
|
|
year=2024, publication_type='ARTICLE', raw_data={'journal': 'Журнал связи'}, source_hash='editor'))
|
|
db.commit()
|
|
|
|
def database():
|
|
with factory() as db:
|
|
yield db
|
|
|
|
settings = Settings(_env_file=None, session_secret='browser-editor-test', admin_username='admin', admin_password='test')
|
|
original = council._articles_by_author
|
|
council._articles_by_author = lambda: {}
|
|
app.dependency_overrides[get_db] = database
|
|
app.dependency_overrides[get_settings] = lambda: settings
|
|
client = TestClient(app)
|
|
output = Path('.impeccable/review/council-editor')
|
|
output.mkdir(parents=True, exist_ok=True)
|
|
|
|
def serve(route):
|
|
request = route.request
|
|
url = urlsplit(request.url)
|
|
response = client.request(request.method, url.path + ('?' + url.query if url.query else ''),
|
|
content=request.post_data_buffer,
|
|
headers={k: v for k, v in request.headers.items() if k in {'content-type', 'x-council-edit'}})
|
|
route.fulfill(status=response.status_code, body=response.content,
|
|
headers={k: v for k, v in response.headers.items() if k in {'content-type', 'content-disposition'}})
|
|
|
|
try:
|
|
with sync_playwright() as playwright:
|
|
browser = playwright.chromium.launch(executable_path=os.getenv('BROWSER_EXECUTABLE'))
|
|
context = browser.new_context(viewport={'width': 1440, 'height': 1000})
|
|
context.route('**/*', serve)
|
|
page = context.new_page()
|
|
errors = []
|
|
page.on('pageerror', lambda error: errors.append(str(error)))
|
|
page.goto('http://miem.test/admin/council')
|
|
page.locator('.council__candidate-summary').click()
|
|
expect(page.locator('.council__article strong')).to_have_text('Исследование передачи данных')
|
|
expect(page.locator('[data-council-edit]')).to_have_count(0)
|
|
expect(page.locator('[data-council-dialog]')).to_have_count(0)
|
|
article = page.locator('[data-council-article]')
|
|
pencil = article.locator('[data-council-edit]')
|
|
client.cookies.set(SESSION_COOKIE, sign_session('admin', settings))
|
|
page.reload()
|
|
page.locator('.council__candidate-summary').click()
|
|
article.focus()
|
|
page.keyboard.press('Enter')
|
|
expect(pencil).to_be_focused()
|
|
page.keyboard.press('Enter')
|
|
expect(page.get_by_label('Название статьи', exact=True)).to_have_value('Исследование передачи данных')
|
|
page.get_by_label('Название статьи', exact=True).fill('Уточнённое исследование')
|
|
page.get_by_label('Название журнала', exact=True).fill('Новый журнал')
|
|
page.get_by_role('dialog').get_by_label('Квартиль').select_option('Q1')
|
|
page.screenshot(path=str(output / 'edit-desktop.png'))
|
|
page.set_viewport_size({'width': 320, 'height': 844})
|
|
assert page.evaluate('document.documentElement.scrollWidth <= innerWidth')
|
|
assert page.get_by_role('dialog').evaluate('e => e.scrollWidth <= e.clientWidth')
|
|
page.screenshot(path=str(output / 'edit-mobile.png'))
|
|
page.get_by_role('button', name='Сохранить', exact=True).click()
|
|
expect(article.locator('strong')).to_have_text('Уточнённое исследование')
|
|
expect(page.locator('.council__candidate')).to_have_attribute('open', '')
|
|
with context.expect_page() as opened:
|
|
page.get_by_role('link', name='Статьи, журналы и квартили').click()
|
|
window = opened.value
|
|
window.wait_for_load_state()
|
|
window.on('pageerror', lambda error: errors.append(str(error)))
|
|
window.get_by_label('ФИО сотрудника').fill('Иванов')
|
|
window.get_by_role('searchbox', name='Название статьи', exact=True).fill('уточнённое')
|
|
window.get_by_role('searchbox', name='Название журнала', exact=True).fill('новый')
|
|
window.get_by_role('button', name='Найти', exact=True).click()
|
|
expect(window.locator('[data-council-article]')).to_have_count(1)
|
|
for width in (1440, 390, 320):
|
|
window.set_viewport_size({'width': width, 'height': 900})
|
|
assert window.evaluate('document.documentElement.scrollWidth <= innerWidth')
|
|
if width in (1440, 320):
|
|
window.screenshot(path=str(output / f'list-{width}.png'), full_page=True)
|
|
window.locator('[data-council-article] strong').click()
|
|
window.locator('[data-council-edit]').click()
|
|
window.get_by_role('dialog').get_by_label('Квартиль').select_option('Q2')
|
|
window.locator('[data-edit-specialties] summary').click()
|
|
window.get_by_label('Использовать связь из справочников').uncheck()
|
|
window.locator('[name="specialty_codes"][value="1.2.2"]').check()
|
|
window.get_by_role('button', name='Сохранить', exact=True).click()
|
|
expect(window.get_by_text('Журнал: Новый журнал · Квартиль: Q2', exact=False)).to_be_visible()
|
|
expect(window.get_by_text('Специальности журнала: 1.2.2 · ручная связь', exact=True)).to_be_visible()
|
|
# The original tab now carries a stale revision.
|
|
article.locator('strong').click()
|
|
pencil.click()
|
|
page.get_by_role('button', name='Сохранить', exact=True).click()
|
|
expect(page.get_by_role('alert')).to_contain_text('Данные уже изменены')
|
|
page.keyboard.press('Escape')
|
|
page.reload()
|
|
page.locator('.council__candidate-summary').click()
|
|
expect(page.get_by_text('Квартиль: Q2', exact=False)).to_be_visible()
|
|
page.get_by_label('Отрасль оценки').select_option('физико-математические')
|
|
page.get_by_role('button', name='Применить', exact=True).click()
|
|
expect(page.get_by_label('Отрасль оценки')).to_have_value('физико-математические')
|
|
page.get_by_label('Специальность ВАК').select_option('1.2.2')
|
|
page.get_by_role('button', name='Применить', exact=True).click()
|
|
expect(page.locator('.council__candidate')).to_have_count(1)
|
|
page.locator('.council__candidate-summary').click()
|
|
expect(page.get_by_text('Публикаций по выбранной специальности: 1', exact=True)).to_be_visible()
|
|
window.get_by_role('searchbox', name='Название статьи', exact=True).fill('Нет совпадений')
|
|
window.get_by_role('button', name='Найти', exact=True).click()
|
|
expect(window.get_by_text('Статьи не найдены.', exact=False)).to_be_visible()
|
|
assert not errors, errors
|
|
browser.close()
|
|
finally:
|
|
council._articles_by_author = original
|
|
app.dependency_overrides.clear()
|
|
client.close()
|
|
engine.dispose()
|
|
print(f'Council editor browser checks passed; screenshots: {output}')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|