Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Tests;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Component\FileCache\FileCacheFactory;
|
Chris@14
|
6 use Drupal\Component\Utility\NestedArray;
|
Chris@0
|
7 use Drupal\Component\Utility\Random;
|
Chris@0
|
8 use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
|
Chris@0
|
9 use Drupal\Core\DependencyInjection\ContainerBuilder;
|
Chris@0
|
10 use Drupal\Core\StringTranslation\TranslatableMarkup;
|
Chris@0
|
11 use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
|
Chris@0
|
12 use PHPUnit\Framework\TestCase;
|
Chris@0
|
13
|
Chris@0
|
14 /**
|
Chris@0
|
15 * Provides a base class and helpers for Drupal unit tests.
|
Chris@0
|
16 *
|
Chris@0
|
17 * @ingroup testing
|
Chris@0
|
18 */
|
Chris@0
|
19 abstract class UnitTestCase extends TestCase {
|
Chris@0
|
20
|
Chris@12
|
21 use PhpunitCompatibilityTrait;
|
Chris@12
|
22
|
Chris@0
|
23 /**
|
Chris@0
|
24 * The random generator.
|
Chris@0
|
25 *
|
Chris@0
|
26 * @var \Drupal\Component\Utility\Random
|
Chris@0
|
27 */
|
Chris@0
|
28 protected $randomGenerator;
|
Chris@0
|
29
|
Chris@0
|
30 /**
|
Chris@0
|
31 * The app root.
|
Chris@0
|
32 *
|
Chris@0
|
33 * @var string
|
Chris@0
|
34 */
|
Chris@0
|
35 protected $root;
|
Chris@0
|
36
|
Chris@0
|
37 /**
|
Chris@0
|
38 * {@inheritdoc}
|
Chris@0
|
39 */
|
Chris@0
|
40 protected function setUp() {
|
Chris@0
|
41 parent::setUp();
|
Chris@0
|
42 // Ensure that an instantiated container in the global state of \Drupal from
|
Chris@0
|
43 // a previous test does not leak into this test.
|
Chris@0
|
44 \Drupal::unsetContainer();
|
Chris@0
|
45
|
Chris@0
|
46 // Ensure that the NullFileCache implementation is used for the FileCache as
|
Chris@0
|
47 // unit tests should not be relying on caches implicitly.
|
Chris@0
|
48 FileCacheFactory::setConfiguration([FileCacheFactory::DISABLE_CACHE => TRUE]);
|
Chris@0
|
49 // Ensure that FileCacheFactory has a prefix.
|
Chris@0
|
50 FileCacheFactory::setPrefix('prefix');
|
Chris@0
|
51
|
Chris@0
|
52 $this->root = dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))));
|
Chris@0
|
53 }
|
Chris@0
|
54
|
Chris@0
|
55 /**
|
Chris@0
|
56 * Generates a unique random string containing letters and numbers.
|
Chris@0
|
57 *
|
Chris@0
|
58 * @param int $length
|
Chris@0
|
59 * Length of random string to generate.
|
Chris@0
|
60 *
|
Chris@0
|
61 * @return string
|
Chris@0
|
62 * Randomly generated unique string.
|
Chris@0
|
63 *
|
Chris@0
|
64 * @see \Drupal\Component\Utility\Random::name()
|
Chris@0
|
65 */
|
Chris@0
|
66 public function randomMachineName($length = 8) {
|
Chris@0
|
67 return $this->getRandomGenerator()->name($length, TRUE);
|
Chris@0
|
68 }
|
Chris@0
|
69
|
Chris@0
|
70 /**
|
Chris@0
|
71 * Gets the random generator for the utility methods.
|
Chris@0
|
72 *
|
Chris@0
|
73 * @return \Drupal\Component\Utility\Random
|
Chris@0
|
74 * The random generator
|
Chris@0
|
75 */
|
Chris@0
|
76 protected function getRandomGenerator() {
|
Chris@0
|
77 if (!is_object($this->randomGenerator)) {
|
Chris@0
|
78 $this->randomGenerator = new Random();
|
Chris@0
|
79 }
|
Chris@0
|
80 return $this->randomGenerator;
|
Chris@0
|
81 }
|
Chris@0
|
82
|
Chris@0
|
83 /**
|
Chris@0
|
84 * Asserts if two arrays are equal by sorting them first.
|
Chris@0
|
85 *
|
Chris@0
|
86 * @param array $expected
|
Chris@0
|
87 * @param array $actual
|
Chris@0
|
88 * @param string $message
|
Chris@0
|
89 */
|
Chris@0
|
90 protected function assertArrayEquals(array $expected, array $actual, $message = NULL) {
|
Chris@0
|
91 ksort($expected);
|
Chris@0
|
92 ksort($actual);
|
Chris@0
|
93 $this->assertEquals($expected, $actual, $message);
|
Chris@0
|
94 }
|
Chris@0
|
95
|
Chris@0
|
96 /**
|
Chris@14
|
97 * Returns a stub config factory that behaves according to the passed array.
|
Chris@0
|
98 *
|
Chris@0
|
99 * Use this to generate a config factory that will return the desired values
|
Chris@0
|
100 * for the given config names.
|
Chris@0
|
101 *
|
Chris@0
|
102 * @param array $configs
|
Chris@14
|
103 * An associative array of configuration settings whose keys are
|
Chris@14
|
104 * configuration object names and whose values are key => value arrays for
|
Chris@14
|
105 * the configuration object in question. Defaults to an empty array.
|
Chris@0
|
106 *
|
Chris@0
|
107 * @return \PHPUnit_Framework_MockObject_MockBuilder
|
Chris@14
|
108 * A MockBuilder object for the ConfigFactory with the desired return
|
Chris@14
|
109 * values.
|
Chris@0
|
110 */
|
Chris@0
|
111 public function getConfigFactoryStub(array $configs = []) {
|
Chris@0
|
112 $config_get_map = [];
|
Chris@0
|
113 $config_editable_map = [];
|
Chris@0
|
114 // Construct the desired configuration object stubs, each with its own
|
Chris@0
|
115 // desired return map.
|
Chris@0
|
116 foreach ($configs as $config_name => $config_values) {
|
Chris@14
|
117 // Define a closure over the $config_values, which will be used as a
|
Chris@14
|
118 // returnCallback below. This function will mimic
|
Chris@14
|
119 // \Drupal\Core\Config\Config::get and allow using dotted keys.
|
Chris@14
|
120 $config_get = function ($key = '') use ($config_values) {
|
Chris@14
|
121 // Allow to pass in no argument.
|
Chris@14
|
122 if (empty($key)) {
|
Chris@14
|
123 return $config_values;
|
Chris@14
|
124 }
|
Chris@14
|
125 // See if we have the key as is.
|
Chris@14
|
126 if (isset($config_values[$key])) {
|
Chris@14
|
127 return $config_values[$key];
|
Chris@14
|
128 }
|
Chris@14
|
129 $parts = explode('.', $key);
|
Chris@14
|
130 $value = NestedArray::getValue($config_values, $parts, $key_exists);
|
Chris@14
|
131 return $key_exists ? $value : NULL;
|
Chris@14
|
132 };
|
Chris@0
|
133
|
Chris@0
|
134 $immutable_config_object = $this->getMockBuilder('Drupal\Core\Config\ImmutableConfig')
|
Chris@0
|
135 ->disableOriginalConstructor()
|
Chris@0
|
136 ->getMock();
|
Chris@0
|
137 $immutable_config_object->expects($this->any())
|
Chris@0
|
138 ->method('get')
|
Chris@14
|
139 ->will($this->returnCallback($config_get));
|
Chris@0
|
140 $config_get_map[] = [$config_name, $immutable_config_object];
|
Chris@0
|
141
|
Chris@0
|
142 $mutable_config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
|
Chris@0
|
143 ->disableOriginalConstructor()
|
Chris@0
|
144 ->getMock();
|
Chris@0
|
145 $mutable_config_object->expects($this->any())
|
Chris@0
|
146 ->method('get')
|
Chris@14
|
147 ->will($this->returnCallback($config_get));
|
Chris@0
|
148 $config_editable_map[] = [$config_name, $mutable_config_object];
|
Chris@0
|
149 }
|
Chris@0
|
150 // Construct a config factory with the array of configuration object stubs
|
Chris@0
|
151 // as its return map.
|
Chris@12
|
152 $config_factory = $this->createMock('Drupal\Core\Config\ConfigFactoryInterface');
|
Chris@0
|
153 $config_factory->expects($this->any())
|
Chris@0
|
154 ->method('get')
|
Chris@0
|
155 ->will($this->returnValueMap($config_get_map));
|
Chris@0
|
156 $config_factory->expects($this->any())
|
Chris@0
|
157 ->method('getEditable')
|
Chris@0
|
158 ->will($this->returnValueMap($config_editable_map));
|
Chris@0
|
159 return $config_factory;
|
Chris@0
|
160 }
|
Chris@0
|
161
|
Chris@0
|
162 /**
|
Chris@0
|
163 * Returns a stub config storage that returns the supplied configuration.
|
Chris@0
|
164 *
|
Chris@0
|
165 * @param array $configs
|
Chris@0
|
166 * An associative array of configuration settings whose keys are
|
Chris@0
|
167 * configuration object names and whose values are key => value arrays
|
Chris@0
|
168 * for the configuration object in question.
|
Chris@0
|
169 *
|
Chris@0
|
170 * @return \Drupal\Core\Config\StorageInterface
|
Chris@0
|
171 * A mocked config storage.
|
Chris@0
|
172 */
|
Chris@0
|
173 public function getConfigStorageStub(array $configs) {
|
Chris@12
|
174 $config_storage = $this->createMock('Drupal\Core\Config\NullStorage');
|
Chris@0
|
175 $config_storage->expects($this->any())
|
Chris@0
|
176 ->method('listAll')
|
Chris@0
|
177 ->will($this->returnValue(array_keys($configs)));
|
Chris@0
|
178
|
Chris@0
|
179 foreach ($configs as $name => $config) {
|
Chris@0
|
180 $config_storage->expects($this->any())
|
Chris@0
|
181 ->method('read')
|
Chris@0
|
182 ->with($this->equalTo($name))
|
Chris@0
|
183 ->will($this->returnValue($config));
|
Chris@0
|
184 }
|
Chris@0
|
185 return $config_storage;
|
Chris@0
|
186 }
|
Chris@0
|
187
|
Chris@0
|
188 /**
|
Chris@0
|
189 * Mocks a block with a block plugin.
|
Chris@0
|
190 *
|
Chris@0
|
191 * @param string $machine_name
|
Chris@0
|
192 * The machine name of the block plugin.
|
Chris@0
|
193 *
|
Chris@0
|
194 * @return \Drupal\block\BlockInterface|\PHPUnit_Framework_MockObject_MockObject
|
Chris@0
|
195 * The mocked block.
|
Chris@14
|
196 *
|
Chris@14
|
197 * @deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Unit test
|
Chris@14
|
198 * base classes should not have dependencies on extensions. Set up mocks in
|
Chris@14
|
199 * individual tests.
|
Chris@14
|
200 *
|
Chris@14
|
201 * @see https://www.drupal.org/node/2896072
|
Chris@0
|
202 */
|
Chris@0
|
203 protected function getBlockMockWithMachineName($machine_name) {
|
Chris@0
|
204 $plugin = $this->getMockBuilder('Drupal\Core\Block\BlockBase')
|
Chris@0
|
205 ->disableOriginalConstructor()
|
Chris@0
|
206 ->getMock();
|
Chris@0
|
207 $plugin->expects($this->any())
|
Chris@0
|
208 ->method('getMachineNameSuggestion')
|
Chris@0
|
209 ->will($this->returnValue($machine_name));
|
Chris@0
|
210
|
Chris@0
|
211 $block = $this->getMockBuilder('Drupal\block\Entity\Block')
|
Chris@0
|
212 ->disableOriginalConstructor()
|
Chris@0
|
213 ->getMock();
|
Chris@0
|
214 $block->expects($this->any())
|
Chris@0
|
215 ->method('getPlugin')
|
Chris@0
|
216 ->will($this->returnValue($plugin));
|
Chris@14
|
217 @trigger_error(__METHOD__ . ' is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Unit test base classes should not have dependencies on extensions. Set up mocks in individual tests.', E_USER_DEPRECATED);
|
Chris@0
|
218 return $block;
|
Chris@0
|
219 }
|
Chris@0
|
220
|
Chris@0
|
221 /**
|
Chris@0
|
222 * Returns a stub translation manager that just returns the passed string.
|
Chris@0
|
223 *
|
Chris@0
|
224 * @return \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\StringTranslation\TranslationInterface
|
Chris@0
|
225 * A mock translation object.
|
Chris@0
|
226 */
|
Chris@0
|
227 public function getStringTranslationStub() {
|
Chris@12
|
228 $translation = $this->createMock('Drupal\Core\StringTranslation\TranslationInterface');
|
Chris@0
|
229 $translation->expects($this->any())
|
Chris@0
|
230 ->method('translate')
|
Chris@0
|
231 ->willReturnCallback(function ($string, array $args = [], array $options = []) use ($translation) {
|
Chris@0
|
232 return new TranslatableMarkup($string, $args, $options, $translation);
|
Chris@0
|
233 });
|
Chris@0
|
234 $translation->expects($this->any())
|
Chris@0
|
235 ->method('translateString')
|
Chris@0
|
236 ->willReturnCallback(function (TranslatableMarkup $wrapper) {
|
Chris@0
|
237 return $wrapper->getUntranslatedString();
|
Chris@0
|
238 });
|
Chris@0
|
239 $translation->expects($this->any())
|
Chris@0
|
240 ->method('formatPlural')
|
Chris@0
|
241 ->willReturnCallback(function ($count, $singular, $plural, array $args = [], array $options = []) use ($translation) {
|
Chris@0
|
242 $wrapper = new PluralTranslatableMarkup($count, $singular, $plural, $args, $options, $translation);
|
Chris@0
|
243 return $wrapper;
|
Chris@0
|
244 });
|
Chris@0
|
245 return $translation;
|
Chris@0
|
246 }
|
Chris@0
|
247
|
Chris@0
|
248 /**
|
Chris@0
|
249 * Sets up a container with a cache tags invalidator.
|
Chris@0
|
250 *
|
Chris@0
|
251 * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cache_tags_validator
|
Chris@0
|
252 * The cache tags invalidator.
|
Chris@0
|
253 *
|
Chris@0
|
254 * @return \Symfony\Component\DependencyInjection\ContainerInterface|\PHPUnit_Framework_MockObject_MockObject
|
Chris@0
|
255 * The container with the cache tags invalidator service.
|
Chris@0
|
256 */
|
Chris@0
|
257 protected function getContainerWithCacheTagsInvalidator(CacheTagsInvalidatorInterface $cache_tags_validator) {
|
Chris@12
|
258 $container = $this->createMock('Symfony\Component\DependencyInjection\ContainerInterface');
|
Chris@0
|
259 $container->expects($this->any())
|
Chris@0
|
260 ->method('get')
|
Chris@0
|
261 ->with('cache_tags.invalidator')
|
Chris@0
|
262 ->will($this->returnValue($cache_tags_validator));
|
Chris@0
|
263
|
Chris@0
|
264 \Drupal::setContainer($container);
|
Chris@0
|
265 return $container;
|
Chris@0
|
266 }
|
Chris@0
|
267
|
Chris@0
|
268 /**
|
Chris@0
|
269 * Returns a stub class resolver.
|
Chris@0
|
270 *
|
Chris@0
|
271 * @return \Drupal\Core\DependencyInjection\ClassResolverInterface|\PHPUnit_Framework_MockObject_MockObject
|
Chris@0
|
272 * The class resolver stub.
|
Chris@0
|
273 */
|
Chris@0
|
274 protected function getClassResolverStub() {
|
Chris@12
|
275 $class_resolver = $this->createMock('Drupal\Core\DependencyInjection\ClassResolverInterface');
|
Chris@0
|
276 $class_resolver->expects($this->any())
|
Chris@0
|
277 ->method('getInstanceFromDefinition')
|
Chris@0
|
278 ->will($this->returnCallback(function ($class) {
|
Chris@0
|
279 if (is_subclass_of($class, 'Drupal\Core\DependencyInjection\ContainerInjectionInterface')) {
|
Chris@0
|
280 return $class::create(new ContainerBuilder());
|
Chris@0
|
281 }
|
Chris@0
|
282 else {
|
Chris@0
|
283 return new $class();
|
Chris@0
|
284 }
|
Chris@0
|
285 }));
|
Chris@0
|
286 return $class_resolver;
|
Chris@0
|
287 }
|
Chris@0
|
288
|
Chris@0
|
289 }
|