class SimpletestResultsForm

Test results form for $test_id.

Note that the UI strings are not translated because this form is also used from run-tests.sh.

@internal

Hierarchy

Expanded class hierarchy of SimpletestResultsForm

See also

simpletest_script_open_browser()

run-tests.sh

1 file declares its use of SimpletestResultsForm
simpletest.module in core/modules/simpletest/simpletest.module
Provides testing functionality.
1 string reference to 'SimpletestResultsForm'
simpletest.routing.yml in core/modules/simpletest/simpletest.routing.yml
core/modules/simpletest/simpletest.routing.yml

File

core/modules/simpletest/src/Form/SimpletestResultsForm.php, line 25

Namespace

Drupal\simpletest\Form
View source
class SimpletestResultsForm extends FormBase {
    
    /**
     * Associative array of themed result images keyed by status.
     *
     * @var array
     */
    protected $statusImageMap;
    
    /**
     * The database connection service.
     *
     * @var \Drupal\Core\Database\Connection
     */
    protected $database;
    
    /**
     * The environment cleaner service.
     *
     * @var \Drupal\Core\Test\EnvironmentCleanerInterface
     */
    protected $cleaner;
    
    /**
     * {@inheritdoc}
     */
    public static function create(ContainerInterface $container) {
        return new static($container->get('database'), $container->get('environment_cleaner'));
    }
    
    /**
     * Constructs a \Drupal\simpletest\Form\SimpletestResultsForm object.
     *
     * @param \Drupal\Core\Database\Connection $database
     *   The database connection service.
     */
    public function __construct(Connection $database, EnvironmentCleanerInterface $cleaner) {
        $this->database = $database;
        $this->cleaner = $cleaner;
    }
    
    /**
     * Builds the status image map.
     */
    protected static function buildStatusImageMap() {
        $image_pass = [
            '#theme' => 'image',
            '#uri' => 'core/misc/icons/73b355/check.svg',
            '#width' => 18,
            '#height' => 18,
            '#alt' => 'Pass',
        ];
        $image_fail = [
            '#theme' => 'image',
            '#uri' => 'core/misc/icons/e32700/error.svg',
            '#width' => 18,
            '#height' => 18,
            '#alt' => 'Fail',
        ];
        $image_exception = [
            '#theme' => 'image',
            '#uri' => 'core/misc/icons/e29700/warning.svg',
            '#width' => 18,
            '#height' => 18,
            '#alt' => 'Exception',
        ];
        $image_debug = [
            '#theme' => 'image',
            '#uri' => 'core/misc/icons/e29700/warning.svg',
            '#width' => 18,
            '#height' => 18,
            '#alt' => 'Debug',
        ];
        return [
            'pass' => $image_pass,
            'fail' => $image_fail,
            'exception' => $image_exception,
            'debug' => $image_debug,
        ];
    }
    
    /**
     * {@inheritdoc}
     */
    public function getFormId() {
        return 'simpletest_results_form';
    }
    
    /**
     * {@inheritdoc}
     */
    public function buildForm(array $form, FormStateInterface $form_state, $test_id = NULL) {
        // Make sure there are test results to display and a re-run is not being
        // performed.
        $results = [];
        if (is_numeric($test_id) && !($results = $this->getResults($test_id))) {
            $this->messenger()
                ->addError($this->t('No test results to display.'));
            return $this->redirect('simpletest.test_form');
        }
        // Load all classes and include CSS.
        $form['#attached']['library'][] = 'simpletest/drupal.simpletest';
        // Add the results form.
        $filter = static::addResultForm($form, $results, $this->getStringTranslation());
        // Actions.
        $form['#action'] = Url::fromRoute('simpletest.result_form', [
            'test_id' => 're-run',
        ])->toString();
        $form['action'] = [
            '#type' => 'fieldset',
            '#title' => $this->t('Actions'),
            '#attributes' => [
                'class' => [
                    'container-inline',
                ],
            ],
            '#weight' => -11,
        ];
        $form['action']['filter'] = [
            '#type' => 'select',
            '#title' => 'Filter',
            '#options' => [
                'all' => $this->t('All (@count)', [
                    '@count' => count($filter['pass']) + count($filter['fail']),
                ]),
                'pass' => $this->t('Pass (@count)', [
                    '@count' => count($filter['pass']),
                ]),
                'fail' => $this->t('Fail (@count)', [
                    '@count' => count($filter['fail']),
                ]),
            ],
        ];
        $form['action']['filter']['#default_value'] = $filter['fail'] ? 'fail' : 'all';
        // Categorized test classes for to be used with selected filter value.
        $form['action']['filter_pass'] = [
            '#type' => 'hidden',
            '#default_value' => implode(',', $filter['pass']),
        ];
        $form['action']['filter_fail'] = [
            '#type' => 'hidden',
            '#default_value' => implode(',', $filter['fail']),
        ];
        $form['action']['op'] = [
            '#type' => 'submit',
            '#value' => $this->t('Run tests'),
        ];
        $form['action']['return'] = [
            '#type' => 'link',
            '#title' => $this->t('Return to list'),
            '#url' => Url::fromRoute('simpletest.test_form'),
        ];
        if (is_numeric($test_id)) {
            $this->cleaner
                ->cleanResultsTable($test_id);
        }
        return $form;
    }
    
