reviewer-1.2.x-dev/modules/reviewer_ui/tests/src/FunctionalJavascript/UiTest.php
modules/reviewer_ui/tests/src/FunctionalJavascript/UiTest.php
<?php
declare(strict_types=1);
namespace Drupal\Tests\reviewer_ui\FunctionalJavascript;
use Behat\Mink\Element\NodeElement;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\reviewer_ui\Form\Results;
use Drupal\Tests\reviewer\Traits\ReviewerCreationTrait;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
/**
* Test the reviewer admin page.
*/
#[Group('reviewer')]
#[CoversClass(Results::class)]
class UiTest extends WebDriverTestBase {
use ReviewerCreationTrait;
/**
* {@inheritdoc}
*/
protected static $modules = [
'field',
'link',
'node',
'system',
'user',
'reviewer',
'reviewer_ui',
'reviewer_test',
];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
/**
* {@inheritdoc}
*
* @throws \Exception
*/
protected function setUp(): void {
parent::setUp();
$this->createContentTypes();
if ($user = $this->drupalCreateUser(['reviewer view results page'])) {
$this->drupalLogin($user);
}
}
/**
* Test that the page exists and the expected elements are present.
*/
public function testElementsPresent(): void {
$html = $this->getPage();
self::assertStringContainsString('css/reviewer-ui.css', $html);
self::assertStringContainsString('js/reviewer-ui.js', $html);
self::assertStringContainsString('Reviewer Results', $html);
self::assertStringContainsString('data-drupal-selector="edit-filters"', $html);
self::assertStringContainsString('data-drupal-selector="edit-ignore"', $html);
self::assertStringContainsString('data-drupal-selector="edit-unignore-all"', $html);
self::assertStringContainsString('<table class="reviewer-results-table', $html);
self::assertStringContainsString('<span>Passed</span>', $html);
self::assertStringContainsString('<span>Failed</span>', $html);
self::assertStringContainsString('<span>Ignored Error</span>', $html);
self::assertStringContainsString('<span>Errored</span>', $html);
self::assertStringContainsString('<span>Not Run</span>', $html);
}
/**
* Test that failures show on page load.
*
* @throws \Exception
*/
public function testFailuresCheckedOnLoad(): void {
$this->getPage();
$session = $this->assertSession();
$session->checkboxChecked('show[failed]');
$session->checkboxNotChecked('show[all]');
$session->checkboxNotChecked('show[ignored]');
$session->checkboxNotChecked('show[passed]');
$session->checkboxNotChecked('show[not-run]');
}
/**
* Test the interactions between the all checkboxes and others.
*
* @throws \Exception
*/
public function testFilterInteractions(): void {
$this->getPage();
$session = $this->assertSession();
$all = $session->elementExists('css', '[name="show[all]"]');
$failed = $session->elementExists('css', '[name="show[failed]"]');
$ignored = $session->elementExists('css', '[name="show[ignored]"]');
$passed = $session->elementExists('css', '[name="show[passed]"]');
$not_run = $session->elementExists('css', '[name="show[not-run]"]');
$all->click();
$session->checkboxChecked('show[all]');
$session->checkboxChecked('show[failed]');
$session->checkboxChecked('show[ignored]');
$session->checkboxChecked('show[passed]');
$session->checkboxChecked('show[not-run]');
$failed->click();
$session->checkboxNotChecked('show[all]');
$session->checkboxNotChecked('show[failed]');
$session->checkboxChecked('show[ignored]');
$session->checkboxChecked('show[passed]');
$session->checkboxChecked('show[not-run]');
$failed->click();
$session->checkboxChecked('show[all]');
$session->checkboxChecked('show[failed]');
$session->checkboxChecked('show[ignored]');
$session->checkboxChecked('show[passed]');
$session->checkboxChecked('show[not-run]');
$ignored->click();
$passed->click();
$session->checkboxNotChecked('show[all]');
$session->checkboxChecked('show[failed]');
$session->checkboxNotChecked('show[ignored]');
$session->checkboxNotChecked('show[passed]');
$session->checkboxChecked('show[not-run]');
$all->click();
$session->checkboxChecked('show[all]');
$session->checkboxChecked('show[failed]');
$session->checkboxChecked('show[ignored]');
$session->checkboxChecked('show[passed]');
$session->checkboxChecked('show[not-run]');
$all->click();
$session->checkboxNotChecked('show[all]');
$session->checkboxNotChecked('show[failed]');
$session->checkboxNotChecked('show[ignored]');
$session->checkboxNotChecked('show[passed]');
$session->checkboxNotChecked('show[not-run]');
$failed->click();
$ignored->click();
$passed->click();
$not_run->click();
$session->checkboxChecked('show[all]');
$session->checkboxChecked('show[failed]');
$session->checkboxChecked('show[ignored]');
$session->checkboxChecked('show[passed]');
$session->checkboxChecked('show[not-run]');
}
/**
* Test that the reason field is focused when the ignore checkbox is checked.
*
* @throws \Behat\Mink\Exception\ElementNotFoundException
*/
public function testReasonFocusedOnIgnore(): void {
$this->getPage();
$session = $this->assertSession();
$session->elementExists(
'css',
'[data-drupal-selector="edit-review-test"]',
)->click();
$session->elementExists(
'css',
'[name="ignored[review_test.checklist_test.error_test_task]"]'
)->click();
$this->assertJsCondition('document.activeElement === document.querySelector("[name=\"reasons[review_test.checklist_test.error_test_task]\"]")');
}
/**
* Test that the filters hide and show the correct results.
*
* @throws \Behat\Mink\Exception\ElementNotFoundException
*/
public function testFilter(): void {
$display = 'display: none;';
$not_run_class = 'reviewer--not-run';
$pass_class = 'reviewer--pass';
$ignored_fail_class = 'reviewer--ignored-failure';
$ignored_error_class = 'reviewer--ignored-error';
$fail_class = 'reviewer--fail';
$error_class = 'reviewer--error';
$this->getPage();
$session = $this->assertSession();
$all = $session->elementExists('css', '[name="show[all]"]');
$failed = $session->elementExists('css', '[name="show[failed]"]');
$ignored = $session->elementExists('css', '[name="show[ignored]"]');
$passed = $session->elementExists('css', '[name="show[passed]"]');
$not_run = $session->elementExists('css', '[name="show[not-run]"]');
$results = $this->getSession()->getPage()->findAll('css', '.reviewer-result');
foreach ($results as $result) {
if ($result->hasClass($fail_class) || $result->hasClass($error_class)) {
self::assertFalse($result->hasAttribute('style'));
if ($details = $this->getDetails($result)) {
self::assertSame('', $details->getAttribute('style') ?? '');
}
}
else {
self::assertSame($display, $result->getAttribute('style'));
}
}
$failed->click();
$results = $this->getSession()->getPage()->findAll('css', '.reviewer-result');
foreach ($results as $result) {
self::assertSame($display, $result->getAttribute('style'));
if ($details = $this->getDetails($result)) {
self::assertSame($display, $details->getAttribute('style'));
}
}
$all->click();
$results = $this->getSession()->getPage()->findAll('css', '.reviewer-result');
foreach ($results as $result) {
self::assertSame('', $result->getAttribute('style'));
if ($details = $this->getDetails($result)) {
self::assertSame('', $details->getAttribute('style'));
}
}
$all->click();
$ignored->click();
$results = $this->getSession()->getPage()->findAll('css', '.reviewer-result');
foreach ($results as $result) {
if ($result->hasClass($ignored_error_class) || $result->hasClass($ignored_fail_class)) {
self::assertSame('', $result->getAttribute('style'));
if ($details = $this->getDetails($result)) {
self::assertSame('', $details->getAttribute('style'));
}
}
else {
self::assertSame($display, $result->getAttribute('style'));
}
}
$ignored->click();
$passed->click();
$results = $this->getSession()->getPage()->findAll('css', '.reviewer-result');
foreach ($results as $result) {
if ($result->hasClass($pass_class)) {
self::assertSame('', $result->getAttribute('style'));
if ($details = $this->getDetails($result)) {
self::assertSame('', $details->getAttribute('style'));
}
}
else {
self::assertSame($display, $result->getAttribute('style'));
}
}
$passed->click();
$not_run->click();
$results = $this->getSession()->getPage()->findAll('css', '.reviewer-result');
foreach ($results as $result) {
if ($result->hasClass($not_run_class)) {
self::assertSame('', $result->getAttribute('style'));
if ($details = $this->getDetails($result)) {
self::assertSame('', $details->getAttribute('style'));
}
}
else {
self::assertSame($display, $result->getAttribute('style'));
}
}
}
/**
* Test that submitting the form keeps the filter state.
*
* @throws \Exception
*/
public function testSubmitKeepsFilterState(): void {
$this->getPage();
$session = $this->assertSession();
$session->checkboxChecked('show[failed]');
$session
->elementExists('css', '[name="show[ignored]"]')
->click();
$session
->elementExists('css', '[name="ignore"]')
->click();
$session->waitForText('Reviewer Results');
$session->checkboxChecked('show[failed]');
$session->checkboxChecked('show[ignored]');
$session
->elementExists('css', '[name="unignore_all"]')
->click();
$session->waitForText('Reviewer Results');
$session->checkboxChecked('show[failed]');
$session->checkboxChecked('show[ignored]');
}
/**
* Test ignoring and unignoring all items.
*
* @throws \Exception
*/
public function testIgnoring(): void {
$this->getPage();
$session = $this->assertSession();
$session->elementExists(
'css',
'[data-drupal-selector="edit-review-test"]',
)->click();
$session->elementExists(
'css',
'[name="ignored[review_test.checklist_test.error_test_task]"]'
)->click();
$session->elementExists(
'css',
'[name="reasons[review_test.checklist_test.error_test_task]"]',
)->setValue('Ignored!!!');
$session
->elementExists('css', '[name="ignore"]')
->click();
$session->waitForText('Reviewer Results');
$session->checkboxChecked('ignored[review_test.checklist_test.error_test_task]');
$session->fieldValueEquals(
'reasons[review_test.checklist_test.error_test_task]',
'Ignored!!!',
);
$session
->elementExists('css', '[name="unignore_all"]')
->click();
$session->waitForText('Reviewer Results');
$session->checkboxNotChecked('ignored[review_test.checklist_test.error_test_task]');
$session->fieldValueEquals(
'reasons[review_test.checklist_test.error_test_task]',
'',
);
$session->checkboxChecked('ignored[review_test.checklist_test.ignored_error_test_task]');
$session->fieldDisabled('ignored[review_test.checklist_test.ignored_error_test_task]');
$session->fieldValueEquals(
'reasons[review_test.checklist_test.ignored_error_test_task]',
'Ignored in code.',
);
$session->fieldDisabled('reasons[review_test.checklist_test.ignored_error_test_task]');
}
/**
* Test fixing reviews.
*
* @throws \Behat\Mink\Exception\ElementNotFoundException
*/
public function testFixing(): void {
$this->getPage();
$session = $this->assertSession();
$session->elementExists('css', '[name="show[all]"]')->click();
// Test that reviews with only unfixable tasks have the checkbox disabled.
$session->elementExists(
'css',
'[data-drupal-selector="edit-review-test"]',
)->click();
$fix_disabled = $session->elementExists(
'css',
'[name="fix[review_test]"]',
);
self::assertTrue($fix_disabled->hasAttribute('disabled'));
// Test that reviews with all passed tasks have the checkbox disabled.
$session->elementExists(
'css',
"[data-drupal-selector='edit-entity-review-test{$this->contentTypePass[0]->id()}']",
)->click();
$fix_disabled = $session->elementExists(
'css',
"[name='fix[entity_review_test.{$this->contentTypePass[0]->id()}]']",
);
self::assertTrue($fix_disabled->hasAttribute('disabled'));
// Fix a reviews issues.
$session->elementExists(
'css',
"[data-drupal-selector='edit-entity-review-test{$this->contentTypeFail[0]->id()}']",
)->click();
$session
->elementExists(
'css',
"[name='fix[entity_review_test.{$this->contentTypeFail[0]->id()}]']",
)
->check();
$session
->elementExists(
'css',
'[name="fix_issues"]',
)
->click();
$session->waitForText('Let Reviewer fix configuration issues?');
$session->buttonExists('Confirm')->click();
$session->waitForText('Reviewer Results');
// Check that the selected review is fixed.
$session->elementTextEquals(
'css',
"[aria-controls='edit-entity-review-test{$this->contentTypeFail[0]->id()}'] span",
'Passed',
);
// Check that other reviews were not fixed.
$session->elementTextEquals(
'css',
"[aria-controls='edit-entity-review-test{$this->contentTypeFail[1]->id()}'] span",
'Failed',
);
}
/**
* Load the results page.
*/
private function getPage(): string {
return $this->drupalGet('/admin/reports/reviewer');
}
/**
* Get the details element containing another element.
*/
private function getDetails(NodeElement $element): NodeElement|null {
try {
while ($element->getTagName() !== 'details') {
$element = $element->getParent();
}
}
catch (\Exception) {
return NULL;
}
return $element;
}
}
