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 = [
306 'module' => 'a_module',
307 'type' => 'the_type',
308 'name' => 'some_name',
310 ['module' => 'another_module'],
314 $this->moduleHandler->expects($this->at(0))
315 ->method('loadInclude')
316 ->with('a_module', 'the_type', 'some_name');
317 $this->moduleHandler->expects($this->at(1))
318 ->method('loadInclude')
319 ->with('another_module', 'inc', 'another_module');
320 $this->formStateCacheStore->expects($this->once())
322 ->with($form_build_id)
323 ->willReturn($cached_form_state);
325 $this->formCache->getCache($form_build_id, $form_state);
331 public function testSetCacheWithForm() {
332 $form_build_id = 'the_form_build_id';
334 '#form_id' => 'the_form_id',
336 $form_state = new FormState();
338 $this->formCacheStore->expects($this->once())
339 ->method('setWithExpire')
340 ->with($form_build_id, $form, $this->isType('int'));
342 $form_state_data = $form_state->getCacheableArray();
343 $this->formStateCacheStore->expects($this->once())
344 ->method('setWithExpire')
345 ->with($form_build_id, $form_state_data, $this->isType('int'));
347 $this->formCache->setCache($form_build_id, $form, $form_state);
353 public function testSetCacheWithoutForm() {
354 $form_build_id = 'the_form_build_id';
356 $form_state = new FormState();
358 $this->formCacheStore->expects($this->never())
359 ->method('setWithExpire');
361 $form_state_data = $form_state->getCacheableArray();
362 $this->formStateCacheStore->expects($this->once())
363 ->method('setWithExpire')
364 ->with($form_build_id, $form_state_data, $this->isType('int'));
366 $this->formCache->setCache($form_build_id, $form, $form_state);
372 public function testSetCacheAuthUser() {
373 $form_build_id = 'the_form_build_id';
375 $form_state = new FormState();
377 $cache_token = 'the_cache_token';
379 $form_data['#cache_token'] = $cache_token;
380 $this->formCacheStore->expects($this->once())
381 ->method('setWithExpire')
382 ->with($form_build_id, $form_data, $this->isType('int'));
384 $form_state_data = $form_state->getCacheableArray();
385 $this->formStateCacheStore->expects($this->once())
386 ->method('setWithExpire')
387 ->with($form_build_id, $form_state_data, $this->isType('int'));
389 $this->csrfToken->expects($this->once())
391 ->willReturn($cache_token);
392 $this->account->expects($this->once())
393 ->method('isAuthenticated')
396 $this->formCache->setCache($form_build_id, $form, $form_state);
402 public function testSetCacheBuildIdMismatch() {
403 $form_build_id = 'the_form_build_id';
405 '#form_id' => 'the_form_id',
406 '#build_id' => 'stale_form_build_id',
408 $form_state = new FormState();
410 $this->formCacheStore->expects($this->never())
411 ->method('setWithExpire');
412 $this->formStateCacheStore->expects($this->never())
413 ->method('setWithExpire');
414 $this->logger->expects($this->once())
416 ->with('Form build-id mismatch detected while attempting to store a form in the cache.');
417 $this->formCache->setCache($form_build_id, $form, $form_state);
421 * @covers ::deleteCache
423 public function testDeleteCache() {
424 $form_build_id = 'the_form_build_id';
426 $this->formCacheStore->expects($this->once())
428 ->with($form_build_id);
429 $this->formStateCacheStore->expects($this->once())
431 ->with($form_build_id);
432 $this->formCache->deleteCache($form_build_id);