Initial commit: aplicatie de cantarire si etichetare
Aplicatie Flask + SQLite pentru productie alimentara: cantarirea componentelor unui produs finit si tiparirea etichetei prin QZ Tray. - produse finite (retete) formate din componente cantarite - designer vizual de etichete (mm/px, zona sigura, campuri variabile, cod QR cu continut din mai multe bucati) - legare produs finit -> sablon de eticheta - navigare pe doua taburi: Cantarire / Setari - administrare: componente, produse finite, sabloane, campuri, istoric - backup, resetare baza de date, checklist de pregatire, /healthz - CLI de administrare si serviciu systemd pentru productie - vendor/syncpulse-scale-bridge (GPL-3.0-or-later) pentru citirea cantarului
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
"""Numele sabloanelor: creare cu nume propriu si redenumire."""
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from cantarire.repositories import ValidationError
|
||||
|
||||
|
||||
def _names(client):
|
||||
with client.application.app_context():
|
||||
from cantarire.repositories import list_templates
|
||||
|
||||
return [t["name"] for t in list_templates()]
|
||||
|
||||
|
||||
def _template_by_name(client, name):
|
||||
with client.application.app_context():
|
||||
from cantarire.repositories import list_templates
|
||||
|
||||
found = [t for t in list_templates() if t["name"] == name]
|
||||
assert found, f"{name!r} nu exista; gasit: {_names(client)}"
|
||||
return found[0]
|
||||
|
||||
|
||||
def test_create_with_custom_name(client):
|
||||
response = client.post("/sabloane/designer/nou", data={"name": "Etichetă 60x40"},
|
||||
follow_redirects=True)
|
||||
assert response.status_code == 200
|
||||
template = _template_by_name(client, "Etichetă 60x40")
|
||||
assert template["design_json"]
|
||||
# mergem direct in designer, nu in lista
|
||||
assert "Trage elementele pe etichetă" in response.get_data(as_text=True)
|
||||
|
||||
|
||||
def test_create_with_custom_dimensions(client):
|
||||
client.post("/sabloane/designer/nou",
|
||||
data={"name": "Mică", "width_mm": "60", "height_mm": "40"},
|
||||
follow_redirects=True)
|
||||
template = _template_by_name(client, "Mică")
|
||||
assert template["width_mm"] == 60 and template["height_mm"] == 40
|
||||
with client.application.app_context():
|
||||
from cantarire import designer
|
||||
|
||||
design = designer.load_design(template["design_json"], 60, 40)
|
||||
# elementele implicite incap in 60x40
|
||||
for block in design["blocks"]:
|
||||
assert block["x"] + block["w"] <= 60.001
|
||||
assert block["y"] + block["h"] <= 40.001
|
||||
|
||||
|
||||
def test_create_without_name_generates_unique_name(client):
|
||||
client.post("/sabloane/designer/nou", data={}, follow_redirects=True)
|
||||
client.post("/sabloane/designer/nou", data={}, follow_redirects=True)
|
||||
names = _names(client)
|
||||
assert "Sablon designer" in names
|
||||
assert "Sablon designer 2" in names
|
||||
|
||||
|
||||
def test_duplicate_name_is_rejected(client):
|
||||
client.post("/sabloane/designer/nou", data={"name": "Dublura"}, follow_redirects=True)
|
||||
response = client.post("/sabloane/designer/nou", data={"name": "Dublura"},
|
||||
follow_redirects=True)
|
||||
assert "Exista deja un sablon numit" in response.get_data(as_text=True)
|
||||
assert _names(client).count("Dublura") == 1
|
||||
|
||||
|
||||
def test_name_is_case_insensitive_unique(client):
|
||||
client.post("/sabloane/designer/nou", data={"name": "Eticheta Mare"},
|
||||
follow_redirects=True)
|
||||
response = client.post("/sabloane/designer/nou", data={"name": "eticheta mare"},
|
||||
follow_redirects=True)
|
||||
assert "Exista deja un sablon numit" in response.get_data(as_text=True)
|
||||
|
||||
|
||||
def test_rename_from_designer(client):
|
||||
client.post("/sabloane/designer/nou", data={"name": "Nume vechi"},
|
||||
follow_redirects=True)
|
||||
template = _template_by_name(client, "Nume vechi")
|
||||
|
||||
response = client.post(f"/sabloane/{template['id']}/redenumire",
|
||||
data={"name": "Nume nou", "next": "designer"},
|
||||
follow_redirects=True)
|
||||
assert response.status_code == 200
|
||||
assert "a fost redenumit" in response.get_data(as_text=True)
|
||||
assert "Nume nou" in response.get_data(as_text=True)
|
||||
with client.application.app_context():
|
||||
from cantarire.repositories import get_template
|
||||
|
||||
stored = get_template(template["id"])
|
||||
assert stored["name"] == "Nume nou"
|
||||
assert stored["design_json"] # designul nu se pierde
|
||||
|
||||
|
||||
def test_rename_to_existing_name_is_rejected(client):
|
||||
client.post("/sabloane/designer/nou", data={"name": "Primul"}, follow_redirects=True)
|
||||
client.post("/sabloane/designer/nou", data={"name": "Al doilea"}, follow_redirects=True)
|
||||
second = _template_by_name(client, "Al doilea")
|
||||
|
||||
response = client.post(f"/sabloane/{second['id']}/redenumire",
|
||||
data={"name": "Primul"}, follow_redirects=True)
|
||||
assert "Exista deja un sablon" in response.get_data(as_text=True)
|
||||
with client.application.app_context():
|
||||
from cantarire.repositories import get_template
|
||||
|
||||
assert get_template(second["id"])["name"] == "Al doilea"
|
||||
|
||||
|
||||
def test_rename_to_same_name_is_noop(client):
|
||||
client.post("/sabloane/designer/nou", data={"name": "Neschimbat"},
|
||||
follow_redirects=True)
|
||||
template = _template_by_name(client, "Neschimbat")
|
||||
response = client.post(f"/sabloane/{template['id']}/redenumire",
|
||||
data={"name": "Neschimbat", "next": "designer"},
|
||||
follow_redirects=True)
|
||||
assert response.status_code == 200
|
||||
assert _names(client).count("Neschimbat") == 1
|
||||
|
||||
|
||||
def test_rename_with_empty_name_is_rejected(client):
|
||||
client.post("/sabloane/designer/nou", data={"name": "Are nume"},
|
||||
follow_redirects=True)
|
||||
template = _template_by_name(client, "Are nume")
|
||||
response = client.post(f"/sabloane/{template['id']}/redenumire",
|
||||
data={"name": " ", "next": "designer"},
|
||||
follow_redirects=True)
|
||||
assert "Numele sablonului este obligatoriu" in response.get_data(as_text=True)
|
||||
with client.application.app_context():
|
||||
from cantarire.repositories import get_template
|
||||
|
||||
assert get_template(template["id"])["name"] == "Are nume"
|
||||
|
||||
|
||||
def test_rename_unknown_template(client):
|
||||
response = client.post("/sabloane/9999/redenumire", data={"name": "X"},
|
||||
follow_redirects=True)
|
||||
assert "Sabloul nu exista" in response.get_data(as_text=True)
|
||||
|
||||
|
||||
def test_list_page_has_name_input(client):
|
||||
html = client.get("/sabloane").get_data(as_text=True)
|
||||
assert 'name="name"' in html
|
||||
assert "Nume șablon nou" in html
|
||||
assert "+ Șablon nou" in html
|
||||
# modul HTML/CSS nu mai exista
|
||||
assert "HTML/CSS" not in html
|
||||
|
||||
|
||||
def test_designer_page_has_rename_form(client):
|
||||
client.post("/sabloane/designer/nou", data={"name": "Cu redenumire"},
|
||||
follow_redirects=True)
|
||||
template = _template_by_name(client, "Cu redenumire")
|
||||
html = client.get(f"/sabloane/{template['id']}/designer").get_data(as_text=True)
|
||||
assert 'class="rename-form"' in html
|
||||
assert "Redenumește" in html
|
||||
assert 'value="Cu redenumire"' in html
|
||||
assert f'action="/sabloane/{template["id"]}/redenumire"' in html
|
||||
|
||||
|
||||
def test_validation_error_still_raised_for_blank_name(client):
|
||||
"""Guard la nivel de repository, independent de ruta."""
|
||||
with client.application.app_context():
|
||||
from cantarire.repositories import create_template
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
create_template({
|
||||
"name": " ", "width_mm": 100, "height_mm": 60,
|
||||
"body_html": " ", "design_json": "{}",
|
||||
})
|
||||
Reference in New Issue
Block a user