feat: add steal mechanic to Code Farm with 60s protection window and half-coin reward
This commit is contained in:
+124
-1
@@ -1,9 +1,11 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from playwright.sync_api import expect
|
||||
|
||||
from tests.conftest import BASE_URL
|
||||
from tests.e2e.game.index import reset_farm
|
||||
from tests.e2e.game.index import reset_farm, warp_ready
|
||||
|
||||
|
||||
def _plant_growing(username, crop="python", slot=0):
|
||||
@@ -14,6 +16,42 @@ def _plant_growing(username, crop="python", slot=0):
|
||||
store.plant({"uid": user["uid"], "username": username}, slot, crop)
|
||||
|
||||
|
||||
def _warp_stealable(username):
|
||||
from devplacepy.database import get_table
|
||||
from devplacepy.services.game import economy, store
|
||||
|
||||
user = get_table("users").find_one(username=username)
|
||||
farm = store.get_farm(user["uid"])
|
||||
past = (
|
||||
datetime.now(timezone.utc)
|
||||
- timedelta(seconds=economy.STEAL_GRACE_SECONDS + 10)
|
||||
).isoformat()
|
||||
for plot in store.get_plots(farm["uid"]):
|
||||
if plot.get("crop_key"):
|
||||
get_table("game_plots").update(
|
||||
{"uid": plot["uid"], "ready_at": past}, ["uid"]
|
||||
)
|
||||
|
||||
|
||||
def _farm_coins(username):
|
||||
from devplacepy.database import get_table
|
||||
from devplacepy.services.game import store
|
||||
|
||||
user = get_table("users").find_one(username=username)
|
||||
farm = store.get_farm(user["uid"])
|
||||
return int(farm.get("coins", 0))
|
||||
|
||||
|
||||
def _has_badge(username, badge_name):
|
||||
from devplacepy.database import get_table
|
||||
|
||||
user = get_table("users").find_one(username=username)
|
||||
return (
|
||||
get_table("badges").find_one(user_uid=user["uid"], badge_name=badge_name)
|
||||
is not None
|
||||
)
|
||||
|
||||
|
||||
def test_view_other_farm(bob):
|
||||
page, _ = bob
|
||||
reset_farm("alice_test")
|
||||
@@ -50,3 +88,88 @@ def test_unknown_farm_is_404(bob):
|
||||
f"{BASE_URL}/game/farm/nope_nobody", wait_until="domcontentloaded"
|
||||
)
|
||||
assert response is not None and response.status == 404
|
||||
|
||||
|
||||
def test_ready_build_is_protected_during_grace(bob):
|
||||
page, _ = bob
|
||||
reset_farm("alice_test")
|
||||
_plant_growing("alice_test", crop="python")
|
||||
warp_ready("alice_test")
|
||||
page.goto(f"{BASE_URL}/game/farm/alice_test", wait_until="domcontentloaded")
|
||||
page.locator("[data-game-grid]").first.wait_for(state="visible")
|
||||
page.wait_for_timeout(800)
|
||||
expect(page.locator(".plot-ready-label").first).to_be_visible()
|
||||
assert page.locator("form[data-game-action='steal']").count() == 0
|
||||
|
||||
|
||||
def test_steal_button_appears_after_grace(bob):
|
||||
page, _ = bob
|
||||
reset_farm("alice_test")
|
||||
_plant_growing("alice_test", crop="python")
|
||||
_warp_stealable("alice_test")
|
||||
page.goto(f"{BASE_URL}/game/farm/alice_test", wait_until="domcontentloaded")
|
||||
page.locator("[data-game-grid]").first.wait_for(state="visible")
|
||||
steal = page.locator("form[data-game-action='steal'] button").first
|
||||
steal.wait_for(state="visible")
|
||||
assert "Steal" in steal.inner_text()
|
||||
|
||||
|
||||
def test_steal_takes_build_and_pays_thief(bob):
|
||||
page, _ = bob
|
||||
reset_farm("alice_test")
|
||||
reset_farm("bob_test", coins=0)
|
||||
_plant_growing("alice_test", crop="python")
|
||||
_warp_stealable("alice_test")
|
||||
alice_coins_before = _farm_coins("alice_test")
|
||||
page.goto(f"{BASE_URL}/game/farm/alice_test", wait_until="domcontentloaded")
|
||||
page.locator("[data-game-grid]").first.wait_for(state="visible")
|
||||
steal = page.locator("form[data-game-action='steal'] button").first
|
||||
steal.wait_for(state="visible")
|
||||
steal.click()
|
||||
confirm_btn = page.locator(".dialog-confirm")
|
||||
confirm_btn.wait_for(state="visible")
|
||||
confirm_btn.click()
|
||||
expect(page.locator("form[data-game-action='steal']")).to_have_count(0)
|
||||
page.wait_for_timeout(400)
|
||||
assert _farm_coins("bob_test") == 18
|
||||
assert _farm_coins("alice_test") == alice_coins_before
|
||||
assert _has_badge("bob_test", "Cat Burglar")
|
||||
assert _has_badge("alice_test", "Robbed")
|
||||
|
||||
|
||||
def test_owner_sees_harvest_not_steal(alice):
|
||||
page, _ = alice
|
||||
reset_farm("alice_test")
|
||||
_plant_growing("alice_test", crop="python")
|
||||
_warp_stealable("alice_test")
|
||||
page.goto(f"{BASE_URL}/game", wait_until="domcontentloaded")
|
||||
page.locator("[data-game-grid]").first.wait_for(state="visible")
|
||||
expect(page.locator("form[data-game-action='harvest'] button").first).to_be_visible()
|
||||
assert page.locator("form[data-game-action='steal']").count() == 0
|
||||
|
||||
|
||||
def test_victim_gets_anonymous_notification(bob):
|
||||
page, _ = bob
|
||||
from devplacepy.database import get_table
|
||||
|
||||
reset_farm("alice_test")
|
||||
reset_farm("bob_test", coins=0)
|
||||
alice = get_table("users").find_one(username="alice_test")
|
||||
get_table("notifications").delete(user_uid=alice["uid"], type="harvest_stolen")
|
||||
_plant_growing("alice_test", crop="python")
|
||||
_warp_stealable("alice_test")
|
||||
page.goto(f"{BASE_URL}/game/farm/alice_test", wait_until="domcontentloaded")
|
||||
page.locator("[data-game-grid]").first.wait_for(state="visible")
|
||||
steal = page.locator("form[data-game-action='steal'] button").first
|
||||
steal.wait_for(state="visible")
|
||||
steal.click()
|
||||
confirm_btn = page.locator(".dialog-confirm")
|
||||
confirm_btn.wait_for(state="visible")
|
||||
confirm_btn.click()
|
||||
expect(page.locator("form[data-game-action='steal']")).to_have_count(0)
|
||||
page.wait_for_timeout(400)
|
||||
note = get_table("notifications").find_one(
|
||||
user_uid=alice["uid"], type="harvest_stolen"
|
||||
)
|
||||
assert note is not None
|
||||
assert "bob_test" not in note["message"]
|
||||
|
||||
Reference in New Issue
Block a user