33
44namespace Itools \SmartString \Tests \Integration ;
55
6+ use Itools \SmartString \Deprecations ;
67use Itools \SmartString \SmartString ;
78use PHPUnit \Framework \Attributes \DataProvider ;
89use ReflectionClass ;
910use ReflectionMethod ;
1011use Itools \SmartString \Tests \Support \SmartStringTestCase ;
1112
1213/**
13- * Every public method must appear in the docs method reference, so new
14- * methods can't ship undocumented.
14+ * Every public method must appear in the docs method reference and in
15+ * ai-reference.md (the one docs file that ships in the Composer bundle),
16+ * so new methods can't ship undocumented.
1517 *
1618 * Exemptions:
1719 * - magic methods, jsonSerialize(), getIterator(): interface plumbing, never
1820 * called directly (getIterator only throws a foreach-misuse error)
19- * - everything in the Deprecations trait: renamed and retired methods
20- * keep working but stay out of the docs by design - docs show only the
21- * current names
21+ * - everything in the Deprecations trait (derived by reflection) : renamed and
22+ * retired methods keep working but stay out of the docs by design - docs
23+ * show only the current names
2224 */
2325class DocsCoverageTest extends SmartStringTestCase
2426{
25- private const EXEMPT = [' and ' , ' andPrefix ' , ' apply ' , ' dateTimeFormat ' , ' help ' , ' if ' , ' ifBlank ' , ' phoneFormat ' , ' textToHtml ' , 'jsonSerialize ' , 'getIterator ' ];
27+ private const INTERFACE_PLUMBING = ['jsonSerialize ' , 'getIterator ' ];
2628
2729 #[DataProvider('publicMethodsProvider ' )]
2830 public function testMethodIsInMethodReference (string $ method ): void
@@ -34,14 +36,31 @@ public function testMethodIsInMethodReference(string $method): void
3436 );
3537 }
3638
39+ #[DataProvider('publicMethodsProvider ' )]
40+ public function testMethodIsInAiReference (string $ method ): void
41+ {
42+ // ai-reference writes methods bare (`textOnly(): SmartString`), so no arrow prefix
43+ $ reference = file_get_contents (dirname (__DIR__ , 2 ) . '/docs/ai-reference.md ' );
44+ $ this ->assertTrue (
45+ str_contains ($ reference , "$ method( " ),
46+ "Public method $ method() is not mentioned in docs/ai-reference.md "
47+ );
48+ }
49+
3750 public static function publicMethodsProvider (): array
3851 {
52+ $ deprecated = array_map (
53+ static fn (ReflectionMethod $ m ) => $ m ->getName (),
54+ (new ReflectionClass (Deprecations::class))->getMethods (ReflectionMethod::IS_PUBLIC )
55+ );
56+ $ exempt = [...$ deprecated , ...self ::INTERFACE_PLUMBING ];
57+
3958 $ methods = (new ReflectionClass (SmartString::class))->getMethods (ReflectionMethod::IS_PUBLIC );
4059
4160 $ rows = [];
4261 foreach ($ methods as $ method ) {
4362 $ name = $ method ->getName ();
44- if (str_starts_with ($ name , '__ ' ) || in_array ($ name , self :: EXEMPT , true )) {
63+ if (str_starts_with ($ name , '__ ' ) || in_array ($ name , $ exempt , true )) {
4564 continue ;
4665 }
4766 $ rows [$ name ] = [$ name ];
@@ -51,10 +70,12 @@ public static function publicMethodsProvider(): array
5170
5271 /**
5372 * The exemption list stays honest: exempt methods must still exist.
73+ * (The Deprecations trait names exist by definition, so only the
74+ * hand-listed plumbing needs checking.)
5475 */
5576 public function testExemptMethodsStillExist (): void
5677 {
57- foreach (self ::EXEMPT as $ method ) {
78+ foreach (self ::INTERFACE_PLUMBING as $ method ) {
5879 $ this ->assertTrue (method_exists (SmartString::class, $ method ), "Exempt method $ method() no longer exists - remove it from the list " );
5980 }
6081 }
0 commit comments