Version 1
[yaffs-website] / web / core / tests / Drupal / Tests / Core / Form / FormCacheTest.php
1 <?php
2
3 namespace Drupal\Tests\Core\Form;
4
5 use Drupal\Core\Form\FormCache;
6 use Drupal\Core\Form\FormState;
7 use Drupal\Tests\UnitTestCase;
8
9 /**
10  * @coversDefaultClass \Drupal\Core\Form\FormCache
11  * @group Form
12  */
13 class FormCacheTest extends UnitTestCase {
14
15   /**
16    * The form cache object under test.
17    *
18    * @var \Drupal\Core\Form\FormCache
19    */
20   protected $formCache;
21
22   /**
23    * The expirable key value factory.
24    *
25    * @var \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface|\PHPUnit_Framework_MockObject_MockObject
26    */
27   protected $keyValueExpirableFactory;
28
29   /**
30    * The current user.
31    *
32    * @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
33    */
34   protected $account;
35
36   /**
37    * The CSRF token generator.
38    *
39    * @var \Drupal\Core\Access\CsrfTokenGenerator|\PHPUnit_Framework_MockObject_MockObject
40    */
41   protected $csrfToken;
42
43   /**
44    * The mocked module handler.
45    *
46    * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
47    */
48   protected $moduleHandler;
49
50   /**
51    * The expirable key value store used by form cache.
52    *
53    * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface|\PHPUnit_Framework_MockObject_MockObject
54    */
55   protected $formCacheStore;
56
57   /**
58    * The expirable key value store used by form state cache.
59    *
60    * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface|\PHPUnit_Framework_MockObject_MockObject
61    */
62   protected $formStateCacheStore;
63
64   /**
65    * The logger channel.
66    *
67    * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject
68    */
69   protected $logger;
70
71   /**
72    * The request stack.
73    *
74    * @var \Symfony\Component\HttpFoundation\RequestStack|\PHPUnit_Framework_MockObject_MockObject
75    */
76   protected $requestStack;
77
78   /**
79    * A policy rule determining the cacheability of a request.
80    *
81    * @var \Drupal\Core\PageCache\RequestPolicyInterface|\PHPUnit_Framework_MockObject_MockObject
82    */
83   protected $requestPolicy;
84
85   /**
86    * {@inheritdoc}
87    */
88   protected $runTestInSeparateProcess = TRUE;
89
90   /**
91    * {@inheritdoc}
92    */
93   protected $preserveGlobalState = FALSE;
94
95   /**
96    * {@inheritdoc}
97    */
98   protected function setUp() {
99     parent::setUp();
100
101     $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
102
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())
107       ->method('get')
108       ->will($this->returnValueMap([
109         ['form', $this->formCacheStore],
110         ['form_state', $this->formStateCacheStore],
111       ]));
112
113     $this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator')
114       ->disableOriginalConstructor()
115       ->getMock();
116     $this->account = $this->getMock('Drupal\Core\Session\AccountInterface');
117
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');
121
122     $this->formCache = new FormCache($this->root, $this->keyValueExpirableFactory, $this->moduleHandler, $this->account, $this->csrfToken, $this->logger, $this->requestStack, $this->requestPolicy);
123   }
124
125   /**
126    * @covers ::getCache
127    */
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];
133
134     $this->formCacheStore->expects($this->once())
135       ->method('get')
136       ->with($form_build_id)
137       ->willReturn($cached_form);
138     $this->csrfToken->expects($this->once())
139       ->method('validate')
140       ->with($cache_token)
141       ->willReturn(TRUE);
142     $this->account->expects($this->never())
143       ->method('isAnonymous');
144
145     $form = $this->formCache->getCache($form_build_id, $form_state);
146     $this->assertSame($cached_form, $form);
147   }
148
149   /**
150    * @covers ::getCache
151    */
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];
157
158     $this->formCacheStore->expects($this->once())
159       ->method('get')
160       ->with($form_build_id)
161       ->willReturn($cached_form);
162     $this->csrfToken->expects($this->once())
163       ->method('validate')
164       ->with($cache_token)
165       ->willReturn(FALSE);
166     $this->account->expects($this->never())
167       ->method('isAnonymous');
168
169     $form = $this->formCache->getCache($form_build_id, $form_state);
170     $this->assertNull($form);
171   }
172
173   /**
174    * @covers ::getCache
175    */
176   public function testGetCacheAnonUser() {
177     $form_build_id = 'the_form_build_id';
178     $form_state = new FormState();
179     $cached_form = ['#cache_token' => NULL];
180
181     $this->formCacheStore->expects($this->once())
182       ->method('get')
183       ->with($form_build_id)
184       ->willReturn($cached_form);
185     $this->account->expects($this->once())
186       ->method('isAnonymous')
187       ->willReturn(TRUE);
188     $this->csrfToken->expects($this->never())
189       ->method('validate');
190
191     $form = $this->formCache->getCache($form_build_id, $form_state);
192     $this->assertSame($cached_form, $form);
193   }
194
195   /**
196    * @covers ::getCache
197    */
198   public function testGetCacheAuthUser() {
199     $form_build_id = 'the_form_build_id';
200     $form_state = new FormState();
201     $cached_form = ['#cache_token' => NULL];
202
203     $this->formCacheStore->expects($this->once())
204       ->method('get')
205       ->with($form_build_id)
206       ->willReturn($cached_form);
207     $this->account->expects($this->once())
208       ->method('isAnonymous')
209       ->willReturn(FALSE);
210
211     $form = $this->formCache->getCache($form_build_id, $form_state);
212     $this->assertNull($form);
213   }
214
215   /**
216    * @covers ::getCache
217    */
218   public function testGetCacheNoForm() {
219     $form_build_id = 'the_form_build_id';
220     $form_state = new FormState();
221     $cached_form = NULL;
222
223     $this->formCacheStore->expects($this->once())
224       ->method('get')
225       ->with($form_build_id)
226       ->willReturn($cached_form);
227     $this->account->expects($this->never())
228       ->method('isAnonymous');
229
230     $form = $this->formCache->getCache($form_build_id, $form_state);
231     $this->assertNull($form);
232   }
233
234   /**
235    * @covers ::getCache
236    */
237   public function testGetCacheImmutableForm() {
238     $form_build_id = 'the_form_build_id';
239     $form_state = (new FormState())
240       ->addBuildInfo('immutable', TRUE);
241     $cached_form = [
242       '#build_id' => 'the_old_build_form_id',
243     ];
244
245     $this->account->expects($this->once())
246       ->method('isAnonymous')
247       ->willReturn(TRUE);
248     $this->formCacheStore->expects($this->once())
249       ->method('get')
250       ->with($form_build_id)
251       ->willReturn($cached_form);
252
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']);
258   }
259
260   /**
261    * @covers ::loadCachedFormState
262    */
263   public function testLoadCachedFormState() {
264     $form_build_id = 'the_form_build_id';
265     $form_state = new FormState();
266     $cached_form = ['#cache_token' => NULL];
267
268     $this->formCacheStore->expects($this->once())
269       ->method('get')
270       ->with($form_build_id)
271       ->willReturn($cached_form);
272     $this->account->expects($this->once())
273       ->method('isAnonymous')
274       ->willReturn(TRUE);
275
276     $cached_form_state = ['storage' => ['foo' => 'bar']];
277     $this->formStateCacheStore->expects($this->once())
278       ->method('get')
279       ->with($form_build_id)
280       ->willReturn($cached_form_state);
281
282     $this->formCache->getCache($form_build_id, $form_state);
283     $this->assertSame($cached_form_state['storage'], $form_state->getStorage());
284   }
285
286   /**
287    * @covers ::loadCachedFormState
288    */
289   public function testLoadCachedFormStateWithFiles() {
290     $form_build_id = 'the_form_build_id';
291     $form_state = new FormState();
292     $cached_form = ['#cache_token' => NULL];
293
294     $this->formCacheStore->expects($this->once())
295       ->method('get')
296       ->with($form_build_id)
297       ->willReturn($cached_form);
298     $this->account->expects($this->once())
299       ->method('isAnonymous')
300       ->willReturn(TRUE);
301
302     $cached_form_state = ['build_info' => ['files' => [
303       [
304         'module' => 'a_module',
305         'type' => 'the_type',
306         'name' => 'some_name',
307       ],
308       [
309         'module' => 'another_module',
310       ],
311     ]]];
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())
319       ->method('get')
320       ->with($form_build_id)
321       ->willReturn($cached_form_state);
322
323     $this->formCache->getCache($form_build_id, $form_state);
324   }
325
326   /**
327    * @covers ::setCache
328    */
329   public function testSetCacheWithForm() {
330     $form_build_id = 'the_form_build_id';
331     $form = [
332       '#form_id' => 'the_form_id'
333     ];
334     $form_state = new FormState();
335
336     $this->formCacheStore->expects($this->once())
337       ->method('setWithExpire')
338       ->with($form_build_id, $form, $this->isType('int'));
339
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'));
344
345     $this->formCache->setCache($form_build_id, $form, $form_state);
346   }
347
348   /**
349    * @covers ::setCache
350    */
351   public function testSetCacheWithoutForm() {
352     $form_build_id = 'the_form_build_id';
353     $form = NULL;
354     $form_state = new FormState();
355
356     $this->formCacheStore->expects($this->never())
357       ->method('setWithExpire');
358
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'));
363
364     $this->formCache->setCache($form_build_id, $form, $form_state);
365   }
366
367   /**
368    * @covers ::setCache
369    */
370   public function testSetCacheAuthUser() {
371     $form_build_id = 'the_form_build_id';
372     $form = [];
373     $form_state = new FormState();
374
375     $cache_token = 'the_cache_token';
376     $form_data = $form;
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'));
381
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'));
386
387     $this->csrfToken->expects($this->once())
388       ->method('get')
389       ->willReturn($cache_token);
390     $this->account->expects($this->once())
391       ->method('isAuthenticated')
392       ->willReturn(TRUE);
393
394     $this->formCache->setCache($form_build_id, $form, $form_state);
395   }
396
397   /**
398    * @covers ::setCache
399    */
400   public function testSetCacheBuildIdMismatch() {
401     $form_build_id = 'the_form_build_id';
402     $form = [
403       '#form_id' => 'the_form_id',
404       '#build_id' => 'stale_form_build_id',
405     ];
406     $form_state = new FormState();
407
408     $this->formCacheStore->expects($this->never())
409       ->method('setWithExpire');
410     $this->formStateCacheStore->expects($this->never())
411       ->method('setWithExpire');
412     $this->logger->expects($this->once())
413       ->method('error')
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);
416   }
417
418
419   /**
420    * @covers ::deleteCache
421    */
422   public function testDeleteCache() {
423     $form_build_id = 'the_form_build_id';
424
425     $this->formCacheStore->expects($this->once())
426       ->method('delete')
427       ->with($form_build_id);
428     $this->formStateCacheStore->expects($this->once())
429       ->method('delete')
430       ->with($form_build_id);
431     $this->formCache->deleteCache($form_build_id);
432   }
433
434 }