ControllerTest::setUp()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 41
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 25
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 41
rs 9.52
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Drupal\Tests\mongodb_watchdog\Functional;
6
7
use Behat\Mink\Exception\ExpectationException;
0 ignored issues
show
Bug introduced by
The type Behat\Mink\Exception\ExpectationException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use Behat\Mink\Exception\ResponseTextException;
0 ignored issues
show
Bug introduced by
The type Behat\Mink\Exception\ResponseTextException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use Drupal\Core\Logger\RfcLogLevel;
0 ignored issues
show
Bug introduced by
The type Drupal\Core\Logger\RfcLogLevel was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use Drupal\Core\StringTranslation\StringTranslationTrait;
0 ignored issues
show
Bug introduced by
The type Drupal\Core\StringTransl...\StringTranslationTrait was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use Drupal\mongodb\MongoDb;
12
use Drupal\mongodb_watchdog\Logger;
13
use Drupal\Tests\BrowserTestBase;
0 ignored issues
show
Bug introduced by
The type Drupal\Tests\BrowserTestBase was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use Drupal\user\Entity\User;
0 ignored issues
show
Bug introduced by
The type Drupal\user\Entity\User was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use Psr\Log\LoggerInterface;
0 ignored issues
show
Bug introduced by
The type Psr\Log\LoggerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
use Psr\Log\LogLevel;
0 ignored issues
show
Bug introduced by
The type Psr\Log\LogLevel was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use Symfony\Component\HttpFoundation\Response;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\HttpFoundation\Response was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
19
/**
20
 * Test the MongoDB report controllers.
21
 *
22
 * @group MongoDB
23
 */
