diff --git a/tests/Support/AssertsToolErrors.php b/tests/Support/AssertsToolErrors.php new file mode 100644 index 0000000..2f8aa66 --- /dev/null +++ b/tests/Support/AssertsToolErrors.php @@ -0,0 +1,47 @@ +", the + * message carries the client JSON {code, message, hint, fields?, …}). + */ +trait AssertsToolErrors +{ + /** + * Asserts a tool error with $code as the client sees it (without "lit_"): the WP_Error code + * and the code in the JSON payload. + * + * @return array The client payload. + */ + public static function assertToolError(mixed $result, string $code, string $message = ''): array + { + Assert::assertInstanceOf(WP_Error::class, $result, $message); + Assert::assertSame('lit_' . $code, $result->get_error_code(), $message); + $payload = self::clientError($result); + Assert::assertSame($code, $payload['code'] ?? null, $message); + + return $payload; + } + + /** @return array The structured error the client sees (message JSON, spec §8.2). */ + public static function clientError(WP_Error $error): array + { + return (array) json_decode($error->get_error_message(), true); + } + + /** @return array The error's fields (input path => problem); asserts it has some. */ + public static function errorFields(WP_Error $error): array + { + $data = $error->get_error_data(); + Assert::assertIsArray($data, 'error data'); + Assert::assertIsArray($data['fields'] ?? null, 'error fields'); + + return $data['fields']; + } +} diff --git a/tests/Unit/Abilities/AbilityRegistrarTest.php b/tests/Unit/Abilities/AbilityRegistrarTest.php index 98a43df..feaded8 100644 --- a/tests/Unit/Abilities/AbilityRegistrarTest.php +++ b/tests/Unit/Abilities/AbilityRegistrarTest.php @@ -96,7 +96,7 @@ final class AbilityRegistrarTest extends TestCase $result = ($this->registrarFor($ability)->argsFor($ability)['permission_callback'])([]); self::assertInstanceOf(WP_Error::class, $result); - self::assertSame('lit_forbidden', $result->get_error_code()); + self::assertToolError($result, 'forbidden'); } public function testPermissionDeniedOutsideOAuthServerRequest(): void @@ -109,7 +109,7 @@ final class AbilityRegistrarTest extends TestCase $result = ($this->registrarFor($ability)->argsFor($ability)['permission_callback'])([]); self::assertInstanceOf(WP_Error::class, $result); - self::assertSame('lit_forbidden', $result->get_error_code()); + self::assertToolError($result, 'forbidden'); } public function testPermissionDelegatesToAbilityWhenGatePasses(): void @@ -149,7 +149,7 @@ final class AbilityRegistrarTest extends TestCase } self::assertInstanceOf(WP_Error::class, $result); - self::assertSame('lit_internal_error', $result->get_error_code()); + self::assertToolError($result, 'internal_error'); self::assertStringNotContainsString('/var/www', $result->get_error_message()); self::assertStringContainsString('lit/test failed', (string) file_get_contents($log)); unlink($log); @@ -170,7 +170,7 @@ final class AbilityRegistrarTest extends TestCase } self::assertInstanceOf(WP_Error::class, $result); - self::assertSame('lit_internal_error', $result->get_error_code()); + self::assertToolError($result, 'internal_error'); self::assertStringNotContainsString('/var/www', $result->get_error_message()); self::assertStringContainsString('lit/test failed', (string) file_get_contents($log)); unlink($log); @@ -196,7 +196,7 @@ final class AbilityRegistrarTest extends TestCase ini_set('error_log', (string) $previous); } - self::assertSame('lit_partial_write', $result->get_error_code()); + self::assertToolError($result, 'partial_write'); self::assertStringNotContainsString('/var/www', $result->get_error_message()); self::assertStringContainsString('meta /var/www', (string) file_get_contents($log)); unlink($log); diff --git a/tests/Unit/Abilities/CursorTest.php b/tests/Unit/Abilities/CursorTest.php index 1b819e8..fae2be8 100644 --- a/tests/Unit/Abilities/CursorTest.php +++ b/tests/Unit/Abilities/CursorTest.php @@ -46,7 +46,7 @@ final class CursorTest extends TestCase public function testInvalidCursorErrorIsAValidationError(): void { - self::assertSame('lit_validation_failed', Cursor::invalid()->get_error_code()); + self::assertToolError(Cursor::invalid(), 'validation_failed'); } public function testInputPropertiesDescribeLimitAndCursor(): void diff --git a/tests/Unit/Abilities/WriteFailedTest.php b/tests/Unit/Abilities/WriteFailedTest.php index b4fd958..3d14b42 100644 --- a/tests/Unit/Abilities/WriteFailedTest.php +++ b/tests/Unit/Abilities/WriteFailedTest.php @@ -18,7 +18,7 @@ final class WriteFailedTest extends TestCase self::assertTrue($failure->rolledBack); self::assertSame($cause, $failure->getPrevious()); self::assertStringContainsString('meta kaputt', $failure->getMessage()); - self::assertSame('lit_write_failed', $failure->toError()->get_error_code()); + self::assertToolError($failure->toError(), 'write_failed'); } public function testRolledBackHintReplacesTheDefaultHintOfWriteFailedOnly(): void @@ -35,7 +35,7 @@ final class WriteFailedTest extends TestCase { $error = WriteFailed::partial('Felder konnten nicht gespeichert werden.', postId: 5, revisionId: 811)->toError(); - self::assertSame('lit_partial_write', $error->get_error_code()); + self::assertToolError($error, 'partial_write'); self::assertSame(5, $error->get_error_data()['post_id']); self::assertSame(811, $error->get_error_data()['revision_id']); } @@ -49,7 +49,7 @@ final class WriteFailedTest extends TestCase details: ['menu_id' => 3] )->toError(); - self::assertSame('lit_partial_write', $error->get_error_code()); + self::assertToolError($error, 'partial_write'); self::assertStringContainsString('Das Menü ist teilweise geändert.', $error->get_error_message()); self::assertStringNotContainsString('Entwurf', $error->get_error_message()); self::assertSame('Mit lit/menu-get prüfen.', $error->get_error_data()['hint']); @@ -71,7 +71,7 @@ final class WriteFailedTest extends TestCase { $error = WriteFailed::rolledBack('Nicht übernommen.', details: ['backup_id' => 88])->toError(); - self::assertSame('lit_write_failed', $error->get_error_code()); + self::assertToolError($error, 'write_failed'); self::assertSame(88, $error->get_error_data()['backup_id']); self::assertStringContainsString('"backup_id":88', $error->get_error_message()); } diff --git a/tests/Unit/Integrations/Core/GuideAbilityTest.php b/tests/Unit/Integrations/Core/GuideAbilityTest.php index 24c9387..a669e86 100644 --- a/tests/Unit/Integrations/Core/GuideAbilityTest.php +++ b/tests/Unit/Integrations/Core/GuideAbilityTest.php @@ -40,7 +40,7 @@ final class GuideAbilityTest extends TestCase $result = $this->ability->execute(['topic' => '../../wp-config']); self::assertInstanceOf(WP_Error::class, $result); - self::assertSame('lit_not_found', $result->get_error_code()); + self::assertToolError($result, 'not_found'); self::assertStringContainsString('divi-shortform', $result->get_error_message()); } diff --git a/tests/Unit/Integrations/Divi/Design/DiviDesignSystemAbilityTest.php b/tests/Unit/Integrations/Divi/Design/DiviDesignSystemAbilityTest.php index 3a5da0b..6ef4d0e 100644 --- a/tests/Unit/Integrations/Divi/Design/DiviDesignSystemAbilityTest.php +++ b/tests/Unit/Integrations/Divi/Design/DiviDesignSystemAbilityTest.php @@ -39,6 +39,6 @@ final class DiviDesignSystemAbilityTest extends TestCase $result = (new DiviDesignSystemAbility(Mockery::mock(DesignSystemReader::class)))->permission([]); - self::assertSame('lit_forbidden', $result->get_error_code()); + self::assertToolError($result, 'forbidden'); } } diff --git a/tests/Unit/Integrations/Divi/Pages/DiviContentComposerTest.php b/tests/Unit/Integrations/Divi/Pages/DiviContentComposerTest.php index 881d169..d46eb8b 100644 --- a/tests/Unit/Integrations/Divi/Pages/DiviContentComposerTest.php +++ b/tests/Unit/Integrations/Divi/Pages/DiviContentComposerTest.php @@ -97,16 +97,16 @@ final class DiviContentComposerTest extends TestCase { $disabled = $this->composer(false)->check('post', [['type' => 'section']]); self::assertInstanceOf(WP_Error::class, $disabled); - self::assertSame('lit_validation_failed', $disabled->get_error_code()); - self::assertArrayHasKey('divi', $disabled->get_error_data()['fields']); + self::assertToolError($disabled, 'validation_failed'); + self::assertArrayHasKey('divi', self::errorFields($disabled)); $invalid = $this->composer()->check('page', [ ['type' => 'section', 'modules' => [['type' => 'button', 'attrs' => ['x.y' => ['desktop' => 1]]]]], ['type' => 'section', 'modules' => [['type' => 'button', 'url' => 'javascript:alert(1)', 'text' => 'x']]], ]); self::assertInstanceOf(WP_Error::class, $invalid); - self::assertSame('lit_invalid_attr_path', $invalid->get_error_code()); - $fields = $invalid->get_error_data()['fields']; + self::assertToolError($invalid, 'invalid_attr_path'); + $fields = self::errorFields($invalid); self::assertArrayHasKey('divi[0].modules[0].modules[0][0].attrs.x.y', $fields); self::assertGreaterThanOrEqual(2, count($fields), 'every error of every section comes back'); self::assertSame([], $this->saved); @@ -130,7 +130,7 @@ final class DiviContentComposerTest extends TestCase $written = $this->composer(true, $registry)->write(42, 'page', $sections); self::assertInstanceOf(WP_Error::class, $written); - self::assertSame('lit_validation_failed', $written->get_error_code()); + self::assertToolError($written, 'validation_failed'); self::assertSame([], $this->saved); } diff --git a/tests/Unit/Integrations/Divi/Pages/DiviPageLoaderTest.php b/tests/Unit/Integrations/Divi/Pages/DiviPageLoaderTest.php index 1afb1c6..46739de 100644 --- a/tests/Unit/Integrations/Divi/Pages/DiviPageLoaderTest.php +++ b/tests/Unit/Integrations/Divi/Pages/DiviPageLoaderTest.php @@ -34,7 +34,7 @@ final class DiviPageLoaderTest extends TestCase $result = (new DiviPageLoader(DiviFixtures::schema()))->load(7, false); self::assertInstanceOf(WP_Error::class, $result); - self::assertSame('lit_unsupported', $result->get_error_code()); + self::assertToolError($result, 'unsupported'); self::assertStringContainsString('Divi-4', $result->get_error_message()); } @@ -50,7 +50,7 @@ final class DiviPageLoaderTest extends TestCase ini_set('error_log', (string) $previous); } - self::assertSame('lit_unsupported', $result->get_error_code()); + self::assertToolError($result, 'unsupported'); self::assertStringContainsString('kein gültiges Block-Markup', $result->get_error_message()); self::assertStringContainsString('divi parse of post 7 failed', (string) file_get_contents($log)); unlink($log); @@ -62,7 +62,7 @@ final class DiviPageLoaderTest extends TestCase $loader = new DiviPageLoader(DiviFixtures::schema()); self::assertInstanceOf(DiviPage::class, $loader->load(7, false)); - self::assertSame('lit_validation_failed', $loader->load(7, true)->get_error_code()); + self::assertToolError($loader->load(7, true), 'validation_failed'); } public function testWritableChecks(): void @@ -70,7 +70,7 @@ final class DiviPageLoaderTest extends TestCase $loader = new DiviPageLoader(DiviFixtures::schema(false)); DiviFixtures::givenPost(''); $empty = $loader->load(7, true); - self::assertSame('lit_unsupported', $loader->writable($empty)->get_error_code()); + self::assertToolError($loader->writable($empty), 'unsupported'); $loader = new DiviPageLoader(DiviFixtures::schema()); DiviFixtures::givenPost("\n

Gutenberg

