3 namespace Drupal\Tests\Core\Form;
5 use Drupal\Core\Form\FormCache;
6 use Drupal\Core\Form\FormState;
7 use Drupal\Tests\UnitTestCase;
10 * @coversDefaultClass \Drupal\Core\Form\FormCache
13 class FormCacheTest extends UnitTestCase {
16 * The form cache object under test.
18 * @var \Drupal\Core\Form\FormCache
23 * The expirable key value factory.
25 * @var \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
27 protected $keyValueExpirableFactory;
32 * @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
37 * The CSRF token generator.
39 * @var \Drupal\Core\Access\CsrfTokenGenerator|\PHPUnit_Framework_MockObject_MockObject
44 * The mocked module handler.
46 * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
48 protected $moduleHandler;
51 * The expirable key value store used by form cache.
53 * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface|\PHPUnit_Framework_MockObject_MockObject
55 protected $formCacheStore;
58 * The expirable key value store used by form state cache.
60 * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface|\PHPUnit_Framework_MockObject_MockObject
62 protected $formStateCacheStore;
67 * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
74 * @var \Symfony\Component\HttpFoundation\RequestStack|\PHPUnit_Framework_MockObject_MockObject
76 protected $requestStack;
79 * A policy rule determining the cacheability of a request.
81 * @var \Drupal\Core\PageCache\RequestPolicyInterface|\PHPUnit_Framework_MockObject_MockObject
83 protected $requestPolicy;
88 protected $runTestInSeparateProcess = TRUE;
93 protected $preserveGlobalState = FALSE;
98 protected function setUp() {
101 $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
103 $this->formCacheStore = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface');
104 $this->formStateCacheStore = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface');
105 $this->keyValueExpirableFactory = $this->getMock('Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface');
106 $this->keyValueExpirableFactory->expects($this->any())
108 ->will($this->returnValueMap([
109 ['form', $this->formCacheStore],
110 ['form_state', $this->formStateCacheStore],
113 $this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator')
114 ->disableOriginalConstructor()
116 $this->account = $this->getMock('Drupal\Core\Session\AccountInterface');
118 $this->logger = $this->getMock('Psr\Log\LoggerInterface');
119 $this->requestStack = $this->getMock('\Symfony\Component\HttpFoundation\RequestStack');
120 $this->requestPolicy = $this->getMock('\Drupal\Core\PageCache\RequestPolicyInterface');
122 $this->formCache = new FormCache($this->root, $this->keyValueExpirableFactory, $this->moduleHandler, $this->account, $this->csrfToken, $this->logger, $this->requestStack, $this->requestPolicy);
128 public function testGetCacheValidToken() {
129 $form_build_id = 'the_form_build_id';
130 $form_state = new FormState();
131 $cache_token = 'the_cache_token';
132 $cached_form = ['#cache_token' => $cache_token];
134 $this->formCacheStore->expects($this->once())
136 ->with($form_build_id)
137 ->willReturn($cached_form);
138 $this->csrfToken->expects($this->once())
142 $this->account->expects($this->never())
143 ->method('isAnonymous');
145 $form = $this->formCache->getCache($form_build_id, $form_state);
146 $this->assertSame($cached_form, $form);
152 public function testGetCacheInvalidToken() {
153 $form_build_id = 'the_form_build_id';
154 $form_state = new FormState();
155 $cache_token = 'the_cache_token';
156 $cached_form = ['#cache_token' => $cache_token];
158 $this->formCacheStore->expects($this->once())
160 ->with($form_build_id)
161 ->willReturn($cached_form);
162 $this->csrfToken->expects($this->once())
166 $this->account->expects($this->never())
167 ->method('isAnonymous');
169 $form = $this->formCache->getCache($form_build_id, $form_state);
170 $this->assertNull($form);
176 public function testGetCacheAnonUser() {
177 $form_build_id = 'the_form_build_id';
178 $form_state = new FormState();
179 $cached_form = ['#cache_token' => NULL];
181 $this->formCacheStore->expects($this->once())
183 ->with($form_build_id)
184 ->willReturn($cached_form);
185 $this->account->expects($this->once())
186 ->method('isAnonymous')
188 $this->csrfToken->expects($this->never())
189 ->method('validate');
191 $form = $this->formCache->getCache($form_build_id, $form_state);
192 $this->assertSame($cached_form, $form);
198 public function testGetCacheAuthUser() {
199 $form_build_id = 'the_form_build_id';
200 $form_state = new FormState();
201 $cached_form = ['#cache_token' => NULL];
203 $this->formCacheStore->expects($this->once())
205 ->with($form_build_id)
206 ->willReturn($cached_form);
207 $this->account->expects($this->once())
208 ->method('isAnonymous')
211 $form = $this->formCache->getCache($form_build_id, $form_state);
212 $this->assertNull($form);
218 public function testGetCacheNoForm() {
219 $form_build_id = 'the_form_build_id';
220 $form_state = new FormState();
223 $this->formCacheStore->expects($this->once())
225 ->with($form_build_id)
226 ->willReturn($cached_form);
227 $this->account->expects($this->never())
228 ->method('isAnonymous');
230 $form = $this->formCache->getCache($form_build_id, $form_state);
231 $this->assertNull($form);
237 public function testGetCacheImmutableForm() {
238 $form_build_id = 'the_form_build_id';
239 $form_state = (new FormState())
240 ->addBuildInfo('immutable', TRUE);
242 '#build_id' => 'the_old_build_form_id',
245 $this->account->expects($this->once())
246 ->method('isAnonymous')
248 $this->formCacheStore->expects($this->once())
250 ->with($form_build_id)
251 ->willReturn($cached_form);
253 $form = $this->formCache->getCache($form_build_id, $form_state);
254 $this->assertSame($cached_form['#build_id'], $form['#build_id_old']);
255 $this->assertNotSame($cached_form['#build_id'], $form['#build_id']);
256 $this->assertSame($form['#build_id'], $form['form_build_id']['#value']);
257 $this->assertSame($form['#build_id'], $form['form_build_id']['#id']);
261 * @covers ::loadCachedFormState
263 public function testLoadCachedFormState() {
264 $form_build_id = 'the_form_build_id';
265 $form_state = new FormState();
266 $cached_form = ['#cache_token' => NULL];
268 $this->formCacheStore->expects($this->once())
270 ->with($form_build_id)
271 ->willReturn($cached_form);
272 $this->account->expects($this->once())
273 ->method('isAnonymous')
276 $cached_form_state = ['storage' => ['foo' => 'bar']];
277 $this->formStateCacheStore->expects($this->once())
279 ->with($form_build_id)
280 ->willReturn($cached_form_state);
282 $this->formCache->getCache($form_build_id, $form_state);
283 $this->assertSame($cached_form_state['storage'], $form_state->getStorage());
287 * @covers ::loadCachedFormState
289 public function testLoadCachedFormStateWithFiles() {
290 $form_build_id = 'the_form_build_id';
291 $form_state = new FormState();
292 $cached_form = ['#cache_token' => NULL];
294 $this->formCacheStore->expects($this->once())
296 ->with($form_build_id)
297 ->willReturn($cached_form);
298 $this->account->expects($this->once())
299 ->method('isAnonymous')
302 $cached_form_state = ['build_info' => ['files' => [
304 'module' => 'a_module',
305 'type' => 'the_type',
306 'name' => 'some_name',
309 'module' => 'another_module',
312 $this->moduleHandler->expects($this->at(0))
313 ->method('loadInclude')
314 ->with('a_module', 'the_type', 'some_name');
315 $this->moduleHandler->expects($this->at(1))
316 ->method('loadInclude')
317 ->with('another_module', 'inc', 'another_module');
318 $this->formStateCacheStore->expects($this->once())
320 ->with($form_build_id)
321 ->willReturn($cached_form_state);
323 $this->formCache->getCache($form_build_id, $form_state);
329 public function testSetCacheWithForm() {
330 $form_build_id = 'the_form_build_id';
332 '#form_id' => 'the_form_id'
334 $form_state = new FormState();
336 $this->formCacheStore->expects($this->once())
337 ->method('setWithExpire')
338 ->with($form_build_id, $form, $this->isType('int'));
340 $form_state_data = $form_state->getCacheableArray();
341 $this->formStateCacheStore->expects($this->once())
342 ->method('setWithExpire')
343 ->with($form_build_id, $form_state_data, $this->isType('int'));
345 $this->formCache->setCache($form_build_id, $form, $form_state);
351 public function testSetCacheWithoutForm() {
352 $form_build_id = 'the_form_build_id';
354 $form_state = new FormState();
356 $this->formCacheStore->expects($this->never())
357 ->method('setWithExpire');
359 $form_state_data = $form_state->getCacheableArray();
360 $this->formStateCacheStore->expects($this->once())
361 ->method('setWithExpire')
362 ->with($form_build_id, $form_state_data, $this->isType('int'));
364 $this->formCache->setCache($form_build_id, $form, $form_state);
370 public function testSetCacheAuthUser() {
371 $form_build_id = 'the_form_build_id';
373 $form_state = new FormState();
375 $cache_token = 'the_cache_token';
377 $form_data['#cache_token'] = $cache_token;
378 $this->formCacheStore->expects($this->once())
379 ->method('setWithExpire')
380 ->with($form_build_id, $form_data, $this->isType('int'));
382 $form_state_data = $form_state->getCacheableArray();
383 $this->formStateCacheStore->expects($this->once())
384 ->method('setWithExpire')
385 ->with($form_build_id, $form_state_data, $this->isType('int'));
387 $this->csrfToken->expects($this->once())
389 ->willReturn($cache_token);
390 $this->account->expects($this->once())
391 ->method('isAuthenticated')
394 $this->formCache->setCache($form_build_id, $form, $form_state);
400 public function testSetCacheBuildIdMismatch() {
401 $form_build_id = 'the_form_build_id';
403 '#form_id' => 'the_form_id',
404 '#build_id' => 'stale_form_build_id',
406 $form_state = new FormState();
408 $this->formCacheStore->expects($this->never())
409 ->method('setWithExpire');
410 $this->formStateCacheStore->expects($this->never())
411 ->method('setWithExpire');
412 $this->logger->expects($this->once())
414 ->with('Form build-id mismatch detected while attempting to store a form in the cache.');
415 $this->formCache->setCache($form_build_id, $form, $form_state);
420 * @covers ::deleteCache
422 public function testDeleteCache() {
423 $form_build_id = 'the_form_build_id';
425 $this->formCacheStore->expects($this->once())
427 ->with($form_build_id);
428 $this->formStateCacheStore->expects($this->once())
430 ->with($form_build_id);
431 $this->formCache->deleteCache($form_build_id);