feat: add TRPG roll command
This commit is contained in:
40
tests/test_permsys_default_allow.py
Normal file
40
tests/test_permsys_default_allow.py
Normal file
@ -0,0 +1,40 @@
|
||||
from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
import pytest
|
||||
|
||||
from konabot.common.database import DatabaseManager
|
||||
from konabot.common.permsys import PermManager, register_default_allow_permission
|
||||
from konabot.common.permsys.entity import PermEntity
|
||||
from konabot.common.permsys.migrates import execute_migration
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def tempdb():
|
||||
with TemporaryDirectory() as _tempdir:
|
||||
tempdir = Path(_tempdir)
|
||||
db = DatabaseManager(tempdir / "perm.sqlite3")
|
||||
yield db
|
||||
await db.close_all_connections()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_register_default_allow_permission_records_key():
|
||||
register_default_allow_permission("test.default.allow")
|
||||
|
||||
async with tempdb() as db:
|
||||
async with db.get_conn() as conn:
|
||||
await execute_migration(conn)
|
||||
|
||||
pm = PermManager(db)
|
||||
await pm.update_permission(
|
||||
PermEntity("sys", "global", "global"),
|
||||
"test.default.allow",
|
||||
True,
|
||||
)
|
||||
|
||||
assert await pm.check_has_permission(
|
||||
[PermEntity("dummy", "user", "1"), PermEntity("sys", "global", "global")],
|
||||
"test.default.allow.sub",
|
||||
)
|
||||
66
tests/test_trpg_roll.py
Normal file
66
tests/test_trpg_roll.py
Normal file
@ -0,0 +1,66 @@
|
||||
import random
|
||||
|
||||
import pytest
|
||||
|
||||
from konabot.plugins.trpg_roll.core import RollError, roll_expression
|
||||
|
||||
|
||||
class FakeRandom:
|
||||
def __init__(self, randint_values: list[int] | None = None, choice_values: list[int] | None = None):
|
||||
self._randint_values = list(randint_values or [])
|
||||
self._choice_values = list(choice_values or [])
|
||||
|
||||
def randint(self, _a: int, _b: int) -> int:
|
||||
assert self._randint_values
|
||||
return self._randint_values.pop(0)
|
||||
|
||||
def choice(self, _seq):
|
||||
assert self._choice_values
|
||||
return self._choice_values.pop(0)
|
||||
|
||||
|
||||
def test_roll_expression_basic():
|
||||
rng = FakeRandom(randint_values=[2, 4, 5])
|
||||
result = roll_expression("3d6", rng=rng)
|
||||
|
||||
assert result.total == 11
|
||||
assert result.format() == "3d6 = 11\n+3d6=[2, 4, 5]"
|
||||
|
||||
|
||||
def test_roll_expression_multiple_terms():
|
||||
rng = FakeRandom(randint_values=[14, 3, 1])
|
||||
result = roll_expression("d20+1d4-2", rng=rng)
|
||||
|
||||
assert result.total == 15
|
||||
assert result.format() == "d20+1d4-2 = 15\n+1d20=[14] +1d4=[3] -2=2"
|
||||
|
||||
|
||||
def test_roll_expression_df():
|
||||
rng = FakeRandom(choice_values=[-1, 0, 1, 1])
|
||||
result = roll_expression("4dF", rng=rng)
|
||||
|
||||
assert result.total == 1
|
||||
assert result.format() == "4dF = 1\n+4dF=[-1, +0, +1, +1]"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("expr", "message"),
|
||||
[
|
||||
("", "请提供要掷的表达式"),
|
||||
("abc", "无法解析表达式"),
|
||||
("1d0", "骰子面数必须大于 0"),
|
||||
("0d6", "骰子个数必须大于 0"),
|
||||
("101d6", "单项最多只能掷 100 个骰子"),
|
||||
("1d1001", "骰子面数不能超过 1000"),
|
||||
("201d1", "单项最多只能掷 100 个骰子"),
|
||||
("1d6*2", "表达式中含有无法识别的内容"),
|
||||
],
|
||||
)
|
||||
def test_roll_expression_invalid(expr: str, message: str):
|
||||
with pytest.raises(RollError, match=message):
|
||||
roll_expression(expr, rng=random.Random(0))
|
||||
|
||||
|
||||
def test_roll_expression_total_roll_limit():
|
||||
with pytest.raises(RollError, match="一次最多只能实际掷 200 个骰子"):
|
||||
roll_expression("100d6+100d6+1d6", rng=random.Random(0))
|
||||
Reference in New Issue
Block a user