Интегрирован wesp в сайт
CI / quality (push) Canceled after 0s

This commit is contained in:
влад
2026-07-17 12:57:18 +03:00
parent 5dfa06ddbe
commit 355c0ef9f1
883 changed files with 194576 additions and 177 deletions
+157
View File
@@ -0,0 +1,157 @@
"""HTTP-интеграция sync: register → push master → pull → confirm."""
from __future__ import annotations
import os
import tempfile
import unittest
import uuid
from datetime import datetime
from sqlalchemy import select
from app import create_app, db
from app.models import Component, Recipe, SyncClient, SyncEngineState, SyncQueue
from app.services.sync_manager import enqueue_sync_queue_task
from app.services.sync_record_data import get_record_data_for_sync
from config import TestingConfig
class SyncIntegrationConfig(TestingConfig):
_TMP_DIR = tempfile.mkdtemp(prefix="wesp-sync-integration-")
SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.join(_TMP_DIR, 'recipes_test.db')}"
SQLALCHEMY_BINDS = {
"reports": f"sqlite:///{os.path.join(_TMP_DIR, 'reports_test.db')}",
}
AUTH_LOGIN = "sync-int-admin"
AUTH_PASSWORD = "sync-int-secret"
class SyncIntegrationTests(unittest.TestCase):
def setUp(self) -> None:
self.app = create_app(SyncIntegrationConfig)
self.client = self.app.test_client()
self.ctx = self.app.app_context()
self.ctx.push()
db.create_all()
self.node_id = "mill-integration-1"
def tearDown(self) -> None:
db.session.remove()
db.drop_all()
self.ctx.pop()
def _register_client(self) -> None:
resp = self.client.post(
"/api/sync/register",
json={"client_id": self.node_id, "client_name": "Mill integration"},
)
self.assertEqual(resp.status_code, 200)
self.assertTrue(resp.get_json().get("success"))
def _mark_bootstrap_ready(self) -> None:
state = db.session.get(SyncEngineState, 1)
if state is None:
state = SyncEngineState(id=1)
db.session.add(state)
state.universal_bootstrap_completed_at = datetime.now()
state.universal_bootstrap_cursor = 999
sc = db.session.execute(
select(SyncClient).where(SyncClient.node_id == self.node_id)
).scalar_one()
sc.personal_snapshot_cursor = 999
sc.personal_snapshot_completed_at = datetime.now()
db.session.commit()
def test_push_recipe_then_pull_component_confirm(self) -> None:
self._register_client()
self._mark_bootstrap_ready()
recipe_id = str(uuid.uuid4())
db.session.add(
Recipe(
id=recipe_id,
name="Mill integration recipe",
heads_per_trip=5,
mixing_time=3,
trip_percent=100.0,
)
)
db.session.commit()
recipe_data = get_record_data_for_sync("recipe", recipe_id)
self.assertIsNotNone(recipe_data)
push_resp = self.client.post(
"/api/sync/push",
json={
"client_id": self.node_id,
"changes": [
{
"table_name": "recipe",
"record_id": recipe_id,
"action": "create",
"data": recipe_data,
}
],
},
)
self.assertEqual(push_resp.status_code, 200)
push_body = push_resp.get_json()
self.assertTrue(push_body.get("success"))
self.assertGreaterEqual(int(push_body.get("total_applied", 0)), 1)
saved = db.session.get(Recipe, recipe_id)
self.assertIsNotNone(saved)
self.assertEqual(saved.name, "Mill integration recipe")
cmp_id = str(uuid.uuid4())
db.session.add(
Component(
id=cmp_id,
name="Server component",
type="grain",
is_active=True,
dry_matter=1.0,
protein=0.0,
energy=0.0,
price=0.0,
)
)
db.session.commit()
enqueue_sync_queue_task("component", cmp_id, "create", priority=2, target_node_id=None)
db.session.commit()
pull_resp = self.client.post(
"/api/sync/pull",
json={"client_id": self.node_id, "limit": 50},
)
self.assertIn(pull_resp.status_code, (200, 202))
if pull_resp.status_code == 202:
pull_resp = self.client.post(
"/api/sync/pull",
json={"client_id": self.node_id, "limit": 50},
)
self.assertEqual(pull_resp.status_code, 200)
pull_body = pull_resp.get_json()
changes = pull_body.get("changes") or []
cmp_changes = [c for c in changes if c.get("table_name") == "component"]
self.assertTrue(cmp_changes, f"expected component in pull, got {changes!r}")
task_ids = [c.get("id") or c.get("task_id") for c in cmp_changes]
task_ids = [t for t in task_ids if t]
confirm_resp = self.client.post(
"/api/sync/confirm",
json={"client_id": self.node_id, "task_ids": task_ids},
)
self.assertEqual(confirm_resp.status_code, 200)
self.assertTrue(confirm_resp.get_json().get("success"))
task_row = db.session.get(SyncQueue, task_ids[0])
self.assertIsNotNone(task_row)
self.assertEqual(task_row.status, "completed")
if __name__ == "__main__":
unittest.main()