activitypub-1.0.x-dev/tests/src/Functional/OutboxTest.php
tests/src/Functional/OutboxTest.php
<?php
namespace Drupal\Tests\activitypub\Functional;
use Drupal\activitypub\Entity\ActivityPubActivityInterface;
use Drupal\Core\Url;
/**
* Tests Outbox functionality.
*
* @group activitypub
*/
class OutboxTest extends ActivityPubTestBase {
/**
* Test outbox responses.
*/
public function testOutboxResponse() {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
$this->enableActivityPub($assert_session);
$this->drupalLogout();
$outbox = Url::fromRoute('activitypub.outbox', ['user' => $this->authenticatedUserOne->id(), 'activitypub_actor' => $this->accountNameOne], ['absolute' => TRUE])->toString();
$this->drupalGet($outbox);
$assert_session->statusCodeEquals(200);
$content = json_decode($page->getContent());
self::assertEquals("OrderedCollection", $content->type);
$first_page = $content->first;
$this->drupalGet($content->first);
$assert_session->statusCodeEquals(200);
$content = json_decode($page->getContent());
self::assertEquals($first_page, $content->id);
// Create type.
$this->createType('Create', 'page', 'Note');
// Send to outbox.
$this->drupalLogin($this->authenticatedUserOne);
$this->drupalGet('node/add/page');
$assert_session->statusCodeEquals(200);
$assert_session->pageTextContains('ActivityPub outbox');
$edit = [
'title[0][value]' => 'Page one',
'body[0][value]' => 'Hello world!',
'activitypub_create' => 'map',
];
$this->submitForm($edit, 'Save');
$assert_session->addressEquals('node/1');
$this->drupalGet('node/1/edit');
$assert_session->responseNotContains('activitypub_create');
$assert_session->responseContains('activitypub_update');
$this->drupalLogout();
$this->drupalGet($outbox);
$assert_session->statusCodeEquals(200);
$content = json_decode($page->getContent());
self::assertEquals(1, $content->totalItems);
$this->drupalGet($content->first);
$assert_session->statusCodeEquals(200);
$content = json_decode($page->getContent());
self::assertEquals(1, count($content->orderedItems));
$this->drupalGet('nodeinfo/content');
$content = json_decode($page->getContent());
self::assertEquals(1, $content->usage->users->total);
self::assertEquals(1, $content->usage->localPosts);
$this->drupalLogin($this->authenticatedUserOne);
$this->drupalGet('node/add/page');
$edit = [
'title[0][value]' => 'Page two',
'body[0][value]' => 'Hello world!',
'activitypub_create' => 'map',
];
$this->submitForm($edit, 'Save');
$assert_session->addressEquals('node/2');
$this->drupalGet('node/2/edit');
$assert_session->responseNotContains('activitypub_create');
$assert_session->responseContains('activitypub_update');
$this->drupalLogout();
$this->drupalGet($outbox);
$assert_session->statusCodeEquals(200);
$content = json_decode($page->getContent());
self::assertEquals(2, $content->totalItems);
$this->drupalGet($content->first);
$assert_session->statusCodeEquals(200);
$content = json_decode($page->getContent());
self::assertEquals(2, count($content->orderedItems));
$this->drupalGet('nodeinfo/content', ['query' => ['page' => 1]]);
$content = json_decode($page->getContent());
self::assertEquals(1, $content->usage->users->total);
self::assertEquals(2, $content->usage->localPosts);
}
/**
* Test to functionality.
*/
public function testTo() {
$assert_session = $this->assertSession();
$this->config('activitypub.settings')->set('log_success_signature', TRUE)->save();
/** @var \Drupal\activitypub\Entity\Storage\ActivityPubActorStorageInterface $storage */
$storage = \Drupal::entityTypeManager()->getStorage('activitypub_activity');
// Setup ActivityPub actors.
$this->enableActivityPub($assert_session, TRUE);
$this->drupalLogout();
// Set outbox handler.
$this->setOutboxHandler();
$actor_href = Url::fromRoute('activitypub.user.self', ['user' => $this->authenticatedUserOne->id(), 'activitypub_actor' => $this->accountNameOne], ['absolute' => TRUE])->toString();
$object_href = Url::fromRoute('activitypub.user.self', ['user' => $this->authenticatedUserTwo->id(), 'activitypub_actor' => $this->accountNameTwo], ['absolute' => TRUE])->toString();
// Create type.
$this->createType('Create', 'page', 'Note');
// Login.
$this->drupalLogin($this->authenticatedUserOne);
// Unpublished one should not create a queue item.
$this->drupalGet('node/add/page');
$edit = [
'title[0][value]' => 'Sending to someone',
'body[0][value]' => 'Hello unknown follower!',
'activitypub_create' => 'map',
'activitypub_to' => $object_href,
'status[value]' => FALSE,
];
$this->submitForm($edit, 'Save');
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(0, $count);
// Send to outbox.
$this->drupalGet('node/add/page');
$edit = [
'title[0][value]' => 'Sending to someone',
'body[0][value]' => 'Hello unknown follower!',
'activitypub_create' => 'map',
'activitypub_to' => $object_href,
];
$this->submitForm($edit, 'Save');
$this->drupalLogout();
/** @var \Drupal\node\NodeInterface $node */
$node = \Drupal::entityTypeManager()->getStorage('node')->load(2);
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(1, $count);
/** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface $activity */
$activity = $storage->load(1);
$build = $activity->buildActivity();
self::assertTrue(in_array(ActivityPubActivityInterface::PUBLIC_URL, $build['to']));
self::assertTrue(in_array($object_href, $build['to']));
$this->runOutboxQueue();
// Verify that signature was ok.
$messages = \Drupal::database()->select('watchdog', 'w')
->fields('w')
->range(1, 1)
->orderBy('wid', 'DESC')
->execute()
->fetchAll();
self::assertEquals('Signature verified for id @id', $messages[0]->message);
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(0, $count);
//$this->viewActivityOverview();
/** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface $activity */
$activity = $storage->load(2);
self::assertEquals($actor_href, $activity->getActor());
self::assertEquals(ActivityPubActivityInterface::INBOX, $activity->getCollection());
self::assertEquals('Create', $activity->getType());
self::assertEquals($this->authenticatedUserTwo->id(), $activity->getOwnerId());
self::assertEquals($node->toUrl('canonical', ['absolute' => TRUE])->toString(), $activity->getObject());
$json = json_decode($activity->getPayLoad(), TRUE);
self::assertEquals('Note', $json['object']['type']);
self::assertEquals($json['id'], $activity->getExternalId());
self::assertEquals($node->toUrl('canonical', ['absolute' => TRUE])->toString(), $json['object']['id']);
self::assertEquals('<p>' . $node->get('body')->value . '</p>', $json['object']['content']);
}
/**
* Test to from sitewide functionality.
*/
public function testToFromSitewide() {
$assert_session = $this->assertSession();
$this->config('activitypub.settings')->set('log_success_signature', TRUE)->save();
/** @var \Drupal\activitypub\Entity\Storage\ActivityPubActorStorageInterface $storage */
$storage = \Drupal::entityTypeManager()->getStorage('activitypub_activity');
// Setup ActivityPub actors.
$this->enableActivityPub($assert_session, TRUE);
$this->drupalLogout();
// Set outbox handler.
$this->setOutboxHandler();
$actor_href = Url::fromRoute('activitypub.user.self', ['user' => $this->authenticatedUserOne->id(), 'activitypub_actor' => $this->accountNameOne], ['absolute' => TRUE])->toString();
$object_href = Url::fromRoute('activitypub.user.self', ['user' => $this->authenticatedUserTwo->id(), 'activitypub_actor' => $this->accountNameTwo], ['absolute' => TRUE])->toString();
// Create type.
$this->createType('Create', 'page', 'Note');
// Login.
$this->drupalLogin($this->authenticatedUserThree);
// Unpublished one should not create a queue item.
$this->drupalGet('node/add/page');
$edit = [
'title[0][value]' => 'Sending to someone',
'body[0][value]' => 'Hello unknown follower!',
'activitypub_create' => 'map',
'activitypub_to' => $object_href,
'status[value]' => FALSE,
];
$this->submitForm($edit, 'Save');
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(0, $count);
// Send to outbox.
$this->drupalGet('node/add/page');
$edit = [
'title[0][value]' => 'Sending to someone',
'body[0][value]' => 'Hello unknown follower!',
'activitypub_create' => 'map',
'activitypub_to' => $object_href,
];
$this->submitForm($edit, 'Save');
$this->drupalLogout();
/** @var \Drupal\node\NodeInterface $node */
$node = \Drupal::entityTypeManager()->getStorage('node')->load(2);
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(1, $count);
/** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface $activity */
$activity = $storage->load(1);
$build = $activity->buildActivity();
self::assertTrue(in_array(ActivityPubActivityInterface::PUBLIC_URL, $build['to']));
self::assertTrue(in_array($object_href, $build['to']));
$this->runOutboxQueue();
// Verify that signature was ok.
$messages = \Drupal::database()->select('watchdog', 'w')
->fields('w')
->range(1, 1)
->orderBy('wid', 'DESC')
->execute()
->fetchAll();
self::assertEquals('Signature verified for id @id', $messages[0]->message);
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(0, $count);
//$this->viewActivityOverview();
/** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface $activity */
$activity = $storage->load(2);
self::assertEquals($actor_href, $activity->getActor());
self::assertEquals(ActivityPubActivityInterface::INBOX, $activity->getCollection());
self::assertEquals('Create', $activity->getType());
self::assertEquals($this->authenticatedUserTwo->id(), $activity->getOwnerId());
self::assertEquals($node->toUrl('canonical', ['absolute' => TRUE])->toString(), $activity->getObject());
$json = json_decode($activity->getPayLoad(), TRUE);
self::assertEquals('Note', $json['object']['type']);
self::assertEquals($json['id'], $activity->getExternalId());
self::assertEquals($node->toUrl('canonical', ['absolute' => TRUE])->toString(), $json['object']['id']);
self::assertEquals('<p>' . $node->get('body')->value . '</p>', $json['object']['content']);
}
/**
* Tests delete requests.
*/
public function testDeleteRequest() {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
/** @var \Drupal\activitypub\Entity\Storage\ActivityPubActorStorageInterface $storage */
$storage = \Drupal::entityTypeManager()->getStorage('activitypub_activity');
// Setup ActivityPub actors.
$this->enableActivityPub($assert_session, TRUE);
$this->drupalLogout();
// Set outbox handler.
$this->setOutboxHandler();
$actor_href = Url::fromRoute('activitypub.user.self', ['user' => $this->authenticatedUserOne->id(), 'activitypub_actor' => $this->accountNameOne], ['absolute' => TRUE])->toString();
$object_href = Url::fromRoute('activitypub.user.self', ['user' => $this->authenticatedUserTwo->id(), 'activitypub_actor' => $this->accountNameTwo], ['absolute' => TRUE])->toString();
$this->followUser($object_href, $actor_href, 2, TRUE);
$this->runOutboxQueue();
//$this->viewActivityOverview();
// Create type.
$this->createType('Create', 'page', 'Note');
// Send to outbox.
$this->drupalLogin($this->authenticatedUserOne);
$this->drupalGet('node/add/page');
$edit = [
'title[0][value]' => 'Page one',
'body[0][value]' => 'Hello world!',
'activitypub_create' => 'map',
'path[0][alias]' => '/content/1',
];
$this->submitForm($edit, 'Save');
$this->drupalLogout();
// Assert content/1 is in the collection.
$this->assertOutboxItems(1, $assert_session, $page);
// Flush all caches, so the alias is known during the outbox queue run.
drupal_flush_all_caches();
$node = \Drupal::entityTypeManager()->getStorage('node')->load(1);
//$this->viewActivityOverview();
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(1, $count);
$this->runOutboxQueue();
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(0, $count);
//$this->viewActivityOverview();
/** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface $activity */
$activityCreate = $storage->load(5);
$activityCreateUrl = $activityCreate->toUrl('canonical', ['absolute' => TRUE])->toString();
$activity = $storage->load(6);
$nodeUrl = $node->toUrl('canonical', ['absolute' => TRUE])->toString();
self::assertEquals(ActivityPubActivityInterface::INBOX, $activity->getCollection());
self::assertEquals('Create', $activity->getType());
self::assertEquals($this->authenticatedUserTwo->id(), $activity->getOwnerId());
self::assertEquals($nodeUrl, $activity->getObject());
$json = json_decode($activity->getPayLoad(), TRUE);
self::assertEquals('Note', $json['object']['type']);
self::assertEquals($json['id'], $activity->getExternalId());
self::assertEquals($node->toUrl('canonical', ['absolute' => TRUE])->toString(), $json['object']['id']);
self::assertEquals('<p>' . $node->get('body')->value . '</p>', $json['object']['content']);
$this->drupalLogin($this->authenticatedUserOne);
$this->drupalGet('node/' . $node->id() . '/delete');
$this->submitForm([], 'Delete');
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(1, $count);
$this->drupalLogout();
// Assert content/1 is gone from the collection.
$this->assertOutboxItems(0, $assert_session, $page);
//$this->viewActivityOverview();
$this->runOutboxQueue();
//$this->viewActivityOverview();
// Assert properties of the DELETE activity.
$activity = $storage->load(7);
self::assertEquals('Delete', $activity->getType());
self::assertEquals($actor_href, $activity->getActor());
self::assertEquals($nodeUrl, $activity->getObject());
self::assertEquals($activityCreateUrl, $activity->getExternalId());
// Assert the other activities are gone.
$storage->resetCache([5, 6]);
$activity = $storage->load(5);
self::assertNull($activity);
$activity = $storage->load(6);
self::assertNull($activity);
$activity = $storage->load(8);
self::assertNull($activity);
}
/**
* Tests updating activities.
*/
public function testUpdateActivity() {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
$this->setOutboxHandler();
// Enable activity pub with two users.
$this->enableActivityPub($assert_session, TRUE);
/** @var \Drupal\activitypub\Entity\Storage\ActivityPubActorStorageInterface $activityStorage */
$activityStorage = \Drupal::entityTypeManager()->getStorage('activitypub_activity');
$nodeStorage = \Drupal::entityTypeManager()->getStorage('node');
// Create type.
$this->createType('Create', 'page', 'Note');
$actor_href_1 = Url::fromRoute('activitypub.user.self', ['user' => $this->authenticatedUserOne->id(), 'activitypub_actor' => $this->accountNameOne], ['absolute' => TRUE])->toString();
$outbox = Url::fromRoute('activitypub.outbox', ['user' => $this->authenticatedUserOne->id(), 'activitypub_actor' => $this->accountNameOne], ['absolute' => TRUE])->toString();
$actor_href_2 = Url::fromRoute('activitypub.user.self', ['user' => $this->authenticatedUserTwo->id(), 'activitypub_actor' => $this->accountNameTwo], ['absolute' => TRUE])->toString();
// Follow the user, so the followee check runs since we don't sign.
$this->followUserProgrammatically($this->authenticatedUserOne->id(), $actor_href_2, $actor_href_1);
$body_message = 'A supre message!';
$this->drupalLogin($this->authenticatedUserOne);
$this->drupalGet('node/add/page');
$edit = [
'title[0][value]' => 'Page one',
'body[0][value]' => $body_message,
'activitypub_create' => 'map',
];
$this->submitForm($edit, 'Save');
// Check outbox, should be 1.
$this->checkOutbox($outbox, $page, $assert_session, 1);
$this->runOutboxQueue();
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(0, $count);
/** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface $activity */
$activity = $activityStorage->load(3);
$stored_payload = json_decode($activity->getPayLoad(), TRUE);
self::assertEquals($stored_payload['object']['content'], trim(check_markup($body_message, 'activitypub')));
$body_message_updated = 'A super message!';
$this->drupalGet('node/1/edit');
$edit = [
'body[0][value]' => $body_message_updated,
'activitypub_update' => '2',
];
$this->submitForm($edit, 'Save');
$nodeStorage->resetCache([1]);
$activityStorage->resetCache([2, 3]);
// Check outbox, should be 1.
$this->checkOutbox($outbox, $page, $assert_session, 1);
$count = \Drupal::queue(ACTIVITYPUB_OUTBOX_QUEUE)->numberOfItems();
self::assertEquals(1, $count);
$this->runOutboxQueue();
$activity = $activityStorage->load(3);
$stored_payload = json_decode($activity->getPayLoad(), TRUE);
self::assertEquals($stored_payload['object']['content'], trim(check_markup($body_message_updated, 'activitypub')));
$activityUpdate = $activityStorage->load(4);
self::assertNull($activityUpdate);
}
}
