Updated to Drupal 8.6.4, which is PHP 7.3 friendly. Also updated HTMLaw library....
[yaffs-website] / web / core / modules / simpletest / tests / src / Unit / TestDiscoveryTest.php
1 <?php
2
3 namespace Drupal\Tests\simpletest\Unit;
4
5 use Composer\Autoload\ClassLoader;
6 use Drupal\Core\Extension\Extension;
7 use Drupal\Core\Extension\ModuleHandlerInterface;
8 use Drupal\simpletest\Exception\MissingGroupException;
9 use Drupal\simpletest\TestDiscovery;
10 use Drupal\Tests\UnitTestCase;
11 use org\bovigo\vfs\vfsStream;
12
13 /**
14  * @coversDefaultClass \Drupal\simpletest\TestDiscovery
15  * @group simpletest
16  */
17 class TestDiscoveryTest extends UnitTestCase {
18
19   /**
20    * @covers ::getTestInfo
21    * @dataProvider infoParserProvider
22    */
23   public function testTestInfoParser($expected, $classname, $doc_comment = NULL) {
24     $info = TestDiscovery::getTestInfo($classname, $doc_comment);
25     $this->assertEquals($expected, $info);
26   }
27
28   public function infoParserProvider() {
29     // A module provided unit test.
30     $tests[] = [
31       // Expected result.
32       [
33         'name' => 'Drupal\Tests\simpletest\Unit\TestDiscoveryTest',
34         'group' => 'simpletest',
35         'description' => 'Tests \Drupal\simpletest\TestDiscovery.',
36         'type' => 'PHPUnit-Unit',
37       ],
38       // Classname.
39       'Drupal\Tests\simpletest\Unit\TestDiscoveryTest',
40     ];
41
42     // A core unit test.
43     $tests[] = [
44       // Expected result.
45       [
46         'name' => 'Drupal\Tests\Core\DrupalTest',
47         'group' => 'DrupalTest',
48         'description' => 'Tests \Drupal.',
49         'type' => 'PHPUnit-Unit',
50       ],
51       // Classname.
52       'Drupal\Tests\Core\DrupalTest',
53     ];
54
55     // Functional PHPUnit test.
56     $tests[] = [
57       // Expected result.
58       [
59         'name' => 'Drupal\FunctionalTests\BrowserTestBaseTest',
60         'group' => 'browsertestbase',
61         'description' => 'Tests BrowserTestBase functionality.',
62         'type' => 'PHPUnit-Functional',
63       ],
64       // Classname.
65       'Drupal\FunctionalTests\BrowserTestBaseTest',
66     ];
67
68     // kernel PHPUnit test.
69     $tests['phpunit-kernel'] = [
70       // Expected result.
71       [
72         'name' => '\Drupal\Tests\file\Kernel\FileItemValidationTest',
73         'group' => 'file',
74         'description' => 'Tests that files referenced in file and image fields are always validated.',
75         'type' => 'PHPUnit-Kernel',
76       ],
77       // Classname.
78       '\Drupal\Tests\file\Kernel\FileItemValidationTest',
79     ];
80
81     // Simpletest classes can not be autoloaded in a PHPUnit test, therefore
82     // provide a docblock.
83     $tests[] = [
84       // Expected result.
85       [
86         'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
87         'group' => 'simpletest',
88         'description' => 'Tests the Simpletest UI internal browser.',
89         'type' => 'Simpletest',
90       ],
91       // Classname.
92       'Drupal\simpletest\Tests\ExampleSimpleTest',
93       // Doc block.
94       "/**
95  * Tests the Simpletest UI internal browser.
96  *
97  * @group simpletest
98  */
99  ",
100     ];
101
102     // Test with a different amount of leading spaces.
103     $tests[] = [
104       // Expected result.
105       [
106         'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
107         'group' => 'simpletest',
108         'description' => 'Tests the Simpletest UI internal browser.',
109         'type' => 'Simpletest',
110       ],
111       // Classname.
112       'Drupal\simpletest\Tests\ExampleSimpleTest',
113       // Doc block.
114       "/**
115    * Tests the Simpletest UI internal browser.
116    *
117    * @group simpletest
118    */
119    */
120  ",
121     ];
122
123     // Make sure that a "* @" inside a string does not get parsed as an
124     // annotation.
125     $tests[] = [
126       // Expected result.
127       [
128         'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
129         'group' => 'simpletest',
130         'description' => 'Tests the Simpletest UI internal browser. * @',
131         'type' => 'Simpletest',
132       ],
133       // Classname.
134       'Drupal\simpletest\Tests\ExampleSimpleTest',
135       // Doc block.
136       "/**
137    * Tests the Simpletest UI internal browser. * @
138    *
139    * @group simpletest
140    */
141  ",
142     ];
143
144     // Multiple @group annotations.
145     $tests[] = [
146       // Expected result.
147       [
148         'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
149         'group' => 'Test',
150         'description' => 'Tests the Simpletest UI internal browser.',
151         'type' => 'Simpletest',
152       ],
153       // Classname.
154       'Drupal\simpletest\Tests\ExampleSimpleTest',
155       // Doc block.
156       "/**
157  * Tests the Simpletest UI internal browser.
158  *
159  * @group Test
160  * @group simpletest
161  */
162  ",
163     ];
164
165     // @dependencies annotation.
166     $tests[] = [
167       // Expected result.
168       [
169         'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
170         'description' => 'Tests the Simpletest UI internal browser.',
171         'type' => 'Simpletest',
172         'requires' => ['module' => ['test']],
173         'group' => 'simpletest',
174       ],
175       // Classname.
176       'Drupal\simpletest\Tests\ExampleSimpleTest',
177       // Doc block.
178       "/**
179  * Tests the Simpletest UI internal browser.
180  *
181  * @dependencies test
182  * @group simpletest
183  */
184  ",
185     ];
186
187     // Multiple @dependencies annotation.
188     $tests[] = [
189       // Expected result.
190       [
191         'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
192         'description' => 'Tests the Simpletest UI internal browser.',
193         'type' => 'Simpletest',
194         'requires' => ['module' => ['test', 'test1', 'test2']],
195         'group' => 'simpletest',
196       ],
197       // Classname.
198       'Drupal\simpletest\Tests\ExampleSimpleTest',
199       // Doc block.
200       "/**
201  * Tests the Simpletest UI internal browser.
202  *
203  * @dependencies test, test1, test2
204  * @group simpletest
205  */
206  ",
207     ];
208
209     // Multi-line summary line.
210     $tests[] = [
211       // Expected result.
212       [
213         'name' => 'Drupal\simpletest\Tests\ExampleSimpleTest',
214         'description' => 'Tests the Simpletest UI internal browser. And the summary line continues an there is no gap to the annotation.',
215         'type' => 'Simpletest',
216         'group' => 'simpletest',
217       ],
218       // Classname.
219       'Drupal\simpletest\Tests\ExampleSimpleTest',
220       // Doc block.
221       "/**
222  * Tests the Simpletest UI internal browser. And the summary line continues an
223  * there is no gap to the annotation.
224  *
225  * @group simpletest
226  */
227  ",
228     ];
229     return $tests;
230   }
231
232   /**
233    * @covers ::getTestInfo
234    */
235   public function testTestInfoParserMissingGroup() {
236     $classname = 'Drupal\KernelTests\field\BulkDeleteTest';
237     $doc_comment = <<<EOT
238 /**
239  * Bulk delete storages and fields, and clean up afterwards.
240  */
241 EOT;
242     $this->setExpectedException(MissingGroupException::class, 'Missing @group annotation in Drupal\KernelTests\field\BulkDeleteTest');
243     TestDiscovery::getTestInfo($classname, $doc_comment);
244   }
245
246   /**
247    * @covers ::getTestInfo
248    */
249   public function testTestInfoParserMissingSummary() {
250     $classname = 'Drupal\KernelTests\field\BulkDeleteTest';
251     $doc_comment = <<<EOT
252 /**
253  * @group field
254  */
255 EOT;
256     $info = TestDiscovery::getTestInfo($classname, $doc_comment);
257     $this->assertEmpty($info['description']);
258   }
259
260   protected function setupVfsWithTestClasses() {
261     vfsStream::setup('drupal');
262
263     $test_file = <<<EOF
264 <?php
265
266 /**
267  * Test description
268  * @group example
269  */
270 class FunctionalExampleTest {}
271 EOF;
272
273     vfsStream::create([
274       'modules' => [
275         'test_module' => [
276           'tests' => [
277             'src' => [
278               'Functional' => [
279                 'FunctionalExampleTest.php' => $test_file,
280                 'FunctionalExampleTest2.php' => str_replace(['FunctionalExampleTest', '@group example'], ['FunctionalExampleTest2', '@group example2'], $test_file),
281               ],
282               'Kernel' => [
283                 'KernelExampleTest3.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleTest3', '@group example2'], $test_file),
284                 'KernelExampleTestBase.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleTestBase', '@group example2'], $test_file),
285                 'KernelExampleTrait.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleTrait', '@group example2'], $test_file),
286                 'KernelExampleInterface.php' => str_replace(['FunctionalExampleTest', '@group example'], ['KernelExampleInterface', '@group example2'], $test_file),
287               ],
288             ],
289           ],
290         ],
291       ],
292     ]);
293   }
294
295   /**
296    * @covers ::getTestClasses
297    */
298   public function testGetTestClasses() {
299     $this->setupVfsWithTestClasses();
300     $class_loader = $this->prophesize(ClassLoader::class);
301     $module_handler = $this->prophesize(ModuleHandlerInterface::class);
302
303     $test_discovery = new TestTestDiscovery('vfs://drupal', $class_loader->reveal(), $module_handler->reveal());
304
305     $extensions = [
306       'test_module' => new Extension('vfs://drupal', 'module', 'modules/test_module/test_module.info.yml'),
307     ];
308     $test_discovery->setExtensions($extensions);
309     $result = $test_discovery->getTestClasses();
310     $this->assertCount(2, $result);
311     $this->assertEquals([
312       'example' => [
313         'Drupal\Tests\test_module\Functional\FunctionalExampleTest' => [
314           'name' => 'Drupal\Tests\test_module\Functional\FunctionalExampleTest',
315           'description' => 'Test description',
316           'group' => 'example',
317           'type' => 'PHPUnit-Functional',
318         ],
319       ],
320       'example2' => [
321         'Drupal\Tests\test_module\Functional\FunctionalExampleTest2' => [
322           'name' => 'Drupal\Tests\test_module\Functional\FunctionalExampleTest2',
323           'description' => 'Test description',
324           'group' => 'example2',
325           'type' => 'PHPUnit-Functional',
326         ],
327         'Drupal\Tests\test_module\Kernel\KernelExampleTest3' => [
328           'name' => 'Drupal\Tests\test_module\Kernel\KernelExampleTest3',
329           'description' => 'Test description',
330           'group' => 'example2',
331           'type' => 'PHPUnit-Kernel',
332         ],
333       ],
334     ], $result);
335   }
336
337   /**
338    * @covers ::getTestClasses
339    */
340   public function testGetTestClassesWithSelectedTypes() {
341     $this->setupVfsWithTestClasses();
342     $class_loader = $this->prophesize(ClassLoader::class);
343     $module_handler = $this->prophesize(ModuleHandlerInterface::class);
344
345     $test_discovery = new TestTestDiscovery('vfs://drupal', $class_loader->reveal(), $module_handler->reveal());
346
347     $extensions = [
348       'test_module' => new Extension('vfs://drupal', 'module', 'modules/test_module/test_module.info.yml'),
349     ];
350     $test_discovery->setExtensions($extensions);
351     $result = $test_discovery->getTestClasses(NULL, ['PHPUnit-Kernel']);
352     $this->assertCount(2, $result);
353     $this->assertEquals([
354       'example' => [],
355       'example2' => [
356         'Drupal\Tests\test_module\Kernel\KernelExampleTest3' => [
357           'name' => 'Drupal\Tests\test_module\Kernel\KernelExampleTest3',
358           'description' => 'Test description',
359           'group' => 'example2',
360           'type' => 'PHPUnit-Kernel',
361         ],
362       ],
363     ], $result);
364   }
365
366   /**
367    * @covers ::getPhpunitTestSuite
368    * @dataProvider providerTestGetPhpunitTestSuite
369    */
370   public function testGetPhpunitTestSuite($classname, $expected) {
371     $this->assertEquals($expected, TestDiscovery::getPhpunitTestSuite($classname));
372   }
373
374   public function providerTestGetPhpunitTestSuite() {
375     $data = [];
376     $data['simpletest-webtest'] = ['\Drupal\rest\Tests\NodeTest', FALSE];
377     $data['simpletest-kerneltest'] = ['\Drupal\hal\Tests\FileNormalizeTest', FALSE];
378     $data['module-unittest'] = [static::class, 'Unit'];
379     $data['module-kerneltest'] = ['\Drupal\KernelTests\Core\Theme\TwigMarkupInterfaceTest', 'Kernel'];
380     $data['module-functionaltest'] = ['\Drupal\FunctionalTests\BrowserTestBaseTest', 'Functional'];
381     $data['module-functionaljavascripttest'] = ['\Drupal\Tests\toolbar\FunctionalJavascript\ToolbarIntegrationTest', 'FunctionalJavascript'];
382     $data['core-unittest'] = ['\Drupal\Tests\ComposerIntegrationTest', 'Unit'];
383     $data['core-unittest2'] = ['Drupal\Tests\Core\DrupalTest', 'Unit'];
384     $data['core-kerneltest'] = ['\Drupal\KernelTests\KernelTestBaseTest', 'Kernel'];
385     $data['core-functionaltest'] = ['\Drupal\FunctionalTests\ExampleTest', 'Functional'];
386     $data['core-functionaljavascripttest'] = ['\Drupal\FunctionalJavascriptTests\ExampleTest', 'FunctionalJavascript'];
387
388     return $data;
389   }
390
391   /**
392    * Ensure that classes are not reflected when the docblock is empty.
393    *
394    * @covers ::getTestInfo
395    */
396   public function testGetTestInfoEmptyDocblock() {
397     // If getTestInfo() performed reflection, it won't be able to find the
398     // class we asked it to analyze, so it will throw a ReflectionException.
399     // We want to make sure it didn't do that, because we already did some
400     // analysis and already have an empty docblock. getTestInfo() will throw
401     // MissingGroupException because the annotation is empty.
402     $this->setExpectedException(MissingGroupException::class);
403     TestDiscovery::getTestInfo('Drupal\Tests\simpletest\ThisTestDoesNotExistTest', '');
404   }
405
406   /**
407    * Ensure TestDiscovery::scanDirectory() ignores certain abstract file types.
408    *
409    * @covers ::scanDirectory
410    */
411   public function testScanDirectoryNoAbstract() {
412     $this->setupVfsWithTestClasses();
413     $files = TestDiscovery::scanDirectory('Drupal\\Tests\\test_module\\Kernel\\', vfsStream::url('drupal/modules/test_module/tests/src/Kernel'));
414     $this->assertNotEmpty($files);
415     $this->assertArrayNotHasKey('Drupal\Tests\test_module\Kernel\KernelExampleTestBase', $files);
416     $this->assertArrayNotHasKey('Drupal\Tests\test_module\Kernel\KernelExampleTrait', $files);
417     $this->assertArrayNotHasKey('Drupal\Tests\test_module\Kernel\KernelExampleInterface', $files);
418     $this->assertArrayHasKey('Drupal\Tests\test_module\Kernel\KernelExampleTest3', $files);
419   }
420
421 }
422
423 class TestTestDiscovery extends TestDiscovery {
424
425   /**
426    * @var \Drupal\Core\Extension\Extension[]
427    */
428   protected $extensions = [];
429
430   public function setExtensions(array $extensions) {
431     $this->extensions = $extensions;
432   }
433
434   /**
435    * {@inheritdoc}
436    */
437   protected function getExtensions() {
438     return $this->extensions;
439   }
440
441 }
442
443 namespace Drupal\simpletest\Tests;
444
445 use Drupal\simpletest\WebTestBase;
446
447 /**
448  * Tests the Simpletest UI internal browser.
449  *
450  * @group simpletest
451  */
452 class ExampleSimpleTest extends WebTestBase {
453 }