    /**
     * {@inheritdoc}
     */
    public function submitForm(array &$form, FormStateInterface $form_state) {
        $pass = $form_state->getValue('filter_pass') ? explode(',', $form_state->getValue('filter_pass')) : [];
        $fail = $form_state->getValue('filter_fail') ? explode(',', $form_state->getValue('filter_fail')) : [];
        if ($form_state->getValue('filter') == 'all') {
            $classes = array_merge($pass, $fail);
        }
        elseif ($form_state->getValue('filter') == 'pass') {
            $classes = $pass;
        }
        else {
            $classes = $fail;
        }
        if (!$classes) {
            $form_state->setRedirect('simpletest.test_form');
            return;
        }
        $form_execute = [];
        $form_state_execute = new FormState();
        foreach ($classes as $class) {
            $form_state_execute->setValue([
                'tests',
                $class,
            ], $class);
        }
        // Submit the simpletest test form to rerun the tests.
        // Under normal circumstances, a form object's submitForm() should never be
        // called directly, FormBuilder::submitForm() should be called instead.
        // However, it calls $form_state->setProgrammed(), which disables the Batch API.
        $simpletest_test_form = SimpletestTestForm::create(\Drupal::getContainer());
        $simpletest_test_form->buildForm($form_execute, $form_state_execute);
        $simpletest_test_form->submitForm($form_execute, $form_state_execute);
        if ($redirect = $form_state_execute->getRedirect()) {
            $form_state->setRedirectUrl($redirect);
        }
    }
    
    /**
     * Get test results for $test_id.
     *
     * @param int $test_id
     *   The test_id to retrieve results of.
     *
     * @return array
     *   Array of results grouped by test_class.
     */
    protected function getResults($test_id) {
        return $this->database
            ->select('simpletest')
            ->fields('simpletest')
            ->condition('test_id', $test_id)
            ->orderBy('test_class')
            ->orderBy('message_id')
            ->execute()
            ->fetchAll();
    }
    
    /**
     * Adds the result form to a $form.
     *
     * This is a static method so that run-tests.sh can use it to generate a
     * results page completely external to Drupal. This is why the UI strings are
     * not wrapped in t().
     *
     * @param array $form
     *   The form to attach the results to.
     * @param array $results
     *   The simpletest results.
     *
     * @return array
     *   A list of tests the passed and failed. The array has two keys, 'pass' and
     *   'fail'. Each contains a list of test classes.
     *
     * @see simpletest_script_open_browser()
     * @see run-tests.sh
     */
    public static function addResultForm(array &$form, array $results) {
        // Transform the test results to be grouped by test class.
        $test_results = [];
        foreach ($results as $result) {
            if (!isset($test_results[$result->test_class])) {
                $test_results[$result->test_class] = [];
            }
            $test_results[$result->test_class][] = $result;
        }
        $image_status_map = static::buildStatusImageMap();
        // Keep track of which test cases passed or failed.
        $filter = [
            'pass' => [],
            'fail' => [],
        ];
        // Summary result widget.
        $form['result'] = [
            '#type' => 'fieldset',
            '#title' => 'Results',
            // Because this is used in a theme-less situation need to provide a
            // default.
'#attributes' => [],
        ];
        $form['result']['summary'] = $summary = [
            '#theme' => 'simpletest_result_summary',
            '#pass' => 0,
            '#fail' => 0,
            '#exception' => 0,
            '#debug' => 0,
        ];
        \Drupal::service('test_discovery')->registerTestNamespaces();
        // Cycle through each test group.
        $header = [
            'Message',
            'Group',
            'Filename',
            'Line',
            'Function',
            [
                'colspan' => 2,
                'data' => 'Status',
            ],
        ];
        $form['result']['results'] = [];
        foreach ($test_results as $group => $assertions) {
            // Create group details with summary information.
            $info = TestDiscovery::getTestInfo($group);
            $form['result']['results'][$group] = [
                '#type' => 'details',
                '#title' => $info['name'],
                '#open' => TRUE,
                '#description' => $info['description'],
            ];
            $form['result']['results'][$group]['summary'] = $summary;
            $group_summary =& $form['result']['results'][$group]['summary'];
            // Create table of assertions for the group.
            $rows = [];
            foreach ($assertions as $assertion) {
                $row = [];
                $row[] = [
                    'data' => [
                        '#markup' => $assertion->message,
                    ],
                ];
                $row[] = $assertion->message_group;
                $row[] = \Drupal::service('file_system')->basename($assertion->file);
                $row[] = $assertion->line;
                $row[] = $assertion->function;
                $row[] = [
                    'data' => $image_status_map[$assertion->status],
                ];
                $class = 'simpletest-' . $assertion->status;
                if ($assertion->message_group == 'Debug') {
                    $class = 'simpletest-debug';
                }
                $rows[] = [
                    'data' => $row,
                    'class' => [
                        $class,
                    ],
                ];
                $group_summary['#' . $assertion->status]++;
                $form['result']['summary']['#' . $assertion->status]++;
            }
            $form['result']['results'][$group]['table'] = [
                '#type' => 'table',
                '#header' => $header,
                '#rows' => $rows,
            ];
            // Set summary information.
            $group_summary['#ok'] = $group_summary['#fail'] + $group_summary['#exception'] == 0;
            $form['result']['results'][$group]['#open'] = !$group_summary['#ok'];
            // Store test group (class) as for use in filter.
            $filter[$group_summary['#ok'] ? 'pass' : 'fail'][] = $group;
        }
        // Overall summary status.
        $form['result']['summary']['#ok'] = $form['result']['summary']['#fail'] + $form['result']['summary']['#exception'] == 0;
        return $filter;
    }

}