24
class ControllerTest extends BrowserTestBase {
25
26
  use StringTranslationTrait;
27
28
  const DEFAULT_URI = 'mongodb://localhost:27017';
29
30
  const CLIENT_TEST_ALIAS = 'test';
31
32
  const DB_DEFAULT_ALIAS = 'default';
33
34
  const PATH_DENIED = '/admin/reports/mongodb/watchdog/access-denied';
35
36
  const PATH_EVENT_BASE = "/admin/reports/mongodb/watchdog/";
37
38
  const PATH_NOT_FOUND = '/admin/reports/mongodb/watchdog/page-not-found';
39
40
  const PATH_OVERVIEW = 'admin/reports/mongodb/watchdog';
41
42
  /**
43
   * Map of PSR3 log constants to RFC 5424 log constants.
44
   *
45
   * @var array<string,int>
46
   */
47
  const LEVEL_TRANSLATION = [
48
    LogLevel::EMERGENCY => RfcLogLevel::EMERGENCY,
49
    LogLevel::ALERT => RfcLogLevel::ALERT,
50
    LogLevel::CRITICAL => RfcLogLevel::CRITICAL,
51
    LogLevel::ERROR => RfcLogLevel::ERROR,
52
    LogLevel::WARNING => RfcLogLevel::WARNING,
53
    LogLevel::NOTICE => RfcLogLevel::NOTICE,
54
    LogLevel::INFO => RfcLogLevel::INFO,
55
    LogLevel::DEBUG => RfcLogLevel::DEBUG,
56
  ];
57
58
  /**
59
   * These modules need to be enabled.
60
   *
61
   * @var string[]
62
   */
63
  protected static $modules = [
64
    // Needed to check admin/help/mongodb.
65
    'help',
66
    MongoDb::MODULE,
67
    Logger::MODULE,
68
  ];
69
70
  /**
71
   * An administrator account.
72
   *
73
   * @var \Drupal\user\Entity\User|false
74
   */
75
  protected User|false $adminUser;
76
77
  /**
78
   * A basic authenticated user account.
79
   *
80
   * @var \Drupal\user\Entity\User|false
81
   */
82
  protected User|false $anyUser;
83
84
  /**
85
   * An administrator-type user account, but not an administrator.
86
   *
87
   * @var \Drupal\user\Entity\User|false
88
   */
89
  protected User|false $bigUser;
90
91
  /**
92
   * The event templates collection.
93
   *
94
   * @var ?\MongoDB\Collection
95
   */
96
  protected $collection;
97
98
  /**
99
   * The default theme, needed after 8.8.0.
100
   *
101
   * @var string
102
   *
103
   * @see https://www.drupal.org/node/3083055
104
   */
105
  protected $defaultTheme = 'stark';
106
107
  /**
108
   * The time the test started, simulating a request time.
109
   *
110
   * @var int
111
   */
112
  protected $requestTime;
113
114
  /**
115
   * The site base URI.
116
   *
117
   * @var string
118
   */
119
  protected $uri;
120
121
  /**
122
   * Remove all Drupal markup placeholders.
123
   *
124
   * @param string $message
125
   *   The raw message.
126
   *
127
   * @return string
128
   *   The replacement message.
129
   */
130
  protected static function neuter(string $message): string {
131
    return str_replace(['{', '}', '@', '%', ':'], '', $message);
132
  }
133
134
  /**
135
   * {@inheritdoc}
136
   *
137
   * Configure settings and create users with specific permissions.
138
   *
139
   * @see \Drupal\Tests\mongodb_watchdog\Functional\ControllerTest::writeSettings()
140
   */
141
  public function setUp(): void {
142
    // $_ENV if it comes from phpunit.xml <env>
143
    // $_SERVER if it comes from the phpunit command line environment.
144
    $this->uri = $_ENV['MONGODB_URI']
145
      ?? $_SERVER['MONGODB_URI']
146
      ?? static::DEFAULT_URI;
147
148
    parent::setUp();
149
150
    // Create users.
151
    $this->adminUser = $this->drupalCreateUser([], 'test_admin', TRUE);
152
    $this->bigUser = $this->drupalCreateUser(
153
      [
154
        'administer site configuration',
155
        'access administration pages',
156
        'access site reports',
157
        'administer users',
158
      ],
159
      'test_honcho'
160
    );
161
    $this->anyUser = $this->drupalCreateUser(
162
      [
163
        'access content',
164
      ],
165
      'test_lambda'
166
    );
167
168
    $this->requestTime = $this->container
169
      ->get('datetime.time')
170
      ->getCurrentTime();
171
172
    try {
173
      $this->collection = $this->container
174
        ->get(MongoDb::SERVICE_DB_FACTORY)
175
        ->get(Logger::DB_LOGGER)
176
        ->selectCollection(Logger::TEMPLATE_COLLECTION);
177
    }
178
    catch (\Exception $e) {
179
      $this->collection = NULL;
180
    }
181
    $this->assertNotNull($this->collection, (string) $this->t('Access MongoDB watchdog collection'));
182
  }
183
184
  /**
185
   * {@inheritdoc}
186
   */
187
  public function tearDown(): void {
188
    // Get the database before container is torn down.
189
    $database = $this->container
190
      ->get(MongoDb::SERVICE_DB_FACTORY)
191
      ->get(Logger::DB_LOGGER);
192
193
    // Might trigger some more log insertions, so do not drop yet.
194
    parent::tearDown();
195
196
    $database->drop();
197
  }
198
199
  /**
200
   * Rewrites the settings.php file of the test site.
201
   *
202
   * @param array<string,mixed> $settings
203
   *   An array of settings to write out, in the format expected by
204
   *   drupal_rewrite_settings().
205
   *
206
   * @throws \Exception
207
   *
208
   * @see \Drupal\Core\Test\FunctionalTestSetupTrait::writeSettings()
209
   */
210
  protected function writeSettings(array $settings): void {
211
    // Taken from trait.
212
    include_once DRUPAL_ROOT . '/core/includes/install.inc';
0 ignored issues
show
Bug introduced by
The constant Drupal\Tests\mongodb_wat...\Functional\DRUPAL_ROOT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
213
    $filename = $this->siteDirectory . '/settings.php';
214
215
    // Customizations.
216
    $settings['settings'] += [
217
      MongoDb::MODULE => (object) [
218
        'value' => $this->getSettingsArray(),
219
        'required' => TRUE,
220
      ],
221
    ];
222
223
    // End of code taken from trait again.
224
    // system_requirements() removes write permissions from settings.php
225
    // whenever it is invoked.
226
    // Not using File API; a potential error must trigger a PHP warning.
227
    chmod($filename, 0666);
228
    drupal_rewrite_settings($settings, $filename);
0 ignored issues
show
Bug introduced by
The function drupal_rewrite_settings was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

228
    /** @scrutinizer ignore-call */ 
229
    drupal_rewrite_settings($settings, $filename);
Loading history...
229
  }
230
231
  /**
232
   * Prepare the Settings from a base set of MongoDB settings.
233
   *
234
   * @return array{clients: array<string,array<string,mixed>>, databases: array<string,array{0:string,1:string}>}
235
   *   A settings array only containing MongoDB-related settings.
236
   */
237
  protected function getSettingsArray(): array {
238
    return [
239
      'clients' => [
240
        static::CLIENT_TEST_ALIAS => [
241
          'uri' => $this->uri,
242
          'uriOptions' => [],
243
          'driverOptions' => [],
244
        ],
245
      ],
246
      'databases' => [
247
        static::DB_DEFAULT_ALIAS => [
248
          static::CLIENT_TEST_ALIAS,
249
          $this->getDatabasePrefix(),
250
        ],
251
        Logger::DB_LOGGER => [
252
          static::CLIENT_TEST_ALIAS,
253
          $this->getDatabasePrefix(),
254
        ],
255
      ],
256
    ];
257
  }
258
259
  /**
260
   * Getter for the test database prefix.
261
   *
262
   * @return string
263
   *   The prefix.
264
   *
265
   * @see \Drupal\KernelTests\KernelTestBase::getDatabasePrefix()
266
   */
267
  protected function getDatabasePrefix(): string {
268
    return $this->databasePrefix;
269
  }
270
271
  /**
272
   * Get the log entry information form the page.
273
   *
274
   * @return array<int,array<string,mixed>>
275
   *   List of entries and their information.
276
   */
277
  protected function getLogEntries(): array {
278
    $entries = [];
279
    if ($table = $this->getLogsEntriesTable()) {
280
      /** @var \Behat\Mink\Element\NodeElement $row */
281
      foreach ($table as $row) {
282
        /** @var \Behat\Mink\Element\NodeElement[] $cells */
283
        $cells = $row->findAll('css', 'td');
284
        $entries[] = [
285
          'severity' => $this->getSeverityConstant($cells[2]->getAttribute('class')),
286
          'type' => $cells[3]->getText(),
287
          'message' => $cells[4]->getText(),
288
        ];
289
      }
290
    }
291
    return $entries;
292
  }
293
294
  /**
295
   * Gets the watchdog severity constant corresponding to the CSS class.
296
   *
297
   * @param string $class
298
   *   CSS class attribute.
299
   *
300
   * @return int|null
301
   *   The watchdog severity constant or NULL if not found.
302
   */
303
  protected function getSeverityConstant(string $class): ?int {
304
    // Class: "mongodb-watchdog__severity--(level)", prefix length = 28.
305
    $level = substr($class, 28);
306
    return static::LEVEL_TRANSLATION[$level];
307
  }
308
309
  /**
310
   * Find the Logs table in the DOM.
311
   *
312
   * @return \Behat\Mink\Element\NodeElement[]
313
   *   The return value of a xpath search.
314
   */
315
  protected function getLogsEntriesTable(): array {
316
    return $this->xpath('.//table/tbody/tr');
317
  }
318
319
  /**
320
   * Asserts that the counts for displayed entries match the expected counts.
321
   *
322
   * @param array<int,string[]> $types
323
   *   The type information to compare against.
324
   */
325
  protected function assertTypeCount(array $types): void {
326
    $entries = $this->getLogEntries();
327
    $reducer = function ($accu, $curr) {
328
      $accu[$curr['type'] . '-' . $curr['severity']] = [
329
        $curr['type'],
330
        $curr['severity'],
331
      ];
332
      return $accu;
333
    };
334
    $actual = array_reduce($entries, $reducer, []);
335
    $expected = array_reduce($types, $reducer, []);
336
    $this->assertEquals($expected, $actual, "Inserted events are found on page");
337
  }
338
339
  /**
340
   * Generate dblog entries.
341
   *
342
   * @param \Psr\Log\LoggerInterface $logger
343
   *   The mongodb.logger service.
344
   * @param int $count
345
   *   Number of log entries to generate.
346
   * @param string $type
347
   *   The type of watchdog entry.
348
   * @param int $severity
349
   *   The severity of the watchdog entry.
350
   */
351
  private function insertLogEntries(
352
    LoggerInterface $logger,
353
    int $count,
354
    string $type = 'custom',
355
    int $severity = RfcLogLevel::EMERGENCY
356
  ): void {
357
    $ip = '::1';
358
    $context = [
359
      'channel' => $type,
360
      'link' => NULL,
361
      'user' => ['uid' => $this->bigUser->id()],
362
      'request_uri' => "http://[$ip]/",
363
      'referer' => $_SERVER['HTTP_REFERER'] ?? '',
364
      'ip' => $ip,
365
      'timestamp' => $this->requestTime,
366
    ];
367
    $message = $this->randomString();
368
    for ($i = 0; $i < $count; $i++) {
369
      $logger->log($severity, $message, $context);
370
    }
371
  }
372
373
  /**
374
   * Verify the logged-in user has the desired access to the log report.
375
   *
376
   * @param int $statusCode
377
   *   HTTP status code.
378
   *
379
   * @throws \Behat\Mink\Exception\ExpectationException
380
   * @throws \Behat\Mink\Exception\ResponseTextException
381
   *
382
   * The first of the assertions would really belong in a functional test for
383
   * the mongodb module. But until it gets a functional test, keeping it here
384
   * saves some test running time over having one more functional test in
385
   * mongodb module just for this.
386
   */
387
  private function verifyReports($statusCode = Response::HTTP_OK): void {
388
    // View MongoDB help page.
389
    $this->drupalGet('/admin/help');
390
    $session = $this->assertSession();
391
    $session->statusCodeEquals($statusCode);
392
    if ($statusCode == Response::HTTP_OK) {
393
      $session->pageTextContains('MongoDB');
394
    }
395
396
    $this->drupalGet('/admin/help/mongodb');
397
    $session = $this->assertSession();
398
    $session->statusCodeEquals($statusCode);
399
    if ($statusCode == Response::HTTP_OK) {
400
      // DBLog help was displayed.
401
      $session->pageTextContains('implements a generic interface');
402
    }
403
404
    // View MongoDB watchdog overview report.
405
    $this->drupalGet(static::PATH_OVERVIEW);
406
    $session = $this->assertSession();
407
    $session->statusCodeEquals($statusCode);
408
    if ($statusCode == Response::HTTP_OK) {
409
      // MongoDB watchdog report was displayed.
410
      $expectedTexts = [
411
        'Recent log messages in MongoDB',
412
        'Filter log messages',
413
        'Type',
414
        'Severity',
415
        'Latest',
416
        'Severity',
417
        'Message',
418
        'Source',
419
      ];
420
      foreach ($expectedTexts as $expectedText) {
421
        $session->pageTextContains($expectedText);
422
      }
423
    }
424
425
    // View MongoDB watchdog page-not-found report.
426
    $this->drupalGet(self::PATH_NOT_FOUND);
427
    $session = $this->assertSession();
428
    $session->statusCodeEquals($statusCode);
429
    if ($statusCode == Response::HTTP_OK) {
430
      // MongoDB watchdog page-not-found report was displayed.
431
      $session->pageTextContains("Top 'page not found' errors in MongoDB");
432
    }
433
434
    // View MongoDB watchdog access-denied report.
435
    $this->drupalGet(static::PATH_DENIED);
436
    $session = $this->assertSession();
437
    $session->statusCodeEquals($statusCode);
438
    if ($statusCode == Response::HTTP_OK) {
439
      // MongoDB watchdog access-denied report was displayed.
440
      $session->pageTextContains("Top 'access denied' errors in MongoDB");
441
    }
442
443
    // Create an event to ensure an event page exists, using the standard PSR-3
444
    // service instead of the Drupal logger channel to ensure getting this
445
    // logger with its specific features.
446
    $expectedMessage = $this->randomString(32);
447
    /** @var \Drupal\mongodb_watchdog\Logger $logger */
448
    $logger = $this->container->get(Logger::SERVICE_LOGGER);
449
    $logger->info($expectedMessage, ['with' => 'context']);
450
451
    $selector = ['message' => $expectedMessage];
452
    $event = $logger->templateCollection()
453
      ->findOne($selector, MongoDb::ID_PROJECTION);
454
    $this->assertNotNull($event);
455
    $eventId = $event['_id'];
456
457
    // View MongoDB Watchdog event page.
458
    $this->drupalGet(static::PATH_EVENT_BASE . $eventId);
459
    $session = $this->assertSession();
460
    $session->statusCodeEquals($statusCode);
461
    // MongoDB watchdog event page was displayed.
462
    if ($statusCode == Response::HTTP_OK) {
463
      $expectedTexts = [
464
        'Event template',
465
        'ID',
466
        'Changed',
467
        'Count',
468
        'Type',
469
        'Message',
470
        'Severity',
471
        $eventId,
472
        'Event occurrences',
473
        $expectedMessage,
474
      ];
475
      foreach ($expectedTexts as $expectedText) {
476
        $session->pageTextContains($expectedText);
477
      }
478
    }
479
  }
480
481
  /**
482
   * The access and contents of the admin/reports/mongodb/watchdog[/*] pages.
483
   *
484
   * @throws \Behat\Mink\Exception\ExpectationException
485
   * @throws \Behat\Mink\Exception\ResponseTextException
486
   *
487
   * @todo verifyRowLimit(), verifyCron(), verifyEvents() as per DbLog.
488
   */
489
  public function testLoggerReportsAccess(): void {
490
    $expectations = [
491
      [$this->adminUser, Response::HTTP_OK],
492
      [$this->bigUser, Response::HTTP_OK],
493
      [$this->anyUser, Response::HTTP_FORBIDDEN],
494
    ];
495
    foreach ($expectations as $expectation) {
496
      /** @var \Drupal\user\Entity\User $account */
497
      [$account, $statusCode] = $expectation;
498
      $this->drupalLogin($account);
499
      try {
500
        $this->verifyReports($statusCode);
501
      }
502
      catch (ResponseTextException $e) {
503
        $this->fail(sprintf("response text exception: %s", $e));
504
      }
505
      catch (ExpectationException $e) {
506
        $this->fail(sprintf("expectation exception: %s", $e));
507
      }
508
    }
509
  }
510
511
  /**
512
   * Test the UI clearing feature.
513
   */
514
  public function testLoggerAddAndUiClear(): void {
515
    // Drop the logger database to ensure no collections.
516
    $this->container->get(MongoDb::SERVICE_DB_FACTORY)
517
      ->get(Logger::DB_LOGGER)
518
      ->drop();
519
520
    /** @var \Drupal\Core\Logger\LoggerChannelInterface $loggerChannel */
521
    $loggerChannel = $this->container->get(Logger::SERVICE_CHANNEL);
522
    // Add a watchdog entry. Be sure not to include placeholder delimiters.
523
    $message = static::neuter($this->randomString(32));
524
    $loggerChannel->notice($message);
525
526
    // Make sure the collections were updated.
527
    /** @var \Drupal\mongodb_watchdog\Logger $logger */
528
    $logger = $this->container->get(Logger::SERVICE_LOGGER);
529
    $templates = $logger->templateCollection();
530
    $this->assertEquals(
531
      1,
532
      $templates->countDocuments(),
533
      'Logging created templates collection and added a template to it.'
534
    );
535
536
    $template = $templates->findOne(['message' => $message], MongoDb::ID_PROJECTION);
537
    $this->assertNotNull($template, "Logged message was found: [$message]");
538
    $templateId = $template['_id'];
539
    $events = $logger->eventCollection($templateId);
540
    $this->assertEquals(
541
      1,
542
      $events->countDocuments(),
543
      'Logging created events collection and added a template to it.'
544
    );
545
546
    // Login the admin user.
547
    $this->drupalLogin($this->adminUser);
548
    // Now post to clear the db table.
549
    $this->drupalGet('admin/reports/mongodb/confirm');
550
    $this->submitForm([], 'Confirm');
551
552
    // Make the sure logs were dropped. After a UI clear, the templates
553
    // collection should exist, since it is recreated as a capped collection as
554
    // part of the clear, but be empty, and there should be no event collection.
555
    $count = $templates->countDocuments();
556
    $failMessage = 'Logger templates collection was cleared';
557
    if ($count > 0) {
558
      $options = ['projection' => ['_id' => 0, 'message' => 1]];
559
      $messages = iterator_to_array($templates->find([], $options));
560
      $failMessage = "Logger templates collection still contains messages: "
561
        . json_encode($messages);
562
    }
563
    $this->assertEquals(0, $count, $failMessage);
564
    $this->assertFalse(
565
      $logger->eventCollections()->valid(),
566
      "Event collections were dropped"
567
    );
568
  }
569
570
  /**
571
   * Test the dblog filter on admin/reports/dblog.
572
   */
573
  public function testFilter(): void {
574
    $this->drupalLogin($this->bigUser);
575
576
    // Clear log to ensure that only generated entries are found.
577
    $database = $this->container
578
      ->get(MongoDb::SERVICE_DB_FACTORY)
579
      ->get(Logger::DB_LOGGER);
580
    $database->drop();
581
582
    $logger = $this->container->get(Logger::SERVICE_LOGGER);
583
584
    // Generate watchdog entries.
585
    $typeNames = [];
586
    $types = [];
587
    for ($i = 0; $i < 3; $i++) {
588
      $typeNames[] = $typeName = $this->randomMachineName();
589
      $severity = RfcLogLevel::EMERGENCY;
590
      for ($j = 0; $j < 3; $j++) {
591
        $types[] = $type = [
592
          'count' => mt_rand(1, 5),
593
          'type' => $typeName,
594
          'severity' => $severity++,
595
        ];
596
        $this->insertLogEntries($logger, $type['count'], $type['type'], $type['severity']);
597
      }
598
    }
599
    // View the dblog.
600
    $this->drupalGet(self::PATH_OVERVIEW);
601
602
    // Confirm all the entries are displayed.
603
    $this->assertTypeCount($types);
604
605
    // Filter by each type and confirm that entries with various severities are
606
    // displayed.
607
    foreach ($typeNames as $typeName) {
608
      $edit = [
609
        'type[]' => [$typeName],
610
      ];
611
      $this->submitForm($edit, 'Filter');
612
613
      // Check whether the displayed event templates match our filter.
614
      $filteredTypes = array_filter(
615
        $types,
616
        function (array $type) use ($typeName) {
617
          return $type['type'] === $typeName;
618
        }
619
      );
620
      $this->assertTypeCount($filteredTypes);
621
    }
622
623
    // Set filter to match each of the combined filter sets and confirm the
624
    // entries displayed.
625
    foreach ($types as $type) {
626
      $edit = [
627
        'type[]' => $typeType = $type['type'],
628
        'severity[]' => $typeSeverity = $type['severity'],
629
      ];
630
      $this->submitForm($edit, 'Filter');
631
632
      $filteredTypes = array_filter(
633
        $types,
634
        function (array $type) use ($typeType, $typeSeverity) {
635
          return $type['type'] === $typeType && $type['severity'] == $typeSeverity;
636
        }
637
      );
638
639
      $this->assertTypeCount($filteredTypes);
640
    }
641
  }
642
643
}
644