1<?php 2 3namespace Drupal\Tests\system\Functional\System; 4 5use Drupal\Tests\BrowserTestBase; 6use Drupal\Tests\Traits\Core\CronRunTrait; 7 8/** 9 * Tests cron runs. 10 * 11 * @group system 12 */ 13class CronRunTest extends BrowserTestBase { 14 15 use CronRunTrait; 16 17 /** 18 * Modules to enable. 19 * 20 * @var array 21 */ 22 protected static $modules = [ 23 'common_test', 24 'common_test_cron_helper', 25 'automated_cron', 26 ]; 27 28 /** 29 * {@inheritdoc} 30 */ 31 protected $defaultTheme = 'stark'; 32 33 /** 34 * Tests cron runs. 35 */ 36 public function testCronRun() { 37 // Run cron anonymously without any cron key. 38 $this->drupalGet('cron'); 39 $this->assertSession()->statusCodeEquals(404); 40 41 // Run cron anonymously with a random cron key. 42 $key = $this->randomMachineName(16); 43 $this->drupalGet('cron/' . $key); 44 $this->assertSession()->statusCodeEquals(403); 45 46 // Run cron anonymously with the valid cron key. 47 $key = \Drupal::state()->get('system.cron_key'); 48 $this->drupalGet('cron/' . $key); 49 $this->assertSession()->statusCodeEquals(204); 50 } 51 52 /** 53 * Ensure that the automated cron run module is working. 54 * 55 * In these tests we do not use REQUEST_TIME to track start time, because we 56 * need the exact time when cron is triggered. 57 */ 58 public function testAutomatedCron() { 59 // Test with a logged in user; anonymous users likely don't cause Drupal to 60 // fully bootstrap, because of the internal page cache or an external 61 // reverse proxy. Reuse this user for disabling cron later in the test. 62 $admin_user = $this->drupalCreateUser(['administer site configuration']); 63 $this->drupalLogin($admin_user); 64 65 // Ensure cron does not run when a non-zero cron interval is specified and 66 // was not passed. 67 $cron_last = time(); 68 $cron_safe_interval = 100; 69 \Drupal::state()->set('system.cron_last', $cron_last); 70 $this->config('automated_cron.settings') 71 ->set('interval', $cron_safe_interval) 72 ->save(); 73 $this->drupalGet(''); 74 $this->assertSame($cron_last, \Drupal::state()->get('system.cron_last'), 'Cron does not run when the cron interval is not passed.'); 75 76 // Test if cron runs when the cron interval was passed. 77 $cron_last = time() - 200; 78 \Drupal::state()->set('system.cron_last', $cron_last); 79 $this->drupalGet(''); 80 sleep(1); 81 // Verify that cron runs when the cron interval has passed. 82 $this->assertLessThan(\Drupal::state()->get('system.cron_last'), $cron_last); 83 84 // Disable cron through the interface by setting the interval to zero. 85 $this->drupalGet('admin/config/system/cron'); 86 $this->submitForm(['interval' => 0], 'Save configuration'); 87 $this->assertSession()->pageTextContains('The configuration options have been saved.'); 88 $this->drupalLogout(); 89 90 // Test if cron does not run when the cron interval is set to zero. 91 $cron_last = time() - 200; 92 \Drupal::state()->set('system.cron_last', $cron_last); 93 $this->drupalGet(''); 94 $this->assertSame($cron_last, \Drupal::state()->get('system.cron_last'), 'Cron does not run when the cron threshold is disabled.'); 95 } 96 97 /** 98 * Make sure exceptions thrown on hook_cron() don't affect other modules. 99 */ 100 public function testCronExceptions() { 101 \Drupal::state()->delete('common_test.cron'); 102 // The common_test module throws an exception. If it isn't caught, the tests 103 // won't finish successfully. 104 // The common_test_cron_helper module sets the 'common_test_cron' variable. 105 $this->cronRun(); 106 $result = \Drupal::state()->get('common_test.cron'); 107 $this->assertEquals('success', $result, 'Cron correctly handles exceptions thrown during hook_cron() invocations.'); 108 } 109 110 /** 111 * Make sure the cron UI reads from the state storage. 112 */ 113 public function testCronUI() { 114 $admin_user = $this->drupalCreateUser(['administer site configuration']); 115 $this->drupalLogin($admin_user); 116 $this->drupalGet('admin/config/system/cron'); 117 // Don't use REQUEST to calculate the exact time, because that will 118 // fail randomly. Look for the word 'years', because without a timestamp, 119 // the time will start at 1 January 1970. 120 $this->assertSession()->pageTextNotContains('years'); 121 122 $cron_last = time() - 200; 123 \Drupal::state()->set('system.cron_last', $cron_last); 124 125 $this->submitForm([], 'Save configuration'); 126 $this->assertSession()->pageTextContains('The configuration options have been saved.'); 127 $this->assertSession()->addressEquals('admin/config/system/cron'); 128 129 // Check that cron does not run when saving the configuration form. 130 $this->assertEquals($cron_last, \Drupal::state()->get('system.cron_last'), 'Cron does not run when saving the configuration form.'); 131 132 // Check that cron runs when triggered manually. 133 $this->submitForm([], 'Run cron'); 134 // Verify that cron runs when triggered manually. 135 $this->assertLessThan(\Drupal::state()->get('system.cron_last'), $cron_last); 136 } 137 138 /** 139 * Ensure that the manual cron run is working. 140 */ 141 public function testManualCron() { 142 $admin_user = $this->drupalCreateUser(['administer site configuration']); 143 $this->drupalLogin($admin_user); 144 145 $this->drupalGet('admin/reports/status/run-cron'); 146 $this->assertSession()->statusCodeEquals(403); 147 148 $this->drupalGet('admin/reports/status'); 149 $this->clickLink('Run cron'); 150 $this->assertSession()->statusCodeEquals(200); 151 $this->assertSession()->pageTextContains('Cron ran successfully.'); 152 } 153 154} 155