\n"); @@ -81,6 +81,6 @@ final class DiviPageLoaderTest extends TestCase DiviFixtures::givenPost('', ['post_status' => 'future', 'post_date_gmt' => '2020-01-01 00:00:00']); $missed = $loader->load(7, true); self::assertTrue($missed->isDiviLayout()); - self::assertSame('lit_validation_failed', $loader->writable($missed)->get_error_code()); + self::assertToolError($loader->writable($missed), 'validation_failed'); } } diff --git a/tests/Unit/Integrations/Divi/Pages/DiviReadAbilitiesTest.php b/tests/Unit/Integrations/Divi/Pages/DiviReadAbilitiesTest.php index c748c83..11e7f0d 100644 --- a/tests/Unit/Integrations/Divi/Pages/DiviReadAbilitiesTest.php +++ b/tests/Unit/Integrations/Divi/Pages/DiviReadAbilitiesTest.php @@ -65,7 +65,7 @@ final class DiviReadAbilitiesTest extends TestCase self::assertSame(['s1', 's1.r0'], array_column($result['nodes'], 'id')); $missing = $ability->execute(['post_id' => 7, 'id' => 's7']); - self::assertSame('lit_not_found', $missing->get_error_code()); + self::assertToolError($missing, 'not_found'); self::assertStringContainsString('tree_rev', $missing->get_error_message()); } @@ -120,7 +120,7 @@ final class DiviReadAbilitiesTest extends TestCase DiviFixtures::givenPost(DiviFixtures::markup('synthetic-basic.html')); $ability = new DiviNodeGetAbility(new DiviPageLoader(DiviFixtures::schema()), $this->design()); - self::assertSame('lit_validation_failed', $ability->execute(['post_id' => 7, 'id' => 'hero'])->get_error_code()); - self::assertSame('lit_not_found', $ability->execute(['post_id' => 7, 'id' => 's5.r0'])->get_error_code()); + self::assertToolError($ability->execute(['post_id' => 7, 'id' => 'hero']), 'validation_failed'); + self::assertToolError($ability->execute(['post_id' => 7, 'id' => 's5.r0']), 'not_found'); } } diff --git a/tests/Unit/Integrations/Divi/Pages/DiviReplaceTextAbilityTest.php b/tests/Unit/Integrations/Divi/Pages/DiviReplaceTextAbilityTest.php index ba92f14..bcdb0c8 100644 --- a/tests/Unit/Integrations/Divi/Pages/DiviReplaceTextAbilityTest.php +++ b/tests/Unit/Integrations/Divi/Pages/DiviReplaceTextAbilityTest.php @@ -107,12 +107,6 @@ final class DiviReplaceTextAbilityTest extends TestCase return $block === null ? null : AttrMap::desktop($block->attrs(), $path); } - /** @return array */ - private static function clientError(WP_Error $error): array - { - return (array) json_decode($error->get_error_message(), true); - } - public function testDryRunListsHitsWithTreeRevAndChangesNothing(): void { $ability = $this->ability(); @@ -177,13 +171,13 @@ final class DiviReplaceTextAbilityTest extends TestCase { $ability = $this->ability(); - self::assertSame('lit_validation_failed', $ability->execute(['search' => 'Termin', 'replace' => 'X', 'dry_run' => false])->get_error_code()); - self::assertSame('lit_validation_failed', $ability->execute([ + self::assertToolError($ability->execute(['search' => 'Termin', 'replace' => 'X', 'dry_run' => false]), 'validation_failed'); + self::assertToolError($ability->execute([ 'search' => 'Termin', 'replace' => 'X', 'dry_run' => false, 'confirm' => true, 'targets' => [['post_id' => 7]], - ])->get_error_code()); - self::assertSame('lit_confirm_required', $ability->execute([ + ]), 'validation_failed'); + self::assertToolError($ability->execute([ 'search' => 'Termin', 'replace' => 'X', 'dry_run' => false, 'targets' => [['post_id' => 7, 'tree_rev' => 'abc']], - ])->get_error_code()); + ]), 'confirm_required'); self::assertSame([], $this->saved); } @@ -225,9 +219,9 @@ final class DiviReplaceTextAbilityTest extends TestCase $short = $ability->execute(['search' => 'T', 'replace' => 'X']); $reference = $ability->execute(['search' => 'Termin', 'replace' => self::REF, 'dry_run' => false, 'confirm' => true, 'targets' => [['post_id' => 7, 'tree_rev' => 'x']]]); - self::assertSame('lit_validation_failed', $short->get_error_code()); + self::assertToolError($short, 'validation_failed'); self::assertArrayHasKey('search', self::clientError($short)['fields']); - self::assertSame('lit_validation_failed', $reference->get_error_code()); + self::assertToolError($reference, 'validation_failed'); self::assertArrayHasKey('replace', self::clientError($reference)['fields']); self::assertSame([], $this->queries); self::assertSame([], $this->saved); @@ -357,7 +351,7 @@ final class DiviReplaceTextAbilityTest extends TestCase self::assertSame([], $this->saved); if ($result instanceof WP_Error) { - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertInstanceOf(WP_Error::class, $dry); return; @@ -454,7 +448,7 @@ final class DiviReplaceTextAbilityTest extends TestCase foreach (['', "Ter\0min", "Ter\x0Bmin"] as $search) { $error = $ability->execute(['search' => $search, 'replace' => 'X']); - self::assertSame('lit_validation_failed', $error->get_error_code(), json_encode($search)); + self::assertToolError($error, 'validation_failed', json_encode($search)); self::assertArrayHasKey('search', self::clientError($error)['fields']); } @@ -478,7 +472,7 @@ final class DiviReplaceTextAbilityTest extends TestCase self::assertStringContainsString('LIMIT 3 OFFSET 0', $this->queries[0]); self::assertStringContainsString('LIMIT 3 OFFSET 2', $this->queries[1]); self::assertIsString($second['next_cursor'], 'the fake query returns three rows again'); - self::assertSame('lit_validation_failed', $invalid->get_error_code()); + self::assertToolError($invalid, 'validation_failed'); self::assertStringContainsString('LIMIT 101 OFFSET 0', $this->queries[2]); self::assertCount(3, $capped['matches']); } diff --git a/tests/Unit/Integrations/Divi/Pages/DiviSaverTest.php b/tests/Unit/Integrations/Divi/Pages/DiviSaverTest.php index a7d7498..d6840c2 100644 --- a/tests/Unit/Integrations/Divi/Pages/DiviSaverTest.php +++ b/tests/Unit/Integrations/Divi/Pages/DiviSaverTest.php @@ -171,7 +171,7 @@ final class DiviSaverTest extends TestCase self::fail('WriteFailed expected'); } catch (WriteFailed $e) { self::assertFalse($e->rolledBack); - self::assertSame('lit_partial_write', $e->toError()->get_error_code()); + self::assertToolError($e->toError(), 'partial_write'); } } diff --git a/tests/Unit/Integrations/Divi/Pages/DiviWriteAbilitiesTest.php b/tests/Unit/Integrations/Divi/Pages/DiviWriteAbilitiesTest.php index 4092095..3678ef2 100644 --- a/tests/Unit/Integrations/Divi/Pages/DiviWriteAbilitiesTest.php +++ b/tests/Unit/Integrations/Divi/Pages/DiviWriteAbilitiesTest.php @@ -71,12 +71,6 @@ final class DiviWriteAbilitiesTest extends TestCase return new DiviDuplicateNodeAbility($this->writer); } - /** @return array The structured error the client sees (message JSON, spec §8.2). */ - private static function clientError(WP_Error $error): array - { - return (array) json_decode($error->get_error_message(), true); - } - public function testInsertComposesAndSavesWithTreeRevAndPostRev(): void { $result = $this->insert()->execute([ @@ -106,7 +100,7 @@ final class DiviWriteAbilitiesTest extends TestCase public function testStaleTreeRevAndInvalidNodesWriteNothing(): void { $stale = $this->insert()->execute(['post_id' => 7, 'tree_rev' => '000000000000', 'nodes' => [['type' => 'section']]]); - self::assertSame('lit_rev_mismatch', $stale->get_error_code()); + self::assertToolError($stale, 'rev_mismatch'); self::assertSame('rev_mismatch', self::clientError($stale)['code'], 'the client sees the code without lit_'); self::assertStringContainsString('lit-divi-outline', $stale->get_error_data()['hint']); self::assertSame($stale->get_error_code(), $this->insert()->permission(['post_id' => 7, 'tree_rev' => 'x'])->get_error_code()); @@ -120,7 +114,7 @@ final class DiviWriteAbilitiesTest extends TestCase ['type' => 'button', 'url' => 'javascript:alert(1)', 'text' => 'x', 'nope' => 1], ], ]); - self::assertSame('lit_invalid_attr_path', $invalid->get_error_code()); + self::assertToolError($invalid, 'invalid_attr_path'); $client = self::clientError($invalid); self::assertSame('invalid_attr_path', $client['code']); self::assertArrayHasKey('nodes[0].attrs.title.fnt', $client['fields']); @@ -128,7 +122,7 @@ final class DiviWriteAbilitiesTest extends TestCase self::assertStringContainsString('lit-divi-catalog', $client['hint']); $wrongPlace = $this->insert()->execute(['post_id' => 7, 'tree_rev' => $this->treeRev(), 'nodes' => [['type' => 'button']]]); - self::assertSame('lit_validation_failed', $wrongPlace->get_error_code()); + self::assertToolError($wrongPlace, 'validation_failed'); $badPosition = $this->insert()->execute([ 'post_id' => 7, @@ -137,7 +131,7 @@ final class DiviWriteAbilitiesTest extends TestCase 'after' => 's0.r0.c1.m1', 'nodes' => [['type' => 'text']], ]); - self::assertSame('lit_validation_failed', $badPosition->get_error_code()); + self::assertToolError($badPosition, 'validation_failed'); self::assertArrayHasKey('position', self::clientError($badPosition)['fields']); $unknown = $this->insert()->execute([ @@ -146,7 +140,7 @@ final class DiviWriteAbilitiesTest extends TestCase 'parent' => 's9', 'nodes' => [['type' => 'section']], ]); - self::assertSame('lit_validation_failed', $unknown->get_error_code()); + self::assertToolError($unknown, 'validation_failed'); self::assertSame([], $this->saved); self::assertSame($this->original, $this->post->post_content); } @@ -177,7 +171,7 @@ final class DiviWriteAbilitiesTest extends TestCase ['id' => 's0.r0.c1.m0', 'set' => ['level' => 'h9']], ['id' => 's0.r0.c1.m9', 'label' => 'x'], ]]); - self::assertSame('lit_validation_failed', $failed->get_error_code()); + self::assertToolError($failed, 'validation_failed'); $fields = self::clientError($failed)['fields']; self::assertArrayHasKey('changes[1].set.level', $fields); self::assertArrayHasKey('changes[2].id', $fields, 'every error of the call in one response (S39)'); @@ -220,7 +214,7 @@ final class DiviWriteAbilitiesTest extends TestCase 'changes' => [['id' => 's0.r0.c1.m2', 'label' => 'x']], ]); - self::assertSame('lit_rev_mismatch', $result->get_error_code()); + self::assertToolError($result, 'rev_mismatch'); self::assertSame([], $this->saved); } @@ -251,14 +245,14 @@ final class DiviWriteAbilitiesTest extends TestCase $intoSection = $this->move()->execute([ 'post_id' => 7, 'tree_rev' => $treeRev, 'id' => 's0.c0.m0', 'parent' => 's1', ]); - self::assertSame('lit_validation_failed', $intoSection->get_error_code()); + self::assertToolError($intoSection, 'validation_failed'); self::assertStringContainsString('Zeilen (row)', self::clientError($intoSection)['fields']['position']); // s0.c1 is a specialty column (specialtyColumns set, holds a row-inner): refuses every child. $intoSpecialtyColumn = $this->move()->execute([ 'post_id' => 7, 'tree_rev' => $treeRev, 'id' => 's0.c0.m0', 'parent' => 's0.c1', ]); - self::assertSame('lit_validation_failed', $intoSpecialtyColumn->get_error_code()); + self::assertToolError($intoSpecialtyColumn, 'validation_failed'); self::assertStringContainsString('Spezialspalten', self::clientError($intoSpecialtyColumn)['fields']['position']); self::assertSame([], $this->saved); @@ -271,7 +265,7 @@ final class DiviWriteAbilitiesTest extends TestCase 'post_id' => 7, 'tree_rev' => $this->treeRev(), 'id' => 's0', 'parent' => 's0.r0.c1', ]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString( 'nicht in sich selbst verschoben', self::clientError($result)['fields']['position'] @@ -285,7 +279,7 @@ final class DiviWriteAbilitiesTest extends TestCase 'post_id' => 7, 'tree_rev' => '000000000000', 'id' => 's0.r0.c1.m2', 'parent' => 's1.r0.c0', ]); - self::assertSame('lit_rev_mismatch', $result->get_error_code()); + self::assertToolError($result, 'rev_mismatch'); self::assertSame('rev_mismatch', self::clientError($result)['code'], 'the client sees the code without lit_'); self::assertSame([], $this->saved); } @@ -349,7 +343,7 @@ final class DiviWriteAbilitiesTest extends TestCase 'post_id' => 7, 'tree_rev' => $this->treeRev(), 'ids' => ['s9'], 'confirm' => true, ]); - self::assertSame('lit_not_found', $result->get_error_code()); + self::assertToolError($result, 'not_found'); self::assertSame('not_found', self::clientError($result)['code']); self::assertSame([], $this->saved); } @@ -371,10 +365,10 @@ final class DiviWriteAbilitiesTest extends TestCase $delete = $this->delete(); $ask = $delete->execute(['post_id' => 7, 'tree_rev' => Rev::of($this->saved[0]), 'ids' => ['s2', 's2.r0']]); - self::assertSame('lit_confirm_required', $ask->get_error_code()); + self::assertToolError($ask, 'confirm_required'); self::assertSame( '1 Divi-Knoten würden samt Inhalt entfernt: s2 section "Leistungen (Kopie)" (1 Kind-Knoten).', - json_decode($ask->get_error_message(), true)['message'] + self::clientError($ask)['message'] ); $deleted = $delete->execute(['post_id' => 7, 'tree_rev' => Rev::of($this->saved[0]), 'ids' => ['s2'], 'confirm' => true]); @@ -490,7 +484,7 @@ final class DiviWriteAbilitiesTest extends TestCase foreach ([$this->move(), $this->delete(), $this->duplicate()] as $ability) { $result = $ability->permission(['post_id' => 7, 'tree_rev' => $this->treeRev()]); self::assertInstanceOf(WP_Error::class, $result, $ability->name()); - self::assertSame('lit_forbidden', $result->get_error_code(), $ability->name()); + self::assertToolError($result, 'forbidden', $ability->name()); } self::assertSame([], $this->saved); } @@ -505,7 +499,7 @@ final class DiviWriteAbilitiesTest extends TestCase 'changes' => [['id' => 's1.g1', 'label' => 'x']], ]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString('nur lesbar', $result->get_error_message()); self::assertSame([], $this->saved); } @@ -518,7 +512,7 @@ final class DiviWriteAbilitiesTest extends TestCase ['id' => 's0.r0.c1.m2', 'set' => ['url' => '/zwei']], ]]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString('changes[0]', self::clientError($result)['fields']['changes[1].id']); self::assertSame([], $this->saved); } @@ -532,7 +526,7 @@ final class DiviWriteAbilitiesTest extends TestCase 'attrs' => ['button.innerContent' => ['desktop' => ['linkUrl' => '/neu']]], ]]]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertArrayHasKey('changes[0].attrs.button.innerContent', self::clientError($result)['fields']); self::assertSame([], $this->saved); } @@ -551,7 +545,7 @@ final class DiviWriteAbilitiesTest extends TestCase ]], ]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertArrayHasKey('nodes[0].attrs.button.innerContent', self::clientError($result)['fields']); self::assertSame([], $this->saved); } @@ -564,7 +558,7 @@ final class DiviWriteAbilitiesTest extends TestCase $broken = $this->update()->execute(['post_id' => 7, 'tree_rev' => $this->treeRev(), 'changes' => [ ['id' => 's0.r0.c0', 'attrs' => $sizing('12_24')], ]]); - self::assertSame('lit_validation_failed', $broken->get_error_code()); + self::assertToolError($broken, 'validation_failed'); self::assertArrayHasKey('changes[0].attrs.module.decoration.sizing', self::clientError($broken)['fields']); self::assertSame([], $this->saved); @@ -636,9 +630,9 @@ final class DiviWriteAbilitiesTest extends TestCase public function testUpdateKeepsExactRowsStrict(): void { $broken = $this->updateOn($this->original, [['id' => 's0.r0.c0', 'attrs' => self::sizing(null)]]); - self::assertSame('lit_validation_failed', $broken->get_error_code()); + self::assertToolError($broken, 'validation_failed'); $broken = $this->updateOn($this->original, [['id' => 's0.r0.c0', 'attrs' => self::sizing('10_24')]]); - self::assertSame('lit_validation_failed', $broken->get_error_code()); + self::assertToolError($broken, 'validation_failed'); self::assertSame([], $this->saved); } @@ -650,7 +644,7 @@ final class DiviWriteAbilitiesTest extends TestCase 'attrs' => ['module.decoration.attributes' => ['desktop' => ['attributes' => [['name' => 'onclick', 'value' => 'x']]]]], ]]]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); $client = self::clientError($result); self::assertSame('validation_failed', $client['code']); self::assertStringContainsString('nur im Divi-Builder', $client['fields']['changes[0].attrs.module.decoration.attributes']); diff --git a/tests/Unit/Integrations/Divi/Pages/DiviWriterTest.php b/tests/Unit/Integrations/Divi/Pages/DiviWriterTest.php index 28b338c..89ca407 100644 --- a/tests/Unit/Integrations/Divi/Pages/DiviWriterTest.php +++ b/tests/Unit/Integrations/Divi/Pages/DiviWriterTest.php @@ -54,9 +54,9 @@ final class DiviWriterTest extends TestCase $writer = $this->writer(Mockery::mock(DiviSaver::class), FakeChangeLog::forbidden()); self::assertInstanceOf(DiviPage::class, $writer->page(['post_id' => 7, 'tree_rev' => Rev::of($content)])); - self::assertSame('lit_rev_mismatch', $writer->page(['post_id' => 7])->get_error_code()); + self::assertToolError($writer->page(['post_id' => 7]), 'rev_mismatch'); $stale = $writer->page(['post_id' => 7, 'tree_rev' => Rev::ofPost(DiviFixtures::givenPost($content))]); - self::assertSame('lit_rev_mismatch', $stale->get_error_code(), 'the post rev is no tree_rev'); + self::assertToolError($stale, 'rev_mismatch', 'the post rev is no tree_rev'); self::assertStringContainsString('nichts wurde', $stale->get_error_message()); } @@ -72,7 +72,7 @@ final class DiviWriterTest extends TestCase Mockery::mock(DiviComposition::class) ); - self::assertSame('lit_unsupported', $writer->page(['post_id' => 7, 'tree_rev' => Rev::of($content)])->get_error_code()); + self::assertToolError($writer->page(['post_id' => 7, 'tree_rev' => Rev::of($content)]), 'unsupported'); } public function testSectionLabelOfANode(): void diff --git a/tests/Unit/Integrations/Divi/Schema/DiviCatalogAbilityTest.php b/tests/Unit/Integrations/Divi/Schema/DiviCatalogAbilityTest.php index 50cf66b..21836c4 100644 --- a/tests/Unit/Integrations/Divi/Schema/DiviCatalogAbilityTest.php +++ b/tests/Unit/Integrations/Divi/Schema/DiviCatalogAbilityTest.php @@ -78,10 +78,10 @@ final class DiviCatalogAbilityTest extends TestCase public function testUnknownModuleAndPermission(): void { - self::assertSame('lit_not_found', $this->ability()->execute(['module' => 'slider-pro'])->get_error_code()); + self::assertToolError($this->ability()->execute(['module' => 'slider-pro']), 'not_found'); Functions\when('current_user_can')->justReturn(false); - self::assertSame('lit_forbidden', $this->ability()->permission([])->get_error_code()); + self::assertToolError($this->ability()->permission([]), 'forbidden'); self::assertTrue($this->ability()->annotations()['readonly']); self::assertTrue($this->ability()->isDirect()); } diff --git a/tests/Unit/Integrations/Media/MediaDeleteAbilityTest.php b/tests/Unit/Integrations/Media/MediaDeleteAbilityTest.php index 8917ae3..9862cff 100644 --- a/tests/Unit/Integrations/Media/MediaDeleteAbilityTest.php +++ b/tests/Unit/Integrations/Media/MediaDeleteAbilityTest.php @@ -41,7 +41,7 @@ final class MediaDeleteAbilityTest extends TestCase $result = $this->ability(self::USAGE, FakeChangeLog::forbidden())->execute(['id' => 33]); - self::assertSame('lit_confirm_required', $result->get_error_code()); + self::assertToolError($result, 'confirm_required'); self::assertStringContainsString('endgültig', $result->get_error_message()); self::assertStringContainsString('1 Stelle', $result->get_error_message()); self::assertSame(self::USAGE, $result->get_error_data()['usages']); @@ -51,7 +51,7 @@ final class MediaDeleteAbilityTest extends TestCase { $result = $this->ability([], FakeChangeLog::forbidden(), true)->execute(['id' => 33, 'confirm' => false]); - self::assertSame('lit_confirm_required', $result->get_error_code()); + self::assertToolError($result, 'confirm_required'); self::assertStringContainsString('Papierkorb', $result->get_error_message()); } @@ -61,7 +61,7 @@ final class MediaDeleteAbilityTest extends TestCase $result = $this->ability(self::USAGE, FakeChangeLog::forbidden())->execute(['id' => 33, 'confirm' => true]); - self::assertSame('lit_in_use', $result->get_error_code()); + self::assertToolError($result, 'in_use'); self::assertSame(self::USAGE, $result->get_error_data()['usages']); } @@ -71,7 +71,7 @@ final class MediaDeleteAbilityTest extends TestCase $result = $this->ability(self::POSSIBLE, FakeChangeLog::forbidden())->execute(['id' => 33, 'confirm' => true]); - self::assertSame('lit_in_use', $result->get_error_code()); + self::assertToolError($result, 'in_use'); } public function testForceDeletesUsedMedia(): void @@ -115,7 +115,7 @@ final class MediaDeleteAbilityTest extends TestCase $result = $this->ability([], FakeChangeLog::forbidden())->execute(['id' => 33, 'confirm' => true]); - self::assertSame('lit_write_failed', $result->get_error_code()); + self::assertToolError($result, 'write_failed'); } public function testRefusedDeleteThatRemovedDataIsAPartialWrite(): void @@ -133,7 +133,7 @@ final class MediaDeleteAbilityTest extends TestCase $result = $this->ability([], $log)->execute(['id' => 33, 'confirm' => true]); - self::assertSame('lit_partial_write', $result->get_error_code()); + self::assertToolError($result, 'partial_write'); self::assertSame(33, $result->get_error_data()['attachment_id']); $log->assertPartials(['ability' => 'lit/media-delete', 'object_type' => 'attachment', 'object_id' => '33']); } @@ -162,7 +162,7 @@ final class MediaDeleteAbilityTest extends TestCase unlink($file); } - self::assertSame('lit_in_use', $result->get_error_code()); + self::assertToolError($result, 'in_use'); self::assertSame(MediaUsageFinder::FAILED_TITLE, $result->get_error_data()['usages'][0]['title']); } @@ -193,8 +193,8 @@ final class MediaDeleteAbilityTest extends TestCase $ability = $this->ability([], FakeChangeLog::forbidden()); - self::assertSame('lit_validation_failed', $ability->permission(['id' => 33])->get_error_code()); - self::assertSame('lit_validation_failed', $ability->execute(['id' => 33, 'confirm' => true])->get_error_code()); + self::assertToolError($ability->permission(['id' => 33]), 'validation_failed'); + self::assertToolError($ability->execute(['id' => 33, 'confirm' => true]), 'validation_failed'); } public function testChecksDeletePostOnTheAttachment(): void @@ -203,7 +203,7 @@ final class MediaDeleteAbilityTest extends TestCase $result = $this->ability([], FakeChangeLog::forbidden())->permission(['id' => 33]); - self::assertSame('lit_forbidden', $result->get_error_code()); + self::assertToolError($result, 'forbidden'); } public function testIsDestructiveAndDescribesWhatTheUsageCheckMisses(): void diff --git a/tests/Unit/Integrations/Media/MediaDownloadAbilityTest.php b/tests/Unit/Integrations/Media/MediaDownloadAbilityTest.php index 7817abf..d6edfbc 100644 --- a/tests/Unit/Integrations/Media/MediaDownloadAbilityTest.php +++ b/tests/Unit/Integrations/Media/MediaDownloadAbilityTest.php @@ -59,7 +59,7 @@ final class MediaDownloadAbilityTest extends TestCase $result = (new MediaDownloadAbility(new Limits()))->execute(['id' => 40]); - self::assertSame('lit_unsupported', $result->get_error_code()); + self::assertToolError($result, 'unsupported'); } public function testDownloadsAreCappedAtTenMegabytesEvenWithAHigherUploadLimit(): void @@ -69,7 +69,7 @@ final class MediaDownloadAbilityTest extends TestCase $result = (new MediaDownloadAbility(new Limits()))->execute(['id' => 40]); - self::assertSame('lit_unsupported', $result->get_error_code()); + self::assertToolError($result, 'unsupported'); self::assertStringContainsString('Limit 10 MB', $result->get_error_message()); self::assertStringContainsString('URL', (string) $result->get_error_data()['hint']); } @@ -81,7 +81,7 @@ final class MediaDownloadAbilityTest extends TestCase $result = (new MediaDownloadAbility(new Limits()))->execute(['id' => 40, 'size' => 'huge']); - self::assertSame('lit_not_found', $result->get_error_code()); + self::assertToolError($result, 'not_found'); self::assertNull((new MediaDownloadAbility(new Limits()))->outputSchema()); } @@ -92,6 +92,6 @@ final class MediaDownloadAbilityTest extends TestCase $result = (new MediaDownloadAbility(new Limits()))->execute(['id' => 40]); - self::assertSame('lit_not_found', $result->get_error_code()); + self::assertToolError($result, 'not_found'); } } diff --git a/tests/Unit/Integrations/Media/MediaGetAbilityTest.php b/tests/Unit/Integrations/Media/MediaGetAbilityTest.php index 91cfa1b..e501511 100644 --- a/tests/Unit/Integrations/Media/MediaGetAbilityTest.php +++ b/tests/Unit/Integrations/Media/MediaGetAbilityTest.php @@ -45,7 +45,7 @@ final class MediaGetAbilityTest extends TestCase Functions\when('get_post')->justReturn(new WP_Post(['ID' => 5, 'post_type' => 'page'])); $ability = new MediaGetAbility(Mockery::mock(MediaPresenter::class), Mockery::mock(MediaUsageFinder::class)); - self::assertSame('lit_not_found', $ability->permission(['id' => 5])->get_error_code()); + self::assertToolError($ability->permission(['id' => 5]), 'not_found'); } public function testIsIndirectAndReadonly(): void diff --git a/tests/Unit/Integrations/Media/MediaGuardTest.php b/tests/Unit/Integrations/Media/MediaGuardTest.php index e8cacdc..8e49fa3 100644 --- a/tests/Unit/Integrations/Media/MediaGuardTest.php +++ b/tests/Unit/Integrations/Media/MediaGuardTest.php @@ -13,17 +13,17 @@ final class MediaGuardTest extends TestCase { public function testInvalidIdIsAValidationError(): void { - self::assertSame('lit_validation_failed', MediaGuard::attachment('abc')->get_error_code()); - self::assertSame('lit_validation_failed', MediaGuard::attachment(0)->get_error_code()); + self::assertToolError(MediaGuard::attachment('abc'), 'validation_failed'); + self::assertToolError(MediaGuard::attachment(0), 'validation_failed'); } public function testMissingOrNonAttachmentIsNotFound(): void { Functions\when('get_post')->justReturn(null); - self::assertSame('lit_not_found', MediaGuard::attachment(33)->get_error_code()); + self::assertToolError(MediaGuard::attachment(33), 'not_found'); Functions\when('get_post')->justReturn(new WP_Post(['ID' => 33, 'post_type' => 'page'])); - self::assertSame('lit_not_found', MediaGuard::attachment(33)->get_error_code()); + self::assertToolError(MediaGuard::attachment(33), 'not_found'); } public function testChecksTheRequestedCapabilityOnTheAttachment(): void @@ -32,7 +32,7 @@ final class MediaGuardTest extends TestCase Functions\when('get_post')->justReturn($attachment); Functions\expect('current_user_can')->once()->with('delete_post', 33)->andReturn(false); - self::assertSame('lit_forbidden', MediaGuard::attachment('33', 'delete_post')->get_error_code()); + self::assertToolError(MediaGuard::attachment('33', 'delete_post'), 'forbidden'); } public function testRefusesTrashedAttachmentsUnlessAllowed(): void @@ -42,7 +42,7 @@ final class MediaGuardTest extends TestCase Functions\when('current_user_can')->justReturn(true); $error = MediaGuard::attachment(33); - self::assertSame('lit_validation_failed', $error->get_error_code()); + self::assertToolError($error, 'validation_failed'); self::assertStringContainsString('Papierkorb', $error->get_error_message()); self::assertSame($attachment, MediaGuard::attachment(33, 'read_post', true)); } diff --git a/tests/Unit/Integrations/Media/MediaImporterTest.php b/tests/Unit/Integrations/Media/MediaImporterTest.php index 6724102..af8d17f 100644 --- a/tests/Unit/Integrations/Media/MediaImporterTest.php +++ b/tests/Unit/Integrations/Media/MediaImporterTest.php @@ -136,7 +136,7 @@ final class MediaImporterTest extends TestCase { $result = $this->importer()->fromBase64(str_repeat('A', 2 * 1024 * 1024), 'big.png', []); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString('Limit 1 MB', $result->get_error_message()); self::assertSame([], $this->tempFiles, 'no temp file may be written for an oversized upload'); } @@ -147,7 +147,7 @@ final class MediaImporterTest extends TestCase $result = $this->importer()->fromBase64(str_repeat('A', 16 * 1024 * 1024), 'big.png', []); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString('Limit 10 MB', $result->get_error_message()); self::assertStringContainsString('lit/media-upload-from-url', (string) $result->get_error_data()['hint']); self::assertSame([], $this->tempFiles); @@ -157,7 +157,7 @@ final class MediaImporterTest extends TestCase { $result = $this->importer()->fromBase64('***', 'x.png', []); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertSame([], $this->tempFiles); } @@ -168,7 +168,7 @@ final class MediaImporterTest extends TestCase $result = $this->importer()->fromBase64(base64_encode('get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertNotSame([], $this->tempFiles); $this->assertTempFilesRemoved(); } @@ -182,7 +182,7 @@ final class MediaImporterTest extends TestCase $result = $this->importer()->fromBase64(base64_encode('PNGDATA'), 'logo.png', []); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString('png', $result->get_error_message()); } @@ -198,7 +198,7 @@ final class MediaImporterTest extends TestCase $result = $this->importer()->fromBase64(base64_encode('PNGDATA'), 'logo.png', []); $logged = (string) file_get_contents($this->errorLog); - self::assertSame('lit_write_failed', $result->get_error_code()); + self::assertToolError($result, 'write_failed'); self::assertStringNotContainsString('/var/www', $result->get_error_message()); self::assertStringNotContainsString('/var/www', (string) json_encode($result->get_error_data())); self::assertStringContainsString('WordPress hat die Datei nicht übernommen', $result->get_error_message()); @@ -238,7 +238,7 @@ final class MediaImporterTest extends TestCase self::fail('WriteFailed expected'); } catch (WriteFailed $e) { self::assertTrue($e->rolledBack); - self::assertSame('lit_write_failed', $e->toError()->get_error_code()); + self::assertToolError($e->toError(), 'write_failed'); } $this->assertTempFilesRemoved(); } @@ -258,7 +258,7 @@ final class MediaImporterTest extends TestCase self::assertFalse($e->rolledBack); self::assertSame(55, $e->postId); $error = $e->toError(); - self::assertSame('lit_partial_write', $error->get_error_code()); + self::assertToolError($error, 'partial_write'); self::assertStringContainsString('Medium 55', $error->get_error_message()); self::assertSame(55, $error->get_error_data()['attachment_id']); } @@ -282,7 +282,7 @@ final class MediaImporterTest extends TestCase $result = $this->importer()->fromUrl('http://127.0.0.1/wp-config.php', null, []); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testOnlyHttpUrlsAreFetched(): void @@ -292,7 +292,7 @@ final class MediaImporterTest extends TestCase $result = $this->importer()->fromUrl('ftp://example.com/logo.png', null, []); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testUrlImportDownloadsSafelyWithTheSizeLimit(): void @@ -332,7 +332,7 @@ final class MediaImporterTest extends TestCase $result = $this->importer()->fromUrl('https://example.com/fehlt.jpg', null, []); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString('Not Found', $result->get_error_message()); $this->assertTempFilesRemoved(); } @@ -344,7 +344,7 @@ final class MediaImporterTest extends TestCase $result = $this->importer()->fromUrl('https://example.com/fehlt.jpg', null, []); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString('404', $result->get_error_message()); $this->assertTempFilesRemoved(); } @@ -356,7 +356,7 @@ final class MediaImporterTest extends TestCase $result = $this->importer()->fromUrl('https://example.com/gross.jpg', null, []); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString('Limit 1 MB', $result->get_error_message()); $this->assertTempFilesRemoved(); } @@ -368,7 +368,7 @@ final class MediaImporterTest extends TestCase $result = $this->importer()->fromUrl('https://example.com/gross.jpg', null, []); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString('Limit 1 MB', $result->get_error_message()); $this->assertTempFilesRemoved(); } @@ -396,7 +396,7 @@ final class MediaImporterTest extends TestCase $result = $this->importer()->fromBase64(base64_encode(''), 'seite.html', []); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); $this->assertTempFilesRemoved(); } @@ -416,7 +416,7 @@ final class MediaImporterTest extends TestCase $result = $this->importer()->fromBase64(base64_encode('PNGDATA'), 'logo.png', []); - self::assertSame('lit_write_failed', $result->get_error_code()); + self::assertToolError($result, 'write_failed'); self::assertFileDoesNotExist($moved); self::assertFalse(has_filter('wp_handle_upload')); } @@ -462,6 +462,6 @@ final class MediaImporterTest extends TestCase $result = $this->importer()->fromUrl('https://example.com/logo.png', null, []); - self::assertSame('lit_write_failed', $result->get_error_code()); + self::assertToolError($result, 'write_failed'); } } diff --git a/tests/Unit/Integrations/Media/MediaPreviewAbilityTest.php b/tests/Unit/Integrations/Media/MediaPreviewAbilityTest.php index 572c62b..d0fbe73 100644 --- a/tests/Unit/Integrations/Media/MediaPreviewAbilityTest.php +++ b/tests/Unit/Integrations/Media/MediaPreviewAbilityTest.php @@ -68,7 +68,7 @@ final class MediaPreviewAbilityTest extends TestCase $result = (new MediaPreviewAbility())->execute(['id' => 33]); - self::assertSame('lit_unsupported', $result->get_error_code()); + self::assertToolError($result, 'unsupported'); self::assertStringContainsString( 'lit/media-download (direkt: lit-media-download)', (string) $result->get_error_data()['hint'] @@ -82,7 +82,7 @@ final class MediaPreviewAbilityTest extends TestCase $result = (new MediaPreviewAbility())->execute(['id' => 33]); - self::assertSame('lit_not_found', $result->get_error_code()); + self::assertToolError($result, 'not_found'); } public function testIsADirectToolWithoutOutputSchema(): void diff --git a/tests/Unit/Integrations/Media/MediaSearchAbilityTest.php b/tests/Unit/Integrations/Media/MediaSearchAbilityTest.php index a99cff8..f78ceb5 100644 --- a/tests/Unit/Integrations/Media/MediaSearchAbilityTest.php +++ b/tests/Unit/Integrations/Media/MediaSearchAbilityTest.php @@ -68,7 +68,7 @@ final class MediaSearchAbilityTest extends TestCase $result = (new MediaSearchAbility($this->presenter(), Mockery::mock(MediaUsageFinder::class))) ->execute(['missing_alt' => true, 'mime' => 'application/pdf']); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testMissingAltAllowsAnImageSubtypeMime(): void @@ -108,7 +108,7 @@ final class MediaSearchAbilityTest extends TestCase $result = (new MediaSearchAbility($this->presenter(), Mockery::mock(MediaUsageFinder::class))) ->execute(['cursor' => '???']); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testExcludesAttachmentsTheUserCannotEdit(): void @@ -303,7 +303,7 @@ final class MediaSearchAbilityTest extends TestCase Functions\when('current_user_can')->justReturn(false); $ability = new MediaSearchAbility($this->presenter(), Mockery::mock(MediaUsageFinder::class)); - self::assertSame('lit_forbidden', $ability->permission([])->get_error_code()); + self::assertToolError($ability->permission([]), 'forbidden'); self::assertTrue($ability->isDirect()); } } diff --git a/tests/Unit/Integrations/Media/MediaUpdateAbilityTest.php b/tests/Unit/Integrations/Media/MediaUpdateAbilityTest.php index 0895521..eff33b2 100644 --- a/tests/Unit/Integrations/Media/MediaUpdateAbilityTest.php +++ b/tests/Unit/Integrations/Media/MediaUpdateAbilityTest.php @@ -92,7 +92,7 @@ final class MediaUpdateAbilityTest extends TestCase ]]); self::assertInstanceOf(WP_Error::class, $result); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString('3 von 4', $result->get_error_message()); self::assertStringContainsString('nichts wurde gespeichert', $result->get_error_message()); $failures = $result->get_error_data()['failures']; @@ -109,7 +109,7 @@ final class MediaUpdateAbilityTest extends TestCase { $result = (new MediaUpdateAbility($this->log()))->execute(['items' => [['id' => '99', 'alt' => 'x']]]); - self::assertSame('lit_not_found', $result->get_error_code()); + self::assertToolError($result, 'not_found'); self::assertSame(99, $result->get_error_data()['failures'][0]['id']); } @@ -138,7 +138,7 @@ final class MediaUpdateAbilityTest extends TestCase ['id' => 34, 'alt' => 'neu', 'modified' => '2026-09-24 07:00:00'], ]]); - self::assertSame('lit_rev_mismatch', $result->get_error_code()); + self::assertToolError($result, 'rev_mismatch'); self::assertSame(1, $result->get_error_data()['failures'][0]['index']); self::assertStringContainsString('lit/media-get', $result->get_error_data()['hint']); self::assertSame([], $this->altUpdates); @@ -162,7 +162,7 @@ final class MediaUpdateAbilityTest extends TestCase self::fail('WriteFailed expected'); } catch (WriteFailed $e) { self::assertTrue($e->rolledBack); - self::assertSame('lit_write_failed', $e->toError()->get_error_code()); + self::assertToolError($e->toError(), 'write_failed'); self::assertStringContainsString('neu lesen', $e->toError()->get_error_data()['hint']); self::assertStringContainsString('Datenbankfehler', $e->getMessage()); } @@ -232,7 +232,7 @@ final class MediaUpdateAbilityTest extends TestCase self::fail('WriteFailed expected'); } catch (WriteFailed $e) { $error = $e->toError(); - self::assertSame('lit_partial_write', $error->get_error_code()); + self::assertToolError($error, 'partial_write'); self::assertSame([33], $error->get_error_data()['changed_ids']); self::assertStringContainsString('33', $error->get_error_message()); } diff --git a/tests/Unit/Integrations/Media/MediaUploadAbilitiesTest.php b/tests/Unit/Integrations/Media/MediaUploadAbilitiesTest.php index 938c8fe..30d2d2e 100644 --- a/tests/Unit/Integrations/Media/MediaUploadAbilitiesTest.php +++ b/tests/Unit/Integrations/Media/MediaUploadAbilitiesTest.php @@ -106,7 +106,7 @@ final class MediaUploadAbilitiesTest extends TestCase $result = (new MediaUploadAbility($importer, $this->uploads(), new Limits())) ->execute(['filename' => 'x.png', 'data' => 'AAAA']); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testAPartialUploadIsLoggedAsPartialAndRethrown(): void @@ -136,7 +136,7 @@ final class MediaUploadAbilitiesTest extends TestCase $ability = new MediaUploadFromUrlAbility(Mockery::mock(MediaImporter::class), $this->uploads()); self::assertTrue($ability->permission(['url' => 'https://example.com/a.png'])); - self::assertSame('lit_forbidden', $ability->permission(['url' => 'https://example.com/a.png', 'post_id' => 5])->get_error_code()); + self::assertToolError($ability->permission(['url' => 'https://example.com/a.png', 'post_id' => 5]), 'forbidden'); } public function testPermissionRefusesUsersWithoutUploadRights(): void @@ -144,7 +144,7 @@ final class MediaUploadAbilitiesTest extends TestCase Functions\when('current_user_can')->justReturn(false); $ability = new MediaUploadAbility(Mockery::mock(MediaImporter::class), $this->uploads(), new Limits()); - self::assertSame('lit_forbidden', $ability->permission(['filename' => 'a.png', 'data' => 'AAAA'])->get_error_code()); + self::assertToolError($ability->permission(['filename' => 'a.png', 'data' => 'AAAA']), 'forbidden'); } public function testUploadsForAParentThatDoesNotExistAreRefused(): void @@ -153,7 +153,7 @@ final class MediaUploadAbilitiesTest extends TestCase Functions\when('get_post')->justReturn(null); $ability = new MediaUploadAbility(Mockery::mock(MediaImporter::class), $this->uploads(), new Limits()); - self::assertSame('lit_not_found', $ability->permission(['filename' => 'a.png', 'data' => 'AAAA', 'post_id' => 9])->get_error_code()); + self::assertToolError($ability->permission(['filename' => 'a.png', 'data' => 'AAAA', 'post_id' => 9]), 'not_found'); } public function testDescriptionNamesTheConfiguredLimit(): void diff --git a/tests/Unit/Integrations/WordPress/Content/ContentCreateAbilityTest.php b/tests/Unit/Integrations/WordPress/Content/ContentCreateAbilityTest.php index 512a8d5..80bb101 100644 --- a/tests/Unit/Integrations/WordPress/Content/ContentCreateAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Content/ContentCreateAbilityTest.php @@ -76,7 +76,7 @@ final class ContentCreateAbilityTest extends TestCase $result = (new ContentCreateAbility($this->schema(), $writer, FakeChangeLog::forbidden())) ->execute(['post_type' => 'lit_person', 'title' => 'Anna']); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testCreatesADraftWritesExtrasLogsAndReturnsAToolResult(): void @@ -131,7 +131,7 @@ final class ContentCreateAbilityTest extends TestCase self::assertTrue($failure->rolledBack); self::assertStringContainsString('Pods could not save the fields.', $failure->getMessage()); - self::assertSame('lit_write_failed', $failure->toError()->get_error_code()); + self::assertToolError($failure->toError(), 'write_failed'); } public function testMetaFieldsTheUserMayNotAddAreRefusedAndTheDraftIsRemoved(): void @@ -149,8 +149,8 @@ final class ContentCreateAbilityTest extends TestCase $result = (new ContentCreateAbility($this->schema(), $writer, $log))->execute(self::INPUT); - self::assertSame('lit_validation_failed', $result->get_error_code()); - self::assertArrayHasKey('fields.city', $result->get_error_data()['fields']); + self::assertToolError($result, 'validation_failed'); + self::assertArrayHasKey('fields.city', self::errorFields($result)); } public function testARefusedDraftThatCannotBeDeletedIsAPartialWrite(): void @@ -219,7 +219,7 @@ final class ContentCreateAbilityTest extends TestCase self::assertFalse($failure->rolledBack); self::assertNull($failure->postId); - self::assertSame('lit_partial_write', $failure->toError()->get_error_code()); + self::assertToolError($failure->toError(), 'partial_write'); $log->assertPartials(['ability' => 'lit/content-create', 'object_type' => 'lit_person', 'object_id' => '']); } @@ -261,6 +261,6 @@ final class ContentCreateAbilityTest extends TestCase self::assertTrue($ability->permission(['post_type' => 'page'])); Functions\when('current_user_can')->justReturn(false); - self::assertSame('lit_forbidden', $ability->permission(['post_type' => 'page'])->get_error_code()); + self::assertToolError($ability->permission(['post_type' => 'page']), 'forbidden'); } } diff --git a/tests/Unit/Integrations/WordPress/Content/ContentCreateDiviTest.php b/tests/Unit/Integrations/WordPress/Content/ContentCreateDiviTest.php index de1e24d..510e947 100644 --- a/tests/Unit/Integrations/WordPress/Content/ContentCreateDiviTest.php +++ b/tests/Unit/Integrations/WordPress/Content/ContentCreateDiviTest.php @@ -128,14 +128,14 @@ final class ContentCreateDiviTest extends TestCase Functions\expect('wp_insert_post')->never(); $inactive = $this->ability($this->composer(false))->execute(self::INPUT); - self::assertSame('lit_unsupported', $inactive->get_error_code()); + self::assertToolError($inactive, 'unsupported'); $none = $this->ability(null)->execute(self::INPUT); - self::assertSame('lit_unsupported', $none->get_error_code()); + self::assertToolError($none, 'unsupported'); $both = $this->ability($this->composer())->execute(self::INPUT + ['content' => '

