diff --git a/images/class_images/ffxiv_astrologian.png b/images/class_images/ffxiv_astrologian.png new file mode 100644 index 0000000..cc6459c Binary files /dev/null and b/images/class_images/ffxiv_astrologian.png differ diff --git a/images/class_images/ffxiv_dancer.png b/images/class_images/ffxiv_dancer.png new file mode 100644 index 0000000..39c894e Binary files /dev/null and b/images/class_images/ffxiv_dancer.png differ diff --git a/images/class_images/ffxiv_dark_knight.png b/images/class_images/ffxiv_dark_knight.png new file mode 100644 index 0000000..8a130af Binary files /dev/null and b/images/class_images/ffxiv_dark_knight.png differ diff --git a/images/class_images/ffxiv_gunbreaker.png b/images/class_images/ffxiv_gunbreaker.png new file mode 100644 index 0000000..a471dd9 Binary files /dev/null and b/images/class_images/ffxiv_gunbreaker.png differ diff --git a/images/class_images/ffxiv_machinist.png b/images/class_images/ffxiv_machinist.png new file mode 100644 index 0000000..c24badd Binary files /dev/null and b/images/class_images/ffxiv_machinist.png differ diff --git a/images/class_images/ffxiv_red_mage.png b/images/class_images/ffxiv_red_mage.png new file mode 100644 index 0000000..6873dd5 Binary files /dev/null and b/images/class_images/ffxiv_red_mage.png differ diff --git a/images/class_images/ffxiv_samurai.png b/images/class_images/ffxiv_samurai.png new file mode 100644 index 0000000..1ce99ca Binary files /dev/null and b/images/class_images/ffxiv_samurai.png differ diff --git a/images/roster_classes/ffxiv_astrologian.png b/images/roster_classes/ffxiv_astrologian.png new file mode 100644 index 0000000..1244333 Binary files /dev/null and b/images/roster_classes/ffxiv_astrologian.png differ diff --git a/images/roster_classes/ffxiv_dancer.png b/images/roster_classes/ffxiv_dancer.png new file mode 100644 index 0000000..9485915 Binary files /dev/null and b/images/roster_classes/ffxiv_dancer.png differ diff --git a/images/roster_classes/ffxiv_dark_knight.png b/images/roster_classes/ffxiv_dark_knight.png new file mode 100644 index 0000000..b2e5578 Binary files /dev/null and b/images/roster_classes/ffxiv_dark_knight.png differ diff --git a/images/roster_classes/ffxiv_gunbreaker.png b/images/roster_classes/ffxiv_gunbreaker.png new file mode 100644 index 0000000..e184343 Binary files /dev/null and b/images/roster_classes/ffxiv_gunbreaker.png differ diff --git a/images/roster_classes/ffxiv_machinist.png b/images/roster_classes/ffxiv_machinist.png new file mode 100644 index 0000000..15fb986 Binary files /dev/null and b/images/roster_classes/ffxiv_machinist.png differ diff --git a/images/roster_classes/ffxiv_red_mage.png b/images/roster_classes/ffxiv_red_mage.png new file mode 100644 index 0000000..902d52f Binary files /dev/null and b/images/roster_classes/ffxiv_red_mage.png differ diff --git a/images/roster_classes/ffxiv_samurai.png b/images/roster_classes/ffxiv_samurai.png new file mode 100644 index 0000000..67be8e8 Binary files /dev/null and b/images/roster_classes/ffxiv_samurai.png differ diff --git a/tests/game/ffxiv_icon_coverage_test.php b/tests/game/ffxiv_icon_coverage_test.php new file mode 100644 index 0000000..48d8b69 --- /dev/null +++ b/tests/game/ffxiv_icon_coverage_test.php @@ -0,0 +1,91 @@ +.png for the character rows + * and roster_classes/.png for the grid, so a seeded class with + * no file behind it has no icon. The audit that produced issue #8 found 12 + * such gaps; these tests assert no *new* gap appears, with the ones still + * outstanding listed explicitly. + */ +class ffxiv_icon_coverage_test extends TestCase +{ + /** + * Gaps tracked in #8 and deliberately still open: + * Reaper and Sage (Endwalker) plus Viper and Pictomancer (Dawntrail) + * are absent from XIVAPI v1, whose lighter-gold tone the shipped icons + * match; the v2 raw range has them in a visibly darker tone. ffxiv_unknown + * has no upstream source at all and needs authoring (avathar/bbguild#391). + */ + private const KNOWN_GAPS = array( + 'ffxiv_pictomancer', + 'ffxiv_reaper', + 'ffxiv_sage', + 'ffxiv_unknown', + 'ffxiv_viper', + ); + + /** + * @return list Every imagename seeded by the installer + */ + private function seeded_imagenames(): array + { + $src = file_get_contents(dirname(__DIR__, 2) . '/game/ffxiv_installer.php'); + + preg_match_all("/'imagename'\s*=>\s*'([^']+)'/", $src, $m); + + $names = array_values(array_unique(array_filter(array_map('trim', $m[1])))); + sort($names); + + return $names; + } + + private function assertNoUnexpectedGaps(string $dir): void + { + $base = dirname(__DIR__, 2) . '/images/' . $dir . '/'; + $missing = array(); + + foreach ($this->seeded_imagenames() as $name) + { + if (!file_exists($base . $name . '.png')) + { + $missing[] = $name; + } + } + + $unexpected = array_values(array_diff($missing, self::KNOWN_GAPS)); + + $this->assertSame( + array(), + $unexpected, + $dir . ' is missing icons that are not tracked as known gaps: ' . implode(', ', $unexpected) + ); + } + + public function test_class_images_cover_every_seeded_class(): void + { + $this->assertNoUnexpectedGaps('class_images'); + } + + public function test_roster_classes_cover_every_seeded_class(): void + { + $this->assertNoUnexpectedGaps('roster_classes'); + } + + public function test_the_installer_seeds_the_full_job_list(): void + { + // Guards the parser above: if the installer's array syntax changes, + // the coverage tests must not silently pass on an empty list. + $this->assertCount(28, $this->seeded_imagenames()); + } +}