diff --git a/modules/sms_devel/src/Form/SmsDevelMessageForm.php b/modules/sms_devel/src/Form/SmsDevelMessageForm.php
index f29db10..9703e0b 100644
--- a/modules/sms_devel/src/Form/SmsDevelMessageForm.php
+++ b/modules/sms_devel/src/Form/SmsDevelMessageForm.php
@@ -64,6 +64,12 @@ public function getFormId() {
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
+ $results = $form_state->getTemporaryValue('results');
+
+ if ($results) {
+ $form = array_merge($form, $this->verboseResults($results));
+ }
+
$form['number'] = [
'#type' => 'tel',
'#title' => $this->t('Phone number'),
@@ -99,6 +105,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
'#title' => $this->t('Force skip queue'),
'#description' => $this->t('Send or receive the message immediately. If the gateway-specific skip queue setting is turned on, then this option is already applied.'),
'#default_value' => TRUE,
+ '#name' => 'skip_queue',
];
$form['options']['automated'] = [
'#type' => 'checkbox',
@@ -106,6 +113,17 @@ public function buildForm(array $form, FormStateInterface $form_state) {
'#description' => $this->t('Flag this message as automated.'),
'#default_value' => TRUE,
];
+ $form['options']['verbose'] = [
+ '#type' => 'checkbox',
+ '#title' => $this->t('Verbose output'),
+ '#description' => $this->t('Show full details of messages.'),
+ '#default_value' => TRUE,
+ '#states' => [
+ 'visible' => [
+ ':input[name="' . $form['options']['skip_queue']['#name'] . '"]' => ['checked' => TRUE],
+ ],
+ ],
+ ];
$form['options']['send_on'] = [
'#type' => 'datetime',
'#title' => $this->t('Send on'),
@@ -204,12 +222,18 @@ public function submitSend(array &$form, FormStateInterface $form_state) {
$this->message->setDirection(Direction::OUTGOING);
try {
- if ($form_state->getValue('skip_queue')) {
+ $skip_queue = $form_state->getValue('skip_queue');
+ $verbose = $form_state->getValue('verbose');
+ if ($verbose && $skip_queue) {
$messages = $this->smsProvider->send($this->message);
+ $results = [];
foreach ($messages as $message) {
$result = $message->getResult();
$this->resultMessage($result);
+ $results[] = $result;
}
+ $form_state->setTemporaryValue('results', $results);
+ $form_state->setRebuild();
}
else {
$this->smsProvider->queue($this->message);
@@ -252,4 +276,95 @@ protected function resultMessage(SmsMessageResultInterface $result) {
}
}
+ /**
+ * Render message results as a HTML table.
+ *
+ * @param \Drupal\sms\Message\SmsMessageResultInterface[] $results
+ *
+ * @return array
+ * A render array.
+ */
+ protected function verboseResults(array $results) {
+ $render = [];
+
+ // Renders plain text, or 'Undefined' message if falsey.
+ $renderString = function($value) {
+ return !empty($value) ? ['#plain_text' => $value] : ['#markup' => $this->t('Undefined')];
+ };
+
+ // Renders a date text, or 'Undefined' message if falsey.
+ $renderDate = function($timestamp) {
+ if ($timestamp) {
+ $date = DrupalDateTime::createFromTimestamp($timestamp);
+ return ['#plain_text' => $date->format('c')];
+ }
+ else {
+ return ['#markup' => $this->t('Undefined')];
+ }
+ };
+
+ $render['results'] = [
+ '#type' => 'table',
+ '#caption' => [
+ 'heading' => [
+ '#type' => 'inline_template',
+ '#template' => '
Results
',
+ ]
+ ],
+ '#header' => [
+ $this->t('Result'),
+ $this->t('Error'),
+ $this->t('Error Message'),
+ $this->t('Credits Used'),
+ $this->t('Credits Balance'),
+ ],
+ ];
+
+ foreach ($results as $i => $result) {
+ $row = [];
+ $row[]['#plain_text'] = $this->t("#@number", ['@number' => $i]);
+
+ $error = $result->getError();
+ $row[] = $error ? ['#plain_text' => $error] : ['#markup' => $this->t('Success')];
+ $row[] = $renderString($result->getErrorMessage());
+ $row[] = $renderString($result->getCreditsUsed());
+ $row[] = $renderString($result->getCreditsBalance());
+
+ $render['results'][] = $row;
+
+ $reports_cell = [
+ '#type' => 'table',
+ '#header' => [
+ $this->t('Recipient'),
+ $this->t('Message ID'),
+ $this->t('Status'),
+ $this->t('Status Message'),
+ $this->t('Time Delivered'),
+ $this->t('Time Queued'),
+ ],
+ ];
+ foreach ($result->getReports() as $report) {
+ $row = [];
+
+ $row[] = $renderString($report->getRecipient());
+ $row[] = $renderString($report->getMessageId());
+ $row[] = $renderString($report->getStatus());
+ $row[] = $renderString($report->getStatusMessage());
+ $row[] = $renderDate($report->getTimeDelivered());
+ $row[] = $renderDate($report->getTimeQueued());
+
+ $reports_cell[] = $row;
+ }
+
+ $render['results'][][] = [
+ '#wrapper_attributes' => [
+ 'colspan' => count($render['results']['#header']),
+ ],
+ 'data' => $reports_cell,
+ ];
+ }
+
+ return $render;
+ }
+
}
diff --git a/modules/sms_devel/tests/src/Functional/SmsDevelMessageTest.php b/modules/sms_devel/tests/src/Functional/SmsDevelMessageTest.php
index f067278..036f43c 100644
--- a/modules/sms_devel/tests/src/Functional/SmsDevelMessageTest.php
+++ b/modules/sms_devel/tests/src/Functional/SmsDevelMessageTest.php
@@ -46,12 +46,12 @@ public function testSendSkipQueue() {
$edit['skip_queue'] = TRUE;
$this->drupalPostForm(Url::fromRoute('sms_devel.message'), $edit, t('Send'));
- $this->assertResponse(200);
- $this->assertRaw('Message was processed, 1 delivery reports were generated.');
+ $this->assertSession()->statusCodeEquals(200);
+ $this->assertSession()->responseContains('Message was processed, 1 delivery reports were generated.');
$messages = $this->getTestMessages($this->gateway);
- $this->assertEqual(1, count($messages));
- $this->assertEqual($edit['message'], $messages[0]->getMessage());
+ $this->assertEquals(1, count($messages));
+ $this->assertEquals($edit['message'], $messages[0]->getMessage());
}
/**
@@ -63,13 +63,13 @@ public function testSendNoSkipQueue() {
$edit['skip_queue'] = FALSE;
$this->drupalPostForm(Url::fromRoute('sms_devel.message'), $edit, t('Send'));
- $this->assertResponse(200);
- $this->assertRaw('Message added to the outgoing queue.');
+ $this->assertSession()->statusCodeEquals(200);
+ $this->assertSession()->responseContains('Message added to the outgoing queue.');
$messages = SmsMessage::loadMultiple();
$message = reset($messages);
- $this->assertEqual($edit['message'], $message->getMessage(), 'Message is same');
- $this->assertEqual(Direction::OUTGOING, $message->getDirection(), 'Message is outgoing');
+ $this->assertEquals($edit['message'], $message->getMessage(), 'Message is same');
+ $this->assertEquals(Direction::OUTGOING, $message->getDirection(), 'Message is outgoing');
}
/**
@@ -82,10 +82,10 @@ public function testReceiveSkipQueue() {
$edit['skip_queue'] = TRUE;
$this->drupalPostForm(Url::fromRoute('sms_devel.message'), $edit, t('Receive'));
- $this->assertResponse(200);
- $this->assertRaw('Message was processed, 1 delivery reports were generated.');
+ $this->assertSession()->statusCodeEquals(200);
+ $this->assertSession()->responseContains('Message was processed, 1 delivery reports were generated.');
- $this->assertEqual($edit['message'], sms_test_gateway_get_incoming()['message']);
+ $this->assertEquals($edit['message'], sms_test_gateway_get_incoming()['message']);
}
/**
@@ -98,13 +98,13 @@ public function testReceiveNoSkipQueue() {
$edit['skip_queue'] = FALSE;
$this->drupalPostForm(Url::fromRoute('sms_devel.message'), $edit, t('Receive'));
- $this->assertResponse(200);
- $this->assertRaw('Message added to the incoming queue.');
+ $this->assertSession()->statusCodeEquals(200);
+ $this->assertSession()->responseContains('Message added to the incoming queue.');
$messages = SmsMessage::loadMultiple();
$message = reset($messages);
- $this->assertEqual($edit['message'], $message->getMessage(), 'Message is same');
- $this->assertEqual(Direction::INCOMING, $message->getDirection(), 'Message is incoming');
+ $this->assertEquals($edit['message'], $message->getMessage(), 'Message is same');
+ $this->assertEquals(Direction::INCOMING, $message->getDirection(), 'Message is incoming');
}
/**
@@ -114,8 +114,8 @@ public function testReceiveGatewayInvalid() {
$edit['gateway'] = '';
$this->drupalPostForm(Url::fromRoute('sms_devel.message'), $edit, t('Receive'));
- $this->assertResponse(200);
- $this->assertRaw('Gateway must be selected if receiving a message.');
+ $this->assertSession()->statusCodeEquals(200);
+ $this->assertSession()->responseContains('Gateway must be selected if receiving a message.');
}
/**
@@ -128,7 +128,7 @@ public function testAutomated() {
$edit['automated'] = FALSE;
$this->drupalPostForm(Url::fromRoute('sms_devel.message'), $edit, t('Send'));
- $this->assertResponse(200);
+ $this->assertSession()->statusCodeEquals(200);
$messages = SmsMessage::loadMultiple();
$message = reset($messages);
@@ -152,11 +152,11 @@ public function testDate() {
$edit['send_on[date]'] = $date_user->format('Y-m-d');
$edit['send_on[time]'] = $date_user->format('H:i:s');
$this->drupalPostForm(Url::fromRoute('sms_devel.message'), $edit, t('Send'));
- $this->assertResponse(200);
+ $this->assertSession()->statusCodeEquals(200);
$messages = SmsMessage::loadMultiple();
$message = reset($messages);
- $this->assertEqual($date->format('U'), $message->getSendTime(), 'Message has send time.');
+ $this->assertEquals($date->format('U'), $message->getSendTime(), 'Message has send time.');
}
/**
@@ -170,11 +170,80 @@ public function testNoFallbackGateway() {
$edit['skip_queue'] = TRUE;
$this->drupalPostForm(Url::fromRoute('sms_devel.message'), $edit, t('Send'));
- $this->assertResponse(200);
- $this->assertRaw('Message could not be sent');
+ $this->assertSession()->statusCodeEquals(200);
+ $this->assertSession()->responseContains('Message could not be sent');
$messages = $this->getTestMessages($this->gateway);
- $this->assertEqual(0, count($messages), 'No messages sent.');
+ $this->assertEquals(0, count($messages), 'No messages sent.');
+ }
+
+ /**
+ * Tests verbose message output.
+ */
+ function testVerboseReports() {
+ $edit['gateway'] = $this->gateway->id();
+ $edit['number'] = $this->randomPhoneNumbers(1)[0];
+ $edit['message'] = $this->randomString();
+ $edit['skip_queue'] = TRUE;
+ $edit['verbose'] = TRUE;
+
+ $this->drupalPostForm(Url::fromRoute('sms_devel.message'), $edit, t('Send'));
+ $this->assertSession()->statusCodeEquals(200);
+ $this->assertSession()->responseContains('Message was processed, 1 delivery reports were generated.');
+
+ $first_row = '#edit-results > tbody > tr:nth-child(1)';
+
+ // Result.
+ $selector = $first_row . ' > td:nth-child(1)';
+ $this->assertSession()->elementTextContains('css', $selector, '#0');
+
+ // Error.
+ $selector = $first_row . ' > td:nth-child(2)';
+ $this->assertSession()->elementTextContains('css', $selector, 'Success');
+
+ // Error Message.
+ $selector = $first_row . ' > td:nth-child(3)';
+ $this->assertSession()->elementTextContains('css', $selector, 'Undefined');
+
+ // Credits Used.
+ $selector = $first_row . ' > td:nth-child(4)';
+ $this->assertSession()->elementTextContains('css', $selector, 'Undefined');
+
+ // Credits Balance.
+ $selector = $first_row . ' > td:nth-child(5)';
+ $this->assertSession()->elementTextContains('css', $selector, 'Undefined');
+
+ $message = $this->getLastTestMessage($this->gateway);
+ $report = $message->getReports()[0];
+ $this->assertEquals($edit['number'], $report->getRecipient());
+
+ $first_row_first_report = '#edit-results > tbody > tr:nth-child(2) > td > table > tbody > tr:nth-child(1)';
+
+ // Recipient.
+ $selector = $first_row_first_report . ' > td:nth-child(1)';
+ $this->assertSession()->elementTextContains('css', $selector, $report->getRecipient());
+
+ // Message ID.
+ $selector = $first_row_first_report . ' > td:nth-child(2)';
+ $this->assertSession()->elementTextContains('css', $selector, $report->getMessageId());
+
+ // Status.
+ $selector = $first_row_first_report . ' > td:nth-child(3)';
+ $this->assertSession()->elementTextContains('css', $selector, $report->getStatus());
+
+ // Status Message.
+ $selector = $first_row_first_report . ' > td:nth-child(4)';
+ $this->assertSession()->elementTextContains('css', $selector, $report->getStatusMessage());
+
+ // Time Delivered.
+ $date = DrupalDateTime::createFromTimestamp($report->getTimeDelivered());
+ $selector = $first_row_first_report . ' > td:nth-child(5)';
+ $this->assertSession()->elementTextContains('css', $selector, $date->format('c'));
+
+ // Time Queued.
+ $date = DrupalDateTime::createFromTimestamp($report->getTimeQueued());
+ $selector = $first_row_first_report . ' > td:nth-child(6)';
+ $this->assertSession()->elementTextContains('css', $selector, $date->format('c'));
}
}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 7d0695a..97e4d4a 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -11,6 +11,7 @@
./tests
./modules/sms_user/tests
+ ./modules/sms_devel/tests