Files
neon-bar86.ru/crm/tests/test_gate_and_text.py
merrow 881ef45be5
ci.yml (push) Invalid workflow file
CI/CD: Gitea Actions — тесты CRM (sqlite) и автодеплой на VPS
- crm/tests: 27 тестов через настоящий server.main на sqlite-бэкенде
  (валидация заказов, цена только из каталога, honeypot, дедупликация,
  трекинг и отмена гостем, стоп-лист, аутентификация, гигиена текста,
  гейт расписания бара)
- .gitea/workflows/ci.yml: test-джоба + deploy (только push в main,
  после тестов): rsync кода -> pre-flight docker compose config ->
  pg_dump бэкап БД (ротация 7) -> up -d --build -> health-check
- деплой на neon-bar86.ru идёт деплой-ключом из secrets репозитория
2026-10-11 23:00:20 +05:00

74 lines
2.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""Чистые функции без сервера: гигиена гостевого текста и гейт «бар открыт»."""
import sys
from datetime import datetime, timedelta
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from server import BAR_TZ, bar_is_open, next_bar_opening # noqa: E402
from storage import clean_guest_text # noqa: E402
# 2026-10-05 — понедельник; от него строим любой день недели
MONDAY = datetime(2026, 10, 5, 12, 0, tzinfo=BAR_TZ)
def dt(day: str, hour: int, minute: int = 0) -> datetime:
shift = "mon tue wed thu fri sat sun".split().index(day)
return MONDAY.replace(hour=hour, minute=minute) + timedelta(days=shift)
# ------------------------------------------------------------- clean_guest_text
def test_clean_text_removes_hidden_chars():
assert clean_guest_text("Кола\u200b", 60) == "Кола" # zero-width space
assert clean_guest_text("\ufeffпиво\u200e", 60) == "пиво" # BOM + LRM
assert clean_guest_text("a\x00b\x1f[c]\x7f", 60) == "ab[c]" # control chars
assert clean_guest_text("ab\u202edc", 60) == "abdc" # bidi override
def test_clean_text_keeps_normal_text_and_emoji():
text = "Столик у окна, пиво 🍺 и — тире"
assert clean_guest_text(text, 60) == text
def test_clean_text_truncates_to_limit():
assert len(clean_guest_text("х" * 500, 60)) == 60
# ------------------------------------------------------------------ бар открыт?
def test_bar_open_in_the_evening():
assert bar_is_open(dt("fri", 21)) is True
assert bar_is_open(dt("sat", 21)) is True
assert bar_is_open(dt("sun", 20)) is True
def test_bar_closed_monday_evening():
# понедельник — вечерних сессий нет (BAR_CLOSED_WEEKDAY)
assert bar_is_open(dt("mon", 21)) is False
def test_bar_tail_after_midnight():
assert bar_is_open(dt("sat", 2)) is True # хвост пятницы до 03:00
assert bar_is_open(dt("sun", 2)) is True # хвост субботы до 03:00
assert bar_is_open(dt("tue", 0, 30)) is False # во вторник хвоста нет
assert bar_is_open(dt("sat", 3, 30)) is False # хвост закончился
def test_preorder_window_is_one_hour():
now = dt("fri", 18, 30)
opening = next_bar_opening(now)
assert opening is not None and (opening - now) <= timedelta(hours=1)
now2 = dt("fri", 17, 0)
opening2 = next_bar_opening(now2)
assert (opening2 - now2) > timedelta(hours=1)
def test_next_opening_skips_monday():
# воскресенье 21:00 → ближайшее открытие во вторник 19:00, не в понедельник
opening = next_bar_opening(dt("sun", 21))
assert opening is not None
assert opening.weekday() == 1 # вторник