x

']); - self::assertSame('lit_validation_failed', $both->get_error_code()); - self::assertArrayHasKey('content', $both->get_error_data()['fields']); + self::assertToolError($both, 'validation_failed'); + self::assertArrayHasKey('content', self::errorFields($both)); } public function testEveryValidationErrorComesBackAndNothingIsCreated(): void @@ -149,10 +149,10 @@ final class ContentCreateDiviTest extends TestCase $error = $this->ability($composer, $writer)->execute(self::INPUT); - self::assertSame('lit_invalid_attr_path', $error->get_error_code()); + self::assertToolError($error, 'invalid_attr_path'); self::assertSame( ['fields.role' => 'Pflichtfeld fehlt.', 'divi[0].attrs.x' => 'unbekannt'], - $error->get_error_data()['fields'] + self::errorFields($error) ); } @@ -181,8 +181,8 @@ final class ContentCreateDiviTest extends TestCase $error = $this->ability($composer)->execute(self::INPUT); self::assertInstanceOf(WP_Error::class, $error); - self::assertSame('lit_validation_failed', $error->get_error_code()); - self::assertArrayHasKey('divi[0].modules[0].text', $error->get_error_data()['fields']); + self::assertToolError($error, 'validation_failed'); + self::assertArrayHasKey('divi[0].modules[0].text', self::errorFields($error)); } public function testARefusedLayoutWhoseDraftCannotBeDeletedIsAPartialWrite(): void @@ -254,8 +254,8 @@ final class ContentCreateDiviTest extends TestCase 'attrs' => ['module.meta.adminLabel' => ['desktop' => 'Lang']], 'modules' => [['type' => 'button', 'text' => 'Los', 'attrs' => ['button.innerContent' => ['desktop' => ['text' => 'x']]]]], ]]]); - self::assertSame('lit_validation_failed', $overlap->get_error_code()); - $fields = $overlap->get_error_data()['fields']; + self::assertToolError($overlap, 'validation_failed'); + $fields = self::errorFields($overlap); self::assertArrayHasKey('divi[0].attrs.module.meta.adminLabel', $fields, 'S41: label and attrs label'); self::assertArrayHasKey('divi[0].modules[0].modules[0][0].attrs.button.innerContent', $fields, 'S40'); self::assertSame([], $saved); diff --git a/tests/Unit/Integrations/WordPress/Content/ContentGetAbilityTest.php b/tests/Unit/Integrations/WordPress/Content/ContentGetAbilityTest.php index 0d1fea8..e21d765 100644 --- a/tests/Unit/Integrations/WordPress/Content/ContentGetAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Content/ContentGetAbilityTest.php @@ -47,7 +47,7 @@ final class ContentGetAbilityTest extends TestCase $schema = Mockery::mock(ContentSchema::class); $ability = new ContentGetAbility($schema, Mockery::mock(PostPresenter::class)); - self::assertSame('lit_not_found', $ability->permission(['post_id' => 99])->get_error_code()); + self::assertToolError($ability->permission(['post_id' => 99]), 'not_found'); } public function testOutputSchemaAllowsNullContentForDivi(): void diff --git a/tests/Unit/Integrations/WordPress/Content/ContentQueryAbilityTest.php b/tests/Unit/Integrations/WordPress/Content/ContentQueryAbilityTest.php index 50bbf4e..f38cd57 100644 --- a/tests/Unit/Integrations/WordPress/Content/ContentQueryAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Content/ContentQueryAbilityTest.php @@ -96,7 +96,7 @@ final class ContentQueryAbilityTest extends TestCase { $result = $this->ability()->execute(['post_type' => 'page', 'cursor' => '???']); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testQueryIsRestrictedToOwnPostsWithoutEditOthersPosts(): void @@ -193,7 +193,7 @@ final class ContentQueryAbilityTest extends TestCase $result = $this->ability($schema)->execute(['post_type' => 'page', 'field' => ['key' => 'ghost']]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString('role', $result->get_error_message()); } @@ -209,9 +209,9 @@ final class ContentQueryAbilityTest extends TestCase $password = $this->ability($schema)->execute(['post_type' => 'page', 'field' => ['key' => 'secret']]); $protected = $this->ability($schema)->execute(['post_type' => 'page', 'field' => ['key' => '_internal']]); - self::assertSame('lit_validation_failed', $password->get_error_code()); + self::assertToolError($password, 'validation_failed'); self::assertSame('Verfügbare Felder: role.', $password->get_error_data()['hint']); - self::assertSame('lit_validation_failed', $protected->get_error_code()); + self::assertToolError($protected, 'validation_failed'); self::assertSame('Verfügbare Felder: role.', $protected->get_error_data()['hint']); } @@ -225,7 +225,7 @@ final class ContentQueryAbilityTest extends TestCase 'taxonomy' => ['taxonomy' => 'ghost', 'terms' => [1]], ]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString('category', $result->get_error_message()); } @@ -235,7 +235,7 @@ final class ContentQueryAbilityTest extends TestCase $schema->allows('isManaged')->andReturn(false); $ability = new ContentQueryAbility($schema, Mockery::mock(PostPresenter::class)); - self::assertSame('lit_not_found', $ability->permission(['post_type' => 'secret'])->get_error_code()); + self::assertToolError($ability->permission(['post_type' => 'secret']), 'not_found'); } public function testPermissionIsForbiddenWithoutEditRights(): void @@ -245,7 +245,7 @@ final class ContentQueryAbilityTest extends TestCase $schema = SchemaFixture::managed(); $ability = new ContentQueryAbility($schema, Mockery::mock(PostPresenter::class)); - self::assertSame('lit_forbidden', $ability->permission(['post_type' => 'page'])->get_error_code()); + self::assertToolError($ability->permission(['post_type' => 'page']), 'forbidden'); } public function testInputSchemaLimitsSearchLengthAndTaxonomyTermsCount(): void diff --git a/tests/Unit/Integrations/WordPress/Content/ContentTypesAbilityTest.php b/tests/Unit/Integrations/WordPress/Content/ContentTypesAbilityTest.php index 38e4067..7b34756 100644 --- a/tests/Unit/Integrations/WordPress/Content/ContentTypesAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Content/ContentTypesAbilityTest.php @@ -65,7 +65,7 @@ final class ContentTypesAbilityTest extends TestCase $result = (new ContentTypesAbility($schema))->execute(['post_type' => 'nope']); self::assertInstanceOf(WP_Error::class, $result); - self::assertSame('lit_not_found', $result->get_error_code()); + self::assertToolError($result, 'not_found'); self::assertStringContainsString('page, post', $result->get_error_message()); } @@ -95,7 +95,7 @@ final class ContentTypesAbilityTest extends TestCase $result = (new ContentTypesAbility($schema))->execute(['post_type' => 'page']); self::assertInstanceOf(WP_Error::class, $result); - self::assertSame('lit_forbidden', $result->get_error_code()); + self::assertToolError($result, 'forbidden'); } public function testPermissionRequiresEditPosts(): void @@ -103,7 +103,7 @@ final class ContentTypesAbilityTest extends TestCase Functions\when('current_user_can')->justReturn(false); $ability = new ContentTypesAbility(Mockery::mock(ContentSchema::class)); - self::assertSame('lit_forbidden', $ability->permission([])->get_error_code()); + self::assertToolError($ability->permission([]), 'forbidden'); } public function testPermissionForbidsANonEditableSpecificType(): void @@ -115,7 +115,7 @@ final class ContentTypesAbilityTest extends TestCase $result = (new ContentTypesAbility($schema))->permission(['post_type' => 'lit_person']); self::assertInstanceOf(WP_Error::class, $result); - self::assertSame('lit_forbidden', $result->get_error_code()); + self::assertToolError($result, 'forbidden'); } public function testPermissionAllowsAnEditableSpecificType(): void diff --git a/tests/Unit/Integrations/WordPress/Content/ContentUpdateAbilityTest.php b/tests/Unit/Integrations/WordPress/Content/ContentUpdateAbilityTest.php index 4ab5b12..8d34db9 100644 --- a/tests/Unit/Integrations/WordPress/Content/ContentUpdateAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Content/ContentUpdateAbilityTest.php @@ -71,7 +71,7 @@ final class ContentUpdateAbilityTest extends TestCase $result = $this->ability(Mockery::mock(PostWriter::class)) ->execute(['post_id' => 5, 'rev' => Rev::ofPost($this->post), 'title' => 'Neu']); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testAMissedScheduleIsRefusedBecauseSavingWouldPublish(): void @@ -84,8 +84,8 @@ final class ContentUpdateAbilityTest extends TestCase $result = $this->ability(Mockery::mock(PostWriter::class)) ->execute(['post_id' => 5, 'rev' => Rev::ofPost($this->post), 'title' => 'Neu']); - self::assertSame('lit_validation_failed', $result->get_error_code()); - self::assertArrayHasKey('post_id', $result->get_error_data()['fields']); + self::assertToolError($result, 'validation_failed'); + self::assertArrayHasKey('post_id', self::errorFields($result)); self::assertStringContainsString('lit/post-schedule', $result->get_error_data()['hint']); } @@ -96,7 +96,7 @@ final class ContentUpdateAbilityTest extends TestCase $result = $this->ability(Mockery::mock(PostWriter::class)) ->execute(['post_id' => 5, 'rev' => 'stale', 'title' => 'Neu']); - self::assertSame('lit_rev_mismatch', $result->get_error_code()); + self::assertToolError($result, 'rev_mismatch'); self::assertStringContainsString('lit-content-get', $result->get_error_data()['hint']); } @@ -105,7 +105,7 @@ final class ContentUpdateAbilityTest extends TestCase $result = $this->ability(Mockery::mock(PostWriter::class)) ->execute(['post_id' => 5, 'rev' => Rev::of('

