ConfigEntityTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <?php
  2. namespace Drupal\Tests\config\Functional;
  3. use Drupal\Component\Render\FormattableMarkup;
  4. use Drupal\Component\Uuid\Uuid;
  5. use Drupal\Core\Entity\EntityMalformedException;
  6. use Drupal\Core\Entity\EntityStorageException;
  7. use Drupal\Core\Config\Entity\ConfigEntityStorage;
  8. use Drupal\Core\Config\Entity\Exception\ConfigEntityIdLengthException;
  9. use Drupal\Core\Url;
  10. use Drupal\Tests\BrowserTestBase;
  11. /**
  12. * Tests configuration entities.
  13. *
  14. * @group config
  15. */
  16. class ConfigEntityTest extends BrowserTestBase {
  17. /**
  18. * The maximum length for the entity storage used in this test.
  19. */
  20. const MAX_ID_LENGTH = ConfigEntityStorage::MAX_ID_LENGTH;
  21. /**
  22. * Modules to enable.
  23. *
  24. * @var array
  25. */
  26. public static $modules = ['config_test'];
  27. /**
  28. * {@inheritdoc}
  29. */
  30. protected $defaultTheme = 'stark';
  31. /**
  32. * Tests CRUD operations.
  33. */
  34. public function testCRUD() {
  35. $default_langcode = \Drupal::languageManager()->getDefaultLanguage()->getId();
  36. // Verify default properties on a newly created empty entity.
  37. $storage = \Drupal::entityTypeManager()->getStorage('config_test');
  38. $empty = $storage->create();
  39. $this->assertIdentical($empty->label, NULL);
  40. $this->assertIdentical($empty->style, NULL);
  41. $this->assertIdentical($empty->language()->getId(), $default_langcode);
  42. // Verify ConfigEntity properties/methods on the newly created empty entity.
  43. $this->assertIdentical($empty->isNew(), TRUE);
  44. $this->assertIdentical($empty->getOriginalId(), NULL);
  45. $this->assertIdentical($empty->bundle(), 'config_test');
  46. $this->assertIdentical($empty->id(), NULL);
  47. $this->assertTrue(Uuid::isValid($empty->uuid()));
  48. $this->assertIdentical($empty->label(), NULL);
  49. $this->assertIdentical($empty->get('id'), NULL);
  50. $this->assertTrue(Uuid::isValid($empty->get('uuid')));
  51. $this->assertIdentical($empty->get('label'), NULL);
  52. $this->assertIdentical($empty->get('style'), NULL);
  53. $this->assertIdentical($empty->language()->getId(), $default_langcode);
  54. // Verify Entity properties/methods on the newly created empty entity.
  55. $this->assertIdentical($empty->getEntityTypeId(), 'config_test');
  56. // The URI can only be checked after saving.
  57. try {
  58. $empty->toUrl();
  59. $this->fail('EntityMalformedException was thrown.');
  60. }
  61. catch (EntityMalformedException $e) {
  62. // Expected exception; just continue testing.
  63. }
  64. // Verify that an empty entity cannot be saved.
  65. try {
  66. $empty->save();
  67. $this->fail('EntityMalformedException was thrown.');
  68. }
  69. catch (EntityMalformedException $e) {
  70. // Expected exception; just continue testing.
  71. }
  72. // Verify that an entity with an empty ID string is considered empty, too.
  73. $empty_id = $storage->create([
  74. 'id' => '',
  75. ]);
  76. $this->assertIdentical($empty_id->isNew(), TRUE);
  77. try {
  78. $empty_id->save();
  79. $this->fail('EntityMalformedException was thrown.');
  80. }
  81. catch (EntityMalformedException $e) {
  82. // Expected exception; just continue testing.
  83. }
  84. // Verify properties on a newly created entity.
  85. $config_test = $storage->create($expected = [
  86. 'id' => $this->randomMachineName(),
  87. 'label' => $this->randomString(),
  88. 'style' => $this->randomMachineName(),
  89. ]);
  90. $this->assertNotEqual($config_test->uuid(), $empty->uuid());
  91. $this->assertIdentical($config_test->label, $expected['label']);
  92. $this->assertIdentical($config_test->style, $expected['style']);
  93. $this->assertIdentical($config_test->language()->getId(), $default_langcode);
  94. // Verify methods on the newly created entity.
  95. $this->assertIdentical($config_test->isNew(), TRUE);
  96. $this->assertIdentical($config_test->getOriginalId(), $expected['id']);
  97. $this->assertIdentical($config_test->id(), $expected['id']);
  98. $this->assertTrue(Uuid::isValid($config_test->uuid()));
  99. $expected['uuid'] = $config_test->uuid();
  100. $this->assertIdentical($config_test->label(), $expected['label']);
  101. // Verify that the entity can be saved.
  102. try {
  103. $status = $config_test->save();
  104. }
  105. catch (EntityMalformedException $e) {
  106. $this->fail('EntityMalformedException was not thrown.');
  107. }
  108. // The entity path can only be checked after saving.
  109. $this->assertIdentical($config_test->toUrl()->toString(), Url::fromRoute('entity.config_test.edit_form', ['config_test' => $expected['id']])->toString());
  110. // Verify that the correct status is returned and properties did not change.
  111. $this->assertIdentical($status, SAVED_NEW);
  112. $this->assertIdentical($config_test->id(), $expected['id']);
  113. $this->assertIdentical($config_test->uuid(), $expected['uuid']);
  114. $this->assertIdentical($config_test->label(), $expected['label']);
  115. $this->assertIdentical($config_test->isNew(), FALSE);
  116. $this->assertIdentical($config_test->getOriginalId(), $expected['id']);
  117. // Save again, and verify correct status and properties again.
  118. $status = $config_test->save();
  119. $this->assertIdentical($status, SAVED_UPDATED);
  120. $this->assertIdentical($config_test->id(), $expected['id']);
  121. $this->assertIdentical($config_test->uuid(), $expected['uuid']);
  122. $this->assertIdentical($config_test->label(), $expected['label']);
  123. $this->assertIdentical($config_test->isNew(), FALSE);
  124. $this->assertIdentical($config_test->getOriginalId(), $expected['id']);
  125. // Verify that a configuration entity can be saved with an ID of the
  126. // maximum allowed length, but not longer.
  127. // Test with a short ID.
  128. $id_length_config_test = $storage->create([
  129. 'id' => $this->randomMachineName(8),
  130. ]);
  131. try {
  132. $id_length_config_test->save();
  133. }
  134. catch (ConfigEntityIdLengthException $e) {
  135. $this->fail($e->getMessage());
  136. }
  137. // Test with an ID of the maximum allowed length.
  138. $id_length_config_test = $storage->create([
  139. 'id' => $this->randomMachineName(static::MAX_ID_LENGTH),
  140. ]);
  141. try {
  142. $id_length_config_test->save();
  143. }
  144. catch (ConfigEntityIdLengthException $e) {
  145. $this->fail($e->getMessage());
  146. }
  147. // Test with an ID exceeding the maximum allowed length.
  148. $id_length_config_test = $storage->create([
  149. 'id' => $this->randomMachineName(static::MAX_ID_LENGTH + 1),
  150. ]);
  151. try {
  152. $status = $id_length_config_test->save();
  153. $this->fail(new FormattableMarkup("config_test entity with ID length @length exceeding the maximum allowed length of @max saved successfully", [
  154. '@length' => strlen($id_length_config_test->id()),
  155. '@max' => static::MAX_ID_LENGTH,
  156. ]));
  157. }
  158. catch (ConfigEntityIdLengthException $e) {
  159. // Expected exception; just continue testing.
  160. }
  161. // Ensure that creating an entity with the same id as an existing one is not
  162. // possible.
  163. $same_id = $storage->create([
  164. 'id' => $config_test->id(),
  165. ]);
  166. $this->assertIdentical($same_id->isNew(), TRUE);
  167. try {
  168. $same_id->save();
  169. $this->fail('Not possible to overwrite an entity entity.');
  170. }
  171. catch (EntityStorageException $e) {
  172. // Expected exception; just continue testing.
  173. }
  174. // Verify that renaming the ID returns correct status and properties.
  175. $ids = [$expected['id'], 'second_' . $this->randomMachineName(4), 'third_' . $this->randomMachineName(4)];
  176. for ($i = 1; $i < 3; $i++) {
  177. $old_id = $ids[$i - 1];
  178. $new_id = $ids[$i];
  179. // Before renaming, everything should point to the current ID.
  180. $this->assertIdentical($config_test->id(), $old_id);
  181. $this->assertIdentical($config_test->getOriginalId(), $old_id);
  182. // Rename.
  183. $config_test->set('id', $new_id);
  184. $this->assertIdentical($config_test->id(), $new_id);
  185. $status = $config_test->save();
  186. $this->assertIdentical($status, SAVED_UPDATED);
  187. $this->assertIdentical($config_test->isNew(), FALSE);
  188. // Verify that originalID points to new ID directly after renaming.
  189. $this->assertIdentical($config_test->id(), $new_id);
  190. $this->assertIdentical($config_test->getOriginalId(), $new_id);
  191. }
  192. // Test config entity prepopulation.
  193. \Drupal::state()->set('config_test.prepopulate', TRUE);
  194. $config_test = $storage->create(['foo' => 'bar']);
  195. $this->assertEquals('baz', $config_test->get('foo'), 'Initial value correctly populated');
  196. }
  197. /**
  198. * Tests CRUD operations through the UI.
  199. */
  200. public function testCRUDUI() {
  201. $this->drupalLogin($this->drupalCreateUser([
  202. 'administer site configuration',
  203. ]));
  204. $id = strtolower($this->randomMachineName());
  205. $label1 = $this->randomMachineName();
  206. $label2 = $this->randomMachineName();
  207. $label3 = $this->randomMachineName();
  208. $message_insert = new FormattableMarkup('%label configuration has been created.', ['%label' => $label1]);
  209. $message_update = new FormattableMarkup('%label configuration has been updated.', ['%label' => $label2]);
  210. $message_delete = new FormattableMarkup('The test configuration %label has been deleted.', ['%label' => $label2]);
  211. // Create a configuration entity.
  212. $edit = [
  213. 'id' => $id,
  214. 'label' => $label1,
  215. ];
  216. $this->drupalPostForm('admin/structure/config_test/add', $edit, 'Save');
  217. $this->assertUrl('admin/structure/config_test');
  218. $this->assertSession()->statusCodeEquals(200);
  219. $this->assertRaw($message_insert);
  220. $this->assertNoRaw($message_update);
  221. $this->assertLinkByHref("admin/structure/config_test/manage/$id");
  222. // Update the configuration entity.
  223. $edit = [
  224. 'label' => $label2,
  225. ];
  226. $this->drupalPostForm("admin/structure/config_test/manage/$id", $edit, 'Save');
  227. $this->assertUrl('admin/structure/config_test');
  228. $this->assertSession()->statusCodeEquals(200);
  229. $this->assertNoRaw($message_insert);
  230. $this->assertRaw($message_update);
  231. $this->assertLinkByHref("admin/structure/config_test/manage/$id");
  232. $this->assertLinkByHref("admin/structure/config_test/manage/$id/delete");
  233. // Delete the configuration entity.
  234. $this->drupalGet("admin/structure/config_test/manage/$id");
  235. $this->clickLink(t('Delete'));
  236. $this->assertUrl("admin/structure/config_test/manage/$id/delete");
  237. $this->drupalPostForm(NULL, [], 'Delete');
  238. $this->assertUrl('admin/structure/config_test');
  239. $this->assertSession()->statusCodeEquals(200);
  240. $this->assertNoRaw($message_update);
  241. $this->assertRaw($message_delete);
  242. $this->assertNoText($label1);
  243. $this->assertNoLinkByHref("admin/structure/config_test/manage/$id");
  244. // Re-create a configuration entity.
  245. $edit = [
  246. 'id' => $id,
  247. 'label' => $label1,
  248. ];
  249. $this->drupalPostForm('admin/structure/config_test/add', $edit, 'Save');
  250. $this->assertUrl('admin/structure/config_test');
  251. $this->assertSession()->statusCodeEquals(200);
  252. $this->assertText($label1);
  253. $this->assertLinkByHref("admin/structure/config_test/manage/$id");
  254. // Rename the configuration entity's ID/machine name.
  255. $edit = [
  256. 'id' => strtolower($this->randomMachineName()),
  257. 'label' => $label3,
  258. ];
  259. $this->drupalPostForm("admin/structure/config_test/manage/$id", $edit, 'Save');
  260. $this->assertUrl('admin/structure/config_test');
  261. $this->assertSession()->statusCodeEquals(200);
  262. $this->assertNoText($label1);
  263. $this->assertNoText($label2);
  264. $this->assertText($label3);
  265. $this->assertNoLinkByHref("admin/structure/config_test/manage/$id");
  266. $id = $edit['id'];
  267. $this->assertLinkByHref("admin/structure/config_test/manage/$id");
  268. // Create a configuration entity with '0' machine name.
  269. $edit = [
  270. 'id' => '0',
  271. 'label' => '0',
  272. ];
  273. $this->drupalPostForm('admin/structure/config_test/add', $edit, 'Save');
  274. $this->assertSession()->statusCodeEquals(200);
  275. $message_insert = new FormattableMarkup('%label configuration has been created.', ['%label' => $edit['label']]);
  276. $this->assertRaw($message_insert);
  277. $this->assertLinkByHref('admin/structure/config_test/manage/0');
  278. $this->assertLinkByHref('admin/structure/config_test/manage/0/delete');
  279. $this->drupalPostForm('admin/structure/config_test/manage/0/delete', [], 'Delete');
  280. $storage = \Drupal::entityTypeManager()->getStorage('config_test');
  281. $this->assertNull($storage->load(0), 'Test entity deleted');
  282. // Create a configuration entity with a property that uses AJAX to show
  283. // extra form elements. Test this scenario in a non-JS case by using a
  284. // 'js-hidden' submit button.
  285. // @see \Drupal\Tests\config\FunctionalJavascript\ConfigEntityTest::testAjaxOnAddPage()
  286. $this->drupalGet('admin/structure/config_test/add');
  287. $id = strtolower($this->randomMachineName());
  288. $edit = [
  289. 'id' => $id,
  290. 'label' => $this->randomString(),
  291. 'size' => 'custom',
  292. ];
  293. $this->assertFieldByName('size');
  294. $this->assertNoFieldByName('size_value');
  295. $this->drupalPostForm(NULL, $edit, 'Change size');
  296. $this->assertFieldByName('size');
  297. $this->assertFieldByName('size_value');
  298. // Submit the form with the regular 'Save' button and check that the entity
  299. // values are correct.
  300. $edit += ['size_value' => 'medium'];
  301. $this->drupalPostForm(NULL, $edit, 'Save');
  302. $entity = $storage->load($id);
  303. $this->assertEquals('custom', $entity->get('size'));
  304. $this->assertEquals('medium', $entity->get('size_value'));
  305. }
  306. }