3 namespace Drupal\system\Tests\Cache;
5 use Drupal\Core\Cache\Cache;
9 * Provides test assertions for testing page-level cache contexts & tags.
11 * Can be used by test classes that extend \Drupal\simpletest\WebTestBase.
13 * @deprecated Scheduled for removal in Drupal 9.0.0. Use
14 * \Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait
17 * @see https://www.drupal.org/node/2896632
19 trait AssertPageCacheContextsAndTagsTrait {
22 * Enables page caching.
24 protected function enablePageCaching() {
25 $config = $this->config('system.performance');
26 $config->set('cache.page.max_age', 300);
31 * Gets a specific header value as array.
33 * @param string $header_name
37 * The header value, potentially exploded by spaces.
39 protected function getCacheHeaderValues($header_name) {
40 $header_value = $this->drupalGetHeader($header_name);
41 if (empty($header_value)) {
45 return explode(' ', $header_value);
50 * Asserts whether an expected cache context was present in the last response.
52 * @param string $expected_cache_context
53 * The expected cache context.
55 protected function assertCacheContext($expected_cache_context) {
56 $cache_contexts = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Contexts'));
57 $this->assertTrue(in_array($expected_cache_context, $cache_contexts), "'" . $expected_cache_context . "' is present in the X-Drupal-Cache-Contexts header.");
61 * Asserts that a cache context was not present in the last response.
63 * @param string $not_expected_cache_context
64 * The expected cache context.
66 protected function assertNoCacheContext($not_expected_cache_context) {
67 $cache_contexts = explode(' ', $this->drupalGetHeader('X-Drupal-Cache-Contexts'));
68 $this->assertFalse(in_array($not_expected_cache_context, $cache_contexts), "'" . $not_expected_cache_context . "' is not present in the X-Drupal-Cache-Contexts header.");
72 * Asserts page cache miss, then hit for the given URL; checks cache headers.
74 * @param \Drupal\Core\Url $url
76 * @param string[] $expected_contexts
77 * The expected cache contexts for the given URL.
78 * @param string[] $expected_tags
79 * The expected cache tags for the given URL.
81 protected function assertPageCacheContextsAndTags(Url $url, array $expected_contexts, array $expected_tags) {
82 $absolute_url = $url->setAbsolute()->toString();
83 sort($expected_contexts);
86 // Assert cache miss + expected cache contexts + tags.
87 $this->drupalGet($absolute_url);
88 $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
89 $this->assertCacheTags($expected_tags);
90 $this->assertCacheContexts($expected_contexts);
92 // Assert cache hit + expected cache contexts + tags.
93 $this->drupalGet($absolute_url);
94 $this->assertCacheTags($expected_tags);
95 $this->assertCacheContexts($expected_contexts);
97 // Assert page cache item + expected cache tags.
98 $cid_parts = [$url->setAbsolute()->toString(), 'html'];
99 $cid = implode(':', $cid_parts);
100 $cache_entry = \Drupal::cache('page')->get($cid);
101 sort($cache_entry->tags);
102 $this->assertEqual($cache_entry->tags, $expected_tags);
103 $this->debugCacheTags($cache_entry->tags, $expected_tags);
107 * Provides debug information for cache tags.
109 * @param string[] $actual_tags
110 * The actual cache tags.
111 * @param string[] $expected_tags
112 * The expected cache tags.
114 protected function debugCacheTags(array $actual_tags, array $expected_tags) {
115 if ($actual_tags !== $expected_tags) {
116 debug('Unwanted cache tags in response: ' . implode(',', array_diff($actual_tags, $expected_tags)));
117 debug('Missing cache tags in response: ' . implode(',', array_diff($expected_tags, $actual_tags)));
122 * Ensures that some cache tags are present in the current response.
124 * @param string[] $expected_tags
126 * @param bool $include_default_tags
127 * (optional) Whether the default cache tags should be included.
129 protected function assertCacheTags(array $expected_tags, $include_default_tags = TRUE) {
130 // The anonymous role cache tag is only added if the user is anonymous.
131 if ($include_default_tags) {
132 if (\Drupal::currentUser()->isAnonymous()) {
133 $expected_tags = Cache::mergeTags($expected_tags, ['config:user.role.anonymous']);
135 $expected_tags[] = 'http_response';
137 $actual_tags = $this->getCacheHeaderValues('X-Drupal-Cache-Tags');
138 $expected_tags = array_unique($expected_tags);
139 sort($expected_tags);
141 $this->assertIdentical($actual_tags, $expected_tags);
142 $this->debugCacheTags($actual_tags, $expected_tags);
146 * Ensures that some cache contexts are present in the current response.
148 * @param string[] $expected_contexts
149 * The expected cache contexts.
150 * @param string $message
151 * (optional) A verbose message to output.
152 * @param bool $include_default_contexts
153 * (optional) Whether the default contexts should automatically be included.
156 * TRUE if the assertion succeeded, FALSE otherwise.
158 protected function assertCacheContexts(array $expected_contexts, $message = NULL, $include_default_contexts = TRUE) {
159 if ($include_default_contexts) {
160 $default_contexts = ['languages:language_interface', 'theme'];
161 // Add the user.permission context to the list of default contexts except
162 // when user is already there.
163 if (!in_array('user', $expected_contexts)) {
164 $default_contexts[] = 'user.permissions';
166 $expected_contexts = Cache::mergeContexts($expected_contexts, $default_contexts);
169 $actual_contexts = $this->getCacheHeaderValues('X-Drupal-Cache-Contexts');
170 sort($expected_contexts);
171 sort($actual_contexts);
172 $match = $actual_contexts === $expected_contexts;
174 debug('Unwanted cache contexts in response: ' . implode(',', array_diff($actual_contexts, $expected_contexts)));
175 debug('Missing cache contexts in response: ' . implode(',', array_diff($expected_contexts, $actual_contexts)));
178 $this->assertIdentical($actual_contexts, $expected_contexts, $message);
180 // For compatibility with both BrowserTestBase and WebTestBase always return
186 * Asserts the max age header.
188 * @param int $max_age
190 protected function assertCacheMaxAge($max_age) {
191 $cache_control_header = $this->drupalGetHeader('Cache-Control');
192 if (strpos($cache_control_header, 'max-age:' . $max_age) === FALSE) {
193 debug('Expected max-age:' . $max_age . '; Response max-age:' . $cache_control_header);
195 $this->assertTrue(strpos($cache_control_header, 'max-age:' . $max_age));