Alt

'), 'title' => 'Neu']); - self::assertSame('lit_rev_mismatch', $result->get_error_code()); + self::assertToolError($result, 'rev_mismatch'); } public function testRawContentOnDiviPagesIsUnsupported(): void @@ -117,7 +117,7 @@ final class ContentUpdateAbilityTest extends TestCase $result = $this->ability($writer) ->execute(['post_id' => 5, 'rev' => Rev::ofPost($this->post), 'content' => '

Neu

']); - self::assertSame('lit_unsupported', $result->get_error_code()); + self::assertToolError($result, 'unsupported'); self::assertStringContainsString(PostPresenter::DIVI_INACTIVE_NOTE, $result->get_error_data()['hint']); } @@ -129,7 +129,7 @@ final class ContentUpdateAbilityTest extends TestCase $result = $this->ability($writer)->execute(['post_id' => 5, 'rev' => Rev::ofPost($this->post)]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testUpdateKeepsTheStatusAndCapturesARestorePointFirst(): void @@ -236,7 +236,7 @@ final class ContentUpdateAbilityTest extends TestCase $failure = $this->executeExpectingFailure($writer, $input); self::assertTrue($failure->rolledBack); - self::assertSame('lit_write_failed', $failure->toError()->get_error_code()); + self::assertToolError($failure->toError(), 'write_failed'); $message = $failure->toError()->get_error_message(); self::assertStringNotContainsString('Nichts wurde gespeichert', $message); self::assertStringContainsString('Die Änderung wurde nicht gespeichert (Revision 811 bleibt erhalten).', $message); @@ -326,7 +326,7 @@ final class ContentUpdateAbilityTest extends TestCase self::assertFalse($failure->rolledBack); self::assertStringContainsString('restore kaputt', $failure->getMessage()); $error = $failure->toError(); - self::assertSame('lit_partial_write', $error->get_error_code()); + self::assertToolError($error, 'partial_write'); self::assertSame(5, $error->get_error_data()['post_id']); self::assertSame(811, $error->get_error_data()['revision_id']); $log->assertPartials([ diff --git a/tests/Unit/Integrations/WordPress/Content/PostWriterTest.php b/tests/Unit/Integrations/WordPress/Content/PostWriterTest.php index 8bd7146..ac7d603 100644 --- a/tests/Unit/Integrations/WordPress/Content/PostWriterTest.php +++ b/tests/Unit/Integrations/WordPress/Content/PostWriterTest.php @@ -48,8 +48,8 @@ final class PostWriterTest extends TestCase 'template' => 'fehlt.php', ], true); - $fields = $result->get_error_data()['fields']; - self::assertSame('lit_validation_failed', $result->get_error_code()); + $fields = self::errorFields($result); + self::assertToolError($result, 'validation_failed'); self::assertSame('Pflichtfeld fehlt.', $fields['fields.role']); self::assertSame('Taxonomie gehört nicht zu diesem Inhaltstyp.', $fields['terms.genre']); self::assertSame('Inhaltstyp unterstützt kein Beitragsbild.', $fields['featured_image']); @@ -72,7 +72,7 @@ final class PostWriterTest extends TestCase $result = $writer->prepare('page', $input, false); self::assertFalse(is_array($result), $path . ' should be rejected'); - return (string) $result->get_error_data()['fields'][$path]; + return (string) self::errorFields($result)[$path]; } public function testParentMustBeAReadableNonDescendantEntryOfAHierarchicalType(): void @@ -152,7 +152,7 @@ final class PostWriterTest extends TestCase false ); - self::assertSame(['fields.secret' => 'Keine Berechtigung, dieses Feld zu ändern.'], $result->get_error_data()['fields']); + self::assertSame(['fields.secret' => 'Keine Berechtigung, dieses Feld zu ändern.'], self::errorFields($result)); self::assertSame([['edit_post_meta', 5, 'city'], ['edit_post_meta', 5, 'secret']], $checked); } diff --git a/tests/Unit/Integrations/WordPress/Menus/MenuAssignLocationAbilityTest.php b/tests/Unit/Integrations/WordPress/Menus/MenuAssignLocationAbilityTest.php index a1b0fe6..0f01a60 100644 --- a/tests/Unit/Integrations/WordPress/Menus/MenuAssignLocationAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Menus/MenuAssignLocationAbilityTest.php @@ -50,10 +50,10 @@ final class MenuAssignLocationAbilityTest extends TestCase $result = (new MenuAssignLocationAbility(FakeChangeLog::forbidden())) ->execute(['location' => 'primary-menu', 'menu_id' => 0]); - self::assertSame('lit_confirm_required', $result->get_error_code()); + self::assertToolError($result, 'confirm_required'); self::assertStringContainsString( '"Hauptmenü" (ID 3)', - json_decode($result->get_error_message(), true)['message'] + self::clientError($result)['message'] ); } @@ -104,7 +104,7 @@ final class MenuAssignLocationAbilityTest extends TestCase $result = (new MenuAssignLocationAbility(FakeChangeLog::forbidden())) ->execute(['location' => 'primary-menu', 'menu_id' => 99]); - self::assertSame('lit_not_found', $result->get_error_code()); + self::assertToolError($result, 'not_found'); } public function testPermissionNeedsThemeOptionRights(): void @@ -114,7 +114,7 @@ final class MenuAssignLocationAbilityTest extends TestCase $ability = new MenuAssignLocationAbility(FakeChangeLog::forbidden()); $input = ['location' => 'primary-menu', 'menu_id' => 8]; - self::assertSame('lit_forbidden', $ability->permission($input)->get_error_code()); + self::assertToolError($ability->permission($input), 'forbidden'); } public function testIsDestructiveBecauseItReplacesTheMenuOfTheLocation(): void diff --git a/tests/Unit/Integrations/WordPress/Menus/MenuCreateAbilityTest.php b/tests/Unit/Integrations/WordPress/Menus/MenuCreateAbilityTest.php index b75ab3c..65bf163 100644 --- a/tests/Unit/Integrations/WordPress/Menus/MenuCreateAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Menus/MenuCreateAbilityTest.php @@ -20,7 +20,7 @@ final class MenuCreateAbilityTest extends TestCase $ability = new MenuCreateAbility(FakeChangeLog::forbidden()); $result = $ability->execute(['name' => 'Neu', 'location' => 'nope']); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertStringContainsString('primary-menu', $result->get_error_message()); } @@ -32,7 +32,7 @@ final class MenuCreateAbilityTest extends TestCase $result = (new MenuCreateAbility(FakeChangeLog::forbidden()))->execute(['name' => 'Hauptmenü']); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testCreatesAndAssignsTheLocation(): void @@ -65,6 +65,6 @@ final class MenuCreateAbilityTest extends TestCase $ability = new MenuCreateAbility(FakeChangeLog::forbidden()); - self::assertSame('lit_forbidden', $ability->permission(['name' => 'Neu'])->get_error_code()); + self::assertToolError($ability->permission(['name' => 'Neu']), 'forbidden'); } } diff --git a/tests/Unit/Integrations/WordPress/Menus/MenuOperationsTest.php b/tests/Unit/Integrations/WordPress/Menus/MenuOperationsTest.php index 68df89a..6cc6362 100644 --- a/tests/Unit/Integrations/WordPress/Menus/MenuOperationsTest.php +++ b/tests/Unit/Integrations/WordPress/Menus/MenuOperationsTest.php @@ -48,9 +48,9 @@ final class MenuOperationsTest extends TestCase $cycle = $operations->apply($this->tree(), [['op' => 'move', 'id' => 1, 'parent_id' => 2]]); $badOp = $operations->apply($this->tree(), [['op' => 'rename', 'id' => 1]]); - self::assertArrayHasKey('operations.0', $unknown->get_error_data()['fields']); - self::assertStringContainsString('unter sich selbst', $cycle->get_error_data()['fields']['operations.0']); - self::assertStringContainsString('add, move oder remove', $badOp->get_error_data()['fields']['operations.0']); + self::assertArrayHasKey('operations.0', self::errorFields($unknown)); + self::assertStringContainsString('unter sich selbst', self::errorFields($cycle)['operations.0']); + self::assertStringContainsString('add, move oder remove', self::errorFields($badOp)['operations.0']); } public function testExistingNodesKeepOnlyTheirIdSoTheWriterKeepsTheirData(): void diff --git a/tests/Unit/Integrations/WordPress/Menus/MenuReadAbilitiesTest.php b/tests/Unit/Integrations/WordPress/Menus/MenuReadAbilitiesTest.php index d9d3a6f..1dfe760 100644 --- a/tests/Unit/Integrations/WordPress/Menus/MenuReadAbilitiesTest.php +++ b/tests/Unit/Integrations/WordPress/Menus/MenuReadAbilitiesTest.php @@ -51,14 +51,14 @@ final class MenuReadAbilitiesTest extends TestCase self::assertSame('Start', $result['items'][0]['title']); self::assertSame(Rev::ofMenu([self::item(10, 0, 'Start')]), $result['menu_rev']); self::assertContains('menu_rev', $ability->outputSchema()['required']); - self::assertSame('lit_not_found', $ability->execute(['menu_id' => 9])->get_error_code()); + self::assertToolError($ability->execute(['menu_id' => 9]), 'not_found'); } public function testReadToolsNeedThemeOptionRights(): void { Functions\when('current_user_can')->justReturn(false); - self::assertSame('lit_forbidden', (new MenuListAbility())->permission([])->get_error_code()); - self::assertSame('lit_forbidden', (new MenuGetAbility())->permission(['menu_id' => 3])->get_error_code()); + self::assertToolError((new MenuListAbility())->permission([]), 'forbidden'); + self::assertToolError((new MenuGetAbility())->permission(['menu_id' => 3]), 'forbidden'); } } diff --git a/tests/Unit/Integrations/WordPress/Menus/MenuSetItemsAbilityTest.php b/tests/Unit/Integrations/WordPress/Menus/MenuSetItemsAbilityTest.php index 51a4798..7a476f8 100644 --- a/tests/Unit/Integrations/WordPress/Menus/MenuSetItemsAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Menus/MenuSetItemsAbilityTest.php @@ -42,10 +42,10 @@ final class MenuSetItemsAbilityTest extends TestCase $stale = $ability->execute(['menu_id' => 3, 'menu_rev' => 'abcdefabcdef', 'items' => [['id' => 10]]]); $missing = $ability->execute(['menu_id' => 3, 'items' => [['id' => 10]]]); - self::assertSame('lit_rev_mismatch', $stale->get_error_code()); + self::assertToolError($stale, 'rev_mismatch'); self::assertStringContainsString('lit/menu-get', $stale->get_error_data()['hint']); self::assertStringContainsString('Menü', $stale->get_error_message()); - self::assertSame('lit_rev_mismatch', $missing->get_error_code()); + self::assertToolError($missing, 'rev_mismatch'); self::assertContains('menu_rev', $ability->inputSchema()['required']); self::assertStringContainsString('menu_rev', $ability->description()); } @@ -68,7 +68,7 @@ final class MenuSetItemsAbilityTest extends TestCase { $ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), FakeChangeLog::forbidden()); - self::assertSame('lit_validation_failed', $ability->execute(['menu_id' => 3, 'menu_rev' => self::rev()])->get_error_code()); + self::assertToolError($ability->execute(['menu_id' => 3, 'menu_rev' => self::rev()]), 'validation_failed'); self::assertSame( 'lit_validation_failed', $ability->execute(['menu_id' => 3, 'menu_rev' => self::rev(), 'items' => [], 'operations' => [['op' => 'remove', 'id' => 10]]]) @@ -81,7 +81,7 @@ final class MenuSetItemsAbilityTest extends TestCase Functions\when('wp_get_nav_menu_object')->justReturn(false); $ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), FakeChangeLog::forbidden()); - self::assertSame('lit_not_found', $ability->execute(['menu_id' => 9, 'items' => []])->get_error_code()); + self::assertToolError($ability->execute(['menu_id' => 9, 'items' => []]), 'not_found'); } public function testRemovalsNeedConfirmationAndNothingIsWritten(): void @@ -92,7 +92,7 @@ final class MenuSetItemsAbilityTest extends TestCase $result = $ability->execute(['menu_id' => 3, 'menu_rev' => self::rev(), 'items' => []]); - self::assertSame('lit_confirm_required', $result->get_error_code()); + self::assertToolError($result, 'confirm_required'); self::assertSame([['id' => 10, 'title' => 'Home']], $result->get_error_data()['removals']); } @@ -109,8 +109,8 @@ final class MenuSetItemsAbilityTest extends TestCase 'items' => [['id' => 10], ['type' => 'custom', 'url' => 'javascript:alert(1)', 'title' => 'X']], ]); - self::assertSame('lit_validation_failed', $result->get_error_code()); - self::assertArrayHasKey('items.1', $result->get_error_data()['fields']); + self::assertToolError($result, 'validation_failed'); + self::assertArrayHasKey('items.1', self::errorFields($result)); } public function testInvalidOperationsWriteNothing(): void @@ -121,7 +121,7 @@ final class MenuSetItemsAbilityTest extends TestCase $result = $ability->execute(['menu_id' => 3, 'menu_rev' => self::rev(), 'operations' => [['op' => 'move', 'id' => 99]]]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testAppliesAndReturnsTheTreeBeforeAndAfter(): void @@ -190,7 +190,7 @@ final class MenuSetItemsAbilityTest extends TestCase ['menu_id' => 3, 'menu_rev' => self::rev(), 'items' => [['type' => 'post', 'object_id' => 7]], 'allow_unpublished' => true] ); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); self::assertArrayHasKey('allow_unpublished', $ability->inputSchema()['properties']); } @@ -209,8 +209,8 @@ final class MenuSetItemsAbilityTest extends TestCase $refused = $ability->execute($input); $allowed = $ability->execute($input + ['allow_unpublished' => true]); - self::assertSame('lit_validation_failed', $refused->get_error_code()); - self::assertStringContainsString('allow_unpublished', $refused->get_error_data()['fields']['items.1']); + self::assertToolError($refused, 'validation_failed'); + self::assertStringContainsString('allow_unpublished', self::errorFields($refused)['items.1']); self::assertStringContainsString('1 neu', $allowed['summary']); self::assertStringContainsString('sofort im Menü sichtbar', $allowed['warnings'][0]); } @@ -230,8 +230,8 @@ final class MenuSetItemsAbilityTest extends TestCase 'operations' => [['op' => 'add', 'item' => ['type' => 'post', 'object_id' => 7]]], ]); - self::assertSame('lit_validation_failed', $result->get_error_code()); - self::assertStringContainsString('Private Inhalte', $result->get_error_data()['fields']['items.1']); + self::assertToolError($result, 'validation_failed'); + self::assertStringContainsString('Private Inhalte', self::errorFields($result)['items.1']); } public function testAWriteFailureIsPassedOnAsWriteFailed(): void @@ -290,7 +290,7 @@ final class MenuSetItemsAbilityTest extends TestCase Functions\when('current_user_can')->justReturn(false); $ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), FakeChangeLog::forbidden()); - self::assertSame('lit_forbidden', $ability->permission(['menu_id' => 3, 'menu_rev' => self::rev()])->get_error_code()); + self::assertToolError($ability->permission(['menu_id' => 3, 'menu_rev' => self::rev()]), 'forbidden'); } public function testIsDestructiveAndDescribesWhenConfirmIsNeeded(): void diff --git a/tests/Unit/Integrations/WordPress/Menus/MenuWriterTest.php b/tests/Unit/Integrations/WordPress/Menus/MenuWriterTest.php index b36fcb8..4edcfe2 100644 --- a/tests/Unit/Integrations/WordPress/Menus/MenuWriterTest.php +++ b/tests/Unit/Integrations/WordPress/Menus/MenuWriterTest.php @@ -334,7 +334,7 @@ final class MenuWriterTest extends TestCase } catch (WriteFailed $e) { self::assertTrue($e->rolledBack); self::assertStringContainsString('kaputt', $e->getMessage()); - self::assertSame('lit_write_failed', $e->toError()->get_error_code()); + self::assertToolError($e->toError(), 'write_failed'); } $restore = $calls[3]; @@ -357,7 +357,7 @@ final class MenuWriterTest extends TestCase } catch (WriteFailed $e) { self::assertFalse($e->rolledBack); $error = $e->toError(); - self::assertSame('lit_partial_write', $error->get_error_code()); + self::assertToolError($error, 'partial_write'); self::assertSame(3, $error->get_error_data()['menu_id']); self::assertSame('Home', $error->get_error_data()['previous_items'][0]['title']); self::assertStringContainsString('lit/menu-get', $error->get_error_data()['hint']); diff --git a/tests/Unit/Integrations/WordPress/PostGuardTest.php b/tests/Unit/Integrations/WordPress/PostGuardTest.php index b88bbe1..7e8fc69 100644 --- a/tests/Unit/Integrations/WordPress/PostGuardTest.php +++ b/tests/Unit/Integrations/WordPress/PostGuardTest.php @@ -23,16 +23,16 @@ final class PostGuardTest extends TestCase public function testRejectsInvalidIds(): void { - self::assertSame('lit_validation_failed', PostGuard::editable('abc', $this->schema())->get_error_code()); - self::assertSame('lit_validation_failed', PostGuard::editable(-3, $this->schema())->get_error_code()); + self::assertToolError(PostGuard::editable('abc', $this->schema()), 'validation_failed'); + self::assertToolError(PostGuard::editable(-3, $this->schema()), 'validation_failed'); } public function testMissingOrUnmanagedPostsAreNotFound(): void { Functions\when('get_post')->alias(static fn (int $id) => $id === 8 ? new WP_Post(['ID' => 8, 'post_type' => 'et_pb_layout']) : null); - self::assertSame('lit_not_found', PostGuard::editable(5, $this->schema())->get_error_code()); - self::assertSame('lit_not_found', PostGuard::editable(8, $this->schema())->get_error_code()); + self::assertToolError(PostGuard::editable(5, $this->schema()), 'not_found'); + self::assertToolError(PostGuard::editable(8, $this->schema()), 'not_found'); } public function testRequiresEditRightsAndReturnsThePost(): void @@ -44,7 +44,7 @@ final class PostGuardTest extends TestCase self::assertSame($post, PostGuard::editable('5', $this->schema())); Functions\when('current_user_can')->justReturn(false); - self::assertSame('lit_forbidden', PostGuard::editable(5, $this->schema())->get_error_code()); + self::assertToolError(PostGuard::editable(5, $this->schema()), 'forbidden'); } public function testTrashedPostsAreRefusedUnlessAllowed(): void @@ -54,8 +54,8 @@ final class PostGuardTest extends TestCase Functions\when('current_user_can')->justReturn(true); $error = PostGuard::editable(5, $this->schema(), 'copy_id'); - self::assertSame('lit_validation_failed', $error->get_error_code()); - self::assertArrayHasKey('copy_id', $error->get_error_data()['fields']); + self::assertToolError($error, 'validation_failed'); + self::assertArrayHasKey('copy_id', self::errorFields($error)); self::assertSame($post, PostGuard::editable(5, $this->schema(), 'post_id', true)); } @@ -107,8 +107,8 @@ final class PostGuardTest extends TestCase $error = PostGuard::statusStable($post, 'original_id'); - self::assertSame('lit_validation_failed', $error->get_error_code()); - self::assertArrayHasKey('original_id', $error->get_error_data()['fields']); + self::assertToolError($error, 'validation_failed'); + self::assertArrayHasKey('original_id', self::errorFields($error)); self::assertStringContainsString('lit-post-publish', $error->get_error_data()['hint']); self::assertStringContainsString('lit/post-schedule', $error->get_error_data()['hint']); self::assertNull(PostGuard::statusStable(new WP_Post(['post_status' => 'publish']))); @@ -141,12 +141,12 @@ final class PostGuardTest extends TestCase Functions\when('get_post_type_object')->justReturn($object); Functions\when('current_user_can')->alias(static fn (string $cap): bool => $cap === 'edit_pages'); - self::assertSame('lit_not_found', PostGuard::postType('et_pb_layout', $this->schema(), 'create_posts')->get_error_code()); - self::assertSame('lit_not_found', PostGuard::postType(null, $this->schema(), 'create_posts')->get_error_code()); + self::assertToolError(PostGuard::postType('et_pb_layout', $this->schema(), 'create_posts'), 'not_found'); + self::assertToolError(PostGuard::postType(null, $this->schema(), 'create_posts'), 'not_found'); self::assertSame($object, PostGuard::postType('page', $this->schema(), 'create_posts')); Functions\when('current_user_can')->justReturn(false); - self::assertSame('lit_forbidden', PostGuard::postType('page', $this->schema(), 'create_posts')->get_error_code()); + self::assertToolError(PostGuard::postType('page', $this->schema(), 'create_posts'), 'forbidden'); } public function testAssertNoMissedScheduleRefusesAMissedScheduleWithTheCallersMessage(): void diff --git a/tests/Unit/Integrations/WordPress/Revisions/RevisionRestoreAbilityTest.php b/tests/Unit/Integrations/WordPress/Revisions/RevisionRestoreAbilityTest.php index 9a6e110..1ec88e4 100644 --- a/tests/Unit/Integrations/WordPress/Revisions/RevisionRestoreAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Revisions/RevisionRestoreAbilityTest.php @@ -50,7 +50,7 @@ final class RevisionRestoreAbilityTest extends TestCase public function testNonRevisionIdIsNotFound(): void { - self::assertSame('lit_not_found', $this->ability(FakeChangeLog::forbidden())->permission(['revision_id' => 5])->get_error_code()); + self::assertToolError($this->ability(FakeChangeLog::forbidden())->permission(['revision_id' => 5]), 'not_found'); } public function testRequiresConfirmation(): void @@ -59,7 +59,7 @@ final class RevisionRestoreAbilityTest extends TestCase $result = $this->ability(FakeChangeLog::forbidden())->execute(['revision_id' => 810]); - self::assertSame('lit_confirm_required', $result->get_error_code()); + self::assertToolError($result, 'confirm_required'); } public function testOrphanRevisionYieldsValidationErrorOnRevisionIdField(): void @@ -71,8 +71,8 @@ final class RevisionRestoreAbilityTest extends TestCase $error = $this->ability(FakeChangeLog::forbidden()) ->permission(['revision_id' => 810, 'rev' => 'irrelevant', 'confirm' => true]); - self::assertSame('lit_validation_failed', $error->get_error_code()); - self::assertArrayHasKey('revision_id', $error->get_error_data()['fields']); + self::assertToolError($error, 'validation_failed'); + self::assertArrayHasKey('revision_id', self::errorFields($error)); } public function testATrashedEntryIsRefused(): void @@ -86,8 +86,8 @@ final class RevisionRestoreAbilityTest extends TestCase $error = $this->ability(FakeChangeLog::forbidden())->execute(['revision_id' => 810, 'rev' => 'x', 'confirm' => true]); - self::assertSame('lit_validation_failed', $error->get_error_code()); - self::assertArrayHasKey('revision_id', $error->get_error_data()['fields']); + self::assertToolError($error, 'validation_failed'); + self::assertArrayHasKey('revision_id', self::errorFields($error)); } public function testAMissedScheduleIsRefusedBecauseRestoringWouldPublish(): void @@ -110,7 +110,7 @@ final class RevisionRestoreAbilityTest extends TestCase 'confirm' => true, ]); - self::assertSame('lit_validation_failed', $error->get_error_code()); + self::assertToolError($error, 'validation_failed'); self::assertStringContainsString('lit-post-publish', $error->get_error_data()['hint']); } @@ -121,7 +121,7 @@ final class RevisionRestoreAbilityTest extends TestCase $result = $this->ability(FakeChangeLog::forbidden()) ->execute(['revision_id' => 810, 'confirm' => true, 'rev' => 'stale']); - self::assertSame('lit_rev_mismatch', $result->get_error_code()); + self::assertToolError($result, 'rev_mismatch'); } public function testSavesTheCurrentStateThenRestores(): void @@ -173,7 +173,7 @@ final class RevisionRestoreAbilityTest extends TestCase 'rev' => $this->currentRev(), ]); - self::assertSame('lit_write_failed', $result->get_error_code()); + self::assertToolError($result, 'write_failed'); self::assertStringNotContainsString('Nichts wurde gespeichert', $result->get_error_message()); self::assertStringContainsString( 'Die Änderung wurde nicht gespeichert (Revision 813 bleibt erhalten).', diff --git a/tests/Unit/Integrations/WordPress/Revisions/RevisionsListAbilityTest.php b/tests/Unit/Integrations/WordPress/Revisions/RevisionsListAbilityTest.php index 8474782..69aac9e 100644 --- a/tests/Unit/Integrations/WordPress/Revisions/RevisionsListAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Revisions/RevisionsListAbilityTest.php @@ -79,6 +79,6 @@ final class RevisionsListAbilityTest extends TestCase { $result = $this->ability()->execute(['post_id' => 5, 'cursor' => 'not-a-cursor']); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } } diff --git a/tests/Unit/Integrations/WordPress/Settings/WpSettingsAbilitiesTest.php b/tests/Unit/Integrations/WordPress/Settings/WpSettingsAbilitiesTest.php index 01382d0..9ac1386 100644 --- a/tests/Unit/Integrations/WordPress/Settings/WpSettingsAbilitiesTest.php +++ b/tests/Unit/Integrations/WordPress/Settings/WpSettingsAbilitiesTest.php @@ -120,8 +120,8 @@ final class WpSettingsAbilitiesTest extends TestCase $result = (new WpSettingsUpdateAbility(new SettingsWhitelist(), FakeChangeLog::forbidden())) ->execute(['settings' => ['blogname' => 'Neu', 'admin_email' => 'x@y.de']]); - self::assertSame('lit_validation_failed', $result->get_error_code()); - self::assertArrayHasKey('admin_email', $result->get_error_data()['fields']); + self::assertToolError($result, 'validation_failed'); + self::assertArrayHasKey('admin_email', self::errorFields($result)); } public function testRejectsAGenuinelyUnknownKey(): void @@ -131,8 +131,8 @@ final class WpSettingsAbilitiesTest extends TestCase $result = (new WpSettingsUpdateAbility(new SettingsWhitelist(), FakeChangeLog::forbidden())) ->execute(['settings' => ['template' => 'twentyten']]); - self::assertSame('lit_validation_failed', $result->get_error_code()); - self::assertArrayHasKey('template', $result->get_error_data()['fields']); + self::assertToolError($result, 'validation_failed'); + self::assertArrayHasKey('template', self::errorFields($result)); } public function testUpdatesOnlyChangedValuesAndFlushesPermalinks(): void @@ -221,7 +221,7 @@ final class WpSettingsAbilitiesTest extends TestCase 'blogdescription' => 'Auch neu', ]); - self::assertSame('lit_write_failed', $error->get_error_code()); + self::assertToolError($error, 'write_failed'); $log->assertRecorded(); $log->assertPartials(); } @@ -252,7 +252,7 @@ final class WpSettingsAbilitiesTest extends TestCase 'blogdescription' => 'Auch neu', ]); - self::assertSame('lit_partial_write', $error->get_error_code()); + self::assertToolError($error, 'partial_write'); self::assertStringContainsString('blogname', $error->get_error_message()); self::assertStringContainsString('lit/wp-settings-get', $error->get_error_data()['hint']); $log->assertPartials([ @@ -278,7 +278,7 @@ final class WpSettingsAbilitiesTest extends TestCase { Functions\when('current_user_can')->alias(static fn (string $cap): bool => $cap !== 'manage_options'); - self::assertSame('lit_forbidden', (new WpSettingsGetAbility(new SettingsWhitelist()))->permission([])->get_error_code()); + self::assertToolError((new WpSettingsGetAbility(new SettingsWhitelist()))->permission([]), 'forbidden'); self::assertSame( 'lit_forbidden', (new WpSettingsUpdateAbility(new SettingsWhitelist(), FakeChangeLog::forbidden()))->permission([])->get_error_code() diff --git a/tests/Unit/Integrations/WordPress/Status/PostClonerTest.php b/tests/Unit/Integrations/WordPress/Status/PostClonerTest.php index f2c58c0..55862cb 100644 --- a/tests/Unit/Integrations/WordPress/Status/PostClonerTest.php +++ b/tests/Unit/Integrations/WordPress/Status/PostClonerTest.php @@ -230,7 +230,7 @@ final class PostClonerTest extends TestCase self::fail('WriteFailed expected'); } catch (WriteFailed $e) { self::assertTrue($e->rolledBack); - self::assertSame('lit_write_failed', $e->toError()->get_error_code()); + self::assertToolError($e->toError(), 'write_failed'); } } diff --git a/tests/Unit/Integrations/WordPress/Status/PostDuplicateAbilityTest.php b/tests/Unit/Integrations/WordPress/Status/PostDuplicateAbilityTest.php index 4a6ee0f..498925e 100644 --- a/tests/Unit/Integrations/WordPress/Status/PostDuplicateAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Status/PostDuplicateAbilityTest.php @@ -71,7 +71,7 @@ final class PostDuplicateAbilityTest extends TestCase $result = $this->ability($cloner, FakeChangeLog::forbidden())->execute(['post_id' => 5]); - self::assertSame('lit_forbidden', $result->get_error_code()); + self::assertToolError($result, 'forbidden'); } public function testATrashedOriginalIsRefused(): void @@ -82,7 +82,7 @@ final class PostDuplicateAbilityTest extends TestCase $result = $this->ability($cloner, FakeChangeLog::forbidden())->execute(['post_id' => 5]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testIsIndirectAndNotIdempotent(): void diff --git a/tests/Unit/Integrations/WordPress/Status/PostPublishAbilityTest.php b/tests/Unit/Integrations/WordPress/Status/PostPublishAbilityTest.php index 024ae10..87fc9d1 100644 --- a/tests/Unit/Integrations/WordPress/Status/PostPublishAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Status/PostPublishAbilityTest.php @@ -95,7 +95,7 @@ final class PostPublishAbilityTest extends TestCase self::assertFalse($e->rolledBack); self::assertSame(5, $e->postId); self::assertStringContainsString('save_post-Hook kaputt', $e->getMessage()); - self::assertSame('lit_partial_write', $e->toError()->get_error_code()); + self::assertToolError($e->toError(), 'partial_write'); } $log->assertPartials(['ability' => 'lit/post-publish', 'object_type' => 'page', 'object_id' => '5']); } @@ -107,7 +107,7 @@ final class PostPublishAbilityTest extends TestCase $result = $this->ability(FakeChangeLog::forbidden())->execute(['post_id' => 5]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testPermissionNeedsPublishRights(): void @@ -115,6 +115,6 @@ final class PostPublishAbilityTest extends TestCase $this->stubPost(['post_status' => 'draft']); Functions\when('current_user_can')->alias(static fn (string $cap): bool => $cap !== 'publish_post'); - self::assertSame('lit_forbidden', $this->ability(FakeChangeLog::forbidden())->permission(['post_id' => 5])->get_error_code()); + self::assertToolError($this->ability(FakeChangeLog::forbidden())->permission(['post_id' => 5]), 'forbidden'); } } diff --git a/tests/Unit/Integrations/WordPress/Status/PostReplaceWithCopyAbilityTest.php b/tests/Unit/Integrations/WordPress/Status/PostReplaceWithCopyAbilityTest.php index cd84fe7..48f7ced 100644 --- a/tests/Unit/Integrations/WordPress/Status/PostReplaceWithCopyAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Status/PostReplaceWithCopyAbilityTest.php @@ -68,7 +68,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase $result = $this->ability($cloner, FakeChangeLog::forbidden()) ->execute(['original_id' => 5, 'copy_id' => 77, 'rev' => Rev::ofPost($this->original)]); - self::assertSame('lit_confirm_required', $result->get_error_code()); + self::assertToolError($result, 'confirm_required'); } public function testCopyMustStemFromTheOriginal(): void @@ -79,7 +79,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase $result = $this->ability($cloner, FakeChangeLog::forbidden())->execute($this->input()); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } /** @return list */ @@ -103,7 +103,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase $result = $this->ability($cloner, FakeChangeLog::forbidden())->execute($this->input()); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testAMissedScheduleOfTheOriginalIsRefused(): void @@ -116,8 +116,8 @@ final class PostReplaceWithCopyAbilityTest extends TestCase $result = $this->ability($cloner, FakeChangeLog::forbidden())->execute($this->input()); - self::assertSame('lit_validation_failed', $result->get_error_code()); - self::assertArrayHasKey('original_id', $result->get_error_data()['fields']); + self::assertToolError($result, 'validation_failed'); + self::assertArrayHasKey('original_id', self::errorFields($result)); } public function testAPendingCopyIsAccepted(): void @@ -142,7 +142,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase $result = $this->ability($cloner, FakeChangeLog::forbidden())->execute($this->input(['rev' => 'veraltet'])); - self::assertSame('lit_rev_mismatch', $result->get_error_code()); + self::assertToolError($result, 'rev_mismatch'); } public function testDisabledTrashIsRefusedBeforeAnyChange(): void @@ -152,7 +152,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase $result = $this->ability($cloner, FakeChangeLog::forbidden(), false)->execute($this->input()); - self::assertSame('lit_unsupported', $result->get_error_code()); + self::assertToolError($result, 'unsupported'); } public function testRevisionThenReplaceThenTrashTheCopy(): void @@ -232,7 +232,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase self::fail('WriteFailed expected'); } catch (WriteFailed $e) { self::assertTrue($e->rolledBack); - self::assertSame('lit_write_failed', $e->toError()->get_error_code()); + self::assertToolError($e->toError(), 'write_failed'); self::assertSame(88, $e->toError()->get_error_data()['backup_id']); $message = $e->toError()->get_error_message(); self::assertStringNotContainsString('Nichts wurde gespeichert', $message); @@ -259,7 +259,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase self::assertSame(5, $e->postId); self::assertSame(900, $e->revisionId); $error = $e->toError(); - self::assertSame('lit_partial_write', $error->get_error_code()); + self::assertToolError($error, 'partial_write'); self::assertSame(88, $error->get_error_data()['backup_id']); self::assertStringContainsString('Sicherung', $error->get_error_message()); self::assertStringContainsString('88', $error->get_error_message()); @@ -280,8 +280,8 @@ final class PostReplaceWithCopyAbilityTest extends TestCase $cloner->expects('replace')->never(); $ability = $this->ability($cloner, FakeChangeLog::forbidden()); - self::assertSame('lit_forbidden', $ability->permission($this->input())->get_error_code()); - self::assertSame('lit_forbidden', $ability->execute($this->input())->get_error_code()); + self::assertToolError($ability->permission($this->input()), 'forbidden'); + self::assertToolError($ability->execute($this->input()), 'forbidden'); } public function testAFailedBackupAbortsBeforeTheOriginalIsTouched(): void @@ -298,7 +298,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase $this->ability($cloner, FakeChangeLog::forbidden())->execute($this->input()); self::fail('WriteFailed expected'); } catch (WriteFailed $e) { - self::assertSame('lit_write_failed', $e->toError()->get_error_code()); + self::assertToolError($e->toError(), 'write_failed'); } } diff --git a/tests/Unit/Integrations/WordPress/Status/PostScheduleAbilityTest.php b/tests/Unit/Integrations/WordPress/Status/PostScheduleAbilityTest.php index 12fa5a3..e36c3a2 100644 --- a/tests/Unit/Integrations/WordPress/Status/PostScheduleAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Status/PostScheduleAbilityTest.php @@ -92,7 +92,7 @@ final class PostScheduleAbilityTest extends TestCase self::assertFalse($e->rolledBack); self::assertSame(5, $e->postId); self::assertStringContainsString('save_post-Hook kaputt', $e->getMessage()); - self::assertSame('lit_partial_write', $e->toError()->get_error_code()); + self::assertToolError($e->toError(), 'partial_write'); } $log->assertPartials(['ability' => 'lit/post-schedule', 'object_type' => 'post', 'object_id' => '5']); } @@ -104,7 +104,7 @@ final class PostScheduleAbilityTest extends TestCase $result = $this->ability(FakeChangeLog::forbidden())->execute(['post_id' => 5, 'date' => '2099-06-01 09:30']); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testPastAndImpossibleDatesAreRejected(): void @@ -115,9 +115,9 @@ final class PostScheduleAbilityTest extends TestCase $past = $ability->execute(['post_id' => 5, 'date' => '2020-01-01 10:00']); $impossible = $ability->execute(['post_id' => 5, 'date' => '2099-13-45 10:00']); - self::assertSame('lit_validation_failed', $past->get_error_code()); + self::assertToolError($past, 'validation_failed'); self::assertStringContainsString('Zukunft', $past->get_error_message()); - self::assertSame('lit_validation_failed', $impossible->get_error_code()); + self::assertToolError($impossible, 'validation_failed'); } public function testADateWithinTheNextMinuteIsRejectedBecauseWordPressWouldPublishAtOnce(): void @@ -131,6 +131,6 @@ final class PostScheduleAbilityTest extends TestCase $result = $this->ability(FakeChangeLog::forbidden()) ->execute(['post_id' => 5, 'date' => $soon->format('Y-m-d H:i')]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } } diff --git a/tests/Unit/Integrations/WordPress/Status/PostTrashAbilityTest.php b/tests/Unit/Integrations/WordPress/Status/PostTrashAbilityTest.php index df680e4..38cfeb0 100644 --- a/tests/Unit/Integrations/WordPress/Status/PostTrashAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Status/PostTrashAbilityTest.php @@ -44,7 +44,7 @@ final class PostTrashAbilityTest extends TestCase $result = $this->ability(FakeChangeLog::forbidden())->execute(['post_id' => 5]); - self::assertSame('lit_confirm_required', $result->get_error_code()); + self::assertToolError($result, 'confirm_required'); } public function testMovesToTrashNeverDeletes(): void @@ -76,7 +76,7 @@ final class PostTrashAbilityTest extends TestCase $result = $ability->execute(['post_id' => 5, 'confirm' => true]); - self::assertSame('lit_unsupported', $result->get_error_code()); + self::assertToolError($result, 'unsupported'); } public function testAHookThrowingDuringTheWriteIsAPartialWrite(): void @@ -93,7 +93,7 @@ final class PostTrashAbilityTest extends TestCase self::assertFalse($e->rolledBack); self::assertSame(5, $e->postId); self::assertStringContainsString('save_post-Hook kaputt', $e->getMessage()); - self::assertSame('lit_partial_write', $e->toError()->get_error_code()); + self::assertToolError($e->toError(), 'partial_write'); } $log->assertPartials(['ability' => 'lit/post-trash', 'object_type' => 'page', 'object_id' => '5']); } diff --git a/tests/Unit/Integrations/WordPress/Status/PostUnpublishAbilityTest.php b/tests/Unit/Integrations/WordPress/Status/PostUnpublishAbilityTest.php index 11eee39..e5bd54f 100644 --- a/tests/Unit/Integrations/WordPress/Status/PostUnpublishAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Status/PostUnpublishAbilityTest.php @@ -52,7 +52,7 @@ final class PostUnpublishAbilityTest extends TestCase self::assertFalse($e->rolledBack); self::assertSame(5, $e->postId); self::assertStringContainsString('save_post-Hook kaputt', $e->getMessage()); - self::assertSame('lit_partial_write', $e->toError()->get_error_code()); + self::assertToolError($e->toError(), 'partial_write'); } $log->assertPartials(['ability' => 'lit/post-unpublish', 'object_type' => 'page', 'object_id' => '5']); } @@ -63,7 +63,7 @@ final class PostUnpublishAbilityTest extends TestCase $result = $this->ability(FakeChangeLog::forbidden(), 'trash')->execute(['post_id' => 5]); - self::assertSame('lit_validation_failed', $result->get_error_code()); + self::assertToolError($result, 'validation_failed'); } public function testDraftIsANoOp(): void diff --git a/tests/Unit/Integrations/WordPress/WordPressIntegrationTest.php b/tests/Unit/Integrations/WordPress/WordPressIntegrationTest.php index ccdd205..b96c3e2 100644 --- a/tests/Unit/Integrations/WordPress/WordPressIntegrationTest.php +++ b/tests/Unit/Integrations/WordPress/WordPressIntegrationTest.php @@ -80,6 +80,6 @@ final class WordPressIntegrationTest extends TestCase ))[0]; $result = $create->execute(['post_type' => 'page', 'title' => 'Start', 'divi' => [['type' => 'section']]]); - self::assertSame('lit_unsupported', $result->get_error_code()); + self::assertToolError($result, 'unsupported'); } } diff --git a/tests/Unit/Support/AssertsToolErrorsTest.php b/tests/Unit/Support/AssertsToolErrorsTest.php new file mode 100644 index 0000000..7590084 --- /dev/null +++ b/tests/Unit/Support/AssertsToolErrorsTest.php @@ -0,0 +1,44 @@ + 'Pflichtfeld']), 'validation_failed'); + + self::assertSame('Titel fehlt.', $payload['message']); + self::assertSame(['title' => 'Pflichtfeld'], self::errorFields(Errors::invalidInput('x', ['title' => 'Pflichtfeld']))); + } + + /** @return array Built in the test: Errors needs the stubs of setUp(). */ + public static function notTheError(): array + { + return [ + 'another code' => [static fn () => Errors::notFound('weg')], + 'no JSON payload' => [static fn () => new WP_Error('lit_validation_failed', 'kein JSON')], + 'no error at all' => [static fn () => ['ok' => true]], + ]; + } + + /** @dataProvider notTheError */ + public function testFailsForAnythingElse(callable $result): void + { + $this->expectException(AssertionFailedError::class); + self::assertToolError($result(), 'validation_failed'); + } + + public function testErrorFieldsFailsWithoutFields(): void + { + $this->expectException(AssertionFailedError::class); + self::errorFields(Errors::invalidInput('x')); + } +} diff --git a/tests/Unit/TestCase.php b/tests/Unit/TestCase.php index 3636e88..7fa1e2c 100644 --- a/tests/Unit/TestCase.php +++ b/tests/Unit/TestCase.php @@ -6,12 +6,14 @@ namespace LIT\MCP\Tests\Unit; use Brain\Monkey; use Brain\Monkey\Functions; +use LIT\MCP\Tests\Support\AssertsToolErrors; use LIT\MCP\Tests\Support\FakeChangeLog; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; use PHPUnit\Framework\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase { + use AssertsToolErrors; use MockeryPHPUnitIntegration; protected function setUp(): void