FeaturesCreateUITest.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. namespace Drupal\features_ui\Tests;
  3. use Drupal\Component\Serialization\Yaml;
  4. use Drupal\Core\Archiver\ArchiveTar;
  5. use Drupal\simpletest\WebTestBase;
  6. use Drupal\Core\StringTranslation\StringTranslationTrait;
  7. /**
  8. * Tests the creation of a feature.
  9. *
  10. * @group features_ui
  11. */
  12. class FeaturesCreateUITest extends WebTestBase {
  13. use StringTranslationTrait;
  14. /**
  15. * @todo Remove the disabled strict config schema checking.
  16. */
  17. protected $strictConfigSchema = FALSE;
  18. /**
  19. * {@inheritdoc}
  20. */
  21. public static $modules = ['block', 'features', 'features_ui'];
  22. /**
  23. * Tests creating a feature via UI and download it.
  24. */
  25. public function testCreateFeaturesUI() {
  26. $feature_name = 'test_feature2';
  27. $admin_user = $this->createUser(['administer site configuration', 'export configuration', 'administer modules']);
  28. $this->drupalLogin($admin_user);
  29. $this->drupalPlaceBlock('local_actions_block');
  30. $this->drupalGet('admin/config/development/features');
  31. $this->clickLink('Create new feature');
  32. $this->assertResponse(200);
  33. $edit = [
  34. 'name' => 'Test feature',
  35. 'machine_name' => $feature_name,
  36. 'description' => 'Test description: <strong>giraffe</strong>',
  37. 'version' => '8.x-1.0',
  38. 'system_simple[sources][selected][system.theme]' => TRUE,
  39. 'system_simple[sources][selected][user.settings]' => TRUE,
  40. ];
  41. $this->drupalPostForm(NULL, $edit, $this->t('Download Archive'));
  42. $this->assertResponse(200);
  43. $archive = $this->getRawContent();
  44. $filename = tempnam($this->tempFilesDirectory, 'feature');
  45. file_put_contents($filename, $archive);
  46. $archive = new ArchiveTar($filename);
  47. $files = $archive->listContent();
  48. $this->assertEqual(4, count($files));
  49. $this->assertEqual($feature_name . '/' . $feature_name . '.info.yml', $files[0]['filename']);
  50. $this->assertEqual($feature_name . '/' . $feature_name . '.features.yml', $files[1]['filename']);
  51. $this->assertEqual($feature_name . '/config/install/system.theme.yml', $files[2]['filename']);
  52. $this->assertEqual($feature_name . '/config/install/user.settings.yml', $files[3]['filename']);
  53. // Ensure that the archive contains the expected values.
  54. $info_filename = tempnam($this->tempFilesDirectory, 'feature');
  55. file_put_contents($info_filename, $archive->extractInString($feature_name . '/' . $feature_name . '.info.yml'));
  56. $features_info_filename = tempnam($this->tempFilesDirectory, 'feature');
  57. file_put_contents($features_info_filename, $archive->extractInString($feature_name . '/' . $feature_name . '.features.yml'));
  58. /** @var \Drupal\Core\Extension\InfoParser $info_parser */
  59. $info_parser = \Drupal::service('info_parser');
  60. $parsed_info = $info_parser->parse($info_filename);
  61. $this->assertEqual('Test feature', $parsed_info['name']);
  62. $parsed_features_info = Yaml::decode(file_get_contents($features_info_filename));
  63. $this->assertEqual([
  64. 'required' => ['system.theme', 'user.settings'],
  65. ], $parsed_features_info);
  66. $archive->extract(\Drupal::service('kernel')->getSitePath() . '/modules');
  67. $module_path = \Drupal::service('kernel')->getSitePath() . '/modules/' . $feature_name;
  68. // Ensure that the features listing renders the right content.
  69. $this->drupalGet('admin/config/development/features');
  70. $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
  71. $this->assertLink('Test feature');
  72. $this->assertEqual($feature_name, (string) $tr->children()[2]);
  73. $description_column = (string) $tr->children()[3]->asXml();
  74. $this->assertTrue(strpos($description_column, 'system.theme') !== FALSE);
  75. $this->assertTrue(strpos($description_column, 'user.settings') !== FALSE);
  76. $this->assertRaw('Test description: <strong>giraffe</strong>');
  77. $this->assertEqual('Uninstalled', (string) $tr->children()[5]);
  78. $this->assertEqual('', (string) $tr->children()[6]);
  79. // Remove one and add new configuration.
  80. $this->clickLink('Test feature');
  81. $edit = [
  82. 'system_simple[included][system.theme]' => FALSE,
  83. 'user_role[sources][selected][authenticated]' => TRUE,
  84. ];
  85. $this->drupalPostForm(NULL, $edit, $this->t('Write'));
  86. $info_filename = $module_path . '/' . $feature_name . '.info.yml';
  87. $parsed_info = $info_parser->parse($info_filename);
  88. $this->assertEqual('Test feature', $parsed_info['name']);
  89. $features_info_filename = $module_path . '/' . $feature_name . '.features.yml';
  90. $parsed_features_info = Yaml::decode(file_get_contents($features_info_filename));
  91. $this->assertEqual([
  92. 'excluded' => ['system.theme'],
  93. 'required' => true,
  94. ], $parsed_features_info);
  95. $this->drupalGet('admin/modules');
  96. $edit = [
  97. 'modules[Other][' . $feature_name . '][enable]' => TRUE,
  98. ];
  99. $this->drupalPostForm(NULL, $edit, $this->t('Install'));
  100. // Check that the feature is listed as installed.
  101. $this->drupalGet('admin/config/development/features');
  102. $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
  103. $this->assertEqual('Installed', (string) $tr->children()[5]);
  104. // Check that a config change results in a feature marked as changed.
  105. \Drupal::configFactory()->getEditable('user.settings')
  106. ->set('anonymous', 'Anonymous giraffe')
  107. ->save();
  108. $this->drupalGet('admin/config/development/features');
  109. $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
  110. $this->assertTrue(strpos($tr->children()[6]->asXml(), 'Changed') !== FALSE);
  111. // Uninstall module.
  112. $this->drupalPostForm('admin/modules/uninstall', [
  113. 'uninstall[' . $feature_name . ']' => TRUE,
  114. ], $this->t('Uninstall'));
  115. $this->drupalPostForm(NULL, [], $this->t('Uninstall'));
  116. $this->drupalGet('admin/config/development/features');
  117. $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
  118. $this->assertTrue(strpos($tr->children()[6]->asXml(), 'Changed') !== FALSE);
  119. $this->clickLink($this->t('Changed'));
  120. $this->assertRaw('<td class="diff-context diff-deletedline">anonymous : Anonymous <span class="diffchange">giraffe</span></td>');
  121. $this->assertRaw('<td class="diff-context diff-addedline">anonymous : Anonymous</td>');
  122. $this->drupalGet('admin/modules');
  123. $edit = [
  124. 'modules[Other][' . $feature_name . '][enable]' => TRUE,
  125. ];
  126. $this->drupalPostForm(NULL, $edit, $this->t('Install'));
  127. $this->drupalGet('admin/config/development/features');
  128. $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
  129. $this->assertEqual('Installed', (string) $tr->children()[5]);
  130. // Ensure that the changed config got overridden.
  131. $this->assertEqual('Anonymous', \Drupal::config('user.settings')->get('anonymous'));
  132. // Change the value, export and ensure that its not shown as changed.
  133. \Drupal::configFactory()->getEditable('user.settings')
  134. ->set('anonymous', 'Anonymous giraffe')
  135. ->save();
  136. // Ensure that exporting this change will result in an unchanged feature.
  137. $this->drupalGet('admin/config/development/features');
  138. $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
  139. $this->assertTrue(strpos($tr->children()[6]->asXml(), 'Changed') !== FALSE);
  140. $this->clickLink('Test feature');
  141. $this->drupalPostForm(NULL, [], $this->t('Write'));
  142. $this->drupalGet('admin/config/development/features');
  143. $tr = $this->xpath('//table[contains(@class, "features-listing")]/tbody/tr[td[3] = "' . $feature_name . '"]')[0];
  144. $this->assertEqual('Installed', (string) $tr->children()[5]);
  145. }
  146. }