test: FakeChangeLog and SchemaFixture instead of repeated mocks (T2)
- tests/Support/FakeChangeLog extends ChangeLog: records record()/recordPartial() calls, increasing ids, optional failure; new FakeChangeLog(id) / partialsOnly() / any(id) / forbidden() mirror what the replaced mocks allowed. assertRecorded() / assertPartials() check count and the named arguments. Calls a fake does not allow throw and are also verified in TestCase::tearDown (one assertion per test that uses a fake), so swallowed change-log calls still fail like a never() expectation. - All ChangeLog mocks of ability/integration tests replaced (the admin tests that stub query/purge/clear keep their mocks); expectException tests that checked the partial log now catch and assert. - SchemaFixture::managed(?divi) replaces the 21 isManaged-only ContentSchema mocks; DiviFixtures::schema() uses it. Tests 1397 -> 1404 (FakeChangeLogTest); no test has fewer assertions. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,8 @@ use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Content\ContentCreateAbility;
|
||||
use LIT\MCP\Integrations\WordPress\Content\PostWriter;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use Mockery\MockInterface;
|
||||
@@ -27,8 +29,7 @@ final class ContentCreateAbilityTest extends TestCase
|
||||
{
|
||||
Functions\when('get_post_type_object')->justReturn((object) ['cap' => (object) ['create_posts' => 'edit_pages']]);
|
||||
Functions\when('current_user_can')->justReturn(true);
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
|
||||
return $schema;
|
||||
}
|
||||
@@ -72,7 +73,7 @@ final class ContentCreateAbilityTest extends TestCase
|
||||
$writer->allows('prepare')->andReturn(Errors::invalidInput('ungültig', ['fields.role' => 'Pflichtfeld fehlt.']));
|
||||
Functions\expect('wp_insert_post')->never();
|
||||
|
||||
$result = (new ContentCreateAbility($this->schema(), $writer, Mockery::mock(ChangeLog::class)))
|
||||
$result = (new ContentCreateAbility($this->schema(), $writer, FakeChangeLog::forbidden()))
|
||||
->execute(['post_type' => 'lit_person', 'title' => 'Anna']);
|
||||
|
||||
self::assertSame('lit_validation_failed', $result->get_error_code());
|
||||
@@ -97,8 +98,7 @@ final class ContentCreateAbilityTest extends TestCase
|
||||
], true)->andReturn(42);
|
||||
Actions\expectDone('lit_mcp_after_save')->once()->with(42, 'lit/content-create', $input);
|
||||
$post = $this->stubResultLinks();
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->with('lit/content-create', 'lit_person', '42', 'Entwurf "Anna" angelegt', null)->andReturn(7);
|
||||
$log = new FakeChangeLog(7);
|
||||
|
||||
$result = (new ContentCreateAbility($schema, $writer, $log))->execute($input);
|
||||
|
||||
@@ -108,6 +108,13 @@ final class ContentCreateAbilityTest extends TestCase
|
||||
self::assertSame(['w'], $result['warnings']);
|
||||
self::assertStringContainsString('Entwurf', $result['summary']);
|
||||
self::assertSame(Rev::ofPost($post), $result['rev']);
|
||||
$log->assertRecorded([
|
||||
'ability' => 'lit/content-create',
|
||||
'object_type' => 'lit_person',
|
||||
'object_id' => '42',
|
||||
'summary' => 'Entwurf "Anna" angelegt',
|
||||
'revision_id' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testFailingExtrasDeleteCreatedTermsAndTheNewDraft(): void
|
||||
@@ -118,8 +125,7 @@ final class ContentCreateAbilityTest extends TestCase
|
||||
Functions\when('wp_insert_post')->justReturn(42);
|
||||
Functions\expect('wp_delete_post')->once()->with(42, true)->andReturn(new WP_Post(['ID' => 42]));
|
||||
Actions\expectDone('lit_mcp_after_save')->never();
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->never();
|
||||
$log = FakeChangeLog::forbidden();
|
||||
|
||||
$failure = $this->execute($writer, $log);
|
||||
|
||||
@@ -139,8 +145,7 @@ final class ContentCreateAbilityTest extends TestCase
|
||||
Functions\when('get_current_user_id')->justReturn(3);
|
||||
Functions\when('wp_insert_post')->justReturn(42);
|
||||
Functions\expect('wp_delete_post')->once()->with(42, true)->andReturn(new WP_Post(['ID' => 42]));
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->never();
|
||||
$log = FakeChangeLog::forbidden();
|
||||
|
||||
$result = (new ContentCreateAbility($this->schema(), $writer, $log))->execute(self::INPUT);
|
||||
|
||||
@@ -157,8 +162,7 @@ final class ContentCreateAbilityTest extends TestCase
|
||||
Functions\when('get_current_user_id')->justReturn(3);
|
||||
Functions\when('wp_insert_post')->justReturn(42);
|
||||
Functions\when('wp_delete_post')->justReturn(false);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial');
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
|
||||
try {
|
||||
(new ContentCreateAbility($this->schema(), $writer, $log))->execute(self::INPUT);
|
||||
@@ -167,6 +171,7 @@ final class ContentCreateAbilityTest extends TestCase
|
||||
self::assertFalse($e->rolledBack);
|
||||
self::assertSame(42, $e->postId);
|
||||
}
|
||||
$log->assertPartials([]);
|
||||
}
|
||||
|
||||
public function testADraftThatCannotBeDeletedIsAPartialWriteAndLogged(): void
|
||||
@@ -176,16 +181,14 @@ final class ContentCreateAbilityTest extends TestCase
|
||||
$writer->expects('deleteCreatedTerms');
|
||||
Functions\when('wp_insert_post')->justReturn(42);
|
||||
Functions\when('wp_delete_post')->justReturn(false);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial')
|
||||
->with('lit/content-create', 'lit_person', '42', Mockery::type('string'))
|
||||
->andReturn(9);
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
|
||||
$failure = $this->execute($writer, $log);
|
||||
|
||||
self::assertFalse($failure->rolledBack);
|
||||
self::assertSame(42, $failure->postId);
|
||||
self::assertStringContainsString('Eintrag 42', $failure->toError()->get_error_message());
|
||||
$log->assertPartials(['ability' => 'lit/content-create', 'object_type' => 'lit_person', 'object_id' => '42']);
|
||||
}
|
||||
|
||||
public function testLeftoverCreatedTermsMakeItAPartialWrite(): void
|
||||
@@ -195,13 +198,13 @@ final class ContentCreateAbilityTest extends TestCase
|
||||
$writer->expects('deleteCreatedTerms')->andThrow(new RuntimeException('term 15 bleibt'));
|
||||
Functions\when('wp_insert_post')->justReturn(42);
|
||||
Functions\when('wp_delete_post')->justReturn(new WP_Post(['ID' => 42]));
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial');
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
|
||||
$failure = $this->execute($writer, $log);
|
||||
|
||||
self::assertFalse($failure->rolledBack);
|
||||
self::assertStringContainsString('term 15 bleibt', $failure->getMessage());
|
||||
$log->assertPartials([]);
|
||||
}
|
||||
|
||||
public function testAnInsertThatThrowsIsAPartialWriteWithoutId(): void
|
||||
@@ -210,16 +213,14 @@ final class ContentCreateAbilityTest extends TestCase
|
||||
Functions\when('wp_insert_post')->alias(static function (): never {
|
||||
throw new RuntimeException('save_post hook kaputt');
|
||||
});
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial')
|
||||
->with('lit/content-create', 'lit_person', '', Mockery::type('string'))
|
||||
->andReturn(9);
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
|
||||
$failure = $this->execute($writer, $log);
|
||||
|
||||
self::assertFalse($failure->rolledBack);
|
||||
self::assertNull($failure->postId);
|
||||
self::assertSame('lit_partial_write', $failure->toError()->get_error_code());
|
||||
$log->assertPartials(['ability' => 'lit/content-create', 'object_type' => 'lit_person', 'object_id' => '']);
|
||||
}
|
||||
|
||||
public function testFailuresAfterTheWriteOnlyAddWarnings(): void
|
||||
@@ -231,8 +232,7 @@ final class ContentCreateAbilityTest extends TestCase
|
||||
Actions\expectDone('lit_mcp_after_save')->once()->whenHappen(static function (): void {
|
||||
throw new RuntimeException('listener kaputt');
|
||||
});
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->andThrow(new RuntimeException('db weg'));
|
||||
$log = new FakeChangeLog(1, new RuntimeException('db weg'));
|
||||
$file = (string) tempnam(sys_get_temp_dir(), 'lit-mcp-log');
|
||||
$previous = ini_set('error_log', $file);
|
||||
|
||||
@@ -248,12 +248,13 @@ final class ContentCreateAbilityTest extends TestCase
|
||||
self::assertStringContainsString('listener kaputt', (string) file_get_contents($file));
|
||||
self::assertStringContainsString('db weg', (string) file_get_contents($file));
|
||||
unlink($file);
|
||||
$log->assertRecorded([]);
|
||||
}
|
||||
|
||||
public function testStatusIsNotAnInputAndPermissionNeedsCreateRights(): void
|
||||
{
|
||||
$schema = $this->schema();
|
||||
$ability = new ContentCreateAbility($schema, Mockery::mock(PostWriter::class), Mockery::mock(ChangeLog::class));
|
||||
$ability = new ContentCreateAbility($schema, Mockery::mock(PostWriter::class), FakeChangeLog::forbidden());
|
||||
|
||||
self::assertArrayNotHasKey('status', $ability->inputSchema()['properties']);
|
||||
self::assertFalse($ability->inputSchema()['additionalProperties']);
|
||||
|
||||
@@ -16,6 +16,8 @@ use LIT\MCP\Integrations\WordPress\Content\ContentCreateAbility;
|
||||
use LIT\MCP\Integrations\WordPress\Content\PostWriter;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Tests\Support\DiviWriterFixture;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use Mockery\MockInterface;
|
||||
@@ -34,9 +36,7 @@ final class ContentCreateDiviTest extends TestCase
|
||||
Functions\when('get_post_type_object')->justReturn((object) ['cap' => (object) ['create_posts' => 'edit_pages']]);
|
||||
Functions\when('current_user_can')->justReturn(true);
|
||||
Functions\when('get_current_user_id')->justReturn(3);
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema->allows('diviEnabled')->andReturn(true);
|
||||
$schema = SchemaFixture::managed(true);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
@@ -66,9 +66,7 @@ final class ContentCreateDiviTest extends TestCase
|
||||
|
||||
private function log(): ChangeLog
|
||||
{
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andReturn(9);
|
||||
$log->allows('recordPartial');
|
||||
$log = FakeChangeLog::any(9);
|
||||
|
||||
return $log;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Integrations\WordPress\Content\ContentGetAbility;
|
||||
use LIT\MCP\Integrations\WordPress\Content\PostPresenter;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use WP_Post;
|
||||
@@ -19,8 +20,7 @@ final class ContentGetAbilityTest extends TestCase
|
||||
$post = new WP_Post(['ID' => 5, 'post_type' => 'page']);
|
||||
Functions\when('get_post')->justReturn($post);
|
||||
Functions\when('current_user_can')->justReturn(true);
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
$presenter = Mockery::mock(PostPresenter::class);
|
||||
$presenter->expects('full')->with($post)->andReturn(['id' => 5]);
|
||||
$ability = new ContentGetAbility($schema, $presenter);
|
||||
@@ -34,8 +34,7 @@ final class ContentGetAbilityTest extends TestCase
|
||||
$post = new WP_Post(['ID' => 5, 'post_type' => 'page', 'post_status' => 'trash']);
|
||||
Functions\when('get_post')->justReturn($post);
|
||||
Functions\when('current_user_can')->justReturn(true);
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
$presenter = Mockery::mock(PostPresenter::class);
|
||||
$presenter->expects('full')->with($post)->andReturn(['id' => 5]);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ use LIT\MCP\Integrations\WordPress\Content\ContentQueryAbility;
|
||||
use LIT\MCP\Integrations\WordPress\Content\PostPresenter;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\FieldDefinition;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use WP_Post;
|
||||
@@ -241,8 +242,7 @@ final class ContentQueryAbilityTest extends TestCase
|
||||
{
|
||||
Functions\when('get_post_type_object')->justReturn((object) ['cap' => (object) ['edit_posts' => 'edit_posts']]);
|
||||
Functions\when('current_user_can')->justReturn(false);
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
$ability = new ContentQueryAbility($schema, Mockery::mock(PostPresenter::class));
|
||||
|
||||
self::assertSame('lit_forbidden', $ability->permission(['post_type' => 'page'])->get_error_code());
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace LIT\MCP\Tests\Unit\Integrations\WordPress\Content;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Integrations\WordPress\Content\ContentTypesAbility;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use WP_Error;
|
||||
@@ -89,8 +90,7 @@ final class ContentTypesAbilityTest extends TestCase
|
||||
{
|
||||
Functions\when('get_post_type_object')->justReturn((object) ['cap' => (object) ['edit_posts' => 'edit_pages']]);
|
||||
Functions\when('current_user_can')->justReturn(false);
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
|
||||
$result = (new ContentTypesAbility($schema))->execute(['post_type' => 'page']);
|
||||
|
||||
@@ -110,8 +110,7 @@ final class ContentTypesAbilityTest extends TestCase
|
||||
{
|
||||
Functions\when('current_user_can')->alias(static fn (string $cap): bool => $cap === 'edit_posts');
|
||||
Functions\when('get_post_type_object')->justReturn((object) ['cap' => (object) ['edit_posts' => 'edit_pages']]);
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
|
||||
$result = (new ContentTypesAbility($schema))->permission(['post_type' => 'lit_person']);
|
||||
|
||||
@@ -123,8 +122,7 @@ final class ContentTypesAbilityTest extends TestCase
|
||||
{
|
||||
Functions\when('current_user_can')->justReturn(true);
|
||||
Functions\when('get_post_type_object')->justReturn((object) ['cap' => (object) ['edit_posts' => 'edit_posts']]);
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
|
||||
self::assertTrue((new ContentTypesAbility($schema))->permission(['post_type' => 'page']));
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ use LIT\MCP\Integrations\WordPress\Content\ContentUpdateAbility;
|
||||
use LIT\MCP\Integrations\WordPress\Content\PostPresenter;
|
||||
use LIT\MCP\Integrations\WordPress\Content\PostWriter;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use RuntimeException;
|
||||
@@ -39,15 +41,14 @@ final class ContentUpdateAbilityTest extends TestCase
|
||||
|
||||
private function schema(): ContentSchema
|
||||
{
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
private function ability(PostWriter $writer, ?ChangeLog $log = null): ContentUpdateAbility
|
||||
{
|
||||
return new ContentUpdateAbility($this->schema(), $writer, $log ?? Mockery::mock(ChangeLog::class));
|
||||
return new ContentUpdateAbility($this->schema(), $writer, $log ?? FakeChangeLog::forbidden());
|
||||
}
|
||||
|
||||
public function testRevIsRequired(): void
|
||||
@@ -155,8 +156,7 @@ final class ContentUpdateAbilityTest extends TestCase
|
||||
Actions\expectDone('lit_mcp_after_save')->once()->with(5, 'lit/content-update', $input);
|
||||
Functions\when('get_preview_post_link')->justReturn('https://kunde.de/team/');
|
||||
Functions\when('get_edit_post_link')->justReturn('https://kunde.de/wp-admin/post.php?post=5&action=edit');
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->with('lit/content-update', 'page', '5', Mockery::type('string'), 811)->andReturn(4711);
|
||||
$log = new FakeChangeLog(4711);
|
||||
|
||||
$result = $this->ability($writer, $log)->execute($input);
|
||||
|
||||
@@ -166,6 +166,12 @@ final class ContentUpdateAbilityTest extends TestCase
|
||||
self::assertSame('updated', $result['changed'][0]['action']);
|
||||
self::assertSame(Rev::ofPost($this->post), $result['rev']);
|
||||
self::assertStringContainsString('Status unverändert: publish', $result['summary']);
|
||||
$log->assertRecorded([
|
||||
'ability' => 'lit/content-update',
|
||||
'object_type' => 'page',
|
||||
'object_id' => '5',
|
||||
'revision_id' => 811,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,8 +203,7 @@ final class ContentUpdateAbilityTest extends TestCase
|
||||
private function executeExpectingFailure(PostWriter $writer, array $input, ?ChangeLog $log = null): WriteFailed
|
||||
{
|
||||
if ($log === null) {
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->never();
|
||||
$log = FakeChangeLog::forbidden();
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -298,14 +303,14 @@ final class ContentUpdateAbilityTest extends TestCase
|
||||
});
|
||||
Functions\when('wp_revisions_enabled')->justReturn(true);
|
||||
Functions\expect('wp_restore_post_revision')->never();
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial');
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
|
||||
$failure = $this->executeExpectingFailure($writer, $input, $log);
|
||||
|
||||
self::assertFalse($failure->rolledBack);
|
||||
self::assertCount(1, $updates);
|
||||
self::assertStringContainsString('publish', $failure->getMessage());
|
||||
$log->assertPartials([]);
|
||||
}
|
||||
|
||||
public function testAnIncompleteRollbackIsAPartialWriteAndLogged(): void
|
||||
@@ -314,10 +319,7 @@ final class ContentUpdateAbilityTest extends TestCase
|
||||
$updates = [];
|
||||
$this->captureUpdates($updates);
|
||||
Functions\when('wp_revisions_enabled')->justReturn(false);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial')
|
||||
->with('lit/content-update', 'page', '5', Mockery::type('string'), 811)
|
||||
->andReturn(12);
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
|
||||
$failure = $this->executeExpectingFailure($writer, $input, $log);
|
||||
|
||||
@@ -327,6 +329,12 @@ final class ContentUpdateAbilityTest extends TestCase
|
||||
self::assertSame('lit_partial_write', $error->get_error_code());
|
||||
self::assertSame(5, $error->get_error_data()['post_id']);
|
||||
self::assertSame(811, $error->get_error_data()['revision_id']);
|
||||
$log->assertPartials([
|
||||
'ability' => 'lit/content-update',
|
||||
'object_type' => 'page',
|
||||
'object_id' => '5',
|
||||
'revision_id' => 811,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testFailuresAfterTheWriteOnlyAddWarnings(): void
|
||||
@@ -345,8 +353,7 @@ final class ContentUpdateAbilityTest extends TestCase
|
||||
Actions\expectDone('lit_mcp_after_save')->once()->whenHappen(static function (): void {
|
||||
throw new RuntimeException('listener kaputt');
|
||||
});
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->andThrow(new RuntimeException('db weg'));
|
||||
$log = new FakeChangeLog(1, new RuntimeException('db weg'));
|
||||
$file = (string) tempnam(sys_get_temp_dir(), 'lit-mcp-log');
|
||||
$previous = ini_set('error_log', $file);
|
||||
|
||||
@@ -361,5 +368,6 @@ final class ContentUpdateAbilityTest extends TestCase
|
||||
self::assertCount(2, $result['warnings']);
|
||||
self::assertStringContainsString('listener kaputt', (string) file_get_contents($file));
|
||||
unlink($file);
|
||||
$log->assertRecorded([]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ namespace LIT\MCP\Tests\Unit\Integrations\WordPress\Content;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Content\NewDraft;
|
||||
use LIT\MCP\Integrations\WordPress\Content\PostWriter;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use RuntimeException;
|
||||
@@ -22,9 +22,7 @@ final class NewDraftTest extends TestCase
|
||||
Functions\when('wp_delete_post')->alias(static function (): never {
|
||||
throw new RuntimeException('delete_post hook kaputt');
|
||||
});
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial')
|
||||
->with('lit/content-create', 'page', '42', 'Entwurf 42: Anlegen nur teilweise zurückgenommen');
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
$draft = new NewDraft($writer, $log, 'lit/content-create', 'page');
|
||||
|
||||
try {
|
||||
@@ -40,6 +38,12 @@ final class NewDraftTest extends TestCase
|
||||
$e->getMessage()
|
||||
);
|
||||
}
|
||||
$log->assertPartials([
|
||||
'ability' => 'lit/content-create',
|
||||
'object_type' => 'page',
|
||||
'object_id' => '42',
|
||||
'summary' => 'Entwurf 42: Anlegen nur teilweise zurückgenommen',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testACleanDiscardIsRolledBackWithTheGivenReason(): void
|
||||
@@ -47,8 +51,7 @@ final class NewDraftTest extends TestCase
|
||||
$writer = Mockery::mock(PostWriter::class);
|
||||
$writer->expects('deleteCreatedTerms');
|
||||
Functions\expect('wp_delete_post')->once()->with(42, true)->andReturn(true);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial')->never();
|
||||
$log = FakeChangeLog::forbidden();
|
||||
$draft = new NewDraft($writer, $log, 'lit/content-create', 'page');
|
||||
|
||||
try {
|
||||
|
||||
@@ -5,10 +5,9 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\WordPress\Menus;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Menus\MenuAssignLocationAbility;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
|
||||
final class MenuAssignLocationAbilityTest extends TestCase
|
||||
{
|
||||
@@ -29,28 +28,26 @@ final class MenuAssignLocationAbilityTest extends TestCase
|
||||
public function testAssignsAndReportsThePreviousMenu(): void
|
||||
{
|
||||
Functions\expect('set_theme_mod')->once()->with('nav_menu_locations', ['primary-menu' => 8]);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')
|
||||
->with(
|
||||
'lit/menu-assign-location',
|
||||
'menu_location',
|
||||
'primary-menu',
|
||||
'Menü 8 der Position primary-menu zugewiesen'
|
||||
)
|
||||
->andReturn(6);
|
||||
$log = new FakeChangeLog(6);
|
||||
|
||||
$result = (new MenuAssignLocationAbility($log))->execute(['location' => 'primary-menu', 'menu_id' => 8]);
|
||||
|
||||
self::assertSame(3, $result['previous_menu_id']);
|
||||
self::assertSame('assigned', $result['changed'][0]['action']);
|
||||
self::assertSame(6, $result['log_id']);
|
||||
$log->assertRecorded([
|
||||
'ability' => 'lit/menu-assign-location',
|
||||
'object_type' => 'menu_location',
|
||||
'object_id' => 'primary-menu',
|
||||
'summary' => 'Menü 8 der Position primary-menu zugewiesen',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testRemovingAnAssignmentNeedsConfirmation(): void
|
||||
{
|
||||
Functions\expect('set_theme_mod')->never();
|
||||
|
||||
$result = (new MenuAssignLocationAbility(Mockery::mock(ChangeLog::class)))
|
||||
$result = (new MenuAssignLocationAbility(FakeChangeLog::forbidden()))
|
||||
->execute(['location' => 'primary-menu', 'menu_id' => 0]);
|
||||
|
||||
self::assertSame('lit_confirm_required', $result->get_error_code());
|
||||
@@ -63,15 +60,7 @@ final class MenuAssignLocationAbilityTest extends TestCase
|
||||
public function testZeroRemovesTheAssignmentAndNamesTheRemovedMenu(): void
|
||||
{
|
||||
Functions\expect('set_theme_mod')->once()->with('nav_menu_locations', []);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')
|
||||
->with(
|
||||
'lit/menu-assign-location',
|
||||
'menu_location',
|
||||
'primary-menu',
|
||||
'Menü "Hauptmenü" (ID 3) von der Position primary-menu entfernt'
|
||||
)
|
||||
->andReturn(7);
|
||||
$log = new FakeChangeLog(7);
|
||||
|
||||
$result = (new MenuAssignLocationAbility($log))
|
||||
->execute(['location' => 'primary-menu', 'menu_id' => 0, 'confirm' => true]);
|
||||
@@ -80,14 +69,19 @@ final class MenuAssignLocationAbilityTest extends TestCase
|
||||
self::assertSame(3, $result['previous_menu_id']);
|
||||
self::assertStringContainsString('"Hauptmenü" (ID 3)', $result['summary']);
|
||||
self::assertSame(7, $result['log_id']);
|
||||
$log->assertRecorded([
|
||||
'ability' => 'lit/menu-assign-location',
|
||||
'object_type' => 'menu_location',
|
||||
'object_id' => 'primary-menu',
|
||||
'summary' => 'Menü "Hauptmenü" (ID 3) von der Position primary-menu entfernt',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testRemovingFromAnEmptyLocationNeedsNoConfirmation(): void
|
||||
{
|
||||
Functions\when('get_nav_menu_locations')->justReturn([]);
|
||||
Functions\expect('set_theme_mod')->once()->with('nav_menu_locations', []);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andReturn(8);
|
||||
$log = new FakeChangeLog(8);
|
||||
|
||||
$result = (new MenuAssignLocationAbility($log))->execute(['location' => 'primary-menu', 'menu_id' => 0]);
|
||||
|
||||
@@ -97,7 +91,7 @@ final class MenuAssignLocationAbilityTest extends TestCase
|
||||
|
||||
public function testDescribesTheConfirmationForRemoval(): void
|
||||
{
|
||||
$ability = new MenuAssignLocationAbility(Mockery::mock(ChangeLog::class));
|
||||
$ability = new MenuAssignLocationAbility(FakeChangeLog::forbidden());
|
||||
|
||||
self::assertArrayHasKey('confirm', $ability->inputSchema()['properties']);
|
||||
self::assertStringContainsString('confirm: true', $ability->description());
|
||||
@@ -107,7 +101,7 @@ final class MenuAssignLocationAbilityTest extends TestCase
|
||||
{
|
||||
Functions\expect('set_theme_mod')->never();
|
||||
|
||||
$result = (new MenuAssignLocationAbility(Mockery::mock(ChangeLog::class)))
|
||||
$result = (new MenuAssignLocationAbility(FakeChangeLog::forbidden()))
|
||||
->execute(['location' => 'primary-menu', 'menu_id' => 99]);
|
||||
|
||||
self::assertSame('lit_not_found', $result->get_error_code());
|
||||
@@ -117,7 +111,7 @@ final class MenuAssignLocationAbilityTest extends TestCase
|
||||
{
|
||||
Functions\when('current_user_can')->justReturn(false);
|
||||
|
||||
$ability = new MenuAssignLocationAbility(Mockery::mock(ChangeLog::class));
|
||||
$ability = new MenuAssignLocationAbility(FakeChangeLog::forbidden());
|
||||
$input = ['location' => 'primary-menu', 'menu_id' => 8];
|
||||
|
||||
self::assertSame('lit_forbidden', $ability->permission($input)->get_error_code());
|
||||
@@ -125,7 +119,7 @@ final class MenuAssignLocationAbilityTest extends TestCase
|
||||
|
||||
public function testIsDestructiveBecauseItReplacesTheMenuOfTheLocation(): void
|
||||
{
|
||||
$ability = new MenuAssignLocationAbility(Mockery::mock(ChangeLog::class));
|
||||
$ability = new MenuAssignLocationAbility(FakeChangeLog::forbidden());
|
||||
|
||||
self::assertSame(['readonly' => false, 'destructive' => true, 'idempotent' => true], $ability->annotations());
|
||||
}
|
||||
|
||||
@@ -5,10 +5,9 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Tests\Unit\Integrations\WordPress\Menus;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Menus\MenuCreateAbility;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use WP_Error;
|
||||
|
||||
final class MenuCreateAbilityTest extends TestCase
|
||||
@@ -18,7 +17,7 @@ final class MenuCreateAbilityTest extends TestCase
|
||||
Functions\when('get_registered_nav_menus')->justReturn(['primary-menu' => 'Hauptmenü']);
|
||||
Functions\expect('wp_create_nav_menu')->never();
|
||||
|
||||
$ability = new MenuCreateAbility(Mockery::mock(ChangeLog::class));
|
||||
$ability = new MenuCreateAbility(FakeChangeLog::forbidden());
|
||||
$result = $ability->execute(['name' => 'Neu', 'location' => 'nope']);
|
||||
|
||||
self::assertSame('lit_validation_failed', $result->get_error_code());
|
||||
@@ -31,7 +30,7 @@ final class MenuCreateAbilityTest extends TestCase
|
||||
new WP_Error('menu_exists', 'Der Menüname existiert bereits.')
|
||||
);
|
||||
|
||||
$result = (new MenuCreateAbility(Mockery::mock(ChangeLog::class)))->execute(['name' => 'Hauptmenü']);
|
||||
$result = (new MenuCreateAbility(FakeChangeLog::forbidden()))->execute(['name' => 'Hauptmenü']);
|
||||
|
||||
self::assertSame('lit_validation_failed', $result->get_error_code());
|
||||
}
|
||||
@@ -45,23 +44,26 @@ final class MenuCreateAbilityTest extends TestCase
|
||||
'nav_menu_locations',
|
||||
['footer-menu' => 2, 'primary-menu' => 8]
|
||||
);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')
|
||||
->with('lit/menu-create', 'nav_menu', '8', 'Menü "Neu" angelegt (Position primary-menu)')
|
||||
->andReturn(5);
|
||||
$log = new FakeChangeLog(5);
|
||||
|
||||
$result = (new MenuCreateAbility($log))->execute(['name' => 'Neu', 'location' => 'primary-menu']);
|
||||
|
||||
self::assertSame(8, $result['menu_id']);
|
||||
self::assertSame('created', $result['changed'][0]['action']);
|
||||
self::assertSame(5, $result['log_id']);
|
||||
$log->assertRecorded([
|
||||
'ability' => 'lit/menu-create',
|
||||
'object_type' => 'nav_menu',
|
||||
'object_id' => '8',
|
||||
'summary' => 'Menü "Neu" angelegt (Position primary-menu)',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testPermissionNeedsThemeOptionRights(): void
|
||||
{
|
||||
Functions\when('current_user_can')->justReturn(false);
|
||||
|
||||
$ability = new MenuCreateAbility(Mockery::mock(ChangeLog::class));
|
||||
$ability = new MenuCreateAbility(FakeChangeLog::forbidden());
|
||||
|
||||
self::assertSame('lit_forbidden', $ability->permission(['name' => 'Neu'])->get_error_code());
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@ namespace LIT\MCP\Tests\Unit\Integrations\WordPress\Menus;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\Rev;
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Menus\MenuOperations;
|
||||
use LIT\MCP\Integrations\WordPress\Menus\MenuSetItemsAbility;
|
||||
use LIT\MCP\Integrations\WordPress\Menus\MenuTree;
|
||||
use LIT\MCP\Integrations\WordPress\Menus\MenuWriter;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use RuntimeException;
|
||||
@@ -37,7 +37,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
{
|
||||
$writer = Mockery::mock(MenuWriter::class);
|
||||
$writer->expects('apply')->never();
|
||||
$ability = new MenuSetItemsAbility($writer, new MenuOperations(), Mockery::mock(ChangeLog::class));
|
||||
$ability = new MenuSetItemsAbility($writer, new MenuOperations(), FakeChangeLog::forbidden());
|
||||
|
||||
$stale = $ability->execute(['menu_id' => 3, 'menu_rev' => 'abcdefabcdef', 'items' => [['id' => 10]]]);
|
||||
$missing = $ability->execute(['menu_id' => 3, 'items' => [['id' => 10]]]);
|
||||
@@ -55,8 +55,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
$writer = Mockery::mock(MenuWriter::class);
|
||||
$writer->allows('plan')->andReturn(['errors' => [], 'removals' => [], 'warnings' => []]);
|
||||
$writer->allows('apply')->andReturn(['created' => 0, 'updated' => 1, 'removed' => 0]);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andReturn(30);
|
||||
$log = new FakeChangeLog(30);
|
||||
|
||||
$result = (new MenuSetItemsAbility($writer, new MenuOperations(), $log))->execute(
|
||||
['menu_id' => 3, 'menu_rev' => self::rev(), 'items' => [['id' => 10]]]
|
||||
@@ -67,7 +66,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
|
||||
public function testItemsAndOperationsAreMutuallyExclusive(): void
|
||||
{
|
||||
$ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), Mockery::mock(ChangeLog::class));
|
||||
$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::assertSame(
|
||||
@@ -80,7 +79,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
public function testUnknownMenuIsNotFound(): void
|
||||
{
|
||||
Functions\when('wp_get_nav_menu_object')->justReturn(false);
|
||||
$ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), Mockery::mock(ChangeLog::class));
|
||||
$ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), FakeChangeLog::forbidden());
|
||||
|
||||
self::assertSame('lit_not_found', $ability->execute(['menu_id' => 9, 'items' => []])->get_error_code());
|
||||
}
|
||||
@@ -89,7 +88,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
{
|
||||
Functions\expect('wp_update_nav_menu_item')->never();
|
||||
Functions\expect('wp_delete_post')->never();
|
||||
$ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), Mockery::mock(ChangeLog::class));
|
||||
$ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), FakeChangeLog::forbidden());
|
||||
|
||||
$result = $ability->execute(['menu_id' => 3, 'menu_rev' => self::rev(), 'items' => []]);
|
||||
|
||||
@@ -102,7 +101,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
Functions\when('wp_parse_url')->alias('parse_url');
|
||||
Functions\expect('wp_update_nav_menu_item')->never();
|
||||
Functions\expect('wp_delete_post')->never();
|
||||
$ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), Mockery::mock(ChangeLog::class));
|
||||
$ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), FakeChangeLog::forbidden());
|
||||
|
||||
$result = $ability->execute([
|
||||
'menu_id' => 3, 'menu_rev' => self::rev(),
|
||||
@@ -118,7 +117,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
{
|
||||
$writer = Mockery::mock(MenuWriter::class);
|
||||
$writer->expects('apply')->never();
|
||||
$ability = new MenuSetItemsAbility($writer, new MenuOperations(), Mockery::mock(ChangeLog::class));
|
||||
$ability = new MenuSetItemsAbility($writer, new MenuOperations(), FakeChangeLog::forbidden());
|
||||
|
||||
$result = $ability->execute(['menu_id' => 3, 'menu_rev' => self::rev(), 'operations' => [['op' => 'move', 'id' => 99]]]);
|
||||
|
||||
@@ -130,8 +129,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
$writer = Mockery::mock(MenuWriter::class);
|
||||
$writer->allows('plan')->andReturn(['errors' => [], 'removals' => [], 'warnings' => []]);
|
||||
$writer->expects('apply')->andReturn(['created' => 1, 'updated' => 1, 'removed' => 0]);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->with('lit/menu-set-items', 'nav_menu', '3', Mockery::type('string'))->andReturn(21);
|
||||
$log = new FakeChangeLog(21);
|
||||
|
||||
$result = (new MenuSetItemsAbility($writer, new MenuOperations(), $log))->execute([
|
||||
'menu_id' => 3, 'menu_rev' => self::rev(),
|
||||
@@ -141,6 +139,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
self::assertSame('Home', $result['previous_items'][0]['title']);
|
||||
self::assertSame(21, $result['log_id']);
|
||||
self::assertStringContainsString('1 neu, 1 geändert, 0 entfernt', $result['summary']);
|
||||
$log->assertRecorded(['ability' => 'lit/menu-set-items', 'object_type' => 'nav_menu', 'object_id' => '3']);
|
||||
}
|
||||
|
||||
public function testConfirmedRemovalsAreWrittenAndTheOldTreeIsReturned(): void
|
||||
@@ -151,8 +150,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
);
|
||||
$writer->expects('apply')->with(3, [], Mockery::type('array'))
|
||||
->andReturn(['created' => 0, 'updated' => 0, 'removed' => 1]);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andReturn(22);
|
||||
$log = new FakeChangeLog(22);
|
||||
|
||||
$result = (new MenuSetItemsAbility($writer, new MenuOperations(), $log))->execute(
|
||||
['menu_id' => 3, 'menu_rev' => self::rev(), 'items' => [], 'confirm' => true]
|
||||
@@ -169,8 +167,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
Functions\when('wp_get_nav_menu_items')->justReturn($items);
|
||||
Functions\expect('wp_delete_post')->never();
|
||||
Functions\expect('wp_update_nav_menu_item')->never();
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->never();
|
||||
$log = FakeChangeLog::forbidden();
|
||||
|
||||
$result = (new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), $log))->execute(
|
||||
['menu_id' => 3, 'menu_rev' => self::rev(), 'items' => MenuTree::build($items)]
|
||||
@@ -187,7 +184,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
$writer = Mockery::mock(MenuWriter::class);
|
||||
$writer->expects('plan')->with(Mockery::type('array'), Mockery::type('array'), true)
|
||||
->andReturn(['errors' => ['items.0' => 'x'], 'removals' => [], 'warnings' => []]);
|
||||
$ability = new MenuSetItemsAbility($writer, new MenuOperations(), Mockery::mock(ChangeLog::class));
|
||||
$ability = new MenuSetItemsAbility($writer, new MenuOperations(), FakeChangeLog::forbidden());
|
||||
|
||||
$result = $ability->execute(
|
||||
['menu_id' => 3, 'menu_rev' => self::rev(), 'items' => [['type' => 'post', 'object_id' => 7]], 'allow_unpublished' => true]
|
||||
@@ -205,8 +202,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
);
|
||||
Functions\when('get_post_type')->justReturn('page');
|
||||
Functions\expect('wp_update_nav_menu_item')->once()->andReturn(60);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andReturn(24);
|
||||
$log = new FakeChangeLog(24);
|
||||
$ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), $log);
|
||||
$input = ['menu_id' => 3, 'menu_rev' => self::rev(), 'operations' => [['op' => 'add', 'item' => ['type' => 'post', 'object_id' => 7]]]];
|
||||
|
||||
@@ -226,7 +222,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
new \WP_Post(['ID' => 7, 'post_type' => 'page', 'post_status' => 'private', 'post_title' => 'Intern'])
|
||||
);
|
||||
Functions\expect('wp_update_nav_menu_item')->never();
|
||||
$ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), Mockery::mock(ChangeLog::class));
|
||||
$ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), FakeChangeLog::forbidden());
|
||||
|
||||
$result = $ability->execute([
|
||||
'menu_id' => 3, 'menu_rev' => self::rev(),
|
||||
@@ -243,8 +239,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
$writer = Mockery::mock(MenuWriter::class);
|
||||
$writer->allows('plan')->andReturn(['errors' => [], 'removals' => [], 'warnings' => []]);
|
||||
$writer->expects('apply')->andThrow(WriteFailed::rolledBack('Menü nicht gespeichert.'));
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->shouldNotReceive('recordPartial');
|
||||
$log = FakeChangeLog::forbidden();
|
||||
$ability = new MenuSetItemsAbility($writer, new MenuOperations(), $log);
|
||||
|
||||
$this->expectException(WriteFailed::class);
|
||||
@@ -256,12 +251,16 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
$writer = Mockery::mock(MenuWriter::class);
|
||||
$writer->allows('plan')->andReturn(['errors' => [], 'removals' => [], 'warnings' => []]);
|
||||
$writer->expects('apply')->andThrow(WriteFailed::partial('Menü nicht gespeichert.'));
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial')->with('lit/menu-set-items', 'nav_menu', '3', Mockery::type('string'));
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
$ability = new MenuSetItemsAbility($writer, new MenuOperations(), $log);
|
||||
|
||||
$this->expectException(WriteFailed::class);
|
||||
$ability->execute(['menu_id' => 3, 'menu_rev' => self::rev(), 'items' => [['id' => 10]]]);
|
||||
try {
|
||||
$ability->execute(['menu_id' => 3, 'menu_rev' => self::rev(), 'items' => [['id' => 10]]]);
|
||||
self::fail('WriteFailed expected');
|
||||
} catch (WriteFailed $e) {
|
||||
self::assertFalse($e->rolledBack);
|
||||
}
|
||||
$log->assertPartials(['ability' => 'lit/menu-set-items', 'object_type' => 'nav_menu', 'object_id' => '3']);
|
||||
}
|
||||
|
||||
public function testAChangeLogFailureIsOnlyAWarning(): void
|
||||
@@ -269,8 +268,7 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
$writer = Mockery::mock(MenuWriter::class);
|
||||
$writer->allows('plan')->andReturn(['errors' => [], 'removals' => [], 'warnings' => ['"X" ist nicht veröffentlicht']]);
|
||||
$writer->allows('apply')->andReturn(['created' => 0, 'updated' => 1, 'removed' => 0]);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andThrow(new RuntimeException('db down'));
|
||||
$log = new FakeChangeLog(1, new RuntimeException('db down'));
|
||||
$file = (string) tempnam(sys_get_temp_dir(), 'lit');
|
||||
$errorLog = ini_set('error_log', $file);
|
||||
|
||||
@@ -290,14 +288,14 @@ final class MenuSetItemsAbilityTest extends TestCase
|
||||
public function testPermissionNeedsThemeOptionRights(): void
|
||||
{
|
||||
Functions\when('current_user_can')->justReturn(false);
|
||||
$ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), Mockery::mock(ChangeLog::class));
|
||||
$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());
|
||||
}
|
||||
|
||||
public function testIsDestructiveAndDescribesWhenConfirmIsNeeded(): void
|
||||
{
|
||||
$ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), Mockery::mock(ChangeLog::class));
|
||||
$ability = new MenuSetItemsAbility(new MenuWriter(), new MenuOperations(), FakeChangeLog::forbidden());
|
||||
|
||||
self::assertSame(['readonly' => false, 'destructive' => true, 'idempotent' => false], $ability->annotations());
|
||||
self::assertStringContainsString('confirm: true', $ability->description());
|
||||
|
||||
@@ -7,10 +7,9 @@ namespace LIT\MCP\Tests\Unit\Integrations\WordPress;
|
||||
use Brain\Monkey\Actions;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\Rev;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\PostChangeResult;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use RuntimeException;
|
||||
use WP_Post;
|
||||
|
||||
@@ -38,8 +37,7 @@ final class PostChangeResultTest extends TestCase
|
||||
$post = new WP_Post(['ID' => 5, 'post_title' => 'Team']);
|
||||
Actions\expectDone('lit_mcp_after_save')->once()->with(5, 'lit/content-update', ['post_id' => 5]);
|
||||
Functions\when('get_post')->justReturn($post);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->with('lit/content-update', 'page', '5', 'geändert', 811)->andReturn(9);
|
||||
$log = new FakeChangeLog(9);
|
||||
|
||||
$change = new PostChangeResult('lit/content-update', $log, 5, 'die Änderung', ['vorher']);
|
||||
$change->afterSave(['post_id' => 5]);
|
||||
@@ -52,6 +50,13 @@ final class PostChangeResultTest extends TestCase
|
||||
self::assertSame(Rev::ofPost($post), $result['rev']);
|
||||
self::assertSame(9, $result['log_id']);
|
||||
self::assertSame(['vorher'], $result['warnings']);
|
||||
$log->assertRecorded([
|
||||
'ability' => 'lit/content-update',
|
||||
'object_type' => 'page',
|
||||
'object_id' => '5',
|
||||
'summary' => 'geändert',
|
||||
'revision_id' => 811,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testFailuresAfterTheWriteBecomeWarnings(): void
|
||||
@@ -60,8 +65,7 @@ final class PostChangeResultTest extends TestCase
|
||||
throw new RuntimeException('listener kaputt');
|
||||
});
|
||||
Functions\when('get_post')->justReturn(null);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->andThrow(new RuntimeException('log kaputt'));
|
||||
$log = new FakeChangeLog(1, new RuntimeException('log kaputt'));
|
||||
$fallback = new WP_Post(['ID' => 5]);
|
||||
|
||||
$change = new PostChangeResult('lit/post-publish', $log, 5);
|
||||
@@ -77,13 +81,14 @@ final class PostChangeResultTest extends TestCase
|
||||
'Änderungsprotokoll konnte nicht geschrieben werden; die Änderung ist gespeichert.',
|
||||
], $result['warnings']);
|
||||
self::assertStringContainsString('listener kaputt', (string) file_get_contents($this->errorLog));
|
||||
$log->assertRecorded([]);
|
||||
}
|
||||
|
||||
public function testWithoutAReadablePostTheRevIsNull(): void
|
||||
{
|
||||
Functions\when('get_post')->justReturn(null);
|
||||
|
||||
$change = new PostChangeResult('lit/content-create', Mockery::mock(ChangeLog::class), 5, 'der Entwurf');
|
||||
$change = new PostChangeResult('lit/content-create', FakeChangeLog::forbidden(), 5, 'der Entwurf');
|
||||
|
||||
self::assertNull($change->reread());
|
||||
self::assertNull($change->result('ok', null)->toArray()['rev']);
|
||||
|
||||
@@ -8,7 +8,7 @@ use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Integrations\WordPress\Render\PageRenderer;
|
||||
use LIT\MCP\Integrations\WordPress\Render\PageRenderSummaryAbility;
|
||||
use LIT\MCP\Integrations\WordPress\Render\RenderSummary;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use WP_Post;
|
||||
@@ -123,8 +123,7 @@ final class PageRenderSummaryAbilityTest extends TestCase
|
||||
Functions\when('get_post')->justReturn($post);
|
||||
Functions\when('current_user_can')->justReturn(true);
|
||||
Functions\when('get_permalink')->justReturn('https://k.test/start/');
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
$renderer = Mockery::mock(PageRenderer::class);
|
||||
$renderer->expects('render')->with($post)->andReturn(self::HTML);
|
||||
$ability = new PageRenderSummaryAbility($schema, $renderer);
|
||||
|
||||
@@ -9,9 +9,9 @@ use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\Rev;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Revisions\RevisionRestoreAbility;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use RuntimeException;
|
||||
use WP_Post;
|
||||
|
||||
@@ -38,8 +38,7 @@ final class RevisionRestoreAbilityTest extends TestCase
|
||||
|
||||
private function ability(ChangeLog $log): RevisionRestoreAbility
|
||||
{
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
|
||||
return new RevisionRestoreAbility($schema, $log);
|
||||
}
|
||||
@@ -51,14 +50,14 @@ final class RevisionRestoreAbilityTest extends TestCase
|
||||
|
||||
public function testNonRevisionIdIsNotFound(): void
|
||||
{
|
||||
self::assertSame('lit_not_found', $this->ability(Mockery::mock(ChangeLog::class))->permission(['revision_id' => 5])->get_error_code());
|
||||
self::assertSame('lit_not_found', $this->ability(FakeChangeLog::forbidden())->permission(['revision_id' => 5])->get_error_code());
|
||||
}
|
||||
|
||||
public function testRequiresConfirmation(): void
|
||||
{
|
||||
Functions\expect('wp_restore_post_revision')->never();
|
||||
|
||||
$result = $this->ability(Mockery::mock(ChangeLog::class))->execute(['revision_id' => 810]);
|
||||
$result = $this->ability(FakeChangeLog::forbidden())->execute(['revision_id' => 810]);
|
||||
|
||||
self::assertSame('lit_confirm_required', $result->get_error_code());
|
||||
}
|
||||
@@ -69,7 +68,7 @@ final class RevisionRestoreAbilityTest extends TestCase
|
||||
? new WP_Post(['ID' => 810, 'post_type' => 'revision', 'post_parent' => 0])
|
||||
: null);
|
||||
|
||||
$error = $this->ability(Mockery::mock(ChangeLog::class))
|
||||
$error = $this->ability(FakeChangeLog::forbidden())
|
||||
->permission(['revision_id' => 810, 'rev' => 'irrelevant', 'confirm' => true]);
|
||||
|
||||
self::assertSame('lit_validation_failed', $error->get_error_code());
|
||||
@@ -85,7 +84,7 @@ final class RevisionRestoreAbilityTest extends TestCase
|
||||
});
|
||||
Functions\expect('wp_restore_post_revision')->never();
|
||||
|
||||
$error = $this->ability(Mockery::mock(ChangeLog::class))->execute(['revision_id' => 810, 'rev' => 'x', 'confirm' => true]);
|
||||
$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']);
|
||||
@@ -105,7 +104,7 @@ final class RevisionRestoreAbilityTest extends TestCase
|
||||
Functions\expect('wp_save_post_revision')->never();
|
||||
Functions\expect('wp_restore_post_revision')->never();
|
||||
|
||||
$error = $this->ability(Mockery::mock(ChangeLog::class))->execute([
|
||||
$error = $this->ability(FakeChangeLog::forbidden())->execute([
|
||||
'revision_id' => 810,
|
||||
'rev' => Rev::ofPost(new WP_Post($current)),
|
||||
'confirm' => true,
|
||||
@@ -119,7 +118,7 @@ final class RevisionRestoreAbilityTest extends TestCase
|
||||
{
|
||||
Functions\expect('wp_restore_post_revision')->never();
|
||||
|
||||
$result = $this->ability(Mockery::mock(ChangeLog::class))
|
||||
$result = $this->ability(FakeChangeLog::forbidden())
|
||||
->execute(['revision_id' => 810, 'confirm' => true, 'rev' => 'stale']);
|
||||
|
||||
self::assertSame('lit_rev_mismatch', $result->get_error_code());
|
||||
@@ -139,8 +138,7 @@ final class RevisionRestoreAbilityTest extends TestCase
|
||||
});
|
||||
Functions\when('get_preview_post_link')->justReturn('https://kunde.de/team/');
|
||||
Functions\when('get_edit_post_link')->justReturn('https://kunde.de/wp-admin/post.php?post=5&action=edit');
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->with('lit/revision-restore', 'page', '5', Mockery::type('string'), 813)->andReturn(12);
|
||||
$log = new FakeChangeLog(12);
|
||||
|
||||
$result = $this->ability($log)->execute([
|
||||
'revision_id' => 810,
|
||||
@@ -154,6 +152,12 @@ final class RevisionRestoreAbilityTest extends TestCase
|
||||
self::assertStringContainsString('2026-09-20 10:00:00', $result['summary']);
|
||||
self::assertStringContainsString('Status unverändert: publish', $result['summary']);
|
||||
self::assertSame([], $result['warnings']);
|
||||
$log->assertRecorded([
|
||||
'ability' => 'lit/revision-restore',
|
||||
'object_type' => 'page',
|
||||
'object_id' => '5',
|
||||
'revision_id' => 813,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testRestoreFailureIsWriteFailed(): void
|
||||
@@ -161,8 +165,7 @@ final class RevisionRestoreAbilityTest extends TestCase
|
||||
Functions\when('wp_save_post_revision')->justReturn(813);
|
||||
Functions\when('wp_get_post_revisions')->justReturn([813 => new WP_Post(['ID' => 813])]);
|
||||
Functions\when('wp_restore_post_revision')->justReturn(false);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->never();
|
||||
$log = FakeChangeLog::forbidden();
|
||||
|
||||
$result = $this->ability($log)->execute([
|
||||
'revision_id' => 810,
|
||||
@@ -188,8 +191,7 @@ final class RevisionRestoreAbilityTest extends TestCase
|
||||
Actions\expectDone('lit_mcp_after_save')->once()->whenHappen(static function (): void {
|
||||
throw new RuntimeException('listener kaputt');
|
||||
});
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->andThrow(new RuntimeException('db weg'));
|
||||
$log = new FakeChangeLog(1, new RuntimeException('db weg'));
|
||||
$file = (string) tempnam(sys_get_temp_dir(), 'lit-mcp-log');
|
||||
$previous = ini_set('error_log', $file);
|
||||
|
||||
@@ -208,5 +210,6 @@ final class RevisionRestoreAbilityTest extends TestCase
|
||||
self::assertCount(2, $result['warnings']);
|
||||
self::assertStringContainsString('listener kaputt', (string) file_get_contents($file));
|
||||
unlink($file);
|
||||
$log->assertRecorded([]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,8 @@ use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\Cursor;
|
||||
use LIT\MCP\Integrations\WordPress\Content\PostPresenter;
|
||||
use LIT\MCP\Integrations\WordPress\Revisions\RevisionsListAbility;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use WP_Post;
|
||||
|
||||
final class RevisionsListAbilityTest extends TestCase
|
||||
@@ -27,8 +26,7 @@ final class RevisionsListAbilityTest extends TestCase
|
||||
|
||||
private function ability(): RevisionsListAbility
|
||||
{
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
|
||||
return new RevisionsListAbility($schema);
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@ namespace LIT\MCP\Tests\Unit\Integrations\WordPress\Settings;
|
||||
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Settings\SettingsWhitelist;
|
||||
use LIT\MCP\Integrations\WordPress\Settings\WpSettingsGetAbility;
|
||||
use LIT\MCP\Integrations\WordPress\Settings\WpSettingsUpdateAbility;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use RuntimeException;
|
||||
@@ -53,8 +53,7 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
{
|
||||
$options = ['blogname' => 'Alt', 'blogdescription' => 'Praxis'];
|
||||
$this->optionStore($options);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andReturn(40);
|
||||
$log = new FakeChangeLog(40);
|
||||
$ability = new WpSettingsUpdateAbility(new SettingsWhitelist(), $log);
|
||||
$input = ['settings' => ['blogname' => 'Müller & Söhne', 'blogdescription' => 'Zahnärzte']];
|
||||
|
||||
@@ -81,8 +80,7 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
{
|
||||
$options = ['blogname' => 'Alt'];
|
||||
$this->optionStore($options);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->andThrow(new RuntimeException('log kaputt'));
|
||||
$log = new FakeChangeLog(1, new RuntimeException('log kaputt'));
|
||||
$file = (string) tempnam(sys_get_temp_dir(), 'lit-mcp-log');
|
||||
$previous = ini_set('error_log', $file);
|
||||
|
||||
@@ -96,6 +94,7 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
self::assertTrue($result['ok']);
|
||||
self::assertNull($result['log_id']);
|
||||
self::assertCount(1, $result['warnings']);
|
||||
$log->assertRecorded([]);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
@@ -118,7 +117,7 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
{
|
||||
Functions\expect('update_option')->never();
|
||||
|
||||
$result = (new WpSettingsUpdateAbility(new SettingsWhitelist(), Mockery::mock(ChangeLog::class)))
|
||||
$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());
|
||||
@@ -129,7 +128,7 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
{
|
||||
Functions\expect('update_option')->never();
|
||||
|
||||
$result = (new WpSettingsUpdateAbility(new SettingsWhitelist(), Mockery::mock(ChangeLog::class)))
|
||||
$result = (new WpSettingsUpdateAbility(new SettingsWhitelist(), FakeChangeLog::forbidden()))
|
||||
->execute(['settings' => ['template' => 'twentyten']]);
|
||||
|
||||
self::assertSame('lit_validation_failed', $result->get_error_code());
|
||||
@@ -162,8 +161,7 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
});
|
||||
$GLOBALS['wp_rewrite'] = $rewrite;
|
||||
Functions\expect('flush_rewrite_rules')->once();
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->with('lit/wp-settings-update', 'option', 'blogname,permalink_structure', Mockery::type('string'))->andReturn(30);
|
||||
$log = new FakeChangeLog(30);
|
||||
|
||||
$result = (new WpSettingsUpdateAbility(new SettingsWhitelist(), $log))->execute(['settings' => [
|
||||
'blogname' => 'Neu',
|
||||
@@ -174,6 +172,11 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
self::assertSame(['blogname', 'permalink_structure'], array_column($result['changed'], 'id'));
|
||||
self::assertSame(['blogname' => 'Alt', 'blogdescription' => 'Gleich', 'permalink_structure' => ''], $result['previous']);
|
||||
self::assertSame(30, $result['log_id']);
|
||||
$log->assertRecorded([
|
||||
'ability' => 'lit/wp-settings-update',
|
||||
'object_type' => 'option',
|
||||
'object_id' => 'blogname,permalink_structure',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testDoesNotTreatAnAlreadyStoredValueAsAWriteFailure(): void
|
||||
@@ -190,8 +193,7 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
'WPLANG' => '',
|
||||
][$key]);
|
||||
Functions\expect('update_option')->once()->with('blogname', 'Neu')->andReturn(true);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->andReturn(31);
|
||||
$log = new FakeChangeLog(31);
|
||||
|
||||
$result = (new WpSettingsUpdateAbility(new SettingsWhitelist(), $log))->execute(['settings' => [
|
||||
'blogname' => 'Neu',
|
||||
@@ -200,6 +202,7 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
|
||||
self::assertSame(['blogname'], array_column($result['changed'], 'id'));
|
||||
self::assertSame(31, $result['log_id']);
|
||||
$log->assertRecorded([]);
|
||||
}
|
||||
|
||||
public function testRestoresPreviousValuesWhenAWriteFailsPartway(): void
|
||||
@@ -211,9 +214,7 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
Functions\expect('update_option')->once()->with('blogname', 'Neu')->andReturn(true);
|
||||
Functions\expect('update_option')->once()->with('blogdescription', 'Auch neu')->andReturn(false);
|
||||
Functions\expect('update_option')->once()->with('blogname', 'Alt')->andReturn(true);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->shouldNotReceive('record');
|
||||
$log->shouldNotReceive('recordPartial');
|
||||
$log = FakeChangeLog::forbidden();
|
||||
|
||||
$error = $this->failure(new WpSettingsUpdateAbility(new SettingsWhitelist(), $log), [
|
||||
'blogname' => 'Neu',
|
||||
@@ -221,6 +222,8 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
]);
|
||||
|
||||
self::assertSame('lit_write_failed', $error->get_error_code());
|
||||
$log->assertRecorded();
|
||||
$log->assertPartials();
|
||||
}
|
||||
|
||||
public function testReportsPartialWriteWhenRestoringAlsoFails(): void
|
||||
@@ -242,9 +245,7 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
});
|
||||
Functions\expect('update_option')->once()->with('blogdescription', 'Auch neu')->andReturn(false);
|
||||
Functions\expect('update_option')->once()->with('blogname', 'Alt')->andReturn(false);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->shouldNotReceive('record');
|
||||
$log->expects('recordPartial')->with('lit/wp-settings-update', 'option', 'blogname', Mockery::type('string'));
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
|
||||
$error = $this->failure(new WpSettingsUpdateAbility(new SettingsWhitelist(), $log), [
|
||||
'blogname' => 'Neu',
|
||||
@@ -254,6 +255,11 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
self::assertSame('lit_partial_write', $error->get_error_code());
|
||||
self::assertStringContainsString('blogname', $error->get_error_message());
|
||||
self::assertStringContainsString('lit/wp-settings-get', $error->get_error_data()['hint']);
|
||||
$log->assertPartials([
|
||||
'ability' => 'lit/wp-settings-update',
|
||||
'object_type' => 'option',
|
||||
'object_id' => 'blogname',
|
||||
]);
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $settings */
|
||||
@@ -275,7 +281,7 @@ final class WpSettingsAbilitiesTest extends TestCase
|
||||
self::assertSame('lit_forbidden', (new WpSettingsGetAbility(new SettingsWhitelist()))->permission([])->get_error_code());
|
||||
self::assertSame(
|
||||
'lit_forbidden',
|
||||
(new WpSettingsUpdateAbility(new SettingsWhitelist(), Mockery::mock(ChangeLog::class)))->permission([])->get_error_code()
|
||||
(new WpSettingsUpdateAbility(new SettingsWhitelist(), FakeChangeLog::forbidden()))->permission([])->get_error_code()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,10 @@ use Brain\Monkey\Actions;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\Rev;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Integrations\WordPress\Status\PostCloner;
|
||||
use LIT\MCP\Integrations\WordPress\Status\PostDuplicateAbility;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use WP_Post;
|
||||
@@ -34,8 +35,7 @@ final class PostDuplicateAbilityTest extends TestCase
|
||||
|
||||
private function ability(PostCloner $cloner, ChangeLog $log): PostDuplicateAbility
|
||||
{
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
|
||||
return new PostDuplicateAbility($schema, $cloner, $log);
|
||||
}
|
||||
@@ -45,8 +45,7 @@ final class PostDuplicateAbilityTest extends TestCase
|
||||
$cloner = Mockery::mock(PostCloner::class);
|
||||
$cloner->expects('duplicate')->with($this->original)->andReturn(77);
|
||||
Actions\expectDone('lit_mcp_after_save')->once()->with(77, 'lit/post-duplicate', ['post_id' => 5]);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->with('lit/post-duplicate', 'page', '77', 'Kopie von "Team" (ID 5) angelegt', null)->andReturn(8);
|
||||
$log = new FakeChangeLog(8);
|
||||
|
||||
$result = $this->ability($cloner, $log)->execute(['post_id' => 5]);
|
||||
|
||||
@@ -55,6 +54,13 @@ final class PostDuplicateAbilityTest extends TestCase
|
||||
self::assertSame(8, $result['log_id']);
|
||||
self::assertSame(Rev::ofPost($this->copy), $result['rev']);
|
||||
self::assertSame([], $result['warnings']);
|
||||
$log->assertRecorded([
|
||||
'ability' => 'lit/post-duplicate',
|
||||
'object_type' => 'page',
|
||||
'object_id' => '77',
|
||||
'summary' => 'Kopie von "Team" (ID 5) angelegt',
|
||||
'revision_id' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testNeedsTheRightToCreateEntriesOfThatType(): void
|
||||
@@ -63,7 +69,7 @@ final class PostDuplicateAbilityTest extends TestCase
|
||||
$cloner = Mockery::mock(PostCloner::class);
|
||||
$cloner->expects('duplicate')->never();
|
||||
|
||||
$result = $this->ability($cloner, Mockery::mock(ChangeLog::class))->execute(['post_id' => 5]);
|
||||
$result = $this->ability($cloner, FakeChangeLog::forbidden())->execute(['post_id' => 5]);
|
||||
|
||||
self::assertSame('lit_forbidden', $result->get_error_code());
|
||||
}
|
||||
@@ -74,14 +80,14 @@ final class PostDuplicateAbilityTest extends TestCase
|
||||
$cloner = Mockery::mock(PostCloner::class);
|
||||
$cloner->expects('duplicate')->never();
|
||||
|
||||
$result = $this->ability($cloner, Mockery::mock(ChangeLog::class))->execute(['post_id' => 5]);
|
||||
$result = $this->ability($cloner, FakeChangeLog::forbidden())->execute(['post_id' => 5]);
|
||||
|
||||
self::assertSame('lit_validation_failed', $result->get_error_code());
|
||||
}
|
||||
|
||||
public function testIsIndirectAndNotIdempotent(): void
|
||||
{
|
||||
$ability = $this->ability(Mockery::mock(PostCloner::class), Mockery::mock(ChangeLog::class));
|
||||
$ability = $this->ability(Mockery::mock(PostCloner::class), FakeChangeLog::forbidden());
|
||||
|
||||
self::assertFalse($ability->isDirect());
|
||||
self::assertFalse($ability->annotations()['idempotent']);
|
||||
|
||||
@@ -7,10 +7,10 @@ namespace LIT\MCP\Tests\Unit\Integrations\WordPress\Status;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Integrations\WordPress\Status\PostPublishAbility;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use RuntimeException;
|
||||
use WP_Post;
|
||||
|
||||
@@ -18,8 +18,7 @@ final class PostPublishAbilityTest extends TestCase
|
||||
{
|
||||
private function ability(ChangeLog $log): PostPublishAbility
|
||||
{
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
|
||||
return new PostPublishAbility($schema, $log);
|
||||
}
|
||||
@@ -37,14 +36,20 @@ final class PostPublishAbilityTest extends TestCase
|
||||
$this->stubPost(['post_status' => 'draft', 'post_date_gmt' => '0000-00-00 00:00:00']);
|
||||
Functions\expect('wp_update_post')->once()->with(['ID' => 5, 'post_status' => 'publish'], true)->andReturn(5);
|
||||
Functions\when('get_post_status')->justReturn('publish');
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->with('lit/post-publish', 'page', '5', '"Team" veröffentlicht', null)->andReturn(9);
|
||||
$log = new FakeChangeLog(9);
|
||||
|
||||
$result = $this->ability($log)->execute(['post_id' => 5]);
|
||||
|
||||
self::assertSame('published', $result['changed'][0]['action']);
|
||||
self::assertSame(9, $result['log_id']);
|
||||
self::assertSame('https://kunde.de/team/', $result['preview_url']);
|
||||
$log->assertRecorded([
|
||||
'ability' => 'lit/post-publish',
|
||||
'object_type' => 'page',
|
||||
'object_id' => '5',
|
||||
'summary' => '"Team" veröffentlicht',
|
||||
'revision_id' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testScheduledPostIsPublishedNowInsteadOfStayingFuture(): void
|
||||
@@ -59,8 +64,7 @@ final class PostPublishAbilityTest extends TestCase
|
||||
'edit_date' => true,
|
||||
], true)->andReturn(5);
|
||||
Functions\when('get_post_status')->justReturn('publish');
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andReturn(1);
|
||||
$log = new FakeChangeLog(1);
|
||||
|
||||
$this->ability($log)->execute(['post_id' => 5]);
|
||||
}
|
||||
@@ -70,7 +74,7 @@ final class PostPublishAbilityTest extends TestCase
|
||||
$this->stubPost(['post_status' => 'publish']);
|
||||
Functions\expect('wp_update_post')->never();
|
||||
|
||||
$result = $this->ability(Mockery::mock(ChangeLog::class))->execute(['post_id' => 5]);
|
||||
$result = $this->ability(FakeChangeLog::forbidden())->execute(['post_id' => 5]);
|
||||
|
||||
self::assertSame([], $result['changed']);
|
||||
self::assertStringContainsString('bereits veröffentlicht', $result['summary']);
|
||||
@@ -82,8 +86,7 @@ final class PostPublishAbilityTest extends TestCase
|
||||
Functions\when('wp_update_post')->alias(static function (): void {
|
||||
throw new RuntimeException('save_post-Hook kaputt');
|
||||
});
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial')->with('lit/post-publish', 'page', '5', Mockery::type('string'));
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
|
||||
try {
|
||||
$this->ability($log)->execute(['post_id' => 5]);
|
||||
@@ -94,6 +97,7 @@ final class PostPublishAbilityTest extends TestCase
|
||||
self::assertStringContainsString('save_post-Hook kaputt', $e->getMessage());
|
||||
self::assertSame('lit_partial_write', $e->toError()->get_error_code());
|
||||
}
|
||||
$log->assertPartials(['ability' => 'lit/post-publish', 'object_type' => 'page', 'object_id' => '5']);
|
||||
}
|
||||
|
||||
public function testATrashedPostIsRefused(): void
|
||||
@@ -101,7 +105,7 @@ final class PostPublishAbilityTest extends TestCase
|
||||
$this->stubPost(['post_status' => 'trash']);
|
||||
Functions\expect('wp_update_post')->never();
|
||||
|
||||
$result = $this->ability(Mockery::mock(ChangeLog::class))->execute(['post_id' => 5]);
|
||||
$result = $this->ability(FakeChangeLog::forbidden())->execute(['post_id' => 5]);
|
||||
|
||||
self::assertSame('lit_validation_failed', $result->get_error_code());
|
||||
}
|
||||
@@ -111,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(Mockery::mock(ChangeLog::class))->permission(['post_id' => 5])->get_error_code());
|
||||
self::assertSame('lit_forbidden', $this->ability(FakeChangeLog::forbidden())->permission(['post_id' => 5])->get_error_code());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,11 @@ use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\Rev;
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Integrations\WordPress\Status\PostCloner;
|
||||
use LIT\MCP\Integrations\WordPress\Status\PostReplaceWithCopyAbility;
|
||||
use LIT\MCP\Integrations\WordPress\Status\ReplaceFailed;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use RuntimeException;
|
||||
@@ -39,8 +40,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
|
||||
private function ability(PostCloner $cloner, ChangeLog $log, bool $trash = true): PostReplaceWithCopyAbility
|
||||
{
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
|
||||
return new PostReplaceWithCopyAbility($schema, $cloner, $log, static fn (): bool => $trash);
|
||||
}
|
||||
@@ -65,7 +65,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
$cloner = Mockery::mock(PostCloner::class);
|
||||
$cloner->expects('replace')->never();
|
||||
|
||||
$result = $this->ability($cloner, Mockery::mock(ChangeLog::class))
|
||||
$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());
|
||||
@@ -77,7 +77,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
$cloner = Mockery::mock(PostCloner::class);
|
||||
$cloner->expects('replace')->never();
|
||||
|
||||
$result = $this->ability($cloner, Mockery::mock(ChangeLog::class))->execute($this->input());
|
||||
$result = $this->ability($cloner, FakeChangeLog::forbidden())->execute($this->input());
|
||||
|
||||
self::assertSame('lit_validation_failed', $result->get_error_code());
|
||||
}
|
||||
@@ -101,7 +101,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
$cloner->expects('backup')->never();
|
||||
$cloner->expects('replace')->never();
|
||||
|
||||
$result = $this->ability($cloner, Mockery::mock(ChangeLog::class))->execute($this->input());
|
||||
$result = $this->ability($cloner, FakeChangeLog::forbidden())->execute($this->input());
|
||||
|
||||
self::assertSame('lit_validation_failed', $result->get_error_code());
|
||||
}
|
||||
@@ -114,7 +114,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
$cloner->expects('backup')->never();
|
||||
$cloner->expects('replace')->never();
|
||||
|
||||
$result = $this->ability($cloner, Mockery::mock(ChangeLog::class))->execute($this->input());
|
||||
$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']);
|
||||
@@ -129,8 +129,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
$cloner->allows('backup')->andReturn(88);
|
||||
$cloner->expects('replace');
|
||||
Functions\when('wp_trash_post')->justReturn(new WP_Post(['ID' => 77]));
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andReturn(11);
|
||||
$log = new FakeChangeLog(11);
|
||||
|
||||
self::assertTrue($this->ability($cloner, $log)->execute($this->input())['ok']);
|
||||
}
|
||||
@@ -141,7 +140,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
$cloner->expects('replace')->never();
|
||||
Functions\expect('wp_save_post_revision')->never();
|
||||
|
||||
$result = $this->ability($cloner, Mockery::mock(ChangeLog::class))->execute($this->input(['rev' => 'veraltet']));
|
||||
$result = $this->ability($cloner, FakeChangeLog::forbidden())->execute($this->input(['rev' => 'veraltet']));
|
||||
|
||||
self::assertSame('lit_rev_mismatch', $result->get_error_code());
|
||||
}
|
||||
@@ -151,7 +150,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
$cloner = Mockery::mock(PostCloner::class);
|
||||
$cloner->expects('replace')->never();
|
||||
|
||||
$result = $this->ability($cloner, Mockery::mock(ChangeLog::class), false)->execute($this->input());
|
||||
$result = $this->ability($cloner, FakeChangeLog::forbidden(), false)->execute($this->input());
|
||||
|
||||
self::assertSame('lit_unsupported', $result->get_error_code());
|
||||
}
|
||||
@@ -181,8 +180,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
$order[] = 'trash';
|
||||
return new WP_Post(['ID' => 77]);
|
||||
});
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->with('lit/post-replace-with-copy', 'page', '5', Mockery::type('string'), 900)->andReturn(11);
|
||||
$log = new FakeChangeLog(11);
|
||||
|
||||
$result = $this->ability($cloner, $log)->execute($this->input());
|
||||
|
||||
@@ -194,6 +192,12 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
self::assertSame(Rev::ofPost($this->original), $result['rev']);
|
||||
self::assertSame(['replaced', 'trashed'], array_column($result['changed'], 'action'));
|
||||
self::assertSame([], $result['warnings']);
|
||||
$log->assertRecorded([
|
||||
'ability' => 'lit/post-replace-with-copy',
|
||||
'object_type' => 'page',
|
||||
'object_id' => '5',
|
||||
'revision_id' => 900,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testAFailedTrashOfTheCopyIsAWarningOnly(): void
|
||||
@@ -204,8 +208,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
$cloner->allows('backup')->andReturn(88);
|
||||
$cloner->expects('replace');
|
||||
Functions\when('wp_trash_post')->justReturn(false);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andReturn(11);
|
||||
$log = new FakeChangeLog(11);
|
||||
|
||||
$result = $this->ability($cloner, $log)->execute($this->input());
|
||||
|
||||
@@ -225,7 +228,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
Functions\expect('wp_trash_post')->never();
|
||||
|
||||
try {
|
||||
$this->ability($cloner, Mockery::mock(ChangeLog::class))->execute($this->input());
|
||||
$this->ability($cloner, FakeChangeLog::forbidden())->execute($this->input());
|
||||
self::fail('WriteFailed expected');
|
||||
} catch (WriteFailed $e) {
|
||||
self::assertTrue($e->rolledBack);
|
||||
@@ -246,10 +249,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
$cloner->expects('replace')->andThrow(new RuntimeException('hook kaputt'));
|
||||
$cloner->expects('restore')->with($this->original, self::SNAPSHOT, PostCloner::PARTS)->andThrow(new RuntimeException('Restore incomplete: terms'));
|
||||
Functions\expect('wp_trash_post')->never();
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial')
|
||||
->with('lit/post-replace-with-copy', 'page', '5', Mockery::type('string'), 900)
|
||||
->andReturn(12);
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
|
||||
try {
|
||||
$this->ability($cloner, $log)->execute($this->input());
|
||||
@@ -264,6 +264,12 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
self::assertStringContainsString('Sicherung', $error->get_error_message());
|
||||
self::assertStringContainsString('88', $error->get_error_message());
|
||||
}
|
||||
$log->assertPartials([
|
||||
'ability' => 'lit/post-replace-with-copy',
|
||||
'object_type' => 'page',
|
||||
'object_id' => '5',
|
||||
'revision_id' => 900,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testNeedsTheRightToCreateEntriesForTheBackup(): void
|
||||
@@ -272,7 +278,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
$cloner = Mockery::mock(PostCloner::class);
|
||||
$cloner->expects('backup')->never();
|
||||
$cloner->expects('replace')->never();
|
||||
$ability = $this->ability($cloner, Mockery::mock(ChangeLog::class));
|
||||
$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());
|
||||
@@ -289,7 +295,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
Functions\expect('wp_trash_post')->never();
|
||||
|
||||
try {
|
||||
$this->ability($cloner, Mockery::mock(ChangeLog::class))->execute($this->input());
|
||||
$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());
|
||||
@@ -298,7 +304,7 @@ final class PostReplaceWithCopyAbilityTest extends TestCase
|
||||
|
||||
public function testRequiresRevAndIsDestructive(): void
|
||||
{
|
||||
$ability = $this->ability(Mockery::mock(PostCloner::class), Mockery::mock(ChangeLog::class));
|
||||
$ability = $this->ability(Mockery::mock(PostCloner::class), FakeChangeLog::forbidden());
|
||||
|
||||
self::assertContains('rev', $ability->inputSchema()['required']);
|
||||
self::assertContains('backup_id', $ability->outputSchema()['required']);
|
||||
|
||||
@@ -8,10 +8,10 @@ use Brain\Monkey\Functions;
|
||||
use DateTimeZone;
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Integrations\WordPress\Status\PostScheduleAbility;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use RuntimeException;
|
||||
use WP_Post;
|
||||
|
||||
@@ -29,8 +29,7 @@ final class PostScheduleAbilityTest extends TestCase
|
||||
|
||||
private function ability(ChangeLog $log): PostScheduleAbility
|
||||
{
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
|
||||
return new PostScheduleAbility($schema, $log);
|
||||
}
|
||||
@@ -45,13 +44,13 @@ final class PostScheduleAbilityTest extends TestCase
|
||||
'edit_date' => true,
|
||||
], true)->andReturn(5);
|
||||
Functions\when('get_post_status')->justReturn('future');
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->andReturn(4);
|
||||
$log = new FakeChangeLog(4);
|
||||
|
||||
$result = $this->ability($log)->execute(['post_id' => 5, 'date' => '2099-06-01 09:30']);
|
||||
|
||||
self::assertSame('scheduled', $result['changed'][0]['action']);
|
||||
self::assertStringContainsString('2099-06-01 09:30', $result['summary']);
|
||||
$log->assertRecorded([]);
|
||||
}
|
||||
|
||||
public function testWarnsThatAPrivatePostBecomesPublic(): void
|
||||
@@ -59,8 +58,7 @@ final class PostScheduleAbilityTest extends TestCase
|
||||
Functions\when('get_post')->justReturn(new WP_Post(['ID' => 5, 'post_type' => 'post', 'post_title' => 'Intern', 'post_status' => 'private']));
|
||||
Functions\when('wp_update_post')->justReturn(5);
|
||||
Functions\when('get_post_status')->justReturn('future');
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andReturn(4);
|
||||
$log = new FakeChangeLog(4);
|
||||
|
||||
$result = $this->ability($log)->execute(['post_id' => 5, 'date' => '2099-06-01 09:30']);
|
||||
|
||||
@@ -73,8 +71,7 @@ final class PostScheduleAbilityTest extends TestCase
|
||||
{
|
||||
Functions\when('wp_update_post')->justReturn(5);
|
||||
Functions\when('get_post_status')->justReturn('future');
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andReturn(4);
|
||||
$log = new FakeChangeLog(4);
|
||||
|
||||
$result = $this->ability($log)->execute(['post_id' => 5, 'date' => '2099-06-01 09:30']);
|
||||
|
||||
@@ -86,8 +83,7 @@ final class PostScheduleAbilityTest extends TestCase
|
||||
Functions\when('wp_update_post')->alias(static function (): void {
|
||||
throw new RuntimeException('save_post-Hook kaputt');
|
||||
});
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial')->with('lit/post-schedule', 'post', '5', Mockery::type('string'));
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
|
||||
try {
|
||||
$this->ability($log)->execute(['post_id' => 5, 'date' => '2099-06-01 09:30']);
|
||||
@@ -98,6 +94,7 @@ final class PostScheduleAbilityTest extends TestCase
|
||||
self::assertStringContainsString('save_post-Hook kaputt', $e->getMessage());
|
||||
self::assertSame('lit_partial_write', $e->toError()->get_error_code());
|
||||
}
|
||||
$log->assertPartials(['ability' => 'lit/post-schedule', 'object_type' => 'post', 'object_id' => '5']);
|
||||
}
|
||||
|
||||
public function testATrashedPostIsRefused(): void
|
||||
@@ -105,7 +102,7 @@ final class PostScheduleAbilityTest extends TestCase
|
||||
Functions\when('get_post')->justReturn(new WP_Post(['ID' => 5, 'post_type' => 'post', 'post_status' => 'trash']));
|
||||
Functions\expect('wp_update_post')->never();
|
||||
|
||||
$result = $this->ability(Mockery::mock(ChangeLog::class))->execute(['post_id' => 5, 'date' => '2099-06-01 09:30']);
|
||||
$result = $this->ability(FakeChangeLog::forbidden())->execute(['post_id' => 5, 'date' => '2099-06-01 09:30']);
|
||||
|
||||
self::assertSame('lit_validation_failed', $result->get_error_code());
|
||||
}
|
||||
@@ -113,7 +110,7 @@ final class PostScheduleAbilityTest extends TestCase
|
||||
public function testPastAndImpossibleDatesAreRejected(): void
|
||||
{
|
||||
Functions\expect('wp_update_post')->never();
|
||||
$ability = $this->ability(Mockery::mock(ChangeLog::class));
|
||||
$ability = $this->ability(FakeChangeLog::forbidden());
|
||||
|
||||
$past = $ability->execute(['post_id' => 5, 'date' => '2020-01-01 10:00']);
|
||||
$impossible = $ability->execute(['post_id' => 5, 'date' => '2099-13-45 10:00']);
|
||||
@@ -131,7 +128,7 @@ final class PostScheduleAbilityTest extends TestCase
|
||||
->setTimezone(new DateTimeZone('Europe/Berlin'));
|
||||
Functions\when('get_post_status')->justReturn('future');
|
||||
|
||||
$result = $this->ability(Mockery::mock(ChangeLog::class))
|
||||
$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());
|
||||
|
||||
@@ -7,10 +7,10 @@ namespace LIT\MCP\Tests\Unit\Integrations\WordPress\Status;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Integrations\WordPress\Status\PostTrashAbility;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use RuntimeException;
|
||||
use WP_Post;
|
||||
|
||||
@@ -33,8 +33,7 @@ final class PostTrashAbilityTest extends TestCase
|
||||
{
|
||||
Functions\when('get_post')->justReturn(new WP_Post(['ID' => 5, 'post_type' => 'page', 'post_title' => 'Alt', 'post_status' => 'publish']));
|
||||
Functions\when('current_user_can')->justReturn(true);
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
|
||||
return new PostTrashAbility($schema, $log);
|
||||
}
|
||||
@@ -43,7 +42,7 @@ final class PostTrashAbilityTest extends TestCase
|
||||
{
|
||||
Functions\expect('wp_trash_post')->never();
|
||||
|
||||
$result = $this->ability(Mockery::mock(ChangeLog::class))->execute(['post_id' => 5]);
|
||||
$result = $this->ability(FakeChangeLog::forbidden())->execute(['post_id' => 5]);
|
||||
|
||||
self::assertSame('lit_confirm_required', $result->get_error_code());
|
||||
}
|
||||
@@ -52,13 +51,19 @@ final class PostTrashAbilityTest extends TestCase
|
||||
{
|
||||
Functions\expect('wp_trash_post')->once()->with(5)->andReturn(new WP_Post(['ID' => 5]));
|
||||
Functions\expect('wp_delete_post')->never();
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->with('lit/post-trash', 'page', '5', '"Alt" in den Papierkorb gelegt', null)->andReturn(2);
|
||||
$log = new FakeChangeLog(2);
|
||||
|
||||
$result = $this->ability($log)->execute(['post_id' => 5, 'confirm' => true]);
|
||||
|
||||
self::assertSame('trashed', $result['changed'][0]['action']);
|
||||
self::assertStringContainsString('Papierkorb', $result['summary']);
|
||||
$log->assertRecorded([
|
||||
'ability' => 'lit/post-trash',
|
||||
'object_type' => 'page',
|
||||
'object_id' => '5',
|
||||
'summary' => '"Alt" in den Papierkorb gelegt',
|
||||
'revision_id' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testRefusesWhenTheTrashIsDisabledInsteadOfDeleting(): void
|
||||
@@ -66,9 +71,8 @@ final class PostTrashAbilityTest extends TestCase
|
||||
Functions\when('get_post')->justReturn(new WP_Post(['ID' => 5, 'post_type' => 'page', 'post_status' => 'publish']));
|
||||
Functions\when('current_user_can')->justReturn(true);
|
||||
Functions\expect('wp_trash_post')->never();
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$ability = new PostTrashAbility($schema, Mockery::mock(ChangeLog::class), static fn (): bool => false);
|
||||
$schema = SchemaFixture::managed();
|
||||
$ability = new PostTrashAbility($schema, FakeChangeLog::forbidden(), static fn (): bool => false);
|
||||
|
||||
$result = $ability->execute(['post_id' => 5, 'confirm' => true]);
|
||||
|
||||
@@ -80,8 +84,7 @@ final class PostTrashAbilityTest extends TestCase
|
||||
Functions\when('wp_trash_post')->alias(static function (): void {
|
||||
throw new RuntimeException('save_post-Hook kaputt');
|
||||
});
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial')->with('lit/post-trash', 'page', '5', Mockery::type('string'));
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
|
||||
try {
|
||||
$this->ability($log)->execute(['post_id' => 5, 'confirm' => true]);
|
||||
@@ -92,11 +95,12 @@ final class PostTrashAbilityTest extends TestCase
|
||||
self::assertStringContainsString('save_post-Hook kaputt', $e->getMessage());
|
||||
self::assertSame('lit_partial_write', $e->toError()->get_error_code());
|
||||
}
|
||||
$log->assertPartials(['ability' => 'lit/post-trash', 'object_type' => 'page', 'object_id' => '5']);
|
||||
}
|
||||
|
||||
public function testAnAlreadyTrashedPostIsANoOp(): void
|
||||
{
|
||||
$ability = $this->ability(Mockery::mock(ChangeLog::class));
|
||||
$ability = $this->ability(FakeChangeLog::forbidden());
|
||||
Functions\when('get_post')->justReturn(new WP_Post(['ID' => 5, 'post_type' => 'page', 'post_title' => 'Alt', 'post_status' => 'trash']));
|
||||
Functions\expect('wp_trash_post')->never();
|
||||
|
||||
@@ -110,8 +114,7 @@ final class PostTrashAbilityTest extends TestCase
|
||||
{
|
||||
$this->options(['show_on_front' => 'page', 'page_on_front' => '5', 'page_for_posts' => '9']);
|
||||
Functions\when('wp_trash_post')->justReturn(new WP_Post(['ID' => 5]));
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andReturn(3);
|
||||
$log = new FakeChangeLog(3);
|
||||
$ability = $this->ability($log);
|
||||
|
||||
$confirm = $ability->execute(['post_id' => 5]);
|
||||
@@ -141,8 +144,7 @@ final class PostTrashAbilityTest extends TestCase
|
||||
: []
|
||||
);
|
||||
Functions\when('wp_trash_post')->justReturn(new WP_Post(['ID' => 5]));
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->allows('record')->andReturn(3);
|
||||
$log = new FakeChangeLog(3);
|
||||
|
||||
$result = $this->ability($log)->execute(['post_id' => 5, 'confirm' => true]);
|
||||
|
||||
@@ -153,7 +155,7 @@ final class PostTrashAbilityTest extends TestCase
|
||||
|
||||
public function testIsDestructiveAndIndirect(): void
|
||||
{
|
||||
$ability = $this->ability(Mockery::mock(ChangeLog::class));
|
||||
$ability = $this->ability(FakeChangeLog::forbidden());
|
||||
|
||||
self::assertTrue($ability->annotations()['destructive']);
|
||||
self::assertFalse($ability->isDirect());
|
||||
|
||||
@@ -7,10 +7,10 @@ namespace LIT\MCP\Tests\Unit\Integrations\WordPress\Status;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\Abilities\WriteFailed;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Integrations\WordPress\Status\PostUnpublishAbility;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use RuntimeException;
|
||||
use WP_Post;
|
||||
|
||||
@@ -22,8 +22,7 @@ final class PostUnpublishAbilityTest extends TestCase
|
||||
Functions\when('current_user_can')->justReturn(true);
|
||||
Functions\when('get_preview_post_link')->justReturn('https://kunde.de/?p=5&preview=true');
|
||||
Functions\when('get_edit_post_link')->justReturn('https://kunde.de/wp-admin/post.php?post=5&action=edit');
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
|
||||
return new PostUnpublishAbility($schema, $log);
|
||||
}
|
||||
@@ -31,12 +30,12 @@ final class PostUnpublishAbilityTest extends TestCase
|
||||
public function testPublishedPostBecomesDraft(): void
|
||||
{
|
||||
Functions\expect('wp_update_post')->once()->with(['ID' => 5, 'post_status' => 'draft'], true)->andReturn(5);
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('record')->andReturn(3);
|
||||
$log = new FakeChangeLog(3);
|
||||
|
||||
$result = $this->ability($log, 'publish')->execute(['post_id' => 5]);
|
||||
|
||||
self::assertSame('unpublished', $result['changed'][0]['action']);
|
||||
$log->assertRecorded([]);
|
||||
}
|
||||
|
||||
public function testAHookThrowingDuringTheWriteIsAPartialWrite(): void
|
||||
@@ -44,8 +43,7 @@ final class PostUnpublishAbilityTest extends TestCase
|
||||
Functions\when('wp_update_post')->alias(static function (): void {
|
||||
throw new RuntimeException('save_post-Hook kaputt');
|
||||
});
|
||||
$log = Mockery::mock(ChangeLog::class);
|
||||
$log->expects('recordPartial')->with('lit/post-unpublish', 'page', '5', Mockery::type('string'));
|
||||
$log = FakeChangeLog::partialsOnly();
|
||||
|
||||
try {
|
||||
$this->ability($log, 'publish')->execute(['post_id' => 5]);
|
||||
@@ -56,13 +54,14 @@ final class PostUnpublishAbilityTest extends TestCase
|
||||
self::assertStringContainsString('save_post-Hook kaputt', $e->getMessage());
|
||||
self::assertSame('lit_partial_write', $e->toError()->get_error_code());
|
||||
}
|
||||
$log->assertPartials(['ability' => 'lit/post-unpublish', 'object_type' => 'page', 'object_id' => '5']);
|
||||
}
|
||||
|
||||
public function testATrashedPostIsRefusedInsteadOfBecomingADraft(): void
|
||||
{
|
||||
Functions\expect('wp_update_post')->never();
|
||||
|
||||
$result = $this->ability(Mockery::mock(ChangeLog::class), 'trash')->execute(['post_id' => 5]);
|
||||
$result = $this->ability(FakeChangeLog::forbidden(), 'trash')->execute(['post_id' => 5]);
|
||||
|
||||
self::assertSame('lit_validation_failed', $result->get_error_code());
|
||||
}
|
||||
@@ -71,7 +70,7 @@ final class PostUnpublishAbilityTest extends TestCase
|
||||
{
|
||||
Functions\expect('wp_update_post')->never();
|
||||
|
||||
$result = $this->ability(Mockery::mock(ChangeLog::class), 'draft')->execute(['post_id' => 5]);
|
||||
$result = $this->ability(FakeChangeLog::forbidden(), 'draft')->execute(['post_id' => 5]);
|
||||
|
||||
self::assertSame([], $result['changed']);
|
||||
}
|
||||
|
||||
@@ -6,10 +6,11 @@ namespace LIT\MCP\Tests\Unit\Integrations\WordPress;
|
||||
|
||||
use LIT\MCP\Abilities\Ability;
|
||||
use Brain\Monkey\Functions;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Integrations\WordPress\Content\ContentComposer;
|
||||
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
||||
use LIT\MCP\Integrations\WordPress\WordPressIntegration;
|
||||
use LIT\MCP\Tests\Support\FakeChangeLog;
|
||||
use LIT\MCP\Tests\Support\SchemaFixture;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
|
||||
@@ -42,7 +43,7 @@ final class WordPressIntegrationTest extends TestCase
|
||||
|
||||
public function testProvidesTheWordPressAbilitiesInOrder(): void
|
||||
{
|
||||
$integration = new WordPressIntegration(Mockery::mock(ContentSchema::class), Mockery::mock(ChangeLog::class));
|
||||
$integration = new WordPressIntegration(Mockery::mock(ContentSchema::class), FakeChangeLog::forbidden());
|
||||
|
||||
self::assertSame('wordpress', $integration->id());
|
||||
self::assertTrue($integration->isAvailable());
|
||||
@@ -54,7 +55,7 @@ final class WordPressIntegrationTest extends TestCase
|
||||
|
||||
public function testEveryAbilityHasAnObjectInputSchemaThatRejectsUnknownKeys(): void
|
||||
{
|
||||
$integration = new WordPressIntegration(Mockery::mock(ContentSchema::class), Mockery::mock(ChangeLog::class));
|
||||
$integration = new WordPressIntegration(Mockery::mock(ContentSchema::class), FakeChangeLog::forbidden());
|
||||
|
||||
foreach ($integration->abilities() as $ability) {
|
||||
$schema = $ability->inputSchema();
|
||||
@@ -68,11 +69,10 @@ final class WordPressIntegrationTest extends TestCase
|
||||
{
|
||||
Functions\when('get_post_type_object')->justReturn((object) ['cap' => (object) ['create_posts' => 'edit_pages']]);
|
||||
Functions\when('current_user_can')->justReturn(true);
|
||||
$schema = Mockery::mock(ContentSchema::class);
|
||||
$schema->allows('isManaged')->andReturn(true);
|
||||
$schema = SchemaFixture::managed();
|
||||
$composer = Mockery::mock(ContentComposer::class);
|
||||
$composer->expects('available')->andReturn(false);
|
||||
$integration = new WordPressIntegration($schema, Mockery::mock(ChangeLog::class), $composer);
|
||||
$integration = new WordPressIntegration($schema, FakeChangeLog::forbidden(), $composer);
|
||||
|
||||
$create = array_values(array_filter(
|
||||
$integration->abilities(),
|
||||
|
||||
Reference in New Issue
Block a user