AppTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  5. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  6. *
  7. * Licensed under The MIT License
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP(tm) Project
  12. * @since 2.0.0
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\Core;
  16. use Cake\Core\App;
  17. use Cake\Core\Configure;
  18. use Cake\Core\Exception\CakeException;
  19. use Cake\Database\Driver\Mysql;
  20. use Cake\TestSuite\TestCase;
  21. use PHPUnit\Framework\Attributes\DataProvider;
  22. use TestApp\Core\TestApp;
  23. /**
  24. * AppTest class
  25. */
  26. class AppTest extends TestCase
  27. {
  28. /**
  29. * tearDown method
  30. */
  31. public function tearDown(): void
  32. {
  33. parent::tearDown();
  34. $this->clearPlugins();
  35. }
  36. /**
  37. * testClassName
  38. *
  39. * $checkCake and $existsInCake are derived from the input parameters
  40. *
  41. * @param string $class Class name
  42. * @param string $type Class type
  43. * @param string $suffix Class suffix
  44. * @param bool $existsInBase Whether class exists in base.
  45. * @param mixed $expected Expected value.
  46. */
  47. #[DataProvider('classNameProvider')]
  48. public function testClassName($class, $type, $suffix = '', $existsInBase = false, $expected = false): void
  49. {
  50. static::setAppNamespace();
  51. $i = 0;
  52. TestApp::$existsInBaseCallback = function ($name, $namespace) use ($existsInBase, $class, $expected, &$i) {
  53. if ($i++ === 0) {
  54. return $existsInBase;
  55. }
  56. $checkCake = (!$existsInBase || strpos('.', $class));
  57. if ($checkCake) {
  58. return (bool)$expected;
  59. }
  60. return false;
  61. };
  62. $return = TestApp::className($class, $type, $suffix);
  63. $this->assertSame($expected === false ? null : $expected, $return);
  64. }
  65. public function testClassNameWithFqcn(): void
  66. {
  67. $this->assertSame(TestCase::class, App::className(TestCase::class));
  68. $this->assertNull(App::className('\Foo'));
  69. }
  70. /**
  71. * @link https://github.com/cakephp/cakephp/issues/16258
  72. */
  73. public function testClassNameWithAppNamespaceUnset(): void
  74. {
  75. Configure::delete('App.namespace');
  76. $result = App::className('Mysql', 'Database/Driver');
  77. $this->assertSame(Mysql::class, $result);
  78. }
  79. /**
  80. * testShortName
  81. *
  82. * @param string $class Class name
  83. * @param string $type Class type
  84. * @param string $suffix Class suffix
  85. * @param mixed $expected Expected value.
  86. */
  87. #[DataProvider('shortNameProvider')]
  88. public function testShortName($class, $type, $suffix = '', $expected = false): void
  89. {
  90. static::setAppNamespace();
  91. $return = TestApp::shortName($class, $type, $suffix);
  92. $this->assertSame($expected, $return);
  93. }
  94. /**
  95. * testShortNameWithNestedAppNamespace
  96. */
  97. public function testShortNameWithNestedAppNamespace(): void
  98. {
  99. static::setAppNamespace('TestApp/Nested');
  100. $return = TestApp::shortName(
  101. 'TestApp/Nested/Controller/PagesController',
  102. 'Controller',
  103. 'Controller'
  104. );
  105. $this->assertSame('Pages', $return);
  106. static::setAppNamespace();
  107. }
  108. /**
  109. * @link https://github.com/cakephp/cakephp/issues/15415
  110. */
  111. public function testShortNameWithAppNamespaceUnset(): void
  112. {
  113. Configure::delete('App.namespace');
  114. $result = App::shortName(Mysql::class, 'Database/Driver');
  115. $this->assertSame('Mysql', $result);
  116. }
  117. /**
  118. * classNameProvider
  119. *
  120. * Return test permutations for testClassName method. Format:
  121. * className
  122. * type
  123. * suffix
  124. * existsInBase (Base meaning App or plugin namespace)
  125. * expected return value
  126. *
  127. * @return array
  128. */
  129. public static function classNameProvider(): array
  130. {
  131. return [
  132. ['Does', 'Not', 'Exist'],
  133. ['Exists', 'In', 'App', true, 'TestApp\In\ExistsApp'],
  134. ['Also/Exists', 'In', 'App', true, 'TestApp\In\Also\ExistsApp'],
  135. ['Also', 'Exists/In', 'App', true, 'TestApp\Exists\In\AlsoApp'],
  136. ['Also', 'Exists/In/Subfolder', 'App', true, 'TestApp\Exists\In\Subfolder\AlsoApp'],
  137. ['No', 'Suffix', '', true, 'TestApp\Suffix\No'],
  138. ['MyPlugin.Exists', 'In', 'Suffix', true, 'MyPlugin\In\ExistsSuffix'],
  139. ['MyPlugin.Also/Exists', 'In', 'Suffix', true, 'MyPlugin\In\Also\ExistsSuffix'],
  140. ['MyPlugin.Also', 'Exists/In', 'Suffix', true, 'MyPlugin\Exists\In\AlsoSuffix'],
  141. ['MyPlugin.Also', 'Exists/In/Subfolder', 'Suffix', true, 'MyPlugin\Exists\In\Subfolder\AlsoSuffix'],
  142. ['MyPlugin.No', 'Suffix', '', true, 'MyPlugin\Suffix\No'],
  143. ['Vend/MPlugin.Exists', 'In', 'Suffix', true, 'Vend\MPlugin\In\ExistsSuffix'],
  144. ['Vend/MPlugin.Also/Exists', 'In', 'Suffix', true, 'Vend\MPlugin\In\Also\ExistsSuffix'],
  145. ['Vend/MPlugin.Also', 'Exists/In', 'Suffix', true, 'Vend\MPlugin\Exists\In\AlsoSuffix'],
  146. ['Vend/MPlugin.Also', 'Exists/In/Subfolder', 'Suffix', true, 'Vend\MPlugin\Exists\In\Subfolder\AlsoSuffix'],
  147. ['Vend/MPlugin.No', 'Suffix', '', true, 'Vend\MPlugin\Suffix\No'],
  148. ['Exists', 'In', 'Cake', false, 'Cake\In\ExistsCake'],
  149. ['Also/Exists', 'In', 'Cake', false, 'Cake\In\Also\ExistsCake'],
  150. ['Also', 'Exists/In', 'Cake', false, 'Cake\Exists\In\AlsoCake'],
  151. ['Also', 'Exists/In/Subfolder', 'Cake', false, 'Cake\Exists\In\Subfolder\AlsoCake'],
  152. ['No', 'Suffix', '', false, 'Cake\Suffix\No'],
  153. // Realistic examples returning nothing
  154. ['App', 'Core', 'Suffix'],
  155. ['Auth', 'Controller/Component'],
  156. ['Unknown', 'Controller', 'Controller'],
  157. // Real examples returning class names
  158. ['App', 'Core', '', false, 'Cake\Core\App'],
  159. ['Auth', 'Controller/Component', 'Component', false, 'Cake\Controller\Component\AuthComponent'],
  160. ['File', 'Cache/Engine', 'Engine', false, 'Cake\Cache\Engine\FileEngine'],
  161. ['Command', 'Shell/Task', 'Task', false, 'Cake\Shell\Task\CommandTask'],
  162. ['Upgrade/Locations', 'Shell/Task', 'Task', false, 'Cake\Shell\Task\Upgrade\LocationsTask'],
  163. ['Pages', 'Controller', 'Controller', true, 'TestApp\Controller\PagesController'],
  164. ];
  165. }
  166. /**
  167. * pluginSplitNameProvider
  168. *
  169. * Return test permutations for testClassName method. Format:
  170. * className
  171. * type
  172. * suffix
  173. * expected return value
  174. *
  175. * @return array
  176. */
  177. public static function shortNameProvider(): array
  178. {
  179. return [
  180. ['TestApp\In\ExistsApp', 'In', 'App', 'Exists'],
  181. ['TestApp\In\Also\ExistsApp', 'In', 'App', 'Also/Exists'],
  182. ['TestApp\Exists\In\AlsoApp', 'Exists/In', 'App', 'Also'],
  183. ['TestApp\Exists\In\Subfolder\AlsoApp', 'Exists/In/Subfolder', 'App', 'Also'],
  184. ['TestApp\Suffix\No', 'Suffix', '', 'No'],
  185. ['MyPlugin\In\ExistsSuffix', 'In', 'Suffix', 'MyPlugin.Exists'],
  186. ['MyPlugin\In\Also\ExistsSuffix', 'In', 'Suffix', 'MyPlugin.Also/Exists'],
  187. ['MyPlugin\Exists\In\AlsoSuffix', 'Exists/In', 'Suffix', 'MyPlugin.Also'],
  188. ['MyPlugin\Exists\In\Subfolder\AlsoSuffix', 'Exists/In/Subfolder', 'Suffix', 'MyPlugin.Also'],
  189. ['MyPlugin\Suffix\No', 'Suffix', '', 'MyPlugin.No'],
  190. ['Vend\MPlugin\In\ExistsSuffix', 'In', 'Suffix', 'Vend/MPlugin.Exists'],
  191. ['Vend\MPlugin\In\Also\ExistsSuffix', 'In', 'Suffix', 'Vend/MPlugin.Also/Exists'],
  192. ['Vend\MPlugin\Exists\In\AlsoSuffix', 'Exists/In', 'Suffix', 'Vend/MPlugin.Also'],
  193. ['Vend\MPlugin\Exists\In\Subfolder\AlsoSuffix', 'Exists/In/Subfolder', 'Suffix', 'Vend/MPlugin.Also'],
  194. ['Vend\MPlugin\Suffix\No', 'Suffix', '', 'Vend/MPlugin.No'],
  195. ['Cake\In\ExistsCake', 'In', 'Cake', 'Exists'],
  196. ['Cake\In\Also\ExistsCake', 'In', 'Cake', 'Also/Exists'],
  197. ['Cake\Exists\In\AlsoCake', 'Exists/In', 'Cake', 'Also'],
  198. ['Cake\Exists\In\Subfolder\AlsoCake', 'Exists/In/Subfolder', 'Cake', 'Also'],
  199. ['Cake\Suffix\No', 'Suffix', '', 'No'],
  200. ['Muffin\Webservice\Webservice\EndpointWebservice', 'Webservice', 'Webservice', 'Muffin/Webservice.Endpoint'],
  201. // Real examples returning class names
  202. ['Cake\Core\App', 'Core', '', 'App'],
  203. ['Cake\Controller\Component\AuthComponent', 'Controller/Component', 'Component', 'Auth'],
  204. ['Cake\Cache\Engine\FileEngine', 'Cache/Engine', 'Engine', 'File'],
  205. ['Cake\Shell\Task\CommandTask', 'Shell/Task', 'Task', 'Command'],
  206. ['Cake\Shell\Task\Upgrade\LocationsTask', 'Shell/Task', 'Task', 'Upgrade/Locations'],
  207. ['TestApp\Controller\PagesController', 'Controller', 'Controller', 'Pages'],
  208. ];
  209. }
  210. /**
  211. * test classPath() with a plugin.
  212. */
  213. public function testClassPathWithPlugins(): void
  214. {
  215. $basepath = TEST_APP . 'Plugin' . DS;
  216. $this->loadPlugins(['TestPlugin', 'Company/TestPluginThree']);
  217. $result = App::classPath('Controller', 'TestPlugin');
  218. $this->assertPathEquals($basepath . 'TestPlugin' . DS . 'src' . DS . 'Controller' . DS, $result[0]);
  219. $result = App::classPath('Controller', 'Company/TestPluginThree');
  220. $expected = $basepath . 'Company' . DS . 'TestPluginThree' . DS . 'src' . DS . 'Controller' . DS;
  221. $this->assertPathEquals($expected, $result[0]);
  222. }
  223. /**
  224. * test path() with a plugin.
  225. */
  226. public function testPathWithPlugins(): void
  227. {
  228. $basepath = TEST_APP . 'Plugin' . DS;
  229. $this->loadPlugins(['TestPlugin', 'Company/TestPluginThree']);
  230. $result = App::path('locales', 'TestPlugin');
  231. $this->assertPathEquals($basepath . 'TestPlugin' . DS . 'resources' . DS . 'locales' . DS, $result[0]);
  232. $result = App::path('locales', 'Company/TestPluginThree');
  233. $expected = $basepath . 'Company' . DS . 'TestPluginThree' . DS . 'resources' . DS . 'locales' . DS;
  234. $this->assertPathEquals($expected, $result[0]);
  235. }
  236. public function testPathWithPluginsException(): void
  237. {
  238. $this->expectException(CakeException::class);
  239. App::path('invalid', 'TestPlugin');
  240. }
  241. /**
  242. * testCore method
  243. */
  244. public function testCore(): void
  245. {
  246. $model = App::core('Model');
  247. $this->assertEquals([CAKE . 'Model' . DS], $model);
  248. $view = App::core('View');
  249. $this->assertEquals([CAKE . 'View' . DS], $view);
  250. $controller = App::core('Controller');
  251. $this->assertEquals([CAKE . 'Controller' . DS], $controller);
  252. $component = App::core('Controller/Component');
  253. $this->assertEquals([CAKE . 'Controller' . DS . 'Component' . DS], str_replace('/', DS, $component));
  254. $auth = App::core('Controller/Component/Auth');
  255. $this->assertEquals([CAKE . 'Controller' . DS . 'Component' . DS . 'Auth' . DS], str_replace('/', DS, $auth));
  256. $datasource = App::core('Model/Datasource');
  257. $this->assertEquals([CAKE . 'Model' . DS . 'Datasource' . DS], str_replace('/', DS, $datasource));
  258. }
  259. }