Files
gamedev-the-steward/tests/unit/test_activity_content_catalog_contract.gd
T
2026-08-13 00:08:30 +02:00

149 lines
4.9 KiB
GDScript

extends GutTest
const ACTION_ID := &"test_activity_metric_action"
func test_valid_activity_metric_action_uses_the_builtin_contract() -> void:
var action := _valid_action()
action.completion_cost_resource_id = SimulationIds.RESOURCE_WOOD
action.completion_cost_amount = 1.0
var catalog := _catalog_with_action(action)
assert_true(catalog.is_valid(), "%s" % [catalog.get_errors()])
assert_not_null(catalog.get_action(ACTION_ID))
func test_activity_metric_handler_rejects_non_activity_targets() -> void:
var action := _valid_action()
action.target_type = SimulationIds.TARGET_FREE
_assert_contract_error(action, "activity")
func test_activity_metric_handler_requires_exactly_one_effect() -> void:
var without_effects := _valid_action()
without_effects.effects = []
_assert_contract_error(without_effects, "exactly one")
var with_multiple_effects := _valid_action()
var second_effect := _valid_effect()
second_effect.effect_id = &"second_metric_effect"
with_multiple_effects.effects = [_valid_effect(), second_effect]
_assert_contract_error(with_multiple_effects, "exactly one")
func test_activity_metric_handler_rejects_wrong_effect_kind() -> void:
var action := _valid_action()
var damage := ActionEffect.new()
damage.effect_id = &"damage_instead_of_metric"
damage.effect_kind = ActionEffect.KIND_DAMAGE
damage.amount = 1.0
action.effects = [damage]
_assert_contract_error(action, "metric_delta")
func test_activity_metric_handler_rejects_unsupported_metric() -> void:
var action := _valid_action()
var effect := _valid_effect()
effect.subject_key = &"morale"
action.effects = [effect]
_assert_contract_error(action, "safety")
func test_activity_metric_handler_rejects_malformed_player_multiplier() -> void:
var action := _valid_action()
var effect := _valid_effect()
effect.parameters = {"player_multiplier": "three", "npc_productivity": true}
action.effects = [effect]
_assert_contract_error(action, "player_multiplier")
func test_activity_metric_handler_rejects_malformed_npc_productivity() -> void:
var action := _valid_action()
var effect := _valid_effect()
effect.parameters = {"player_multiplier": 2.0, "npc_productivity": "yes"}
action.effects = [effect]
_assert_contract_error(action, "npc_productivity")
func test_activity_metric_handler_requires_a_completion_event_type() -> void:
var action := _valid_action()
action.event_type_id = &""
_assert_contract_error(action, "event_type_id")
func test_activity_metric_completion_cost_must_have_a_storage_route() -> void:
var action := _valid_action()
action.completion_cost_resource_id = &"unrouted_activity_cost"
action.completion_cost_amount = 1.0
var unrouted_item := ItemDefinition.new()
unrouted_item.item_id = action.completion_cost_resource_id
unrouted_item.display_name = "Unrouted Activity Cost"
unrouted_item.category = ItemDefinition.CATEGORY_RESOURCE
var catalog := _catalog_with_action(action, [unrouted_item])
assert_false(catalog.is_valid(), "An executable cost needs an authoritative storage route")
assert_true(
_has_error(catalog.get_errors(), "storage"),
"Expected a storage routing error, got %s" % [catalog.get_errors()]
)
func _assert_contract_error(action: ActionDefinition, expected_fragment: String) -> void:
var catalog := _catalog_with_action(action)
assert_false(catalog.is_valid(), "Invalid '%s' contract was published" % action.action_id)
assert_true(
_has_error(catalog.get_errors(), expected_fragment),
"Expected '%s' in %s" % [expected_fragment, catalog.get_errors()]
)
func _catalog_with_action(
action: ActionDefinition, items: Array[ItemDefinition] = []
) -> ContentCatalog:
var core := load(ContentCatalog.CORE_PACK_PATH) as SimulationContentPack
var addon := SimulationContentPack.new()
addon.pack_id = &"activity_contract_test"
addon.display_name = "Activity Contract Test"
addon.required_pack_ids = [&"core"]
addon.required_handler_ids = [SimulationIds.ACTION_HANDLER_ACTIVITY_METRIC_DELTA]
addon.actions = [action]
addon.items = items
var packs: Array[SimulationContentPack] = [addon, core]
var catalog := ContentCatalog.new()
catalog.rebuild(packs)
return catalog
func _valid_action() -> ActionDefinition:
var action := ActionDefinition.new()
action.action_id = ACTION_ID
action.display_name = "Test Activity Metric Action"
action.target_type = SimulationIds.TARGET_ACTIVITY
action.completion_handler_id = SimulationIds.ACTION_HANDLER_ACTIVITY_METRIC_DELTA
action.effects = [_valid_effect()]
action.event_type_id = SimulationIds.EVENT_ACTIVITY_COMPLETED
return action
func _valid_effect() -> ActionEffect:
var effect := ActionEffect.new()
effect.effect_id = &"test_metric_effect"
effect.effect_kind = ActionEffect.KIND_METRIC_DELTA
effect.subject_key = &"safety"
effect.value = 1.0
effect.parameters = {"player_multiplier": 2.0, "npc_productivity": true}
return effect
func _has_error(errors: Array[String], fragment: String) -> bool:
for error in errors:
if fragment in error:
return true
return false