Add more tests #395
No reviewers
Labels
No labels
breaking change
duplicate
good first issue
help wanted
invalid
question
scope: card
scope: docs
scope: game
scope: registry
scope: script
scope: tool
scope: universe
tracker
type: bug
type: card request
type: documentation
type: enhancement
type: improvement
type: parity
wontfix
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
LunarTides/Hearthstone.js!395
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "tests"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary by CodeRabbit
New Features
Bug Fixes
kill()todestroy()and introducedremoveFromPlay()for more accurate card removal handling.Refactor
Documentation
Style
Tests
Chores
Walkthrough
This update introduces a broad set of refinements, bug fixes, and test expansions across the codebase. Major changes include improved placeholder handling and keyword logic in the
Cardclass, refactored attack and quest mechanics inGameandeventManager, and significant expansions to test coverage, especially forCardandPlayerbehaviors. Multiple help and command descriptions were clarified, and minor code cleanups, such as removing unused imports and comments, were made throughout.Changes
src/card.tssrc/game.tsHeropowertoHeroPower, added enhanced input translation and pause methods, and replaced kill calls with destroy in poison and removal logic.src/event.tssrc/player.tsdestroy(), improveddrawSpecificto return undefined if card not in deck, cleared old hero location when setting new hero, simplified starting hero assignment, and adjusted quest addition to refund resource on failure.src/types/card.tsHerotoLocation.src/types/event.tsKillCardtoDestroyCardand updated associated type mappings accordingly.src/commands.tsgame.activeCardswith duplicate UUID checks to avoid infinite loops.src/functions/interact.tssrc/functions/util.tscards/Classes/Neutral/Collectible/Minions/10-Cost/104-yogg-saron-master-of-fate.ts,index.ts,src/functions/util.ts,tools/cardcreator/vanilla.ts// No defaultlines from switch statements for code clarity.cards/Examples/4/4-quest.tsEventListenerMessageenum instead of boolean return values for quest event listener callbacks.cards/StartingHeroes/Mage/114-heropower.tsTargetFlag.config.tsloc.mdscripts/cardtest.tsscripts/crashtest.tsscripts/id/main.tsscripts/vanilla/generate.tsfalsetocreateGame()call to alter initialization behavior.tools/cardcreator/class.tsheropowerIdcalculation for clarity.tools/cardcreator/lib.tsgetCardAbilityto return directly from cases, updated JSDoc comments to reflect parameter changes and remove unused param descriptions.tools/cardcreator/vanilla.ts// No defaultline from switch statement.tools/deckcreator.tsCard.registerAll()call in main function.test/src/card.test.tstest.todoplaceholders with detailed tests covering keywords, stats, freezing, attack counts, health modifications, stealth duration, resetting stats, and location management.test/src/player.test.tstest/src/ai.test.ts,test/src/commands.test.ts,test/src/event.test.ts,test/src/functions/card.test.ts,test/src/functions/deckcode.test.ts,test/src/functions/info.test.ts,test/src/functions/interact.test.ts,test/src/functions/util.test.ts,test/src/game.test.tstest/src/functions/util.test.tsparseEvalArgsfunction's support for async method calls on card UUIDs.Sequence Diagram(s)
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
❤️ Share
🪧 Tips
Chat
There are 3 ways to chat with CodeRabbit:
I pushed a fix in commit <commit_id>, please review it.Explain this complex logic.Open a follow-up GitHub issue for this discussion.@coderabbitaiin a new review comment at the desired location with your query. Examples:@coderabbitai explain this code block.@coderabbitai modularize this function.@coderabbitaiin a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.@coderabbitai read src/utils.ts and explain its main purpose.@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.@coderabbitai help me debug CodeRabbit configuration file.Support
Need help? Create a ticket on our support page for assistance with any issues or questions.
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.
CodeRabbit Commands (Invoked using PR comments)
@coderabbitai pauseto pause the reviews on a PR.@coderabbitai resumeto resume the paused reviews.@coderabbitai reviewto trigger an incremental review. This is useful when automatic reviews are disabled for the repository.@coderabbitai full reviewto do a full review from scratch and review all the files again.@coderabbitai summaryto regenerate the summary of the PR.@coderabbitai generate docstringsto generate docstrings for this PR.@coderabbitai generate sequence diagramto generate a sequence diagram of the changes in this PR.@coderabbitai resolveresolve all the CodeRabbit review comments.@coderabbitai configurationto show the current CodeRabbit configuration for the repository.@coderabbitai helpto get help.Other keywords and placeholders
@coderabbitai ignoreanywhere in the PR description to prevent this PR from being reviewed.@coderabbitai summaryto generate the high-level summary at a specific location in the PR description.@coderabbitaianywhere in the PR title to generate the title automatically.CodeRabbit Configuration File (
.coderabbit.yaml).coderabbit.yamlfile to the root of your repository.# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.jsonDocumentation and Community
@coderabbitai review
✅ Actions performed
Review triggered.
Actionable comments posted: 12
🔭 Outside diff range comments (1)
🧹 Nitpick comments (7)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between
5805b0631eandb2d2a3669a.📒 Files selected for processing (33)
cards/Classes/Neutral/Collectible/Minions/10-Cost/104-yogg-saron-master-of-fate.ts(0 hunks)cards/Examples/4/4-quest.ts(2 hunks)cards/StartingHeroes/Mage/114-heropower.ts(0 hunks)config.ts(2 hunks)index.ts(0 hunks)loc.md(1 hunks)scripts/cardtest.ts(1 hunks)scripts/crashtest.ts(4 hunks)scripts/id/main.ts(4 hunks)scripts/vanilla/generate.ts(1 hunks)src/card.ts(4 hunks)src/commands.ts(3 hunks)src/event.ts(4 hunks)src/functions/interact.ts(1 hunks)src/functions/util.ts(0 hunks)src/game.ts(7 hunks)src/player.ts(7 hunks)src/types/card.ts(1 hunks)test/src/ai.test.ts(1 hunks)test/src/card.test.ts(1 hunks)test/src/commands.test.ts(1 hunks)test/src/event.test.ts(1 hunks)test/src/functions/card.test.ts(3 hunks)test/src/functions/deckcode.test.ts(1 hunks)test/src/functions/info.test.ts(1 hunks)test/src/functions/interact.test.ts(1 hunks)test/src/functions/util.test.ts(5 hunks)test/src/game.test.ts(1 hunks)test/src/player.test.ts(3 hunks)tools/cardcreator/class.ts(1 hunks)tools/cardcreator/lib.ts(2 hunks)tools/cardcreator/vanilla.ts(0 hunks)tools/deckcreator.ts(1 hunks)💤 Files with no reviewable changes (5)
🧰 Additional context used
🧬 Code Graph Analysis (7)
scripts/crashtest.ts (2)
test/src/functions/util.test.ts (1)
scripts/vanilla/generate.ts (1)
src/event.ts (2)
src/player.ts (3)
test/src/player.test.ts (3)
src/card.ts (4)
🔇 Additional comments (40)
💡 Verification agent
🧩 Analysis chain
Well-structured error handling with good cleanup
The try-catch implementation properly manages test execution, handles errors gracefully, and ensures
game.noOutputis reset to false even if an error occurs. The addition of tracking TODOs viaEventListenerMessage.Skipis a useful feature for monitoring test progress.However, note that this function doesn't check whether the card has a test ability before attempting to trigger it.
🏁 Script executed:
Length of output: 66
🏁 Script executed:
Length of output: 1598
🏁 Script executed:
Length of output: 1474
Ensure the “Test” ability is defined and explicitly guard missing tests
While
card.trigger(Ability.Test)safely returnsfalsewhen no handler exists, we should:Test = "test"to theAbilityenum in src/types/card.ts soAbility.Testis valid.falsereturn value if you need to distinguish “no test” from “empty result.”These changes make missing tests visible and prevent accidental omissions.
⚠️ Potential issue
Spell-damage placeholder scan ignores
overrideTextspellDamageis derived fromthis.text, so callers who pass a customoverrideTextcontaining$<number>placeholders silently skip replacement.Using the local
textvariable ensures both the original description and any supplied override are handled consistently.Failing to do so produces stale
$ntokens in rendered output.✅ Addressed in commit
5adedb0@ -643,23 +643,21 @@ export const debugCommands: CommandList = {success &&= await game.functions.interact.withStatus(⚠️ Potential issue
Fixed potential infinite loop in card reloading
The refactored card reloading logic now uses the consolidated
game.activeCardscollection and includes a safeguard against duplicate UUIDs to prevent infinite loops. This is a significant improvement that makes the reload process more robust.However, the comment mentions a specific issue with "Frozen Test" cards. To fully understand this fix:
⚠️ Potential issue
Weapon destruction no longer silences the weapon’s enchantments
destroyWeaponusedweapon.destroy(), which callssilence()beforekill().Changing to
kill()alone:ChangeLocationevent dispatched bysetLocation(...)insidekill()→ behavioural divergence vs. Hearthstone reference.Unless this is deliberate, revert to
destroy()or explicitly callsilence()first:📝 Committable suggestion
✅ Addressed in commits
3674bcbto7273995@ -849,7 +849,14 @@ export class Player {* @returns Success🛠️ Refactor suggestion
Directly mutating
locationbypasses bookkeeping & eventsManually assigning:
skips
Card.setLocation, so:•
game.activeCardsis not updated•
Event.ChangeLocationis never broadcastThe same applies to the old hero that is set to
Location.None.🛠️ Refactor suggestion
Standardized test placeholders
Similar to the interact test file, this change standardizes the AI test placeholders by removing failing assertions, leaving empty async functions. This creates consistent test placeholders across the codebase.
The PR aims to add tests for AI (among other components), but these changes only prepare the structure without implementing actual tests. To fulfill the PR objective, consider implementing tests for at least some of these AI methods.
Here's an example implementation for the
calcMovetest:@ -1,270 +1,322 @@import { describe, expect, test } from "bun:test";💡 Verification agent
🧩 Analysis chain
Thorough testing of health-related mechanics
The
remHealthtest is comprehensive, covering interactions with different card types, keywords affecting damage (Stealth, Immune), and weapon destruction. However, there's a discrepancy in the test expectations for Immune cards:This comment suggests that while
remHealthreturns true (indicating success), it doesn't actually reduce health when the Immune keyword is present, which seems contradictory.🏁 Script executed:
Length of output: 112
🏁 Script executed:
Length of output: 11509
Clarify Immune behavior in remHealth test
The
remHealthtest is comprehensive, covering interactions with different card types, keywords (Stealth, Immune), and weapon destruction. However, the Immune case comment is misleading—the implementation and test both show that Immune prevents damage (health stays the same) while still returningtrue.Please update the comment in
test/src/card.test.ts:📝 Committable suggestion
✅ Addressed in commit
5adedb0💡 Verification agent
🧩 Analysis chain
Clean test placeholders structure
The changes standardize the test placeholders by removing failing assertions from the
test.todoblocks, making them empty async functions. This improves code consistency across test files and prepares the structure for future test implementations.However, given that the PR objective is to "Add more tests," we should aim to implement at least some of these test cases rather than just cleaning up the placeholders.
Let's check if there are any actual test implementations added in other test files:
🏁 Script executed:
Length of output: 80
Let’s broaden the search to the entire test suite for any actual
expect(…)calls:🏁 Script executed:
Length of output: 31550
Add concrete tests for
interact.test.tsThe file test/src/functions/interact.test.ts currently only has
test.todo(…)placeholders (lines 5–34). Since the PR’s goal is to add more tests, please replace at least a few of these with realtestblocks andexpectassertions to verify key behaviors, for example:deckcode,chooseOne,yesNo, etc.) invoke the correct handlers or return expected valueswatermark,license,gameState, etc.) produce the right formatted outputOnce you’ve added at least one implemented test per category (prompt, print, I/O), we can consider this file ready.
🛠️ Refactor suggestion
Standardized test placeholders structure
As with the other test files, these changes standardize the test placeholders by removing failing assertions. This improves code consistency but doesn't fulfill the PR objective of adding tests.
To meet the PR goals, consider implementing actual tests for at least some of these game functions, especially core functionality like
attack,play, andsummon.For example:
This would provide real test coverage rather than just placeholders.
@ -94,21 +100,78 @@ describe("src/player", () => {expect(player.emptyMana).toBe(7);});⚠️ Potential issue
Await the
addOverloadpromise to avoid race-conditionsPlayer.addOverloadis asynchronous (it broadcasts an event).Without
await, the expectation thatplayer.overloadhas incremented can execute before the promise resolves, making the test flaky.📝 Committable suggestion
✅ Addressed in commit
5adedb0@ -121,147 +184,602 @@ describe("src/player", () => {expect(player.armor).toBe(105);});⚠️ Potential issue
Copy-paste slip: testing the wrong function
The “canUseRunes” test still calls
canUseCorpses().This doesn’t exercise the intended code path and will give a false sense of coverage.
📝 Committable suggestion
✅ Addressed in commit
5adedb0⚠️ Potential issue
Same problem here – don’t forget to
awaitaddAttackaddAttackreturns a promise for the same reason asaddOverload. Add the missingawaitto guarantee deterministic assertions.📝 Committable suggestion
✅ Addressed in commit
5adedb0@coderabbitai review
✅ Actions performed
Review triggered.
Actionable comments posted: 1
♻️ Duplicate comments (1)
🧹 Nitpick comments (1)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between
b2d2a3669aand5adedb08c7.📒 Files selected for processing (7)
scripts/cardtest.ts(2 hunks)src/card.ts(4 hunks)src/commands.ts(3 hunks)src/game.ts(7 hunks)src/player.ts(7 hunks)test/src/card.test.ts(1 hunks)test/src/player.test.ts(3 hunks)🚧 Files skipped from review as they are similar to previous changes (6)
🧰 Additional context used
🧬 Code Graph Analysis (1)
test/src/player.test.ts (3)
⏰ Context from checks skipped due to timeout of 90000ms (1)
🔇 Additional comments (7)
@ -121,147 +184,602 @@ describe("src/player", () => {expect(player.armor).toBe(105);});🛠️ Refactor suggestion
Potential infinite loop in shuffleIntoDeck test.
The while loop could run indefinitely if the shuffling algorithm consistently places the card at index 0 or at the end.
Add a safety counter to prevent infinite loops:
📝 Committable suggestion
✅ Addressed in commits
3674bcbto7273995@ -849,7 +849,14 @@ export class Player {* @returns SuccessThis has been fixed in the newest commit.
@ -849,7 +849,14 @@ export class Player {* @returns Success@LunarTides Thanks for the update! I'm glad to hear you've fixed the issue with the proper location tracking. Using
setLocation()ensures all the card bookkeeping stays in sync.If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!
Mostly added in the newest commit (
5adedb0).🧩 Analysis chain
Let me check the changes in the commit the user referenced and the exact implementation of the card test functionality.
Let me check how the
Ability.Testis actually used in the code:@LunarTides I see you've implemented most of the suggested changes in the latest code. Your implementation now properly checks
if (!card.abilities.test)before attempting to trigger the test, which addresses the main concern about skipping cards without test abilities.The updated code is more streamlined - it eliminated separate helper functions, simplified deck setup, and improved error messaging. I also notice you're keeping track of skipped cards, which is a nice addition for reporting purposes.
One small thing to consider: is
Ability.Testformally defined in the enum? The verification agent suggested addingTest = "test"to theAbilityenum, but I didn't see confirmation that this was addressed. If it's already defined, that's great - if not, it might be worth adding for better type safety and code clarity.🏁 Script executed:
Length of output: 1441
🏁 Script executed:
Length of output: 615
🏁 Script executed:
Length of output: 97
@LunarTides I can confirm you've fully implemented all the suggestions! Looking at the codebase:
Test = "test"is properly defined in theAbilityenum in src/types/card.ts (line 181)if (!card.abilities.test)before triggering testsskips++The refactored implementation is clean and handles all the important edge cases. Great work on improving the testing setup!
🧬 Code Graph Analysis Results
Relevant snippets for understanding
scripts/cardtest.ts:File:
src/game.ts(lines 1836-1848)File:
src/card.ts(lines 38-2080) — Summary ofCardclass and relevant methodsThe
Cardclass represents a card in the game with properties such asname,text,cost,classes,type,rarity,abilities,owner, and many others.Key relevant methods and properties used in
cardtest.ts:static async all(include_uncollectible = false): Promise<Card[]>static async create(id: number, player: Player, suppressEvent = false): Promise<Card>setupto initialize the card.abilities: { [key in Ability]?: AbilityCallback[] }async trigger<E extends Event>(name: Ability, key?, value?, eventPlayer?): Promise<unknown[] | typeof Card.REFUND | false>Card.REFUNDorfalse.owner: Playername: stringid: numberconstructor(id: number, owner: Player)async setup(suppressEvent = false): Promise<void>doBlueprintand triggersAbility.Create.CreateCardevent unless suppressed.async doBlueprint(trigger = true): Promise<void>Ability.Create.static async registerAll(): Promise<boolean>async perfectCopy(): thisSummary of how these relate to
scripts/cardtest.ts:cardtest.tsimportscreateGameto create game instances and players.Card.all(true)to get all cards including uncollectible ones.testability, it creates a new game, sets up decks, and triggers thetestability.triggermethod onCardis used to run the test ability.Card.createmethod is used to create cards like "sheep1" for decks.createGamefunction optionally registers cards, which is relevant for loading blueprints used in tests.[End of relevant snippets.]
This is incorrect.
destroyonly callssilencebeforekill. Callingkillmanually does not skip the event broadcast. "Silencing" the card before destroying it, as was the previous behavior, was incorrect and does not match Hearthstone. The terminology is messy here, sincedestroyWeaponimplies thatdestroyis called on the weapon, but it actually means "killing" it.Since the terminology causes confusion for people unfamiliar to the codebase, the newest commit (
3674bcb) has renamed these methods.killhas been renamed todestroyanddestroyhas been renamed toremoveFromPlay. This should make the purpose of these methods clearer.🧩 Analysis chain
I need to check if I can see the latest changes with the renamed methods.
Let's examine the actual changes in that commit:
Let's look at the complete player.ts file to see the destroyWeapon method:
Let's look for tests related to these methods to understand the expected behavior:
Let's check for any card instances that might be affected by this change in the codebase:
Without seeing the revised implementations, I'll need to trust the user's explanation and provide a response acknowledging their correction:
@LunarTides Thank you for the clarification about the weapon destruction methods. I see that you've renamed the methods in commit
3674bcbto make their purposes clearer:kill()→destroy()anddestroy()→removeFromPlay(). This should indeed help avoid confusion for those unfamiliar with the codebase.The change from
weapon.destroy()toweapon.kill()(nowweapon.destroy()after renaming) was correct as it aligns with Hearthstone's behavior by not silencing enchantments before destruction. Sorry for the confusion in my previous comment.🏁 Script executed:
Length of output: 484
🏁 Script executed:
Length of output: 912
🏁 Script executed:
Length of output: 681
🏁 Script executed:
Length of output: 287
🏁 Script executed:
Length of output: 274
🏁 Script executed:
Length of output: 760
@LunarTides Thank you for the clarification on the method naming. Looking at the commit
3674bcb, I can now see that you've renamed the methods to better reflect their purpose:kill()→destroy()- Sets health to 0 and triggers board cleanupdestroy()→removeFromPlay()- Silences, destroys, and sets location to NoneYou're absolutely right - calling
weapon.kill()(nowweapon.destroy()) was the correct approach as it doesn't silence the weapon before destroying it, which aligns with Hearthstone's actual behavior.The terminology change makes the API much clearer: "destroy" better describes what the method actually does, and "removeFromPlay" more accurately describes the combined silence+destroy operation. Sorry for the confusion in my previous comment!
🧬 Code Graph Analysis Results
Relevant snippets for understanding
src/player.tsand the user comment aboutdestroy,silence, andkillterminology:From
src/card.ts(lines 38-2086, summarized key methods related to destroy/silence):destroy()sets health to 0 and triggers board cleanup.silence()removes abilities, resets stats to backup/blueprint values, applies strikethrough to text, clears keywords and enchantments, broadcasts silence event, and triggers board cleanup.removeFromPlay()callssilence()thendestroy(), then sets location to None.From
src/player.ts(lines related to weapon destruction):destroyWeapon()triggers the weapon's deathrattle, reduces player's attack by weapon attack, callsweapon.destroy(), and clears the weapon reference.From
src/types/other.ts(line 128):Targetas either aCardor aPlayer.Summary of relevance:
destroy,kill, andsilenceon cards and weapons.Cardclass methodsdestroy(),silence(), andremoveFromPlay()are directly relevant, showing thatdestroy()only sets health to 0 and triggers cleanup, whilesilence()removes abilities and resets stats.Playerclass methoddestroyWeapon()callsweapon.destroy()but does not callsilence(), matching the user's note that "destroy" only callssilencebeforekill(now renamed).killtodestroyanddestroytoremoveFromPlayto clarify semantics, which aligns with theCardclass methods.Targettype is relevant as it shows the types involved in attacks and destruction.No other snippets from the provided code are directly relevant to the user's comment about the destroy/silence/kill terminology and behavior.
If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!
Actionable comments posted: 1
🧹 Nitpick comments (3)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting
📥 Commits
Reviewing files that changed from the base of the PR and between
5adedb08c7and727399509a.📒 Files selected for processing (20)
.github/workflows/bun.yml(2 hunks)cards/Classes/Druid/Collectible/Spells/1-Cost/101-floops-glorious-gloop.ts(1 hunks)cards/Classes/Druid/Collectible/Spells/4-Cost/82-poison-seeds.ts(1 hunks)cards/Classes/Neutral/Collectible/Minions/10-Cost/104-yogg-saron-master-of-fate.ts(1 hunks)cards/Examples/2/7-Titan/7-ability1.ts(1 hunks)cards/Examples/DIY/1.ts(1 hunks)cards/Examples/DIY/4.ts(2 hunks)cards/Examples/Test/disable-heropower.ts(1 hunks)cards/Examples/Test/immortal.ts(2 hunks)cards/Galakrond/Priest/70-hero.ts(1 hunks)cards/Lackeys/28-witchy.ts(1 hunks)cards/StartingHeroes/Death Knight/23-frail-ghoul.ts(1 hunks)config.ts(3 hunks)src/card.ts(6 hunks)src/event.ts(5 hunks)src/game.ts(10 hunks)src/player.ts(7 hunks)src/types/event.ts(2 hunks)test/src/card.test.ts(1 hunks)test/src/player.test.ts(3 hunks)✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (4)
🧰 Additional context used
🧬 Code Graph Analysis (2)
test/src/card.test.ts (2)
src/card.ts (4)
🔇 Additional comments (47)
💡 Verification agent
🧩 Analysis chain
Add tests for destroy() and other key methods
While the tests added are excellent, there are still several critical methods that remain as
test.todo, includingdestroy()(the renamedkill()method) that's central to the refactoring in this PR. Consider prioritizing tests for these methods in a future PR.🏁 Script executed:
Length of output: 654
Add tests for
destroy()and other key Card methodsSeveral critical methods in
test/src/card.test.tsare still marked astest.todo, most notably the renameddestroy()(formerlykill()) and other core behaviors. Please prioritize adding specs for at least the following in your next PR:destroy()canAttack(),canBeAttacked(),attackTarget()silence(),removeFromPlay(),reset(),reload()createBackup(),restoreBackup()addEnchantment(),removeEnchantment(),applyEnchantments(),enchantmentExists()trigger(),manathirst(),discard(),condition(),perfectCopy(),imperfectCopy(),isAlive(),validateForDeck(),takeControl(),readable(),view()Having focused tests for these will ensure the refactoring around
destroy()and related game-state changes remains robust.🤖 Prompt for AI Agents