Members

Title Sort descending Deprecated Modifiers Object type Summary Overriden Title Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
FormBase::$configFactory protected property The config factory. 3
FormBase::$requestStack protected property The request stack. 1
FormBase::$routeMatch protected property The route match.
FormBase::config protected function Retrieves a configuration object.
FormBase::configFactory protected function Gets the config factory for this form. 3
FormBase::container private function Returns the service container.
FormBase::currentUser protected function Gets the current user.
FormBase::getRequest protected function Gets the request object.
FormBase::getRouteMatch protected function Gets the route match.
FormBase::logger protected function Gets the logger for a specific channel.
FormBase::redirect protected function Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait::redirect
FormBase::resetConfigFactory public function Resets the configuration factory.
FormBase::setConfigFactory public function Sets the config factory for this form.
FormBase::setRequestStack public function Sets the request stack object to use.
FormBase::validateForm public function Form validation handler. Overrides FormInterface::validateForm 73
LinkGeneratorTrait::$linkGenerator protected property The link generator. 1
LinkGeneratorTrait::getLinkGenerator Deprecated protected function Returns the link generator.
LinkGeneratorTrait::l Deprecated protected function Renders a link to a route given a route name and its parameters.
LinkGeneratorTrait::setLinkGenerator Deprecated public function Sets the link generator service.
LoggerChannelTrait::$loggerFactory protected property The logger channel factory service.
LoggerChannelTrait::getLogger protected function Gets the logger for a specific channel.
LoggerChannelTrait::setLoggerFactory public function Injects the logger channel factory.
MessengerTrait::$messenger protected property The messenger. 17
MessengerTrait::messenger public function Gets the messenger. 17
MessengerTrait::setMessenger public function Sets the messenger.
RedirectDestinationTrait::$redirectDestination protected property The redirect destination service. 1
RedirectDestinationTrait::getDestinationArray protected function Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url.
RedirectDestinationTrait::getRedirectDestination protected function Returns the redirect destination service.
RedirectDestinationTrait::setRedirectDestination public function Sets the redirect destination service.
SimpletestResultsForm::$cleaner protected property The environment cleaner service.
SimpletestResultsForm::$database protected property The database connection service.
SimpletestResultsForm::$statusImageMap protected property Associative array of themed result images keyed by status.
SimpletestResultsForm::addResultForm public static function Adds the result form to a $form.
SimpletestResultsForm::buildForm public function Form constructor. Overrides FormInterface::buildForm
SimpletestResultsForm::buildStatusImageMap protected static function Builds the status image map.
SimpletestResultsForm::create public static function Instantiates a new instance of this class. Overrides FormBase::create
SimpletestResultsForm::getFormId public function Returns a unique string identifying the form. Overrides FormInterface::getFormId
SimpletestResultsForm::getResults protected function Get test results for $test_id.
SimpletestResultsForm::submitForm public function Form submission handler. Overrides FormInterface::submitForm
SimpletestResultsForm::__construct public function Constructs a \Drupal\simpletest\Form\SimpletestResultsForm object.
StringTranslationTrait::$stringTranslation protected property The string translation service.
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
UrlGeneratorTrait::$urlGenerator protected property The url generator.
UrlGeneratorTrait::getUrlGenerator Deprecated protected function Returns the URL generator service.
UrlGeneratorTrait::setUrlGenerator Deprecated public function Sets the URL generator service.
UrlGeneratorTrait::url Deprecated protected function Generates a URL or path for a specific route based on the given parameters.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.