"""Roundtrip sync рецептов через dual harness: confirm и reorder period_recipes.""" from __future__ import annotations import time import unittest from datetime import datetime from app import db from app.models import FeedDispenser, FeedingPeriod, PeriodRecipe, Recipe, SyncQueue from app.services.sync_manager import enqueue_sync_queue_task from tests.helpers.sync_dual_harness import SyncDualInstanceHarness class RecipesSyncRoundtripTests(unittest.TestCase): def setUp(self) -> None: self.harness = SyncDualInstanceHarness() self.harness.start() def tearDown(self) -> None: self.harness.stop() def test_period_recipes_reorder_pull_apply_both_terminals(self) -> None: disp_id = "rt-disp" period_id = "rt-period" r1, r2 = "rt-r1", "rt-r2" with self.harness.server_ctx(): db.session.add_all( [ FeedDispenser( id=disp_id, name="D", farm="F", operator="O", type="dispenser", content_hash="", ), FeedingPeriod(id=period_id, name="P", dispenser_id=disp_id), Recipe(id=r1, name="A", heads_per_trip=1, mixing_time=0, content_hash=""), Recipe(id=r2, name="B", heads_per_trip=1, mixing_time=0, content_hash=""), ] ) db.session.flush() now = datetime.now() for rid, ord_ in ((r1, 1), (r2, 2)): db.session.add( PeriodRecipe( period_id=period_id, recipe_id=rid, order=ord_, created_at=now, created_by="system", updated_by="system", ) ) db.session.commit() for rid in (r1, r2): enqueue_sync_queue_task("recipe", rid, "create", priority=2, target_node_id=None) for rid in (r1, r2): enqueue_sync_queue_task( "period_recipes", f"{period_id}:{rid}", "create", priority=2, target_node_id=None, ) db.session.commit() self.harness.drain_sync() client = self.harness.server_test_client() client.put( f"/api/recipes/{r2}/move", json={"period_id": period_id, "from_index": 1, "to_index": 0}, ) time.sleep(0.3) self.harness.drain_sync() for term in ("a", "b"): self.assertEqual( self.harness.period_recipe_order(term, period_id), [r2, r1], msg=term, ) def test_universal_task_completed_after_both_confirm(self) -> None: with self.harness.server_ctx(): from tests.helpers.mill_recipe_fixtures import create_recipe_with_children recipe_id, _, _ = create_recipe_with_children(name="Roundtrip confirm") task = self.harness.latest_task("recipe", recipe_id, "create") self.assertIsNotNone(task) task_id = task.id self.harness.sync_terminal("a") with self.harness.server_ctx(): self.assertEqual(db.session.get(SyncQueue, task_id).status, "processing") self.harness.sync_terminal("b") with self.harness.server_ctx(): self.assertEqual(db.session.get(SyncQueue, task_id).status, "completed") if __name__ == "__main__": unittest.main()