"""E2E: два терминала — DnD/sync (баготест #4).""" from __future__ import annotations import pytest from tests.e2e.recipes_e2e_helpers import ( drag_reorder_recipe, list_dom_recipe_ids, period_recipe_ids, ) pytestmark = pytest.mark.e2e SCENARIO_DUAL_E2E_DND_SYNC = "DUAL_E2E_DND_SYNC" SCENARIO_DUAL_E2E_TRANSFER_REORDER = "DUAL_E2E_TRANSFER_REORDER" def test_dual_reorder_visible_on_both_terminals( page_a, page_b, dual_harness, live_server_a_url, live_server_b_url ) -> None: SCENARIO_DUAL_E2E_DND_SYNC # noqa: F841 disp_id = dual_harness._e2e_disp_id # type: ignore[attr-defined] period_a = dual_harness._e2e_period_a # type: ignore[attr-defined] r1 = dual_harness._e2e_r1 # type: ignore[attr-defined] r2 = dual_harness._e2e_r2 # type: ignore[attr-defined] for page, url in ((page_a, live_server_a_url), (page_b, live_server_b_url)): page.locator(f'[data-action="select-dispenser"][data-dispenser-id="{disp_id}"]').click() page.locator(f'[data-action="select-period"][data-period-id="{period_a}"]').click() page.wait_for_selector("#recipesList .list-item", timeout=10000) assert list_dom_recipe_ids(page_a) == [r1, r2] assert list_dom_recipe_ids(page_b) == [r1, r2] drag_reorder_recipe(page_a, r1, direction="down") page_a.wait_for_timeout(600) from tests.e2e.dual_terminal_conftest import sync_both sync_both(dual_harness) page_b.reload() page_b.wait_for_selector("#recipesDashboard", timeout=15000) page_b.locator(f'[data-action="select-dispenser"][data-dispenser-id="{disp_id}"]').click() page_b.locator(f'[data-action="select-period"][data-period-id="{period_a}"]').click() page_b.wait_for_timeout(500) assert period_recipe_ids(page_a, live_server_a_url, period_a) == [r2, r1] assert period_recipe_ids(page_b, live_server_b_url, period_a) == [r2, r1] def test_dual_edit_recipe_name_both_see( page_a, page_b, dual_harness, live_server_a_url, live_server_b_url ) -> None: r1 = dual_harness._e2e_r1 # type: ignore[attr-defined] current = page_a.request.get(f"{live_server_a_url}/api/recipes/{r1}") assert current.ok payload = current.json() payload["name"] = "Dual renamed" payload["ingredients"] = payload.get("ingredients") or [] payload["unloading_groups"] = payload.get("unloading_groups") or [] put = page_a.request.put(f"{live_server_a_url}/api/recipes/{r1}", data=payload) assert put.ok, put.text() dual_harness.push_from_terminal("a") with dual_harness.server_ctx(): from app import db from app.models import Recipe from app.services.sync_manager import enqueue_sync_queue_task row = db.session.get(Recipe, r1) if row is not None: row.name = "Dual renamed" db.session.commit() enqueue_sync_queue_task("recipe", r1, "update", priority=2) db.session.commit() from tests.e2e.dual_terminal_conftest import sync_both sync_both(dual_harness) for page, url in ((page_a, live_server_a_url), (page_b, live_server_b_url)): resp = page.request.get(f"{url}/api/recipes/{r1}") assert resp.ok assert resp.json().get("name") == "Dual renamed" def test_dual_copy_paste_unloading_groups( page_a, dual_harness, live_server_a_url, live_server_b_url, page_b ) -> None: """После paste на A sync — B видит рецепт в period B (API).""" period_b = dual_harness._e2e_period_b # type: ignore[attr-defined] r1 = dual_harness._e2e_r1 # type: ignore[attr-defined] src = page_a.request.get(f"{live_server_a_url}/api/recipes/{r1}") assert src.ok body = src.json() body["name"] = f"{body.get('name', 'R')} (копия)" body["ingredients"] = body.get("ingredients") or [] body["unloading_groups"] = body.get("unloading_groups") or [ {"name": "G1", "distribution_type": "percent", "value": 100, "order": 1} ] create = page_a.request.post( f"{live_server_a_url}/api/periods/{period_b}/recipes", data=body, ) assert create.ok or create.status in (200, 201), create.text() new_id = create.json().get("id") if create.ok else None dual_harness.push_from_terminal("a") if new_id: with dual_harness.server_ctx(): from app.services.sync_manager import enqueue_sync_queue_task enqueue_sync_queue_task("recipe", new_id, "create", priority=2) enqueue_sync_queue_task( "period_recipes", f"{period_b}:{new_id}", "create", priority=2 ) from app import db db.session.commit() from tests.e2e.dual_terminal_conftest import sync_both sync_both(dual_harness) listed = page_b.request.get(f"{live_server_b_url}/api/periods/{period_b}/recipes") assert listed.ok assert len(listed.json()) >= 1 rid = new_id or listed.json()[0]["id"] detail = page_b.request.get(f"{live_server_b_url}/api/recipes/{rid}") assert detail.ok groups = detail.json().get("unloading_groups") or [] assert groups def test_dual_transfer_then_reorder_on_b( page_a, page_b, dual_harness, live_server_a_url, live_server_b_url ) -> None: SCENARIO_DUAL_E2E_TRANSFER_REORDER # noqa: F841 disp_id = dual_harness._e2e_disp_id # type: ignore[attr-defined] period_a = dual_harness._e2e_period_a # type: ignore[attr-defined] period_b = dual_harness._e2e_period_b # type: ignore[attr-defined] r2 = dual_harness._e2e_r2 # type: ignore[attr-defined] from tests.e2e.recipes_e2e_helpers import drag_transfer_to_period page_a.locator(f'[data-action="select-dispenser"][data-dispenser-id="{disp_id}"]').click() page_a.locator(f'[data-action="select-period"][data-period-id="{period_a}"]').click() drag_transfer_to_period(page_a, r2, period_b) from tests.e2e.dual_terminal_conftest import sync_both sync_both(dual_harness) page_b.locator(f'[data-action="select-dispenser"][data-dispenser-id="{disp_id}"]').click() page_b.locator(f'[data-action="select-period"][data-period-id="{period_b}"]').click() ids_b = period_recipe_ids(page_b, live_server_b_url, period_b) assert r2 in ids_b