3 namespace Drupal\update\Tests;
8 * Tests the Update Manager module through a series of functional tests using
13 class UpdateCoreTest extends UpdateTestBase {
20 public static $modules = ['update_test', 'update', 'language', 'block'];
22 protected function setUp() {
24 $admin_user = $this->drupalCreateUser(['administer site configuration', 'administer modules', 'administer themes']);
25 $this->drupalLogin($admin_user);
26 $this->drupalPlaceBlock('local_actions_block');
30 * Sets the version to x.x.x when no project-specific mapping is defined.
32 * @param string $version
35 protected function setSystemInfo($version) {
38 'version' => $version,
41 $this->config('update_test.settings')->set('system_info', $setting)->save();
45 * Tests the Update Manager module when no updates are available.
47 public function testNoUpdatesAvailable() {
48 foreach ([0, 1] as $minor_version) {
49 foreach ([0, 1] as $patch_version) {
50 foreach (['-alpha1', '-beta1', ''] as $extra_version) {
51 $this->setSystemInfo("8.$minor_version.$patch_version" . $extra_version);
52 $this->refreshUpdateStatus(['drupal' => "$minor_version.$patch_version" . $extra_version]);
53 $this->standardTests();
54 $this->assertText(t('Up to date'));
55 $this->assertNoText(t('Update available'));
56 $this->assertNoText(t('Security update required!'));
57 $this->assertRaw('check.svg', 'Check icon was found.');
64 * Tests the Update Manager module when one normal update is available.
66 public function testNormalUpdateAvailable() {
67 $this->setSystemInfo('8.0.0');
69 // Ensure that the update check requires a token.
70 $this->drupalGet('admin/reports/updates/check');
71 $this->assertResponse(403, 'Accessing admin/reports/updates/check without a CSRF token results in access denied.');
73 foreach ([0, 1] as $minor_version) {
74 foreach (['-alpha1', '-beta1', ''] as $extra_version) {
75 $this->refreshUpdateStatus(['drupal' => "$minor_version.1" . $extra_version]);
76 $this->standardTests();
77 $this->drupalGet('admin/reports/updates');
78 $this->clickLink(t('Check manually'));
79 $this->assertNoText(t('Security update required!'));
80 $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.');
81 $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version.tar.gz")), 'Link to download appears.');
82 $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.');
84 switch ($minor_version) {
86 // Both stable and unstable releases are available.
87 // A stable release is the latest.
88 if ($extra_version == '') {
89 $this->assertNoText(t('Up to date'));
90 $this->assertText(t('Update available'));
91 $this->assertText(t('Recommended version:'));
92 $this->assertNoText(t('Latest version:'));
93 $this->assertRaw('warning.svg', 'Warning icon was found.');
95 // Only unstable releases are available.
96 // An unstable release is the latest.
98 $this->assertText(t('Up to date'));
99 $this->assertNoText(t('Update available'));
100 $this->assertNoText(t('Recommended version:'));
101 $this->assertText(t('Latest version:'));
102 $this->assertRaw('check.svg', 'Check icon was found.');
106 // Both stable and unstable releases are available.
107 // A stable release is the latest.
108 if ($extra_version == '') {
109 $this->assertNoText(t('Up to date'));
110 $this->assertText(t('Update available'));
111 $this->assertText(t('Recommended version:'));
112 $this->assertNoText(t('Latest version:'));
113 $this->assertRaw('warning.svg', 'Warning icon was found.');
115 // Both stable and unstable releases are available.
116 // An unstable release is the latest.
118 $this->assertNoText(t('Up to date'));
119 $this->assertText(t('Update available'));
120 $this->assertText(t('Recommended version:'));
121 $this->assertText(t('Latest version:'));
122 $this->assertRaw('warning.svg', 'Warning icon was found.');
131 * Tests the Update Manager module when a major update is available.
133 public function testMajorUpdateAvailable() {
134 foreach ([0, 1] as $minor_version) {
135 foreach ([0, 1] as $patch_version) {
136 foreach (['-alpha1', '-beta1', ''] as $extra_version) {
137 $this->setSystemInfo("8.$minor_version.$patch_version" . $extra_version);
138 $this->refreshUpdateStatus(['drupal' => '9']);
139 $this->standardTests();
140 $this->drupalGet('admin/reports/updates');
141 $this->clickLink(t('Check manually'));
142 $this->assertNoText(t('Security update required!'));
143 $this->assertRaw(\Drupal::l('9.0.0', Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to release appears.');
144 $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-9-0-0.tar.gz")), 'Link to download appears.');
145 $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to release notes appears.');
146 $this->assertNoText(t('Up to date'));
147 $this->assertText(t('Not supported!'));
148 $this->assertText(t('Recommended version:'));
149 $this->assertNoText(t('Latest version:'));
150 $this->assertRaw('error.svg', 'Error icon was found.');
157 * Tests the Update Manager module when a security update is available.
159 public function testSecurityUpdateAvailable() {
160 foreach ([0, 1] as $minor_version) {
161 $this->setSystemInfo("8.$minor_version.0");
162 $this->refreshUpdateStatus(['drupal' => "$minor_version.2-sec"]);
163 $this->standardTests();
164 $this->assertNoText(t('Up to date'));
165 $this->assertNoText(t('Update available'));
166 $this->assertText(t('Security update required!'));
167 $this->assertRaw(\Drupal::l("8.$minor_version.2", Url::fromUri("http://example.com/drupal-8-$minor_version-2-release")), 'Link to release appears.');
168 $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-2.tar.gz")), 'Link to download appears.');
169 $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-8-$minor_version-2-release")), 'Link to release notes appears.');
170 $this->assertRaw('error.svg', 'Error icon was found.');
175 * Ensures proper results where there are date mismatches among modules.
177 public function testDatestampMismatch() {
180 // We need to think we're running a -dev snapshot to see dates.
181 'version' => '8.1.0-dev',
182 'datestamp' => time(),
185 // This is 2001-09-09 01:46:40 GMT, so test for "2001-Sep-".
186 'datestamp' => '1000000000',
189 $this->config('update_test.settings')->set('system_info', $system_info)->save();
190 $this->refreshUpdateStatus(['drupal' => 'dev']);
191 $this->assertNoText(t('2001-Sep-'));
192 $this->assertText(t('Up to date'));
193 $this->assertNoText(t('Update available'));
194 $this->assertNoText(t('Security update required!'));
198 * Checks that running cron updates the list of available updates.
200 public function testModulePageRunCron() {
201 $this->setSystemInfo('8.0.0');
202 $this->config('update.settings')
203 ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
205 $this->config('update_test.settings')
206 ->set('xml_map', ['drupal' => '0.0'])
210 $this->drupalGet('admin/modules');
211 $this->assertNoText(t('No update information available.'));
215 * Checks the messages at admin/modules when the site is up to date.
217 public function testModulePageUpToDate() {
218 $this->setSystemInfo('8.0.0');
219 // Instead of using refreshUpdateStatus(), set these manually.
220 $this->config('update.settings')
221 ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
223 $this->config('update_test.settings')
224 ->set('xml_map', ['drupal' => '0.0'])
227 $this->drupalGet('admin/reports/updates');
228 $this->clickLink(t('Check manually'));
229 $this->assertText(t('Checked available update data for one project.'));
230 $this->drupalGet('admin/modules');
231 $this->assertNoText(t('There are updates available for your version of Drupal.'));
232 $this->assertNoText(t('There is a security update available for your version of Drupal.'));
236 * Checks the messages at admin/modules when an update is missing.
238 public function testModulePageRegularUpdate() {
239 $this->setSystemInfo('8.0.0');
240 // Instead of using refreshUpdateStatus(), set these manually.
241 $this->config('update.settings')
242 ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
244 $this->config('update_test.settings')
245 ->set('xml_map', ['drupal' => '0.1'])
248 $this->drupalGet('admin/reports/updates');
249 $this->clickLink(t('Check manually'));
250 $this->assertText(t('Checked available update data for one project.'));
251 $this->drupalGet('admin/modules');
252 $this->assertText(t('There are updates available for your version of Drupal.'));
253 $this->assertNoText(t('There is a security update available for your version of Drupal.'));
257 * Checks the messages at admin/modules when a security update is missing.
259 public function testModulePageSecurityUpdate() {
260 $this->setSystemInfo('8.0.0');
261 // Instead of using refreshUpdateStatus(), set these manually.
262 $this->config('update.settings')
263 ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
265 $this->config('update_test.settings')
266 ->set('xml_map', ['drupal' => '0.2-sec'])
269 $this->drupalGet('admin/reports/updates');
270 $this->clickLink(t('Check manually'));
271 $this->assertText(t('Checked available update data for one project.'));
272 $this->drupalGet('admin/modules');
273 $this->assertNoText(t('There are updates available for your version of Drupal.'));
274 $this->assertText(t('There is a security update available for your version of Drupal.'));
276 // Make sure admin/appearance warns you you're missing a security update.
277 $this->drupalGet('admin/appearance');
278 $this->assertNoText(t('There are updates available for your version of Drupal.'));
279 $this->assertText(t('There is a security update available for your version of Drupal.'));
281 // Make sure duplicate messages don't appear on Update status pages.
282 $this->drupalGet('admin/reports/status');
283 // We're expecting "There is a security update..." inside the status report
284 // itself, but the drupal_set_message() appears as an li so we can prefix
285 // with that and search for the raw HTML.
286 $this->assertNoRaw('<li>' . t('There is a security update available for your version of Drupal.'));
288 $this->drupalGet('admin/reports/updates');
289 $this->assertNoText(t('There is a security update available for your version of Drupal.'));
291 $this->drupalGet('admin/reports/updates/settings');
292 $this->assertNoText(t('There is a security update available for your version of Drupal.'));
296 * Tests the Update Manager module when the update server returns 503 errors.
298 public function testServiceUnavailable() {
299 $this->refreshUpdateStatus([], '503-error');
300 // Ensure that no "Warning: SimpleXMLElement..." parse errors are found.
301 $this->assertNoText('SimpleXMLElement');
302 $this->assertUniqueText(t('Failed to get available update data for one project.'));
306 * Tests that exactly one fetch task per project is created and not more.
308 public function testFetchTasks() {
310 'name' => 'aaa_update_test',
313 'name' => 'bbb_update_test',
315 $queue = \Drupal::queue('update_fetch_tasks');
316 $this->assertEqual($queue->numberOfItems(), 0, 'Queue is empty');
317 update_create_fetch_task($projecta);
318 $this->assertEqual($queue->numberOfItems(), 1, 'Queue contains one item');
319 update_create_fetch_task($projectb);
320 $this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items');
321 // Try to add project a again.
322 update_create_fetch_task($projecta);
323 $this->assertEqual($queue->numberOfItems(), 2, 'Queue still contains two items');
325 // Clear storage and try again.
326 update_storage_clear();
327 update_create_fetch_task($projecta);
328 $this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items');
332 * Checks language module in core package at admin/reports/updates.
334 public function testLanguageModuleUpdate() {
335 $this->setSystemInfo('8.0.0');
336 // Instead of using refreshUpdateStatus(), set these manually.
337 $this->config('update.settings')
338 ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
340 $this->config('update_test.settings')
341 ->set('xml_map', ['drupal' => '0.1'])
344 $this->drupalGet('admin/reports/updates');
345 $this->assertText(t('Language'));
349 * Ensures that the local actions appear.
351 public function testLocalActions() {
352 $admin_user = $this->drupalCreateUser(['administer site configuration', 'administer modules', 'administer software updates', 'administer themes']);
353 $this->drupalLogin($admin_user);
355 $this->drupalGet('admin/modules');
356 $this->clickLink(t('Install new module'));
357 $this->assertUrl('admin/modules/install');
359 $this->drupalGet('admin/appearance');
360 $this->clickLink(t('Install new theme'));
361 $this->assertUrl('admin/theme/install');
363 $this->drupalGet('admin/reports/updates');
364 $this->clickLink(t('Install new module or theme'));
365 $this->assertUrl('admin/reports/updates/install');