Initial certificate system
This commit is contained in:
9
backend/tests/test_captcha.py
Normal file
9
backend/tests/test_captcha.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from app.services.captcha import make_captcha, verify_captcha
|
||||
|
||||
|
||||
def test_captcha_can_only_be_used_once():
|
||||
captcha = make_captcha()
|
||||
captcha_id = captcha["captcha_id"]
|
||||
# The real code is intentionally not exposed. This test locks in one-time consumption behavior.
|
||||
assert not verify_captcha(captcha_id, "bad")
|
||||
assert not verify_captcha(captcha_id, "bad")
|
||||
15
backend/tests/test_certificate_number.py
Normal file
15
backend/tests/test_certificate_number.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import re
|
||||
from datetime import date
|
||||
|
||||
from app.services.certificate_number import build_certificate_no
|
||||
|
||||
|
||||
def test_certificate_number_shape():
|
||||
number = build_certificate_no(123, "dby", date(2026, 6, 1))
|
||||
assert re.fullmatch(r"PX2026-DBY-[23456789ABCDEFGHJKLMNPQRSTUVWXYZ]{7}-[23456789ABCDEFGHJKLMNPQRSTUVWXYZ]{2}", number)
|
||||
|
||||
|
||||
def test_certificate_number_changes_with_sequence():
|
||||
first = build_certificate_no(123, "DBY", date(2026, 6, 1))
|
||||
second = build_certificate_no(124, "DBY", date(2026, 6, 1))
|
||||
assert first != second
|
||||
34
backend/tests/test_import_rules.py
Normal file
34
backend/tests/test_import_rules.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from datetime import date
|
||||
|
||||
from app.api.routes.admin_imports import (
|
||||
COL_CERT_NAME,
|
||||
COL_ISSUE_DATE,
|
||||
COL_NAME,
|
||||
COL_PHONE,
|
||||
COL_PROJECT,
|
||||
COL_ISSUER,
|
||||
date_is_valid,
|
||||
parse_issue_date,
|
||||
row_errors,
|
||||
)
|
||||
|
||||
|
||||
def test_parse_issue_date_accepts_common_formats():
|
||||
assert parse_issue_date("2026-06-01") == date(2026, 6, 1)
|
||||
assert parse_issue_date("2026/06/01") == date(2026, 6, 1)
|
||||
|
||||
|
||||
def test_row_errors_require_project_code_to_exist():
|
||||
row = {
|
||||
COL_NAME: "张三",
|
||||
COL_PHONE: "13800000000",
|
||||
COL_PROJECT: "BAD",
|
||||
COL_CERT_NAME: "结业证书",
|
||||
COL_ISSUE_DATE: "2026-06-01",
|
||||
COL_ISSUER: "测试公司",
|
||||
}
|
||||
assert "Project code is inactive or missing" in row_errors(row, {"DBY"})
|
||||
|
||||
|
||||
def test_date_is_valid_rejects_bad_text():
|
||||
assert not date_is_valid("not-a-date")
|
||||
15
backend/tests/test_security.py
Normal file
15
backend/tests/test_security.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from app.core.security import create_access_token, decode_access_token, hash_password, verify_password
|
||||
|
||||
|
||||
def test_password_hash_roundtrip():
|
||||
password_hash = hash_password("Secret123!")
|
||||
assert verify_password("Secret123!", password_hash)
|
||||
assert not verify_password("wrong", password_hash)
|
||||
|
||||
|
||||
def test_access_token_roundtrip():
|
||||
token = create_access_token("7", "system_admin", expires_in=60)
|
||||
payload = decode_access_token(token)
|
||||
assert payload is not None
|
||||
assert payload["sub"] == "7"
|
||||
assert payload["role"] == "system_admin"
|
||||
Reference in New Issue
Block a user