From eb8202584c59b51b359bde7cebeb9ca1207d6f57 Mon Sep 17 00:00:00 2001 From: "bert.hausmans" Date: Wed, 6 May 2026 13:00:07 +0200 Subject: [PATCH] test: ActivityLogIndexesTest regression guard for D-06 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-2 verified that Spatie's activitylog default migration creates the composite indexes RFC-WS-7 §3.14 / addendum D-06 require — via nullableMorphs('subject') and nullableMorphs('causer'), which emit indexes named `subject` on (subject_type, subject_id) and `causer` on (causer_type, causer_id). This test queries information_schema.STATISTICS and fails if either composite is missing, regardless of the index name. It guards against silent regression when: - A future Spatie major release changes nullableMorphs semantics. - A developer rewrites the activity_log migration without preserving the morph indexes. - A schema-dump regeneration drops them. Test count 1539 to 1541. Larastan clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Database/ActivityLogIndexesTest.php | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 api/tests/Feature/Database/ActivityLogIndexesTest.php diff --git a/api/tests/Feature/Database/ActivityLogIndexesTest.php b/api/tests/Feature/Database/ActivityLogIndexesTest.php new file mode 100644 index 00000000..62c9885c --- /dev/null +++ b/api/tests/Feature/Database/ActivityLogIndexesTest.php @@ -0,0 +1,92 @@ +assertCompositeIndexExists( + table: 'activity_log', + columns: ['subject_type', 'subject_id'], + description: 'subject composite index (RFC-WS-7 §3.14 / D-06)', + ); + } + + public function test_causer_composite_index_exists(): void + { + $this->assertCompositeIndexExists( + table: 'activity_log', + columns: ['causer_type', 'causer_id'], + description: 'causer composite index (RFC-WS-7 §3.14 / D-06)', + ); + } + + /** + * @param list $columns + */ + private function assertCompositeIndexExists(string $table, array $columns, string $description): void + { + $database = config('database.connections.mysql.database'); + + $rows = DB::select( + 'SELECT INDEX_NAME, COLUMN_NAME, SEQ_IN_INDEX + FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = ? + AND TABLE_NAME = ? + ORDER BY INDEX_NAME, SEQ_IN_INDEX', + [$database, $table], + ); + + $indexColumns = []; + foreach ($rows as $row) { + $indexColumns[$row->INDEX_NAME][(int) $row->SEQ_IN_INDEX] = $row->COLUMN_NAME; + } + + $found = false; + foreach ($indexColumns as $sequence) { + ksort($sequence); + if (array_values($sequence) === $columns) { + $found = true; + break; + } + } + + $this->assertTrue( + $found, + sprintf( + 'Expected composite index on %s(%s) — %s. Found indexes: %s', + $table, + implode(', ', $columns), + $description, + json_encode($indexColumns, JSON_PRETTY_PRINT), + ), + ); + } +}