summaryrefslogtreecommitdiffstatshomepage
path: root/core/tests/Drupal/KernelTests/AssertConfigTrait.php
blob: 6ac55e2c7198ec73d82fc70d9fcb30e4c581dbe5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<?php

declare(strict_types=1);

namespace Drupal\KernelTests;

use Drupal\Component\Diff\Diff;

/**
 * Trait to help with diffing config.
 */
trait AssertConfigTrait {

  /**
   * Ensures that a specific config diff does not contain unwanted changes.
   *
   * @param \Drupal\Component\Diff\Diff $result
   *   The diff result for the passed in config name.
   * @param string $config_name
   *   The config name to check.
   * @param array $skipped_config
   *   An array of skipped config, keyed by string. If the value is TRUE, the
   *   entire file will be ignored, otherwise it's an array of strings which are
   *   ignored.
   *
   * @throws \Exception
   *   Thrown when a configuration is different.
   */
  protected function assertConfigDiff(Diff $result, $config_name, array $skipped_config) {
    foreach ($result->getEdits() as $op) {
      switch (get_class($op)) {
        case 'Drupal\Component\Diff\Engine\DiffOpCopy':
          // Nothing to do, a copy is what we expect.
          break;

        case 'Drupal\Component\Diff\Engine\DiffOpDelete':
        case 'Drupal\Component\Diff\Engine\DiffOpChange':
          // It is not part of the skipped config, so we can directly throw the
          // exception.
          if (!in_array($config_name, array_keys($skipped_config))) {
            throw new \Exception($config_name . ': ' . var_export($op, TRUE));
          }

          // Allow to skip entire config files.
          if ($skipped_config[$config_name] === TRUE) {
            break;
          }

          // Allow to skip some specific lines of imported config files.
          // Ensure that the only changed lines are the ones we marked as
          // skipped.
          $all_skipped = TRUE;

          $changes = get_class($op) == 'Drupal\Component\Diff\Engine\DiffOpDelete' ? $op->orig : $op->closing;
          foreach ($changes as $closing) {
            // Skip some of the changes, as they are caused by module install
            // code.
            $found = FALSE;
            if (!empty($skipped_config[$config_name])) {
              foreach ($skipped_config[$config_name] as $line) {
                if (str_contains($closing, $line)) {
                  $found = TRUE;
                  break;
                }
              }
            }
            $all_skipped = $all_skipped && $found;
          }

          if (!$all_skipped) {
            throw new \Exception($config_name . ': ' . var_export($op, TRUE));
          }
          break;

        case 'Drupal\Component\Diff\Engine\DiffOpAdd':
          // The _core property does not exist in the default config.
          if ($op->closing[0] === '_core:') {
            break;
          }
          foreach ($op->closing as $closing) {
            // The UUIDs don't exist in the default config.
            if (str_starts_with($closing, 'uuid: ')) {
              break;
            }
            throw new \Exception($config_name . ': ' . var_export($op, TRUE));
          }
          break;

        default:
          throw new \Exception($config_name . ': ' . var_export($op, TRUE));
      }
    }
  }

}