3 namespace Drupal\Tests\update\Functional;
6 use Drupal\Tests\Traits\Core\CronRunTrait;
9 * Tests the Update Manager module through a series of functional tests using
14 class UpdateCoreTest extends UpdateTestBase {
23 public static $modules = ['update_test', 'update', 'language', 'block'];
25 protected function setUp() {
27 $admin_user = $this->drupalCreateUser(['administer site configuration', 'administer modules', 'administer themes']);
28 $this->drupalLogin($admin_user);
29 $this->drupalPlaceBlock('local_actions_block');
33 * Sets the version to x.x.x when no project-specific mapping is defined.
35 * @param string $version
38 protected function setSystemInfo($version) {
41 'version' => $version,
44 $this->config('update_test.settings')->set('system_info', $setting)->save();
48 * Tests the Update Manager module when no updates are available.
50 public function testNoUpdatesAvailable() {
51 foreach ([0, 1] as $minor_version) {
52 foreach ([0, 1] as $patch_version) {
53 foreach (['-alpha1', '-beta1', ''] as $extra_version) {
54 $this->setSystemInfo("8.$minor_version.$patch_version" . $extra_version);
55 $this->refreshUpdateStatus(['drupal' => "$minor_version.$patch_version" . $extra_version]);
56 $this->standardTests();
57 $this->assertText(t('Up to date'));
58 $this->assertNoText(t('Update available'));
59 $this->assertNoText(t('Security update required!'));
60 $this->assertRaw('check.svg', 'Check icon was found.');
67 * Tests the Update Manager module when one normal update is available.
69 public function testNormalUpdateAvailable() {
70 $this->setSystemInfo('8.0.0');
72 // Ensure that the update check requires a token.
73 $this->drupalGet('admin/reports/updates/check');
74 $this->assertResponse(403, 'Accessing admin/reports/updates/check without a CSRF token results in access denied.');
76 foreach ([0, 1] as $minor_version) {
77 foreach (['-alpha1', '-beta1', ''] as $extra_version) {
78 $this->refreshUpdateStatus(['drupal' => "$minor_version.1" . $extra_version]);
79 $this->standardTests();
80 $this->drupalGet('admin/reports/updates');
81 $this->clickLink(t('Check manually'));
82 $this->checkForMetaRefresh();
83 $this->assertNoText(t('Security update required!'));
84 $this->assertRaw(\Drupal::l("8.$minor_version.1" . $extra_version, Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version-release")), 'Link to release appears.');
85 $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version.tar.gz")), 'Link to download appears.');
86 $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version-release")), 'Link to release notes appears.');
88 switch ($minor_version) {
90 // Both stable and unstable releases are available.
91 // A stable release is the latest.
92 if ($extra_version == '') {
93 $this->assertNoText(t('Up to date'));
94 $this->assertText(t('Update available'));
95 $this->assertText(t('Recommended version:'));
96 $this->assertNoText(t('Latest version:'));
97 $this->assertRaw('warning.svg', 'Warning icon was found.');
99 // Only unstable releases are available.
100 // An unstable release is the latest.
102 $this->assertText(t('Up to date'));
103 $this->assertNoText(t('Update available'));
104 $this->assertNoText(t('Recommended version:'));
105 $this->assertText(t('Latest version:'));
106 $this->assertRaw('check.svg', 'Check icon was found.');
110 // Both stable and unstable releases are available.
111 // A stable release is the latest.
112 if ($extra_version == '') {
113 $this->assertNoText(t('Up to date'));
114 $this->assertText(t('Update available'));
115 $this->assertText(t('Recommended version:'));
116 $this->assertNoText(t('Latest version:'));
117 $this->assertRaw('warning.svg', 'Warning icon was found.');
119 // Both stable and unstable releases are available.
120 // An unstable release is the latest.
122 $this->assertNoText(t('Up to date'));
123 $this->assertText(t('Update available'));
124 $this->assertText(t('Recommended version:'));
125 $this->assertText(t('Latest version:'));
126 $this->assertRaw('warning.svg', 'Warning icon was found.');
135 * Tests the Update Manager module when a major update is available.
137 public function testMajorUpdateAvailable() {
138 foreach ([0, 1] as $minor_version) {
139 foreach ([0, 1] as $patch_version) {
140 foreach (['-alpha1', '-beta1', ''] as $extra_version) {
141 $this->setSystemInfo("8.$minor_version.$patch_version" . $extra_version);
142 $this->refreshUpdateStatus(['drupal' => '9']);
143 $this->standardTests();
144 $this->drupalGet('admin/reports/updates');
145 $this->clickLink(t('Check manually'));
146 $this->checkForMetaRefresh();
147 $this->assertNoText(t('Security update required!'));
148 $this->assertRaw(\Drupal::l('9.0.0', Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to release appears.');
149 $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-9-0-0.tar.gz")), 'Link to download appears.');
150 $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to release notes appears.');
151 $this->assertNoText(t('Up to date'));
152 $this->assertText(t('Not supported!'));
153 $this->assertText(t('Recommended version:'));
154 $this->assertNoText(t('Latest version:'));
155 $this->assertRaw('error.svg', 'Error icon was found.');
162 * Tests the Update Manager module when a security update is available.
164 public function testSecurityUpdateAvailable() {
165 foreach ([0, 1] as $minor_version) {
166 $this->setSystemInfo("8.$minor_version.0");
167 $this->refreshUpdateStatus(['drupal' => "$minor_version.2-sec"]);
168 $this->standardTests();
169 $this->assertNoText(t('Up to date'));
170 $this->assertNoText(t('Update available'));
171 $this->assertText(t('Security update required!'));
172 $this->assertRaw(\Drupal::l("8.$minor_version.2", Url::fromUri("http://example.com/drupal-8-$minor_version-2-release")), 'Link to release appears.');
173 $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-2.tar.gz")), 'Link to download appears.');
174 $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-8-$minor_version-2-release")), 'Link to release notes appears.');
175 $this->assertRaw('error.svg', 'Error icon was found.');
180 * Ensures proper results where there are date mismatches among modules.
182 public function testDatestampMismatch() {
185 // We need to think we're running a -dev snapshot to see dates.
186 'version' => '8.1.0-dev',
187 'datestamp' => time(),
190 // This is 2001-09-09 01:46:40 GMT, so test for "2001-Sep-".
191 'datestamp' => '1000000000',
194 $this->config('update_test.settings')->set('system_info', $system_info)->save();
195 $this->refreshUpdateStatus(['drupal' => 'dev']);
196 $this->assertNoText(t('2001-Sep-'));
197 $this->assertText(t('Up to date'));
198 $this->assertNoText(t('Update available'));
199 $this->assertNoText(t('Security update required!'));
203 * Checks that running cron updates the list of available updates.
205 public function testModulePageRunCron() {
206 $this->setSystemInfo('8.0.0');
207 $this->config('update.settings')
208 ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
210 $this->config('update_test.settings')
211 ->set('xml_map', ['drupal' => '0.0'])
215 $this->drupalGet('admin/modules');
216 $this->assertNoText(t('No update information available.'));
220 * Checks the messages at admin/modules when the site is up to date.
222 public function testModulePageUpToDate() {
223 $this->setSystemInfo('8.0.0');
224 // Instead of using refreshUpdateStatus(), set these manually.
225 $this->config('update.settings')
226 ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
228 $this->config('update_test.settings')
229 ->set('xml_map', ['drupal' => '0.0'])
232 $this->drupalGet('admin/reports/updates');
233 $this->clickLink(t('Check manually'));
234 $this->checkForMetaRefresh();
235 $this->assertText(t('Checked available update data for one project.'));
236 $this->drupalGet('admin/modules');
237 $this->assertNoText(t('There are updates available for your version of Drupal.'));
238 $this->assertNoText(t('There is a security update available for your version of Drupal.'));
242 * Checks the messages at admin/modules when an update is missing.
244 public function testModulePageRegularUpdate() {
245 $this->setSystemInfo('8.0.0');
246 // Instead of using refreshUpdateStatus(), set these manually.
247 $this->config('update.settings')
248 ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
250 $this->config('update_test.settings')
251 ->set('xml_map', ['drupal' => '0.1'])
254 $this->drupalGet('admin/reports/updates');
255 $this->clickLink(t('Check manually'));
256 $this->checkForMetaRefresh();
257 $this->assertText(t('Checked available update data for one project.'));
258 $this->drupalGet('admin/modules');
259 $this->assertText(t('There are updates available for your version of Drupal.'));
260 $this->assertNoText(t('There is a security update available for your version of Drupal.'));
264 * Checks the messages at admin/modules when a security update is missing.
266 public function testModulePageSecurityUpdate() {
267 $this->setSystemInfo('8.0.0');
268 // Instead of using refreshUpdateStatus(), set these manually.
269 $this->config('update.settings')
270 ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
272 $this->config('update_test.settings')
273 ->set('xml_map', ['drupal' => '0.2-sec'])
276 $this->drupalGet('admin/reports/updates');
277 $this->clickLink(t('Check manually'));
278 $this->checkForMetaRefresh();
279 $this->assertText(t('Checked available update data for one project.'));
280 $this->drupalGet('admin/modules');
281 $this->assertNoText(t('There are updates available for your version of Drupal.'));
282 $this->assertText(t('There is a security update available for your version of Drupal.'));
284 // Make sure admin/appearance warns you you're missing a security update.
285 $this->drupalGet('admin/appearance');
286 $this->assertNoText(t('There are updates available for your version of Drupal.'));
287 $this->assertText(t('There is a security update available for your version of Drupal.'));
289 // Make sure duplicate messages don't appear on Update status pages.
290 $this->drupalGet('admin/reports/status');
291 // We're expecting "There is a security update..." inside the status report
292 // itself, but the drupal_set_message() appears as an li so we can prefix
293 // with that and search for the raw HTML.
294 $this->assertNoRaw('<li>' . t('There is a security update available for your version of Drupal.'));
296 $this->drupalGet('admin/reports/updates');
297 $this->assertNoText(t('There is a security update available for your version of Drupal.'));
299 $this->drupalGet('admin/reports/updates/settings');
300 $this->assertNoText(t('There is a security update available for your version of Drupal.'));
304 * Tests the Update Manager module when the update server returns 503 errors.
306 public function testServiceUnavailable() {
307 $this->refreshUpdateStatus([], '503-error');
308 // Ensure that no "Warning: SimpleXMLElement..." parse errors are found.
309 $this->assertNoText('SimpleXMLElement');
310 $this->assertUniqueText(t('Failed to get available update data for one project.'));
314 * Tests that exactly one fetch task per project is created and not more.
316 public function testFetchTasks() {
318 'name' => 'aaa_update_test',
321 'name' => 'bbb_update_test',
323 $queue = \Drupal::queue('update_fetch_tasks');
324 $this->assertEqual($queue->numberOfItems(), 0, 'Queue is empty');
325 update_create_fetch_task($projecta);
326 $this->assertEqual($queue->numberOfItems(), 1, 'Queue contains one item');
327 update_create_fetch_task($projectb);
328 $this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items');
329 // Try to add project a again.
330 update_create_fetch_task($projecta);
331 $this->assertEqual($queue->numberOfItems(), 2, 'Queue still contains two items');
333 // Clear storage and try again.
334 update_storage_clear();
335 update_create_fetch_task($projecta);
336 $this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items');
340 * Checks language module in core package at admin/reports/updates.
342 public function testLanguageModuleUpdate() {
343 $this->setSystemInfo('8.0.0');
344 // Instead of using refreshUpdateStatus(), set these manually.
345 $this->config('update.settings')
346 ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
348 $this->config('update_test.settings')
349 ->set('xml_map', ['drupal' => '0.1'])
352 $this->drupalGet('admin/reports/updates');
353 $this->assertText(t('Language'));
357 * Ensures that the local actions appear.
359 public function testLocalActions() {
360 $admin_user = $this->drupalCreateUser(['administer site configuration', 'administer modules', 'administer software updates', 'administer themes']);
361 $this->drupalLogin($admin_user);
363 $this->drupalGet('admin/modules');
364 $this->clickLink(t('Install new module'));
365 $this->assertUrl('admin/modules/install');
367 $this->drupalGet('admin/appearance');
368 $this->clickLink(t('Install new theme'));
369 $this->assertUrl('admin/theme/install');
371 $this->drupalGet('admin/reports/updates');
372 $this->clickLink(t('Install new module or theme'));
373 $this->assertUrl('admin/reports/updates/install');