feedback-3.x-dev/tests/src/Functional/CreateReadUpdateDeleteMessageTest.php
tests/src/Functional/CreateReadUpdateDeleteMessageTest.php
<?php
namespace Drupal\Tests\feedback\Functional;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Url;
use Drupal\Tests\BrowserTestBase;
use Drupal\feedback\Entity\FeedbackMessage;
use Drupal\user\UserInterface;
/**
* Test that feedback messages can be added, viewed, changed, and deleted.
*
* @group feedback
*/
class CreateReadUpdateDeleteMessageTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['feedback', 'block'];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* A published feedback message we will use during the tests.
*
* @var \Drupal\feedback\Entity\FeedbackMessage
*/
protected FeedbackMessage $publishedMessage;
/**
* The body of the published feedback message we will use during the tests.
*
* @var string
*/
protected string $publishedMessageBody;
/**
* An unpublished feedback message we will use during the tests.
*
* @var \Drupal\feedback\Entity\FeedbackMessage
*/
protected FeedbackMessage $unpublishedMessage;
/**
* The body of the unpublished feedback message we will use during the tests.
*
* @var string
*/
protected string $unpublishedMessageBody;
/**
* The ID of the user who submitted the feedback message we are testing with.
*
* @var \Drupal\user\UserInterface
*/
protected UserInterface $unpublishedMessageSender;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
// Setup: Create a user account that we can say sent a message. Note since
// we are creating the messages programmatically, the permissions don't
// really matter.
$this->unpublishedMessageSender = $this->createUser(['add feedback message entities']);
// Setup: Programmatically create two messages.
$common = [
'type' => 'default_feedback',
'link' => 'internal:/node',
'langcode' => 'en',
'created' => time(),
'changed' => time(),
];
$this->publishedMessageBody = \trim($this->getRandomGenerator()->paragraphs(1));
$this->publishedMessage = FeedbackMessage::create([
'status' => 1,
'body' => $this->publishedMessageBody,
'user_id' => 0,
] + $common);
$this->publishedMessage->save();
$this->unpublishedMessageBody = \trim($this->getRandomGenerator()->paragraphs(1));
$this->unpublishedMessage = FeedbackMessage::create([
'status' => 0,
'body' => $this->unpublishedMessageBody,
'user_id' => $this->unpublishedMessageSender->id(),
] + $common);
$this->unpublishedMessage->save();
}
/**
* Test that a user with correct permissions can create a feedback message.
*/
public function testCreateMessage(): void {
// Setup: Place the feedback block.
$this->placeBlock('feedback_block', [
'id' => 'test_feedback_block',
'feedback_type' => 'default_feedback',
'feedback_help' => 'Help text',
'feedback_submit' => 'Submit feedback',
]);
// Setup: Log in as a user with permission to create a feedback message.
$this->drupalLogin($this->createUser(['add feedback message entities']));
// Setup: Navigate to a page with a feedback message form.
$this->drupalGet('<front>');
$feedbackMessage = \trim($this->getRandomGenerator()->paragraphs(1));
$this->submitForm([
'body[0][value]' => $feedbackMessage,
], 'Submit');
// Assertions: Check that we got the status message we expected.
$this->assertSession()->statusMessageContains('Thank you for your feedback.');
// Assertions: Check that we can load the feedback message that was just
// submitted.
$messages = $this->getMessageStorage()->loadByProperties([
'body' => $feedbackMessage,
]);
$this->assertIsArray($messages);
$this->assertCount(1, $messages);
$submittedMessage = reset($messages);
$this->assertInstanceOf(FeedbackMessage::class, $submittedMessage);
$this->assertEquals($feedbackMessage, $submittedMessage->get('body')->first()->getValue()['value']);
}
/**
* Test that a user with correct permissions can delete a feedback message.
*/
public function testDeleteMessage(): void {
// Setup: Log in as a user with permission to delete a feedback message.
$this->drupalLogin($this->createUser(['delete feedback message entities']));
// Setup: Store the message ID so we can try to load it after deleting.
$publishedMessageId = $this->publishedMessage->id();
// Setup: Navigate to the delete form for a published message.
$this->drupalGet($this->publishedMessage->toUrl('delete-form'));
// System under test: Submit the form.
$this->submitForm([], 'Delete');
// Assertions: Check that the message was deleted.
$this->assertNull($this->getMessageStorage()->load($publishedMessageId));
// Setup: Store the message ID so we can try to load it after deleting.
$unpublishedMessageId = $this->unpublishedMessage->id();
// Setup: Navigate to the delete form for an unpublished message.
$this->drupalGet($this->unpublishedMessage->toUrl('delete-form'));
// System under test: Submit the form.
$this->submitForm([], 'Delete');
// Assertions: Check that the message was deleted.
$this->assertNull($this->getMessageStorage()->load($unpublishedMessageId));
}
/**
* Test that the Feedback Message list works as-intended.
*/
public function testListMessages(): void {
// Setup: Log in as a user with permission to see the feedback message list.
$this->drupalLogin($this->createUser([
'access feedback message list',
]));
// System under test: Load the Feedback Message List page.
$this->drupalGet(Url::fromRoute('entity.feedback_message.collection'));
// Assertions: Check that the feedback message list appears.
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery('//table//th[1][text()="Feedback message ID"]'));
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery('//table//th[2][text()="Name"]'));
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery('//table//th[3][text()="Path"]'));
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery('//table//th[4][text()="User"]'));
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery('//table//th[5][text()="Operations"]'));
// Assertions: Check there is a row for the published message we created in
// the setUp.
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery('//table//tr/td[1][.=:message_id]', [
':message_id' => $this->publishedMessage->id(),
]));
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery('//table//tr/td[2]//a[@href=:message_url][.=:message_label]', [
':message_url' => $this->publishedMessage->toUrl('canonical')->toString(),
':message_label' => 'Feedback message ' . $this->publishedMessage->id(),
]));
// It is unclear how to get the URL in the same format as what's displayed
// in the table (e.g.: 'internal:/user/2?check_logged_in=1') in the setUp()
// function before we submit the form. Creating a Url::fromRoute('<front>'),
// storing it, visiting it, and parsing it here returns 'route:<front>', '',
// or '/' (depending on the function called), which isn't helpful. Asking
// the driver for the current URL gives us 'http://web/user/2' or '/user/2',
// but not the HTTP GET query string at the end. So the best we can do here
// is check that the text starts with the substring 'internal:'.
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery('//table//tr/td[3][starts-with(text(),"internal:/")]'));
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery('//table//tr/td[4][.="Anonymous"]'));
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery('//table//tr/td[5][.=""]'));
// Assertions: Check there is a row for the unpublished message we created
// in the setUp.
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery('//table//tr/td[1][.=:message_id]', [
':message_id' => $this->unpublishedMessage->id(),
]));
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery("//table//tr/td[2]//a[@href=:message_url][.=:message_label]", [
':message_url' => $this->unpublishedMessage->toUrl('canonical')->toString(),
':message_label' => 'Feedback message ' . $this->unpublishedMessage->id(),
]));
// It is unclear how to get the URL in the same format as what's displayed
// in the table (e.g.: 'internal:/user/2?check_logged_in=1') in the setUp()
// function before we submit the form. Creating a Url::fromRoute('<front>'),
// storing it, visiting it, and parsing it here returns 'route:<front>', '',
// or '/' (depending on the function called), which isn't helpful. Asking
// the driver for the current URL gives us 'http://web/user/2' or '/user/2',
// but not the HTTP GET query string at the end. So the best we can do here
// is check that the text starts with the substring 'internal:'.
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery('//table//tr/td[3][starts-with(text(),"internal:/")]'));
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery("//table//tr/td[4]//a[@href=:message_sender_url]", [
':message_sender_url' => $this->unpublishedMessageSender->toUrl('canonical')->toString(),
]));
$this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery('//table//tr/td[5][.=""]'));
}
/**
* Test that a user with correct permissions can edit a feedback message.
*/
public function testUpdateMessage(): void {
// Setup: Log in as a user with permission to update a feedback message.
$this->drupalLogin($this->createUser(['edit feedback message entities']));
// System under test: Navigate to the edit form for a published message.
$this->drupalGet($this->publishedMessage->toUrl('edit-form'));
// Assertions: Check that we can see the fields we expect.
$this->assertSession()->fieldExists('body[0][value]');
$this->assertSession()->fieldValueEquals('body[0][value]', $this->publishedMessageBody);
$this->assertSession()->buttonExists('Save');
// System under test: Edit some fields and submit the form.
$newPublishedMessageBody = \trim($this->getRandomGenerator()->paragraphs(1));
$this->submitForm([
'body[0][value]' => $newPublishedMessageBody,
], 'Save');
// Assertions: Check that the message was changed.
$this->assertSession()->statusMessageContains("Saved the Feedback message {$this->publishedMessage->id()} Feedback message.");
$this->assertSession()->fieldValueNotEquals('body[0][value]', $this->publishedMessageBody);
$this->assertSession()->fieldValueEquals('body[0][value]', $newPublishedMessageBody);
// System under test: Navigate to the edit form for an unpublished message.
$this->drupalGet($this->unpublishedMessage->toUrl('edit-form'));
// Assertions: Check that we can see the fields we expect.
$this->assertSession()->fieldExists('body[0][value]');
$this->assertSession()->fieldValueEquals('body[0][value]', $this->unpublishedMessageBody);
$this->assertSession()->buttonExists('Save');
// System under test: Edit some fields and submit the form.
$newUnpublishedMessageBody = \trim($this->getRandomGenerator()->paragraphs(1));
$this->submitForm([
'body[0][value]' => $newUnpublishedMessageBody,
], 'Save');
// Assertions: Check that the message was changed.
$this->assertSession()->statusMessageContains("Saved the Feedback message {$this->unpublishedMessage->id()} Feedback message.");
$this->assertSession()->fieldValueNotEquals('body[0][value]', $this->unpublishedMessageBody);
$this->assertSession()->fieldValueEquals('body[0][value]', $newUnpublishedMessageBody);
}
/**
* Test that a user with correct permissions can view a message.
*/
public function testViewMessage(): void {
// Setup: Log in as a user with permission to view a published message.
$this->drupalLogin($this->createUser(['view published feedback message entities']));
// System under test: Try to view a published message.
$this->drupalGet($this->publishedMessage->toUrl('canonical'));
// Assertions: Check we can see the message and URL it was submitted from.
$this->assertSession()->pageTextContains($this->publishedMessageBody);
$this->assertSession()->pageTextContains('internal:/node');
// System under test: Try to view an unpublished message.
$this->drupalGet($this->unpublishedMessage->toUrl('canonical'));
// Assertions: Check that we cannot see the message.
$this->assertSession()->pageTextContains('You are not authorized to access this page.');
$this->assertSession()->pageTextNotContains($this->unpublishedMessageBody);
// Setup: Log in as a user with permission to view an unpublished message.
$this->drupalLogin($this->createUser(['view unpublished feedback message entities']));
// System under test: Try to view a published message.
$this->drupalGet($this->publishedMessage->toUrl('canonical'));
// Assertions: Check that we cannot see the message.
$this->assertSession()->pageTextContains('You are not authorized to access this page.');
$this->assertSession()->pageTextNotContains($this->publishedMessageBody);
// System under test: Try to view an unpublished message.
$this->drupalGet($this->unpublishedMessage->toUrl('canonical'));
// Assertions: Check we can see the message and URL it was submitted from.
$this->assertSession()->pageTextContains($this->unpublishedMessageBody);
$this->assertSession()->pageTextContains('internal:/node');
}
/**
* Get an entity storage interface for feedback messages.
*
* @return \Drupal\Core\Entity\EntityStorageInterface
* An entity storage interface for feedback messages.
*/
protected function getMessageStorage(): EntityStorageInterface {
return $this->container->get('entity_type.manager')
->getStorage('feedback_message');
}
}
