gm-assistant/tests/test_object_generator_oracle.py

181 lines
5.5 KiB
Python
Raw 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.

# SPDX-FileCopyrightText: 2025 2025
# SPDX-FileContributor: Gergely Polonkai
#
# SPDX-License-Identifier: GPL-3.0-or-later
"""Tests for the Object Generator Oracle"""
from copy import deepcopy
from typing import Literal
import pytest
from pytest_mock import MockerFixture
from gm_assistant.dice import Die
from gm_assistant.oracle.object_generator import ObjectGeneratorOracle, ObjectGeneratorProperty
TEST_PROPERTY_DATA = {
"question": "Test Question",
"roll-type": "d6",
"results": [
{"min-roll": 1, "max-roll": 2, "value": "Value 1-2"},
{"min-roll": 3, "value": "Value 3"},
{"min-roll": 4, "max-roll": 6, "value": "Value 4-6"},
],
}
TEST_ORACLE_DATA = {
"name": "Test Oracle",
"source": "Test Source",
"type": "object-generator",
"properties": [
TEST_PROPERTY_DATA,
{
"question": "Second Question",
"roll-type": "d2",
"results": [
{"min-roll": 1, "value": "Value 1"},
{"min-roll": 2, "value": "Value 2"},
],
},
],
}
@pytest.mark.parametrize("missing", ["question", "roll-type", "results", "min-roll", "value"])
def test_property_missing_data(missing: Literal["question", "roll-type", "results", "min-roll", "value"]) -> None:
"""Test initialising a property with missing data"""
prop_data = deepcopy(TEST_PROPERTY_DATA)
if missing in ("min-roll", "value"):
del prop_data["results"][0][missing] # type: ignore[attr-defined]
else:
del prop_data[missing]
with pytest.raises(ValueError) as ctx:
ObjectGeneratorProperty(prop_data)
if missing in ("min-roll", "value"):
assert str(ctx.value) == f"Missing {missing} value in result 0"
else:
assert str(ctx.value) == f"Missing {missing} value"
def test_property_result_max_smaller_than_min() -> None:
"""Test initialising a property with a maximum roll smaller than the minimum roll"""
prop_data = deepcopy(TEST_PROPERTY_DATA)
prop_data["results"][0]["min-roll"] = 3 # type: ignore[index]
with pytest.raises(ValueError) as ctx:
ObjectGeneratorProperty(prop_data)
assert str(ctx.value) == "max-roll cannot be smaller than min-roll in result 0"
def test_property_missing_roll_value() -> None:
"""Test initialising a property with a missing roll value"""
prop_data = deepcopy(TEST_PROPERTY_DATA)
prop_data["results"] = [prop_data["results"][0]]
with pytest.raises(ValueError) as ctx:
ObjectGeneratorProperty(prop_data)
assert str(ctx.value) == "Not all roll values yield a result for property Test Question"
def test_property_multiple_roll_value() -> None:
"""Test initialising a property with a roll value appearing twice"""
prop_data = deepcopy(TEST_PROPERTY_DATA)
prop_data["results"].append({"min-roll": 2, "value": "Second Value"}) # type: ignore[attr-defined]
with pytest.raises(ValueError) as ctx:
ObjectGeneratorProperty(prop_data)
assert str(ctx.value) == "Roll value 2 is already registered in result 3"
def test_property_init(mocker: MockerFixture) -> None:
"""Test initialising a property with valid data"""
mocked_die = Die("d6")
mocked_die_class = mocker.patch("gm_assistant.oracle.object_generator.Die", return_value=mocked_die)
prop = ObjectGeneratorProperty(TEST_PROPERTY_DATA)
assert prop.question == "Test Question"
assert prop.die == mocked_die
assert prop.results == {
1: "Value 1-2",
2: "Value 1-2",
3: "Value 3",
4: "Value 4-6",
5: "Value 4-6",
6: "Value 4-6",
}
mocked_die_class.assert_called_once_with("d6")
def test_property_generate(mocker: MockerFixture) -> None:
"""Test the ObjectGeneratorProperty.generate() method"""
mocked_roll = mocker.patch("gm_assistant.oracle.object_generator.Die.roll", return_value=3)
prop = ObjectGeneratorProperty(TEST_PROPERTY_DATA)
expected_output = """*Test Question*
Value 3"""
assert prop.generate() == expected_output
mocked_roll.assert_called_once_with()
def test_oracle_init_missing_properties() -> None:
"""Test initialising an Oracle with properties missing"""
oracle_data = deepcopy(TEST_ORACLE_DATA)
del oracle_data["properties"]
with pytest.raises(KeyError) as ctx:
ObjectGeneratorOracle(oracle_data)
assert str(ctx.value) == "'properties'"
def test_oracle_init() -> None:
"""Test initialising an Oracle with valid data"""
oracle = ObjectGeneratorOracle(TEST_ORACLE_DATA)
assert oracle.properties[0].question == "Test Question"
assert oracle.properties[1].question == "Second Question"
def test_oracle_generate(mocker: MockerFixture) -> None:
"""Test the Oracles ``generate`` method"""
mocked_die1 = Die("d6")
mocker.patch.object(mocked_die1, "roll", return_value=5)
mocked_die2 = Die("d2")
mocker.patch.object(mocked_die2, "roll", return_value=1)
mocked_die_class = mocker.patch("gm_assistant.oracle.object_generator.Die", side_effect=[mocked_die1, mocked_die2])
oracle = ObjectGeneratorOracle(TEST_ORACLE_DATA)
expected_output = """*Test Question*
Value 4-6
*Second Question*
Value 1"""
assert oracle.generate() == expected_output
assert mocked_die_class.call_count == 2
mocked_die_class.assert_has_calls([mocker.call("d6"), mocker.call("d2")])
# pylint: disable=no-member
mocked_die1.roll.assert_called_once_with() # type: ignore[attr-defined]
mocked_die2.roll.assert_called_once_with() # type: ignore[attr-defined]