PageRenderTime 56ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/Propel/Tests/Generator/Behavior/Sluggable/SluggableBehaviorTest.php

http://github.com/propelorm/Propel2
PHP | 452 lines | 321 code | 51 blank | 80 comment | 3 complexity | ab17db332416e61464c6928a1bb003d7 MD5 | raw file
  1. <?php
  2. /**
  3. * MIT License. This file is part of the Propel package.
  4. * For the full copyright and license information, please view the LICENSE
  5. * file that was distributed with this source code.
  6. */
  7. namespace Propel\Tests\Generator\Behavior\Sluggable;
  8. use Exception;
  9. use Propel\Runtime\Adapter\Pdo\PgsqlAdapter;
  10. use Propel\Runtime\Exception\PropelException;
  11. use Propel\Runtime\Propel;
  12. use Propel\Tests\Bookstore\Behavior\Map\Table13TableMap;
  13. use Propel\Tests\Bookstore\Behavior\Map\Table14TableMap;
  14. use Propel\Tests\Bookstore\Behavior\Table13;
  15. use Propel\Tests\Bookstore\Behavior\Table13Query;
  16. use Propel\Tests\Bookstore\Behavior\Table14;
  17. use Propel\Tests\Bookstore\Behavior\Table14Query;
  18. use Propel\Tests\Bookstore\Behavior\TableWithScope;
  19. use Propel\Tests\Bookstore\Behavior\TableWithScopeQuery;
  20. use Propel\Tests\Helpers\Bookstore\BookstoreTestBase;
  21. /**
  22. * Tests for SluggableBehavior class
  23. *
  24. * @author François Zaninotto
  25. *
  26. * @group database
  27. */
  28. class SluggableBehaviorTest extends BookstoreTestBase
  29. {
  30. /**
  31. * @return void
  32. */
  33. protected function setUp(): void
  34. {
  35. //prevent issue DSN not Found
  36. self::$isInitialized = false;
  37. parent::setUp();
  38. include_once(__DIR__ . '/SluggableBehaviorTestClasses.php');
  39. }
  40. /**
  41. * @return void
  42. */
  43. public function testParameters()
  44. {
  45. $table13 = Table13TableMap::getTableMap();
  46. $this->assertEquals(count($table13->getColumns()), 3, 'Sluggable adds one columns by default');
  47. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\Behavior\Table13', 'getSlug'), 'Sluggable adds a slug column by default');
  48. $table14 = Table14TableMap::getTableMap();
  49. $this->assertEquals(count($table14->getColumns()), 3, 'Sluggable does not add a column when it already exists');
  50. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\Behavior\Table14', 'getUrl'), 'Sluggable allows customization of slug_column name');
  51. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\Behavior\Table14', 'getSlug'), 'Sluggable adds a standard getter for the slug column');
  52. }
  53. /**
  54. * @return void
  55. */
  56. public function testObjectGetter()
  57. {
  58. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\Behavior\Table13', 'getSlug'), 'Sluggable adds a getter for the slug column');
  59. $t = new Table13();
  60. $t->setSlug('foo');
  61. $this->assertEquals('foo', $t->getSlug(), 'getSlug() returns the object slug');
  62. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\Behavior\Table14', 'getSlug'), 'Sluggable adds a getter for the slug column, even if the column does not have the default name');
  63. $t = new Table14();
  64. $t->setUrl('foo');
  65. $this->assertEquals('foo', $t->getSlug(), 'getSlug() returns the object slug');
  66. }
  67. /**
  68. * @return void
  69. */
  70. public function testObjectSetter()
  71. {
  72. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\Behavior\Table13', 'setSlug'), 'Sluggable adds a setter for the slug column');
  73. $t = new Table13();
  74. $t->setSlug('foo');
  75. $this->assertEquals('foo', $t->getSlug(), 'setSlug() sets the object slug');
  76. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\Behavior\Table14', 'setSlug'), 'Sluggable adds a setter for the slug column, even if the column does not have the default name');
  77. $t = new Table14();
  78. $t->setSlug('foo');
  79. $this->assertEquals('foo', $t->getUrl(), 'setSlug() sets the object slug');
  80. }
  81. /**
  82. * @return void
  83. */
  84. public function testObjectCreateRawSlug()
  85. {
  86. $t = new TestableTable13();
  87. $this->assertEquals('n-a', $t->createRawSlug(), 'createRawSlug() returns an empty string for an empty object with no pattern');
  88. $t->setTitle('Hello, World');
  89. $this->assertEquals('hello-world', $t->createRawSlug(), 'createRawSlug() returns the cleaned up object string representation by default');
  90. $t = new TestableTable14();
  91. $this->assertEquals('/foo/n-a/bar', $t->createRawSlug(), 'createRawSlug() returns a slug for an empty object with a pattern');
  92. $t->setTitle('Hello, World');
  93. $this->assertEquals('/foo/hello-world/bar', $t->createRawSlug(), 'createRawSlug() returns a slug based on a pattern');
  94. }
  95. /**
  96. * @return string[][]
  97. */
  98. public static function cleanupSlugProvider()
  99. {
  100. return [
  101. ['', 'n-a'],
  102. ['foo', 'foo'],
  103. ['foo bar', 'foo-bar'],
  104. ['foo bar', 'foo-bar'],
  105. ['FoO', 'foo'],
  106. ['fôo', 'foo'],
  107. [' foo ', 'foo'],
  108. ['f/o:o', 'f-o-o'],
  109. ['foo1', 'foo1'],
  110. ];
  111. }
  112. /**
  113. * @dataProvider cleanupSlugProvider
  114. *
  115. * @param string $in
  116. * @param string $out
  117. *
  118. * @return void
  119. */
  120. public function testObjectCleanupSlugPart($in, $out)
  121. {
  122. $t = new TestableTable13();
  123. $this->assertEquals($out, $t->cleanupSlugPart($in), 'cleanupSlugPart() cleans up the slug part');
  124. }
  125. /**
  126. * @return array
  127. */
  128. public static function limitSlugSizeProvider()
  129. {
  130. return [
  131. ['123', '123'],
  132. [str_repeat('*', 80), str_repeat('*', 80)],
  133. [str_repeat('*', 97), str_repeat('*', 97)],
  134. [str_repeat('*', 98), str_repeat('*', 97)],
  135. [str_repeat('*', 99), str_repeat('*', 97)],
  136. [str_repeat('*', 100), str_repeat('*', 97)],
  137. [str_repeat('*', 150), str_repeat('*', 97)],
  138. ];
  139. }
  140. /**
  141. * @dataProvider limitSlugSizeProvider
  142. *
  143. * @return void
  144. */
  145. public function testObjectLimitSlugSize($in, $out)
  146. {
  147. $t = new TestableTable14();
  148. $this->assertEquals($out, $t->limitSlugSize($in), 'limitSlugsize() limits the slug size');
  149. }
  150. /**
  151. * @return void
  152. */
  153. public function testObjectMakeSlugUnique()
  154. {
  155. Table13Query::create()->deleteAll();
  156. $t = new TestableTable13();
  157. $this->assertEquals('', $t->makeSlugUnique(''), 'makeSlugUnique() returns the input slug when the input is empty');
  158. $this->assertEquals('foo', $t->makeSlugUnique('foo'), 'makeSlugUnique() returns the input slug when the table is empty');
  159. $t->setSlug('foo');
  160. $t->save();
  161. $t = new TestableTable13();
  162. $this->assertEquals('bar', $t->makeSlugUnique('bar'), 'makeSlugUnique() returns the input slug when the table does not contain a similar slug');
  163. $t->save();
  164. $t = new TestableTable13();
  165. $this->assertEquals('foo-1', $t->makeSlugUnique('foo'), 'makeSlugUnique() returns an incremented input when it already exists');
  166. $t->setSlug('foo-1');
  167. $t->save();
  168. $t = new TestableTable13();
  169. $this->assertEquals('foo-2', $t->makeSlugUnique('foo'), 'makeSlugUnique() returns an incremented input when it already exists');
  170. }
  171. /**
  172. * @return void
  173. */
  174. public function testObjectCreateSlug()
  175. {
  176. Table13Query::create()->deleteAll();
  177. $t = new TestableTable13();
  178. $this->assertEquals('n-a', $t->createSlug(), 'createSlug() returns n-a for an empty object');
  179. $t->setTitle('Hello, World!');
  180. $this->assertEquals('hello-world', $t->createSlug(), 'createSlug() returns a cleaned up slug');
  181. $t->setSlug('hello-world');
  182. $t->save();
  183. $t = new TestableTable13();
  184. $t->setTitle('Hello; wOrld');
  185. $this->assertEquals('hello-world-1', $t->createSlug(), 'createSlug() returns a unique slug');
  186. Table14Query::create()->deleteAll();
  187. $t = new TestableTable14();
  188. $this->assertEquals('/foo/n-a/bar', $t->createSlug(), 'createSlug() returns a slug for an empty object with a pattern');
  189. $t->setTitle('Hello, World!');
  190. $this->assertEquals('/foo/hello-world/bar', $t->createSlug(), 'createSlug() returns a cleaned up slug');
  191. $t->setSlug('/foo/hello-world/bar');
  192. $t->save();
  193. $t = new TestableTable14();
  194. $t->setTitle('Hello; wOrld:');
  195. $this->assertEquals('/foo/hello-world/bar/1', $t->createSlug(), 'createSlug() returns a unique slug');
  196. }
  197. /**
  198. * @return void
  199. */
  200. public function testObjectPreSave()
  201. {
  202. Table14Query::create()->deleteAll();
  203. $t = new Table14();
  204. $t->save();
  205. $this->assertEquals('/foo/n-a/bar', $t->getSlug(), 'preSave() sets a default slug for empty objects');
  206. $t = new Table14();
  207. $t->setTitle('Hello, World');
  208. $t->save();
  209. $this->assertEquals('/foo/hello-world/bar', $t->getSlug(), 'preSave() sets a cleaned up slug for objects');
  210. $t = new Table14();
  211. $t->setTitle('Hello, World');
  212. $t->save();
  213. $this->assertEquals('/foo/hello-world/bar/1', $t->getSlug(), 'preSave() sets a unique slug for objects');
  214. $t = new Table14();
  215. $t->setTitle('Hello, World');
  216. $t->setSlug('/foo/custom/bar');
  217. $t->save();
  218. $this->assertEquals('/foo/custom/bar', $t->getSlug(), 'preSave() uses the given slug if it exists');
  219. $t = new Table14();
  220. $t->setTitle('Hello, World');
  221. $t->setSlug('/foo/custom/bar');
  222. $t->save();
  223. $this->assertEquals('/foo/custom/bar/1', $t->getSlug(), 'preSave() uses the given slug if it exists and makes it unique');
  224. }
  225. /**
  226. * @return void
  227. */
  228. public function testObjectSlugLifecycle()
  229. {
  230. Table13Query::create()->deleteAll();
  231. $t = new Table13();
  232. $t->setTitle('Hello, World');
  233. $t->save();
  234. $this->assertEquals('hello-world', $t->getSlug(), 'preSave() creates a slug for new objects');
  235. $t->setSlug('hello-bar');
  236. $t->save();
  237. $this->assertEquals('hello-bar', $t->getSlug(), 'setSlug() allows to override default slug');
  238. $t->setSlug('');
  239. $t->save();
  240. $this->assertEquals('hello-world', $t->getSlug(), 'setSlug(null) relaunches the slug generation');
  241. Table14Query::create()->deleteAll();
  242. $t = new Table14();
  243. $t->setTitle('Hello, World2');
  244. $t->setSlug('hello-bar2');
  245. $t->save();
  246. $this->assertEquals('hello-bar2', $t->getSlug(), 'setSlug() allows to override default slug, even before save');
  247. $t->setSlug('');
  248. $t->save();
  249. $this->assertEquals('/foo/hello-world2/bar', $t->getSlug(), 'setSlug(null) relaunches the slug generation');
  250. }
  251. /**
  252. * @return void
  253. */
  254. public function testObjectSlugAutoUpdate()
  255. {
  256. Table13Query::create()->deleteAll();
  257. $t = new Table13();
  258. $t->setTitle('Hello, World');
  259. $t->save();
  260. $this->assertEquals('hello-world', $t->getSlug(), 'preSave() creates a slug for new objects');
  261. $t->setTitle('Hello, My World');
  262. $t->save();
  263. $this->assertEquals('hello-my-world', $t->getSlug(), 'preSave() autoupdates slug on object change');
  264. $t->setTitle('Hello, My Whole New World');
  265. $t->setSlug('hello-bar');
  266. $t->save();
  267. $this->assertEquals('hello-bar', $t->getSlug(), 'preSave() does not autoupdate slug when it was set by the user');
  268. }
  269. /**
  270. * @return void
  271. */
  272. public function testObjectSlugAutoUpdatePermanent()
  273. {
  274. Table14Query::create()->deleteAll();
  275. $t = new Table14();
  276. $t->setTitle('Hello, World');
  277. $t->save();
  278. $this->assertEquals('/foo/hello-world/bar', $t->getSlug(), 'preSave() creates a slug for new objects');
  279. $t->setTitle('Hello, My World');
  280. $t->save();
  281. $this->assertEquals('/foo/hello-world/bar', $t->getSlug(), 'preSave() does not autoupdate slug on object change for permanent slugs');
  282. $t->setSlug('hello-bar');
  283. $t->save();
  284. $this->assertEquals('hello-bar', $t->getSlug(), 'setSlug() still works for permanent slugs');
  285. }
  286. /**
  287. * @return void
  288. */
  289. public function testQueryFindOneBySlug()
  290. {
  291. $this->assertFalse(method_exists('\Propel\Tests\Bookstore\Behavior\Table13Query', 'findOneBySlug'), 'The generated query does not provide a findOneBySlug() method if the slug column is "slug".');
  292. $this->assertTrue(method_exists('\Propel\Tests\Bookstore\Behavior\Table14Query', 'findOneBySlug'), 'The generated query provides a findOneBySlug() method even if the slug column doesn\'t have the default name');
  293. Table14Query::create()->deleteAll();
  294. $t1 = new Table14();
  295. $t1->setTitle('Hello, World');
  296. $t1->save();
  297. $t2 = new Table14();
  298. $t2->setTitle('Hello, Cruel World');
  299. $t2->save();
  300. $t = Table14Query::create()->findOneBySlug('/foo/hello-world/bar');
  301. $this->assertEquals($t1, $t, 'findOneBySlug() returns a single object matching the slug');
  302. }
  303. /**
  304. * @return void
  305. */
  306. public function testUniqueViolationWithoutScope()
  307. {
  308. $this->markTestSkipped('Skipping...');
  309. TableWithScopeQuery::create()->deleteAll();
  310. $t = new TableWithScope();
  311. $t->setTitle('Hello, World');
  312. $t->save();
  313. $this->assertEquals('hello-world', $t->getSlug());
  314. $this->expectException(PropelException::class);
  315. $t = new TableWithScope();
  316. $t->setTitle('Hello, World');
  317. $t->save();
  318. }
  319. /**
  320. * @return void
  321. */
  322. public function testNoUniqueViolationWithScope()
  323. {
  324. TableWithScopeQuery::create()->deleteAll();
  325. $t = new TableWithScope();
  326. $t->setTitle('Hello, World');
  327. $t->save();
  328. $this->assertEquals('hello-world', $t->getSlug());
  329. try {
  330. $t = new TableWithScope();
  331. $t->setTitle('Hello, World');
  332. $t->setScope(1);
  333. $t->save();
  334. $this->assertEquals('hello-world', $t->getSlug());
  335. } catch (Exception $e) {
  336. $this->fail($e->getMessage());
  337. }
  338. }
  339. /**
  340. * @return void
  341. */
  342. public function testNumberOfQueriesForMakeUniqSlug()
  343. {
  344. Table13Query::create()->deleteAll();
  345. $con = Propel::getServiceContainer()->getConnection(Table13TableMap::DATABASE_NAME);
  346. $adapter = Propel::getAdapter(Table13TableMap::DATABASE_NAME);
  347. $expectedCount = 4;
  348. if ($adapter instanceof PgsqlAdapter) {
  349. $expectedCount++; //because of the SELECT nextval(...) query
  350. }
  351. for ($i = 0; $i < 5; $i++) {
  352. $nbQuery = $con->getQueryCount();
  353. $t = new Table13();
  354. $t->setTitle('Hello, World');
  355. $t->save($con);
  356. $this->assertLessThanOrEqual($expectedCount, $con->getQueryCount() - $nbQuery, "no more than $expectedCount query to get a slug when it already exist");
  357. }
  358. }
  359. /**
  360. * @return void
  361. */
  362. public function testSlugRegexp()
  363. {
  364. Table13Query::create()->deleteAll();
  365. $con = Propel::getServiceContainer()->getConnection(Table13TableMap::DATABASE_NAME);
  366. for ($i = 0; $i < 3; $i++) {
  367. $t = new Table13();
  368. $t->setTitle('Hello, World');
  369. $t->save($con);
  370. }
  371. $this->assertEquals('hello-world-2', $t->getSlug());
  372. $t = new Table13();
  373. $t->setTitle('World');
  374. $t->save($con);
  375. $this->assertEquals('world', $t->getSlug());
  376. $t = new Table13();
  377. $t->setTitle('World');
  378. $t->save($con);
  379. $this->assertEquals('world-1', $t->getSlug());
  380. $t = new Table13();
  381. $t->setTitle('Hello, World');
  382. $t->save($con);
  383. $this->assertEquals('hello-world-3', $t->getSlug());
  384. $t = new Table13();
  385. $t->setTitle('World');
  386. $t->save($con);
  387. $this->assertEquals('world-2', $t->getSlug());
  388. $t = new Table13();
  389. $t->setTitle('World 000');
  390. $t->save($con);
  391. $this->assertEquals('world-000', $t->getSlug());
  392. $t = new Table13();
  393. $t->setTitle('World');
  394. $t->save($con);
  395. $this->assertEquals('world-101', $t->getSlug());
  396. $t = new Table13();
  397. $t->setTitle('World');
  398. $t->save($con);
  399. $this->assertEquals('world-102', $t->getSlug());
  400. }
  401. }