--- name: bulbapedia-tests description: Fetches move/ability descriptions from Bulbapedia and translates them into atomic TUnit tests in the Gen7 test project. Use when asked to write Bulbapedia-based tests for moves or abilities, e.g. "test tackle" or "write tests for all moves starting with a". argument-hint: allowed-tools: WebFetch(domain:bulbapedia.bulbagarden.net), Read, Glob, Grep, Write(Plugins/PkmnLib.Plugin.Gen7.Tests/**), Edit(Plugins/PkmnLib.Plugin.Gen7.Tests/**), Bash(dotnet build:*), Bash(dotnet test:*) --- # Bulbapedia → Gen7 unit tests Generate atomic unit tests for Gen7 move/ability script implementations, using their Bulbapedia descriptions as the source of truth for correct behavior. ## Hard constraints (tool whitelist) - **Web access**: only `https://bulbapedia.bulbagarden.net/...` via WebFetch. Never fetch any other domain. - **File modifications**: only inside `Plugins/PkmnLib.Plugin.Gen7.Tests/`. Never modify the implementation project (`Plugins/PkmnLib.Plugin.Gen7/`) or anything else — even if you find a bug there. Reading any file in the repo is allowed and encouraged. - **Shell**: only `dotnet build` and `dotnet test`. ## Step 1 — Resolve targets from the argument The argument describes what to test. Interpret it and resolve it to a list of implemented script classes: - A single name (`tackle`, `ability intimidate`) → that one script. Default to moves; the words "ability"/"abilities" switch to abilities. - A pattern (`all moves starting with a`, `abilities containing 'veil'`) → enumerate with Glob against the implementation folders: - Moves: `Plugins/PkmnLib.Plugin.Gen7/Scripts/Moves/*.cs` - Abilities: `Plugins/PkmnLib.Plugin.Gen7/Scripts/Abilities/*.cs` - Only test scripts that actually exist in those folders. If a requested target has no implementation file, don't invent one — list it as skipped in the final report. - Skip base/helper classes (e.g. `BaseChargeMove.cs`) unless explicitly requested; they are covered through the concrete moves. For each target, check whether `Plugins/PkmnLib.Plugin.Gen7.Tests/Scripts/{Moves,Abilities}/Tests.cs` already exists. If so, extend it with missing behaviors (via Edit) instead of overwriting it, and don't duplicate behaviors that already have a test. ## Step 2 — Fetch the Bulbapedia description This fetch procedure is verified to work; follow it exactly. **Primary: WebFetch the rendered wiki page.** URL conventions (spaces become underscores, each word capitalized as on Bulbapedia; the `(move)` suffix is lowercase, `(Ability)` is capitalized): - Moves: `https://bulbapedia.bulbagarden.net/wiki/_(move)` — e.g. `Tackle_(move)`, `Fury_Cutter_(move)` - Abilities: `https://bulbapedia.bulbagarden.net/wiki/_(Ability)` — e.g. `Intimidate_(Ability)` Prompt the fetch with: *"Extract the full Effect section verbatim, including all per-generation subsections."* The Effect section is structured as a base description plus generation-delta subsections, e.g. for Tackle: base text "Tackle inflicts damage and has no secondary effect.", then `Generations V and VI`: "power was increased from 35 to 50...", then `Generation VII onwards`: "power was decreased from 50 to 40." **Fallback / exact wording: the MediaWiki API, also via WebFetch.** When the summarized page extract seems lossy or you need the exact sentence to quote, fetch the raw wikitext (the Effect section is normally section index 1): - `https://bulbapedia.bulbagarden.net/w/api.php?action=parse&page=Tackle_(move)&prop=wikitext&format=json§ion=1` **Name resolution**: if unsure of the exact page title, use the API's opensearch: - `https://bulbapedia.bulbagarden.net/w/api.php?action=opensearch&search=Fury_C&limit=5&format=json` → returns matching titles and URLs (e.g. `Fury Cutter (move)`). **Deriving Gen VII behavior**: this codebase implements **Generation VII**. The Effect section is written as deltas — start from the base description and apply every subsection whose range includes Gen VII (`Generation VII onwards`, `Generations V to VII`, `Generation VI onwards`, ...); ignore subsections entirely outside it (`Generation I`, `Generation VIII`, side games like Legends: Arceus). Ability pages often use range headers like "Generations V to VII" — take the range containing VII. Also note interactions the page calls out (e.g. "does not activate if a Pokémon with Damp is on the field") — those are test cases too. ## Step 3 — Read the implementation Read the script class under `Plugins/PkmnLib.Plugin.Gen7/Scripts/{Moves,Abilities}/.cs` to learn which hooks it overrides (`ChangeBasePower`, `OnIncomingHit`, `OnFaint`, ...) and what its public surface looks like. Tests drive those hook methods directly — do not test behavior the script class isn't responsible for (type effectiveness, generic damage formula, or static data like base power and accuracy; `DataTests/` already covers move/ability data). ## Step 4 — Write atomic tests Follow the existing conventions — `Scripts/Moves/DrainTests.cs` and `Scripts/Abilities/AftermathTests.cs` are the reference examples (`DrainTests.cs` also shows `` usage and a real `[TestFailing]`), `Scripts/Moves/AcrobaticsTests.cs` a minimal one: - File: `Plugins/PkmnLib.Plugin.Gen7.Tests/Scripts/Moves/Tests.cs` or `.../Scripts/Abilities/Tests.cs`. - Namespace: `PkmnLib.Plugin.Gen7.Tests.Scripts.Moves` / `...Abilities`. `TUnit` and `NSubstitute` are global usings; add the `PkmnLib.*` usings the test needs. - **One behavior per test** (atomic). Name: `Method_Scenario_ExpectedOutcome`, e.g. `ChangeBasePower_UserNotHoldingItem_BasePowerDoubles`. - Each test gets an XML doc comment **quoting the Bulbapedia sentence it verifies**: `/// Bulbapedia: "When a Pokémon with this Ability faints from damage caused by a move that makes contact, ..."`. - In doc comments, refer to other classes and members with `` tags instead of plain text — the class-level comment references the script under test (`/// Tests for the ability.`), and test comments reference types or members they mention (`/// If the attacker has no , ...`). - Arrange/Act/Assert with `Substitute.For()`, `Substitute.For()`, etc. Assertions are TUnit style: `await Assert.That(actual).IsEqualTo(expected)`. - Use `[Arguments(...)]` rows for numeric variations (damage fractions, rounding/integer division, overflow guards). - Cover the negative cases the description implies (non-contact move → no trigger, holding an item → no boost, attacker already fainted, null `BattleData`, ...). - `LibraryHelpers.LoadLibrary()` is available when a test genuinely needs the full Gen7 library (e.g. looking up real move data); prefer pure mocks otherwise. ## Step 5 — Build, run, and mark failures 1. Build: `dotnet build Plugins/PkmnLib.Plugin.Gen7.Tests`. Compile errors are always test-authoring mistakes — fix them; the attribute cannot rescue non-compiling code. 2. Run the new tests: `dotnet test Plugins/PkmnLib.Plugin.Gen7.Tests` (TUnit runs on Microsoft.Testing.Platform; to run a single class, pass `-- --treenode-filter '/*/*/Tests/*'`). 3. For each failing test, decide who is wrong: - **The test is wrong** (misread the page, wrong mock setup, asserting behavior of a different generation) → fix the test and rerun. - **The implementation is wrong** (test correctly encodes Gen VII Bulbapedia behavior but the script does something else) → keep the correct assertion and add the marker so it is skipped but tracked: ```csharp [Test, TestFailing("Aftermath deals 1/2 max HP instead of 1/4 (Bulbapedia: '¼ of its own maximum HP')")] ``` `TestFailingAttribute` lives in `PkmnLib.Plugin.Gen7.Tests` and takes the failure reason as its argument — describe concretely what the implementation does wrong. - Never make a wrong test pass by asserting the buggy behavior, and never touch the implementation to make a test pass. 4. Rerun until every test either passes or carries `[TestFailing(...)]`. ## Step 6 — Report Summarize: tests written per target, tests marked `[TestFailing]` with their reasons (these are implementation bugs the user needs to fix), and targets skipped because no Gen7 implementation exists.