1693 lines
74 KiB
Plaintext
1693 lines
74 KiB
Plaintext
<?php
|
|
|
|
/**
|
|
* @file
|
|
* Scheduler module test case file.
|
|
*/
|
|
|
|
/**
|
|
* Provides common helper methods for Scheduler module tests.
|
|
*/
|
|
abstract class SchedulerTestBase extends DrupalWebTestCase {
|
|
/**
|
|
* The profile to install as a basis for testing.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $profile = 'testing';
|
|
|
|
/**
|
|
* A user with administration rights.
|
|
*
|
|
* @var object
|
|
*/
|
|
protected $adminUser;
|
|
|
|
/**
|
|
* Common settings and options.
|
|
*/
|
|
public function commonSettings() {
|
|
|
|
// Create a 'Basic Page' content type.
|
|
$this->drupalCreateContentType(array('type' => 'page', 'name' => t('Basic page')));
|
|
|
|
// Create an administrator user.
|
|
// 'access site reports' is required for admin/reports/dblog.
|
|
// 'administer site configuration' is required for admin/reports/status.
|
|
// 'access content overview' is required for admin/content.
|
|
// 'view scheduled content' is required for admin/content/scheduler.
|
|
$this->adminUser = $this->drupalCreateUser(array(
|
|
'access content overview',
|
|
'access site reports',
|
|
'administer nodes',
|
|
'administer scheduler',
|
|
'administer site configuration',
|
|
'create page content',
|
|
'delete own page content',
|
|
'edit own page content',
|
|
'schedule publishing of nodes',
|
|
'view scheduled content',
|
|
'view own unpublished content',
|
|
));
|
|
|
|
// Add scheduler functionality to the page node type.
|
|
variable_set('scheduler_publish_enable_page', 1);
|
|
variable_set('scheduler_unpublish_enable_page', 1);
|
|
variable_set('scheduler_field_type', 'textfield');
|
|
}
|
|
|
|
/**
|
|
* Helper function for testScheduler(). Schedules content and asserts status.
|
|
*
|
|
* @param array $edit
|
|
* Node data, as if it was sent from the edit form.
|
|
* @param bool $scheduler_cron_only
|
|
* TRUE to only run Scheduler cron, FALSE to run default full Drupal cron.
|
|
*/
|
|
public function helpTestScheduler(array $edit, $scheduler_cron_only = FALSE) {
|
|
// Add a page.
|
|
$langcode = LANGUAGE_NONE;
|
|
$title = $this->randomName();
|
|
$edit["title"] = $title;
|
|
$body = $this->randomName();
|
|
$edit["body[$langcode][0][value]"] = $body;
|
|
$this->drupalLogin($this->adminUser);
|
|
$this->drupalPost('node/add/page', $edit, t('Save'));
|
|
$node = $this->drupalGetNodeByTitle($title);
|
|
// Show the specific page for an anonymous visitor, then assert that the
|
|
// node is correctly published or unpublished.
|
|
$this->drupalLogout();
|
|
$this->drupalGet("node/{$node->nid}");
|
|
if (isset($edit['publish_on'])) {
|
|
$key = 'publish_on';
|
|
$this->assertResponse(403, t('Node is unpublished'));
|
|
}
|
|
else {
|
|
$key = 'unpublish_on';
|
|
$this->assertText($body, t('Node is published'));
|
|
}
|
|
// Verify that the scheduler table is not empty.
|
|
$this->assertTrue(db_query_range('SELECT 1 FROM {scheduler}', 0, 1)->fetchField(), 'Scheduler table is not empty');
|
|
// Modify the scheduler row to a time far enough in the past because
|
|
// scheduler_cron uses REQUEST_TIME and our timestamp has to be before that.
|
|
db_update('scheduler')->fields(array($key => time() - 3600))->execute();
|
|
if ($scheduler_cron_only) {
|
|
scheduler_cron();
|
|
}
|
|
else {
|
|
$this->cronRun();
|
|
}
|
|
// Verify that the scheduler table is empty.
|
|
$this->assertFalse(db_query_range('SELECT 1 FROM {scheduler}', 0, 1)->fetchField(), 'Scheduler table is empty');
|
|
// Show the specific page for an anonymous visitor, then assert that the
|
|
// node is correctly published or unpublished.
|
|
$this->drupalGet("node/{$node->nid}");
|
|
if (isset($edit['publish_on'])) {
|
|
$this->assertText($body, t('Node is published'));
|
|
}
|
|
else {
|
|
$this->assertResponse(403, t('Node is unpublished'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Simulates the scheduled (un)publication of a node.
|
|
*
|
|
* @param object $node
|
|
* The node to schedule.
|
|
* @param string $action
|
|
* The action to perform: either 'publish' or 'unpublish'. Defaults to
|
|
* 'publish'.
|
|
*
|
|
* @return object
|
|
* The updated node, after scheduled (un)publication.
|
|
*/
|
|
public function schedule($node, $action = 'publish') {
|
|
// Simulate scheduling by setting the (un)publication date in the past and
|
|
// running cron.
|
|
$node->{$action . '_on'} = strtotime('-1 day', REQUEST_TIME);
|
|
node_save($node);
|
|
scheduler_cron();
|
|
return node_load($node->nid, NULL, TRUE);
|
|
}
|
|
|
|
/**
|
|
* Check if the latest revision log message of a node matches a given string.
|
|
*
|
|
* @param int $nid
|
|
* The node id of the node to check.
|
|
* @param string $value
|
|
* The value with which the log message will be compared.
|
|
* @param string $message
|
|
* The message to display along with the assertion.
|
|
* @param string $group
|
|
* The type of assertion - examples are "Browser", "PHP".
|
|
*
|
|
* @return bool
|
|
* TRUE if the assertion succeeded, FALSE otherwise.
|
|
*/
|
|
public function assertRevisionLogMessage($nid, $value, $message = '', $group = 'Other') {
|
|
$log_message = db_select('node_revision', 'r')
|
|
->fields('r', array('log'))
|
|
->condition('nid', $nid)
|
|
->orderBy('vid', 'DESC')
|
|
->range(0, 1)
|
|
->execute()
|
|
->fetchColumn();
|
|
return $this->assertEqual($log_message, $value, $message, $group);
|
|
}
|
|
|
|
/**
|
|
* Check if the number of revisions for a node matches a given value.
|
|
*
|
|
* @param int $nid
|
|
* The node id of the node to check.
|
|
* @param string $value
|
|
* The value with which the number of revisions will be compared.
|
|
* @param string $message
|
|
* The message to display along with the assertion.
|
|
* @param string $group
|
|
* The type of assertion - examples are "Browser", "PHP".
|
|
*
|
|
* @return bool
|
|
* TRUE if the assertion succeeded, FALSE otherwise.
|
|
*/
|
|
public function assertRevisionCount($nid, $value, $message = '', $group = 'Other') {
|
|
$count = db_select('node_revision', 'r')
|
|
->fields('r', array('vid'))
|
|
->condition('nid', $nid)
|
|
->countQuery()
|
|
->execute()
|
|
->fetchColumn();
|
|
return $this->assertEqual($count, $value, $message, $group);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Tests the scheduler interface.
|
|
*/
|
|
class SchedulerFunctionalTest extends SchedulerTestBase {
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public static function getInfo() {
|
|
return array(
|
|
'name' => 'Scheduler functionality',
|
|
'description' => 'Tests the Scheduler functions which do not require other modules.',
|
|
'group' => 'Scheduler',
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function setUp() {
|
|
parent::setUp('scheduler', 'dblog');
|
|
parent::commonSettings();
|
|
}
|
|
|
|
/**
|
|
* Tests basic scheduling of content.
|
|
*
|
|
* @param bool $scheduler_cron_only
|
|
* TRUE to only run Scheduler cron, FALSE to run default full Drupal cron.
|
|
*/
|
|
public function testBasicScheduling($scheduler_cron_only = FALSE) {
|
|
// Create node values. Set time to one hour in the future.
|
|
$edit = array(
|
|
'publish_on' => format_date(time() + 3600, 'custom', 'Y-m-d H:i:s'),
|
|
'status' => 1,
|
|
'promote' => 1,
|
|
);
|
|
// Test scheduled publishing.
|
|
$this->helpTestScheduler($edit, $scheduler_cron_only);
|
|
// Test scheduled unpublishing.
|
|
$edit['unpublish_on'] = $edit['publish_on'];
|
|
unset($edit['publish_on']);
|
|
$this->helpTestScheduler($edit, $scheduler_cron_only);
|
|
}
|
|
|
|
/**
|
|
* Tests scheduler when not all cron tasks are run during cron.
|
|
*
|
|
* Verify that we can set variable 'scheduler_cache_clear_all' so the page
|
|
* cache is still cleared.
|
|
*
|
|
* @uses testScheduler()
|
|
*/
|
|
public function testBasicSchedulingWithOnlySchedulerCron() {
|
|
// Cache pages for anonymous users.
|
|
variable_set('cache', 1);
|
|
// Instruct scheduler to clear caches itself, instead of relying on
|
|
// system_cron.
|
|
variable_set('scheduler_cache_clear_all', 1);
|
|
// Instruct the helper method to run only the scheduler cron.
|
|
$scheduler_cron_only = TRUE;
|
|
|
|
$this->testBasicScheduling($scheduler_cron_only);
|
|
}
|
|
|
|
/**
|
|
* Test the different options for past publication dates.
|
|
*/
|
|
public function testPastDates() {
|
|
// Log in.
|
|
$this->drupalLogin($this->adminUser);
|
|
|
|
// Create an unpublished page node.
|
|
$node = $this->drupalCreateNode(array('type' => 'page', 'status' => FALSE));
|
|
|
|
// Test the default behavior: an error message should be shown when the user
|
|
// enters a publication date that is in the past.
|
|
$edit = array(
|
|
'title' => $this->randomName(),
|
|
'publish_on' => format_date(strtotime('-1 day', REQUEST_TIME), 'custom', 'Y-m-d H:i:s'),
|
|
);
|
|
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
|
$this->assertText("The 'publish on' date must be in the future", 'An error message is shown when the publication date is in the past and the "error" behavior is chosen.');
|
|
|
|
// Test the 'publish' behavior: the node should be published immediately.
|
|
variable_set('scheduler_publish_past_date_page', 'publish');
|
|
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
|
$this->assertNoText("The 'publish on' date must be in the future", 'No error message is shown when the publication date is in the past and the "publish" behavior is chosen.');
|
|
$this->assertText(sprintf('%s %s has been updated.', 'Basic page', $edit['title']), 'The node is saved successfully when the publication date is in the past and the "publish" behavior is chosen.');
|
|
|
|
// Reload the changed node and check that it is published.
|
|
$node = node_load($node->nid, NULL, TRUE);
|
|
$this->assertTrue($node->status, 'The node has been published immediately when the publication date is in the past and the "publish" behavior is chosen.');
|
|
|
|
// Test the 'schedule' behavior: the node should be unpublished and become
|
|
// published on the next cron run.
|
|
variable_set('scheduler_publish_past_date_page', 'schedule');
|
|
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
|
$this->assertNoText("The 'publish on' date must be in the future", 'No error message is shown when the publication date is in the past and the "schedule" behavior is chosen.');
|
|
$this->assertText(sprintf('%s %s has been updated.', 'Basic page', check_plain($edit['title'])), 'The node is saved successfully when the publication date is in the past and the "schedule" behavior is chosen.');
|
|
$this->assertText(sprintf('This post is unpublished and will be published %s.', $edit['publish_on']), 'The node is scheduled to be published when the publication date is in the past and the "schedule" behavior is chosen.');
|
|
|
|
// Reload the node and check that it is unpublished but scheduled correctly.
|
|
$node = node_load($node->nid, NULL, TRUE);
|
|
$this->assertFalse($node->status, 'The node has been unpublished when the publication date is in the past and the "schedule" behavior is chosen.');
|
|
$this->assertEqual(format_date($node->publish_on, 'custom', 'Y-m-d H:i:s'), $edit['publish_on'], 'The node is scheduled for the required date');
|
|
|
|
// Simulate a cron run and check that the node is published.
|
|
scheduler_cron();
|
|
$node = node_load($node->nid, NULL, TRUE);
|
|
$this->assertTrue($node->status, 'The node with publication date in the past and the "schedule" behavior has now been published by cron.');
|
|
}
|
|
|
|
/**
|
|
* Tests the creation of new revisions on scheduling.
|
|
*/
|
|
public function testRevisioning() {
|
|
// Create a scheduled node that is not automatically revisioned.
|
|
$created = strtotime('-2 day', REQUEST_TIME);
|
|
$settings = array(
|
|
'revision' => 0,
|
|
'created' => $created,
|
|
);
|
|
$node = $this->drupalCreateNode($settings);
|
|
|
|
// First test scheduled publication with revisioning disabled.
|
|
$node = $this->schedule($node);
|
|
$this->assertRevisionCount($node->nid, 1, 'No new revision was created when a node was published with revisioning disabled.');
|
|
|
|
// Test scheduled unpublication.
|
|
$node = $this->schedule($node, 'unpublish');
|
|
$this->assertRevisionCount($node->nid, 1, 'No new revision was created when a node was unpublished with revisioning disabled.');
|
|
|
|
// Enable revisioning.
|
|
variable_set('scheduler_publish_revision_page', 1);
|
|
variable_set('scheduler_unpublish_revision_page', 1);
|
|
|
|
// Test scheduled publication with revisioning enabled.
|
|
$node = $this->schedule($node);
|
|
$this->assertRevisionCount($node->nid, 2, 'A new revision was created when revisioning is enabled.');
|
|
$expected_message = t('Node published by Scheduler on @now. Previous creation date was @date.', array(
|
|
'@now' => format_date(REQUEST_TIME, 'short'),
|
|
'@date' => format_date($created, 'short'),
|
|
));
|
|
$this->assertRevisionLogMessage($node->nid, $expected_message, 'The correct message was found in the node revision log after scheduled publishing.');
|
|
|
|
// Test scheduled unpublication with revisioning enabled.
|
|
$node = $this->schedule($node, 'unpublish');
|
|
$this->assertRevisionCount($node->nid, 3, 'A new revision was created when a node was unpublished with revisioning enabled.');
|
|
$expected_message = t('Node unpublished by Scheduler on @now. Previous change date was @date.', array(
|
|
'@now' => format_date(REQUEST_TIME, 'short'),
|
|
'@date' => format_date(REQUEST_TIME, 'short'),
|
|
));
|
|
$this->assertRevisionLogMessage($node->nid, $expected_message, 'The correct message was found in the node revision log after scheduled unpublishing.');
|
|
}
|
|
|
|
/**
|
|
* Tests if options can both be displayed as extra fields and vertical tabs.
|
|
*/
|
|
public function testExtraFields() {
|
|
$this->drupalLogin($this->adminUser);
|
|
|
|
// Test if the options are shown as vertical tabs by default.
|
|
$this->drupalGet('node/add/page');
|
|
$this->assertTrue($this->xpath('//div[contains(@class, "vertical-tabs-panes")]/fieldset[@id = "edit-scheduler-settings"]'), 'By default the scheduler options are shown as a vertical tab.');
|
|
|
|
// Test if the options are shown as extra fields when configured to do so.
|
|
variable_set('scheduler_use_vertical_tabs_page', 0);
|
|
$this->drupalGet('node/add/page');
|
|
$this->assertFalse($this->xpath('//div[contains(@class, "vertical-tabs-panes")]/fieldset[@id = "edit-scheduler-settings"]'), 'The scheduler options are not shown as a vertical tab when they are configured to show as an extra field.');
|
|
$this->assertTrue($this->xpath('//fieldset[@id = "edit-scheduler-settings" and contains(@class, "collapsed")]'), 'The scheduler options are shown as a collapsed fieldset when they are configured to show as an extra field.');
|
|
|
|
// Test the option to expand the fieldset.
|
|
variable_set('scheduler_expand_fieldset_page', 1);
|
|
$this->drupalGet('node/add/page');
|
|
$this->assertFalse($this->xpath('//div[contains(@class, "vertical-tabs-panes")]/fieldset[@id = "edit-scheduler-settings"]'), 'The scheduler options are not shown as a vertical tab when they are configured to show as an expanded fieldset.');
|
|
$this->assertTrue($this->xpath('//fieldset[@id = "edit-scheduler-settings" and not(contains(@class, "collapsed"))]'), 'The scheduler options are shown as an expanded fieldset.');
|
|
}
|
|
|
|
/**
|
|
* Tests creating and editing nodes with required scheduling enabled.
|
|
*/
|
|
public function testRequiredScheduling() {
|
|
$this->drupalLogin($this->adminUser);
|
|
|
|
// Define test scenarios with expected results.
|
|
$test_cases = array(
|
|
|
|
// A. Test scenarios that require scheduled publishing.
|
|
// The 1-10 numbering used below matches the test cases described in
|
|
// http://drupal.org/node/1198788#comment-7816119
|
|
//
|
|
// When creating a new unpublished node it is required to enter a
|
|
// publication date.
|
|
array(
|
|
'id' => 1,
|
|
'required' => 'publish',
|
|
'operation' => 'add',
|
|
'status' => 0,
|
|
'expected' => 'required',
|
|
'message' => 'When scheduled publishing is required and a new unpublished node is created, entering a date in the publish on field is required.',
|
|
),
|
|
|
|
// When creating a new published node it is required to enter a
|
|
// publication date. The node will be unpublished on form submit.
|
|
array(
|
|
'id' => 2,
|
|
'required' => 'publish',
|
|
'operation' => 'add',
|
|
'status' => 1,
|
|
'expected' => 'required',
|
|
'message' => 'When scheduled publishing is required and a new published node is created, entering a date in the publish on field is required.',
|
|
),
|
|
|
|
// When editing a published node it is not needed to enter a publication
|
|
// date since the node is already published.
|
|
array(
|
|
'id' => 3,
|
|
'required' => 'publish',
|
|
'operation' => 'edit',
|
|
'scheduled' => 0,
|
|
'status' => 1,
|
|
'expected' => 'not required',
|
|
'message' => 'When scheduled publishing is required and an existing published, unscheduled node is edited, entering a date in the publish on field is not required.',
|
|
),
|
|
|
|
// When editing an unpublished node that is scheduled for publication it
|
|
// is required to enter a publication date.
|
|
array(
|
|
'id' => 4,
|
|
'required' => 'publish',
|
|
'operation' => 'edit',
|
|
'scheduled' => 1,
|
|
'status' => 0,
|
|
'expected' => 'required',
|
|
'message' => 'When scheduled publishing is required and an existing unpublished, scheduled node is edited, entering a date in the publish on field is required.',
|
|
),
|
|
|
|
// When editing an unpublished node that is not scheduled for publication
|
|
// it is not required to enter a publication date since this means that
|
|
// the node has already gone through a publication > unpublication cycle.
|
|
array(
|
|
'id' => 5,
|
|
'required' => 'publish',
|
|
'operation' => 'edit',
|
|
'scheduled' => 0,
|
|
'status' => 0,
|
|
'expected' => 'not required',
|
|
'message' => 'When scheduled publishing is required and an existing unpublished, unscheduled node is edited, entering a date in the publish on field is not required.',
|
|
),
|
|
|
|
// B. Test scenarios that require scheduled unpublishing.
|
|
//
|
|
// When creating a new unpublished node it is required to enter an
|
|
// unpublication date since it is to be expected that the node will be
|
|
// published at some point and should subsequently be unpublished.
|
|
array(
|
|
'id' => 6,
|
|
'required' => 'unpublish',
|
|
'operation' => 'add',
|
|
'status' => 0,
|
|
'expected' => 'required',
|
|
'message' => 'When scheduled unpublishing is required and a new unpublished node is created, entering a date in the unpublish on field is required.',
|
|
),
|
|
|
|
// When creating a new published node it is required to enter an
|
|
// unpublication date.
|
|
array(
|
|
'id' => 7,
|
|
'required' => 'unpublish',
|
|
'operation' => 'add',
|
|
'status' => 1,
|
|
'expected' => 'required',
|
|
'message' => 'When scheduled unpublishing is required and a new published node is created, entering a date in the unpublish on field is required.',
|
|
),
|
|
|
|
// When editing a published node it is required to enter an unpublication
|
|
// date.
|
|
array(
|
|
'id' => 8,
|
|
'required' => 'unpublish',
|
|
'operation' => 'edit',
|
|
'scheduled' => 0,
|
|
'status' => 1,
|
|
'expected' => 'required',
|
|
'message' => 'When scheduled unpublishing is required and an existing published, unscheduled node is edited, entering a date in the unpublish on field is required.',
|
|
),
|
|
|
|
// When editing an unpublished node that is scheduled for publication it
|
|
// it is required to enter an unpublication date.
|
|
array(
|
|
'id' => 9,
|
|
'required' => 'unpublish',
|
|
'operation' => 'edit',
|
|
'scheduled' => 1,
|
|
'status' => 0,
|
|
'expected' => 'required',
|
|
'message' => 'When scheduled unpublishing is required and an existing unpublished, scheduled node is edited, entering a date in the unpublish on field is required.',
|
|
),
|
|
|
|
// When editing an unpublished node that is not scheduled for publication
|
|
// it is not required to enter an unpublication date since this means that
|
|
// the node has already gone through a publication - unpublication cycle.
|
|
array(
|
|
'id' => 10,
|
|
'required' => 'unpublish',
|
|
'operation' => 'edit',
|
|
'scheduled' => 0,
|
|
'status' => 0,
|
|
'expected' => 'not required',
|
|
'message' => 'When scheduled unpublishing is required and an existing unpublished, unscheduled node is edited, entering a date in the unpublish on field is not required.',
|
|
),
|
|
);
|
|
|
|
foreach ($test_cases as $test_case) {
|
|
// Enable required (un)publishing as stipulated by the test case.
|
|
variable_set('scheduler_publish_required_page', $test_case['required'] == 'publish');
|
|
variable_set('scheduler_unpublish_required_page', $test_case['required'] == 'unpublish');
|
|
|
|
// Set the default node status, used when creating a new node.
|
|
$node_options_page = !empty($test_case['status']) ? array('status') : array();
|
|
variable_set('node_options_page', $node_options_page);
|
|
|
|
// To assist viewing and analysing the generated test result pages create
|
|
// a text string showing all the test case parameters.
|
|
$title_data = array();
|
|
foreach ($test_case as $key => $value) {
|
|
if ($key != 'message') {
|
|
$title_data[] = $key . ' = ' . $value;
|
|
}
|
|
}
|
|
$title = implode(', ', $title_data);
|
|
|
|
// If the test case requires editing a node, we need to create one first.
|
|
if ($test_case['operation'] == 'edit') {
|
|
$options = array(
|
|
'title' => $title,
|
|
'type' => 'page',
|
|
'status' => $test_case['status'],
|
|
'publish_on' => !empty($test_case['scheduled']) ? strtotime('+ 1 day', REQUEST_TIME) : 0,
|
|
);
|
|
$node = $this->drupalCreateNode($options);
|
|
}
|
|
|
|
// Make sure the publication date fields are empty so we can check if they
|
|
// throw form validation errors when they are required.
|
|
$edit = array(
|
|
'title' => $title,
|
|
'publish_on' => '',
|
|
'unpublish_on' => '',
|
|
);
|
|
$path = $test_case['operation'] == 'add' ? 'node/add/page' : 'node/' . $node->nid . '/edit';
|
|
$this->drupalPost($path, $edit, t('Save'));
|
|
|
|
// Check for the expected result.
|
|
switch ($test_case['expected']) {
|
|
case 'required':
|
|
$this->assertText(sprintf('%s field is required.', ucfirst($test_case['required']) . ' on'), $test_case['id'] . '. ' . $test_case['message']);
|
|
break;
|
|
|
|
case 'not required':
|
|
$op = $test_case['operation'] == 'add' ? 'created' : 'updated';
|
|
$this->assertText(sprintf('%s %s has been %s.', 'Basic page', $title, $op), $test_case['id'] . '. ' . $test_case['message']);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test that Scheduler does not interfere with non-scheduler-enabled nodes.
|
|
*/
|
|
public function testNonEnabledType() {
|
|
// Create a 'Non-enabled' content type.
|
|
$this->drupalCreateContentType(array('type' => 'story', 'name' => t('Story Book')));
|
|
|
|
// Create a user who can add and edit story content, and log in.
|
|
$this->drupalLogin($this->drupalCreateUser(array(
|
|
'access content overview',
|
|
'access site reports',
|
|
'create story content',
|
|
'delete own story content',
|
|
'edit own story content',
|
|
'schedule publishing of nodes',
|
|
'view scheduled content',
|
|
'view own unpublished content',
|
|
)));
|
|
|
|
foreach ($this->dataNonEnabledType() as $data) {
|
|
list($id, $description, $publishing_enabled, $unpublishing_enabled) = $data;
|
|
|
|
// The first test case specifically checks the behavior of the default
|
|
// unchanged settings, so only change these settings for later runs.
|
|
if ($id > 0) {
|
|
variable_set('scheduler_publish_enable_story', $publishing_enabled);
|
|
variable_set('scheduler_unpublish_enable_story', $unpublishing_enabled);
|
|
}
|
|
|
|
// Create info string to show what combinations are being tested.
|
|
$info = 'Publishing ' . ($publishing_enabled ? 'enabled' : 'not enabled')
|
|
. ', Unpublishing ' . ($unpublishing_enabled ? 'enabled' : 'not enabled')
|
|
. ', ' . $description;
|
|
|
|
// Check that the field(s) are displayed only for the correct settings.
|
|
$title = $id . 'a - ' . $info;
|
|
$this->drupalGet('node/add/story');
|
|
if ($publishing_enabled) {
|
|
$this->assertFieldByName('publish_on', '', "The Publish-on field is shown: $title");
|
|
}
|
|
else {
|
|
$this->assertNoFieldByName('publish_on', '', "The Publish-on field is not shown: $title");
|
|
}
|
|
|
|
if ($unpublishing_enabled) {
|
|
$this->assertFieldByName('unpublish_on', '', "The Unpublish-on field is shown: $title");
|
|
}
|
|
else {
|
|
$this->assertNoFieldByName('unpublish_on', '', "The Unpublish-on field is not shown: $title");
|
|
}
|
|
|
|
// When publishing and/or unpublishing are not enabled but the 'required'
|
|
// setting remains on, the node must be able to be saved without a date.
|
|
variable_set('scheduler_publish_required_story', !$publishing_enabled);
|
|
variable_set('scheduler_unpublish_required_story', !$unpublishing_enabled);
|
|
|
|
$this->drupalPost('node/add/story', array('title' => $title), t('Save'));
|
|
// Check that the node has saved OK.
|
|
$string = sprintf('%s %s has been created.', 'Story Book', check_plain($title));
|
|
$this->assertText($string, "Node added: $title");
|
|
|
|
// Check that the node can be editted and saved again.
|
|
$node = $this->drupalGetNodeByTitle($title);
|
|
if ($node) {
|
|
$this->drupalPost('node/' . $node->nid . '/edit', array(), t('Save'));
|
|
$string = sprintf('%s %s has been updated.', 'Story Book', check_plain($title));
|
|
$this->assertText($string, "Node updated: $title");
|
|
}
|
|
else {
|
|
$this->fail("No node to edit: $title");
|
|
}
|
|
|
|
// Create an unpublished node with a publishing date, which mimics what
|
|
// could be done by a third-party module, or a by-product of the node type
|
|
// being enabled for publishing then being disabled before publishing.
|
|
$title = $id . 'b - ' . $info;
|
|
$edit = array(
|
|
'title' => $title,
|
|
'status' => FALSE,
|
|
'type' => 'story',
|
|
'publish_on' => strtotime('- 2 min', REQUEST_TIME),
|
|
);
|
|
$node = $this->drupalCreateNode($edit);
|
|
|
|
// Run cron and display the dblog.
|
|
$this->cronRun();
|
|
$this->drupalGet('admin/reports/dblog');
|
|
|
|
// Reload the node.
|
|
$node = node_load($node->nid, NULL, TRUE);
|
|
// Check if the node has been published or remains unpublished.
|
|
if ($publishing_enabled) {
|
|
$this->assertTrue($node->status, 'The unpublished node has been published: ' . $title);
|
|
}
|
|
else {
|
|
$this->assertFalse($node->status, 'The unpublished node remains unpublished: ' . $title);
|
|
}
|
|
|
|
// Do the same for unpublishing.
|
|
$title = $id . 'c - ' . $info;
|
|
$edit = array(
|
|
'title' => $title,
|
|
'status' => TRUE,
|
|
'type' => 'story',
|
|
'unpublish_on' => strtotime('- 2 min', REQUEST_TIME),
|
|
);
|
|
$node = $this->drupalCreateNode($edit);
|
|
|
|
// Run cron and display the dblog.
|
|
$this->cronRun();
|
|
$this->drupalGet('admin/reports/dblog');
|
|
|
|
// Reload the node.
|
|
$node = node_load($node->nid, NULL, TRUE);
|
|
// Check if the node has been unpublished or remains published.
|
|
if ($unpublishing_enabled) {
|
|
$this->assertFalse($node->status, 'The published node has been unpublished: ' . $title);
|
|
}
|
|
else {
|
|
$this->assertTrue($node->status, 'The published node remains published: ' . $title);
|
|
}
|
|
|
|
// Display the full content list and the scheduled list. Calls to these
|
|
// pages are for information and debug only. They could be removed.
|
|
$this->drupalGet('admin/content');
|
|
$this->drupalGet('admin/content/scheduler');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Provides data for testNonEnabledType().
|
|
*
|
|
* @return array
|
|
* Each item in the test data array has the follow elements:
|
|
* id - (in) a sequential id for use in node titles
|
|
* description - (string) describing the scenario being checked
|
|
* publishing_enabled - (bool) whether publishing is enabled
|
|
* unpublishing_enabled - (bool) whether unpublishing is enabled
|
|
*/
|
|
public function dataNonEnabledType() {
|
|
$data = [
|
|
// By default check that the scheduler date fields are not displayed.
|
|
0 => [0, 'Default', FALSE, FALSE],
|
|
|
|
// Explicitly disable this content type for both settings.
|
|
1 => [1, 'Disabling both settings', FALSE, FALSE],
|
|
|
|
// Turn on scheduled publishing only.
|
|
2 => [2, 'Enabling publishing only', TRUE, FALSE],
|
|
|
|
// Turn on scheduled unpublishing only.
|
|
3 => [3, 'Enabling unpublishing only', FALSE, TRUE],
|
|
|
|
// For completeness turn on bothbscheduled publishing and unpublishing.
|
|
4 => [4, 'Enabling both publishing and unpublishing', TRUE, TRUE],
|
|
];
|
|
|
|
// Use unset($data[n]) to remove a temporarily unwanted item, use
|
|
// return [$data[n]] to selectively test just one item, or have the
|
|
// default return $data to test everything.
|
|
return $data;
|
|
|
|
}
|
|
|
|
/**
|
|
* Tests the validation when editing a node.
|
|
*
|
|
* The 'required' checks and 'dates in the past' checks are handled in other
|
|
* tests. This test checks validation when the two fields interact.
|
|
*/
|
|
public function testValidationDuringEdit() {
|
|
$this->drupalLogin($this->adminUser);
|
|
|
|
// Set unpublishing to be required.
|
|
variable_set('scheduler_unpublish_required_page', TRUE);
|
|
|
|
// Create an unpublished page node, then edit the node and check that if a
|
|
// publish-on date is entered then an unpublish-on date is also needed.
|
|
$node = $this->drupalCreateNode(array('type' => 'page', 'status' => FALSE));
|
|
$edit = array(
|
|
'publish_on' => date('Y-m-d H:i:s', strtotime('+1 day', REQUEST_TIME)),
|
|
);
|
|
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
|
$this->assertText("If you set a 'publish-on' date then you must also set an 'unpublish-on' date.", 'Validation prevents entering a publish-on date with no unpublish-on date if unpublishing is required.');
|
|
|
|
// Create an unpublished page node, then edit the node and check that if the
|
|
// status is changed to published, then an unpublish-on date is also needed.
|
|
$node = $this->drupalCreateNode(array('type' => 'page', 'status' => FALSE));
|
|
$edit = array(
|
|
'status' => TRUE,
|
|
);
|
|
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
|
$this->assertText("To publish this node you must also set an 'unpublish-on' date.", 'Validation prevents publishing the node directly without an unpublish-on date if unpublishing is required.');
|
|
|
|
// Create an unpublished page node, edit the node and check that if both
|
|
// dates are entered then the unpublish date is later than the publish date.
|
|
$node = $this->drupalCreateNode(array('type' => 'page', 'status' => FALSE));
|
|
$edit = array(
|
|
'publish_on' => date('Y-m-d H:i:s', strtotime('+2 day', REQUEST_TIME)),
|
|
'unpublish_on' => date('Y-m-d H:i:s', strtotime('+1 day', REQUEST_TIME)),
|
|
);
|
|
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
|
$this->assertText("The 'unpublish on' date must be later than the 'publish on' date.", 'Validation prevents entering an unpublish-on date which is earlier than the publish-on date.');
|
|
|
|
}
|
|
|
|
/**
|
|
* Tests the deletion of a scheduled node.
|
|
*/
|
|
public function testScheduledNodeDelete() {
|
|
// Log in.
|
|
$this->drupalLogin($this->adminUser);
|
|
|
|
// 1. Test if it is possible to delete a node that does not have a
|
|
// publication date set, when scheduled publishing is required, and likewise
|
|
// for unpublishing.
|
|
// @see https://drupal.org/node/1614880
|
|
//
|
|
// Create a published and an unpublished node, both without scheduling.
|
|
$published_node = $this->drupalCreateNode(array('type' => 'page', 'status' => 1));
|
|
$unpublished_node = $this->drupalCreateNode(array('type' => 'page', 'status' => 0));
|
|
|
|
// Make scheduled publishing and unpublishing required.
|
|
variable_set('scheduler_publish_required_page', TRUE);
|
|
variable_set('scheduler_unpublish_required_page', TRUE);
|
|
|
|
// Check that deleting the nodes does not throw form validation errors.
|
|
// The text 'error message' is used in a header h2 html tag which is
|
|
// normally made hidden from browsers but will be in the page source.
|
|
// It is also good when testing for the absense of something to also test
|
|
// for the presence of text, hence the second assertion for each check.
|
|
$this->drupalPost('node/' . $published_node->nid . '/edit', array(), t('Delete'));
|
|
$this->assertNoText('Error message', 'No error messages are shown when trying to delete a published node with no scheduling information.');
|
|
$this->assertText('Are you sure you want to delete', 'The deletion warning message is shown immediately when trying to delete a published node with no scheduling information.');
|
|
|
|
$this->drupalPost('node/' . $unpublished_node->nid . '/edit', array(), t('Delete'));
|
|
$this->assertNoText('Error message', 'No error messages are shown when trying to delete an unpublished node with no scheduling information.');
|
|
$this->assertText('Are you sure you want to delete', 'The deletion warning message is shown immediately when trying to delete an unpublished node with no scheduling information.');
|
|
|
|
// 2. Test that nodes can be deleted with no validation errors if the dates
|
|
// are in the past.
|
|
// @see http://drupal.org/node/2627370
|
|
//
|
|
// Create nodes with publish_on and unpublish_on dates in the past.
|
|
$values = array(
|
|
'type' => 'page',
|
|
'status' => TRUE,
|
|
'unpublish_on' => strtotime('- 2 day', REQUEST_TIME),
|
|
);
|
|
$published_node_past = $this->drupalCreateNode($values);
|
|
|
|
$values = array(
|
|
'type' => 'page',
|
|
'status' => FALSE,
|
|
'publish_on' => strtotime('- 2 day', REQUEST_TIME),
|
|
);
|
|
$unpublished_node_past = $this->drupalCreateNode($values);
|
|
|
|
// Attempt to delete the published node and check for no validation error.
|
|
$this->drupalPost('node/' . $published_node_past->nid . '/edit', array(), t('Delete'));
|
|
$this->assertNoText('Error message', 'No error messages are shown when trying to delete a node with an unpublish date in the past.');
|
|
$this->assertText('Are you sure you want to delete', 'The deletion warning message is shown immediately when trying to delete a node with an unpublish date in the past.');
|
|
|
|
// Attempt to delete the unpublished node and check for no validation error.
|
|
$this->drupalPost('node/' . $unpublished_node_past->nid . '/edit', array(), t('Delete'));
|
|
$this->assertNoText('Error message', 'No error messages are shown when trying to delete a node with a publish date in the past.');
|
|
$this->assertText('Are you sure you want to delete', 'The deletion warning message is shown immediately when trying to delete a node with a publish date in the past.');
|
|
|
|
}
|
|
|
|
/**
|
|
* Tests meta-information on scheduled nodes.
|
|
*
|
|
* When nodes are scheduled for unpublication, an X-Robots-Tag HTTP header is
|
|
* sent, alerting crawlers about when an item expires and should be removed
|
|
* from search results.
|
|
*/
|
|
public function testMetaInformation() {
|
|
// Log in.
|
|
$this->drupalLogin($this->adminUser);
|
|
|
|
// Create a published node without scheduling.
|
|
$published_node = $this->drupalCreateNode(array('type' => 'page', 'status' => 1));
|
|
$this->drupalGet('node/' . $published_node->nid);
|
|
|
|
// Since we did not set an unpublish date, there should be no X-Robots-Tag
|
|
// header on the response.
|
|
$this->assertFalse($this->drupalGetHeader('X-Robots-Tag'), 'X-Robots-Tag is not present when no unpublish date is set.');
|
|
|
|
// Set a scheduler unpublish date on the node.
|
|
$unpublish_date = strtotime('+1 day', REQUEST_TIME);
|
|
$edit = array(
|
|
'unpublish_on' => format_date($unpublish_date, 'custom', 'Y-m-d H:i:s'),
|
|
);
|
|
$this->drupalPost('node/' . $published_node->nid . '/edit', $edit, t('Save'));
|
|
|
|
// The node page should now have an X-Robots-Tag header with an
|
|
// unavailable_after-directive and RFC850 date- and time-value.
|
|
$this->drupalGet('node/' . $published_node->nid);
|
|
$robots_tag = $this->drupalGetHeader('X-Robots-Tag');
|
|
$this->assertEqual($robots_tag, 'unavailable_after: ' . date(DATE_RFC850, $unpublish_date), 'X-Robots-Tag is present with correct timestamp derived from unpublish_on date.');
|
|
}
|
|
|
|
/**
|
|
* Tests that users without permission do not see the scheduler date fields.
|
|
*/
|
|
public function testPermissions() {
|
|
// Create a user who can add the content type but who does not have the
|
|
// permission to use the scheduler functionality.
|
|
$this->webUser = $this->drupalCreateUser(array(
|
|
'access content',
|
|
'create page content',
|
|
'edit own page content',
|
|
'view own unpublished content',
|
|
'administer nodes',
|
|
));
|
|
$this->drupalLogin($this->webUser);
|
|
|
|
// Set the defaults for a new node. Nothing in array means all OFF for
|
|
// 'status', 'promote' and 'sticky'.
|
|
variable_set('node_options_page', array());
|
|
|
|
// Check that neither of the fields are displayed when creating a node.
|
|
$this->drupalGet('node/add/page');
|
|
$this->assertNoFieldByName('publish_on', '', 'The Publish-on field is not shown for users who do not have permission to schedule content');
|
|
$this->assertNoFieldByName('unpublish_on', '', 'The Unpublish-on field is not shown for users who do not have permission to schedule content');
|
|
|
|
// Initially run tests when publishing and unpublishing are not required.
|
|
variable_set('scheduler_publish_required_page', FALSE);
|
|
variable_set('scheduler_unpublish_required_page', FALSE);
|
|
|
|
// Check that a new node can be saved and published.
|
|
$title = $this->randomString(15);
|
|
$this->drupalPost('node/add/page', array('title' => $title, 'status' => TRUE), t('Save'));
|
|
// check_plain() is required because the title may have % & or ' in it.
|
|
// Could use randomName() to get round this instead but it is good to use
|
|
// the full variety of characters available in randomString.
|
|
$this->assertText(sprintf('%s %s has been created.', 'Basic page', check_plain($title)), 'A node can be created and published when the user does not have scheduler permissions, and scheduling is not required.');
|
|
$node = $this->drupalGetNodeByTitle($title);
|
|
$this->assertTrue($node->status, 'The new node is published.');
|
|
|
|
// Check that a new node can be saved as unpublished.
|
|
$title = $this->randomString(15);
|
|
$this->drupalPost('node/add/page', array('title' => $title, 'status' => FALSE), t('Save'));
|
|
$this->assertText(sprintf('%s %s has been created.', 'Basic page', check_plain($title)), 'A node can be created and saved as unpublished when the user does not have scheduler permissions, and scheduling is not required.');
|
|
$node = $this->drupalGetNodeByTitle($title);
|
|
$this->assertFalse($node->status, 'The new node is unpublished.');
|
|
|
|
// Set publishing and unpublishing to required, to make it a stronger test.
|
|
variable_set('scheduler_publish_required_page', TRUE);
|
|
variable_set('scheduler_unpublish_required_page', TRUE);
|
|
|
|
// @TODO Add tests when scheduled publishing and unpublishing are required.
|
|
// Cannot be done until we make a decision on what 'required' means.
|
|
// @see https://www.drupal.org/node/2707411
|
|
// "Conflict between 'required publishing' and not having permission"
|
|
}
|
|
|
|
/**
|
|
* Tests Scheduler token support.
|
|
*/
|
|
public function testTokenReplacement() {
|
|
// Log in.
|
|
$this->drupalLogin($this->adminUser);
|
|
|
|
// Define timestamps for consistent use when repeated throughout this test.
|
|
$publish_on_timestamp = REQUEST_TIME + 3600;
|
|
$unpublish_on_timestamp = REQUEST_TIME + 7200;
|
|
|
|
// Create an unpublished page with scheduled dates.
|
|
$settings = array(
|
|
'type' => 'page',
|
|
'status' => FALSE,
|
|
);
|
|
$node = $this->drupalCreateNode($settings);
|
|
|
|
// Create array of test case data.
|
|
$test_cases = array(
|
|
array(
|
|
'token_format' => '',
|
|
'date_format' => 'medium',
|
|
'custom' => '',
|
|
),
|
|
array(
|
|
'token_format' => ':long',
|
|
'date_format' => 'long',
|
|
'custom' => '',
|
|
),
|
|
array(
|
|
'token_format' => ':raw',
|
|
'date_format' => 'custom',
|
|
'custom' => 'U',
|
|
),
|
|
array(
|
|
'token_format' => ':custom:jS F g:ia e O',
|
|
'date_format' => 'custom',
|
|
'custom' => 'jS F g:ia e O',
|
|
),
|
|
);
|
|
|
|
foreach ($test_cases as $test_data) {
|
|
// Define a variable containing the template of tokens to be replaced.
|
|
// The template is not held in the node body, as that is confusing when
|
|
// viewing the test debug, becuase the tokens will not be replaced unless
|
|
// a text format for tokens is added. That is unnecessary for the tests.
|
|
$template = 'Publish on: [node:scheduler-publish' . $test_data['token_format'] . ']. Unpublish on: [node:scheduler-unpublish' . $test_data['token_format'] . '].';
|
|
|
|
// With each of the test cases, test using both numeric and string input.
|
|
foreach (array('numeric', 'string') as $test_data['input_type']) {
|
|
if ($test_data['input_type'] == 'numeric') {
|
|
// Set the node fields to numeric timestanps, as they will be in the
|
|
// final stored node, after hook_node_presave() has been executed.
|
|
$node->publish_on = $publish_on_timestamp;
|
|
$node->unpublish_on = $unpublish_on_timestamp;
|
|
}
|
|
else {
|
|
// Replicate the scheduler fields as if just input by a user during
|
|
// edit, before hook_node_presave() has been executed.
|
|
// @see https://www.drupal.org/node/2750467
|
|
$node->publish_on = format_date($publish_on_timestamp, 'custom', 'Y-m-d H:i:s');
|
|
$node->unpublish_on = format_date($unpublish_on_timestamp, 'custom', 'Y-m-d H:i:s');
|
|
}
|
|
|
|
// Get the output value after tokens have been replaced.
|
|
$token_output = token_replace($template, array('node' => $node));
|
|
|
|
// Create the expected text.
|
|
$publish_on_date = format_date($publish_on_timestamp, $test_data['date_format'], $test_data['custom']);
|
|
$unpublish_on_date = format_date($unpublish_on_timestamp, $test_data['date_format'], $test_data['custom']);
|
|
$expected_output = 'Publish on: ' . $publish_on_date . '. Unpublish on: ' . $unpublish_on_date . '.';
|
|
|
|
// Check that the actual text matches the expected value.
|
|
$tested_format = $test_data['token_format'] ? '"' . $test_data['token_format'] . '"' : 'default';
|
|
$this->assertEqual($token_output, $expected_output, 'Scheduler tokens replaced correctly for ' . $tested_format . ' format with ' . $test_data['input_type'] . ' input data.');
|
|
}
|
|
|
|
// Remove the scheduled dates and check that token replacment still works.
|
|
unset($node->publish_on);
|
|
unset($node->unpublish_on);
|
|
$token_output = token_replace($template, array('node' => $node));
|
|
$expected_output = 'Publish on: [node:scheduler-publish' . $test_data['token_format'] . ']. Unpublish on: [node:scheduler-unpublish' . $test_data['token_format'] . '].';
|
|
$this->assertEqual($token_output, $expected_output, 'Scheduler tokens replaced correctly for ' . $tested_format . ' format with no scheduled dates.');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tests the 'touch' option to update the created date during publishing.
|
|
*/
|
|
public function testAlterCreationDate() {
|
|
// Ensure nodes with past dates will be scheduled not published immediately.
|
|
variable_set('scheduler_publish_past_date_page', 'schedule');
|
|
|
|
// Create a node with a 'created' date two days in the past.
|
|
$created = strtotime('-2 day', REQUEST_TIME);
|
|
$settings = array(
|
|
'type' => 'page',
|
|
'created' => $created,
|
|
'status' => FALSE,
|
|
);
|
|
$node = $this->drupalCreateNode($settings);
|
|
// Check that the node is not published.
|
|
$this->assertFalse($node->status, 'Before cron, the node is not published.');
|
|
|
|
// Schedule the node for publishing and run cron.
|
|
$node = $this->schedule($node, 'publish');
|
|
// Get the created date from the node and check that it has not changed.
|
|
$this->assertTrue($node->status, 'After cron, the node has been published.');
|
|
$created_after_cron = $node->created;
|
|
$this->assertEqual($created, $created_after_cron, 'The node creation date is not changed by default.');
|
|
|
|
// Set option to change the created date to match the publish_on date.
|
|
variable_set('scheduler_publish_touch_page', TRUE);
|
|
|
|
// Schedule the node again and run cron.
|
|
$node = $this->schedule($node, 'publish');
|
|
// Check that the created date has changed to match the publish_on date.
|
|
$created_after_cron = $node->created;
|
|
$this->assertEqual(strtotime('-1 day', REQUEST_TIME), $created_after_cron, "With 'touch' option set, the node creation date is changed to match the publishing date.");
|
|
}
|
|
|
|
/**
|
|
* Test scheduler lightweight cron runs.
|
|
*/
|
|
public function testLightweightCronRun() {
|
|
// Run the lightweight cron anonymously without any cron key.
|
|
$this->drupalGet('scheduler/cron');
|
|
$this->assertResponse(200, 'With no cron key (default) scheduler/cron returns "200 OK"');
|
|
|
|
// Generate and set a cron key.
|
|
$cron_key = substr(md5(rand()), 0, 20);
|
|
variable_set('scheduler_lightweight_access_key', $cron_key);
|
|
|
|
// Run the lightweight cron without any cron key.
|
|
$this->drupalGet('scheduler/cron');
|
|
$this->assertResponse(403, 'After creating a cron key scheduler/cron returns "403 Not Authorized"');
|
|
|
|
// Run the lightweight cron anonymously with a random (wrong) cron key.
|
|
$this->drupalGet('scheduler/cron/' . substr(md5(rand()), 0, 20));
|
|
$this->assertResponse(403, 'scheduler/cron/{wrong key} returns "403 Not Authorized"');
|
|
|
|
// Run the lightweight cron anonymously with the valid cron key.
|
|
$this->drupalGet('scheduler/cron/' . $cron_key);
|
|
$this->assertResponse(200, 'scheduler/cron/{correct key} returns "200 OK"');
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Tests the components of the scheduler interface which use the date module.
|
|
*/
|
|
class SchedulerDateModuleTest extends SchedulerTestBase {
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public static function getInfo() {
|
|
return array(
|
|
'name' => 'Scheduler and Date module',
|
|
'description' => 'Tests the functionality which needs the Date module.',
|
|
'group' => 'Scheduler',
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function setUp() {
|
|
parent::setUp('date', 'date_popup', 'scheduler');
|
|
parent::commonSettings();
|
|
}
|
|
|
|
/**
|
|
* Test the default time functionality.
|
|
*/
|
|
public function testDefaultTime() {
|
|
$this->drupalLogin($this->adminUser);
|
|
|
|
// Perform the checks twice, first using plain text entry then with date
|
|
// popup calendars.
|
|
foreach (array('textfield', 'date_popup') as $field_type) {
|
|
|
|
// Define the form fields and date formats we will test according to
|
|
// whether date calendar popups will be used or not.
|
|
$using_popup = $field_type == 'date_popup';
|
|
$publish_date_field = $using_popup ? 'publish_on[date]' : 'publish_on';
|
|
$unpublish_date_field = $using_popup ? 'unpublish_on[date]' : 'unpublish_on';
|
|
$publish_time_field = $using_popup ? 'publish_on[time]' : 'publish_on';
|
|
$unpublish_time_field = $using_popup ? 'unpublish_on[time]' : 'unpublish_on';
|
|
$time_format = $using_popup ? 'H:i:s' : 'Y-m-d H:i:s';
|
|
|
|
// We cannot easily test the exact validation messages as they contain the
|
|
// REQUEST_TIME of the POST request, which can be one or more seconds in
|
|
// the past. Best we can do is check the fixed part of the message.
|
|
$publish_validation_message = $using_popup ? 'The value input for field Publish on is invalid:' : "The 'publish on' value does not match the expected format of";
|
|
$unpublish_validation_message = $using_popup ? 'The value input for field Unpublish on is invalid:' : "The 'unpublish on' value does not match the expected format of";
|
|
|
|
// For testing we use an offset of 6 hours 30 minutes (23400 seconds).
|
|
// First test with the "date only" functionality disabled.
|
|
$settings = array(
|
|
'scheduler_date_format' => 'Y-m-d H:i:s',
|
|
'scheduler_default_time' => '6:30',
|
|
'scheduler_field_type' => $field_type,
|
|
'scheduler_allow_date_only' => FALSE,
|
|
);
|
|
$this->drupalPost('admin/config/content/scheduler', $settings, t('Save configuration'));
|
|
|
|
// Verify that entering a time is required.
|
|
$edit = array(
|
|
'title' => $this->randomName(),
|
|
$publish_date_field => date('Y-m-d', strtotime('+1 day', REQUEST_TIME)),
|
|
$unpublish_date_field => date('Y-m-d', strtotime('+2 day', REQUEST_TIME)),
|
|
);
|
|
$this->drupalPost('node/add/page', $edit, t('Save'));
|
|
$this->assertText($publish_validation_message, 'Validation error message is shown correctly. By default it is required to enter a time when scheduling content for publication.');
|
|
$this->assertText($unpublish_validation_message, 'Validation error message is shown correctly. By default it is required to enter a time when scheduling content for unpublication.');
|
|
|
|
// Allow the user to enter only the date.
|
|
$settings = array('scheduler_allow_date_only' => TRUE);
|
|
$this->drupalPost('admin/config/content/scheduler', $settings, t('Save configuration'));
|
|
|
|
// Check that the correct default time is added to the scheduled date.
|
|
$this->drupalPost('node/add/page', $edit, t('Save'));
|
|
$this->assertNoText("The 'publish on' value does not match the expected format of", 'If the default time option is enabled the user can skip the time when scheduling content for publication.');
|
|
$this->assertNoText("The 'unpublish on' value does not match the expected format of", 'If the default time option is enabled the user can skip the time when scheduling content for unpublication.');
|
|
$publish_time = date('Y-m-d H:i:s', strtotime('tomorrow', REQUEST_TIME) + 23400);
|
|
$this->assertText(sprintf('This post is unpublished and will be published %s.', $publish_time), 'The user is informed that the content will be published on the requested date, on the default time.');
|
|
|
|
// Check that the default time has been added to the form fields on edit.
|
|
$this->clickLink(t('Edit'));
|
|
$this->assertFieldByName($publish_time_field, date($time_format, strtotime('tomorrow', REQUEST_TIME) + 23400), 'The default time offset has been added to the date field when scheduling content for publication.');
|
|
$this->assertFieldByName($unpublish_time_field, date($time_format, strtotime('tomorrow +1 day', REQUEST_TIME) + 23400), 'The default time offset has been added to the date field when scheduling content for unpublication.');
|
|
|
|
// Check that it is not possible for the admin to enter a date format
|
|
// without a time if the 'date only' option is not enabled.
|
|
$edit = array(
|
|
'scheduler_date_format' => 'Y-m-d',
|
|
'scheduler_allow_date_only' => FALSE,
|
|
);
|
|
$this->drupalPost('admin/config/content/scheduler', $edit, t('Save configuration'));
|
|
$this->assertText('You must either include a time within the date format or enable the date-only option.', format_string('It is not possible to enter a date format without a time if the "date only" option is not enabled and the field type is set to %field_type.', array('%field_type' => $field_type)));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tests configuration of different date formats with the Date Popup field.
|
|
*/
|
|
public function testDatePopupFormats() {
|
|
$this->drupalLogin($this->adminUser);
|
|
|
|
// Define some date formats to test.
|
|
$test_cases = array(
|
|
// By default we are not using the 'date only' option, so passing only a
|
|
// date should fail.
|
|
'Y-m-d' => FALSE,
|
|
'd-m-Y' => FALSE,
|
|
'm-d-Y' => FALSE,
|
|
'n/j/y' => FALSE,
|
|
'd F Y' => FALSE,
|
|
|
|
// Test a number of supported date formats.
|
|
'Y-m-d H:i' => TRUE,
|
|
'd-m-Y h:ia' => TRUE,
|
|
'd m Y h:i a' => TRUE,
|
|
'm-d-Y h:iA' => TRUE,
|
|
'm/d/Y h:i A' => TRUE,
|
|
'n-j-y H:i:s' => TRUE,
|
|
'Y/M/d h:i:sA' => TRUE,
|
|
'Y/M/d h:i:s A' => TRUE,
|
|
'j F y h:i:sa' => TRUE,
|
|
'j F y h:i:s a' => TRUE,
|
|
|
|
// Test a number of date formats with invalid time specifications.
|
|
'y-m-d G:i' => FALSE,
|
|
'y-j-n G:i:sa' => FALSE,
|
|
'Y-m-d g:i:sa' => FALSE,
|
|
'y-m-d g:i:s' => FALSE,
|
|
'n-j-y h:i' => FALSE,
|
|
'd-m-y h:i:s' => FALSE,
|
|
'd/M/y H:i:sA' => FALSE,
|
|
'Y F d H:ia' => FALSE,
|
|
);
|
|
foreach ($test_cases as $date_format => $expected_result) {
|
|
$edit = array(
|
|
'scheduler_date_format' => $date_format,
|
|
'scheduler_field_type' => 'date_popup',
|
|
);
|
|
$this->drupalPost('admin/config/content/scheduler', $edit, t('Save configuration'));
|
|
$message = format_string('When using date popups the date format %format is @expected', array('%format' => $date_format, '@expected' => $expected_result ? 'allowed' : 'not allowed.'));
|
|
$assert = $expected_result ? 'assertNoText' : 'assertText';
|
|
$this->$assert('Error message', $message);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Tests Schedulers interaction with the Rules module.
|
|
*/
|
|
class SchedulerRulesTest extends SchedulerTestBase {
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public static function getInfo() {
|
|
return array(
|
|
'name' => 'Scheduler and Rules Integration',
|
|
'description' => 'Tests the Rules actions and conditions provided by Scheduler.',
|
|
'group' => 'Scheduler',
|
|
);
|
|
}
|
|
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function setUp() {
|
|
parent::setUp('scheduler', 'dblog', 'rules');
|
|
parent::commonSettings();
|
|
|
|
// Create a published node.
|
|
$this->node = $this->drupalCreateNode(array(
|
|
'title' => 'Initial Test Node',
|
|
'type' => 'page',
|
|
'uid' => $this->adminUser->uid,
|
|
'status' => TRUE,
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Tests the four actions which set and remove the Scheduler dates.
|
|
*/
|
|
public function testRulesActions() {
|
|
$this->drupalLogin($this->adminUser);
|
|
$node = $this->node;
|
|
|
|
$message1 = 'RULE 1. Set Publish-on date.';
|
|
$rule = rules_reaction_rule();
|
|
$rule->event('node_presave')
|
|
->condition(rules_condition('data_is', array('data:select' => 'node:title', 'value' => 'Rule 1')))
|
|
->action(rules_action('scheduler_set_publish_date_action', array('data:select' => 'node:node', 'date' => REQUEST_TIME + 1800)))
|
|
->action('drupal_message', array('message' => $message1));
|
|
// Check access and integrity, then save the rule.
|
|
$rule->access();
|
|
$rule->integrityCheck();
|
|
$rule->save('rule_id_1', $message1);
|
|
|
|
$message2 = 'RULE 2. Remove Publish-on date.';
|
|
$rule = rules_reaction_rule();
|
|
$rule->event('node_update')
|
|
->condition(rules_condition('data_is', array('data:select' => 'node:title', 'value' => 'Rule 2')))
|
|
->action(rules_action('scheduler_remove_publish_date_action', array('data:select' => 'node:node')))
|
|
->action('node_publish')
|
|
->action('drupal_message', array('message' => $message2));
|
|
$rule->access();
|
|
$rule->integrityCheck();
|
|
$rule->save('rule_id_2', $message2);
|
|
|
|
$message3 = 'RULE 3. Set Unpublish-on date.';
|
|
$rule = rules_reaction_rule();
|
|
$rule->event('node_presave')
|
|
->condition(rules_condition('data_is', array('data:select' => 'node:title', 'value' => 'Rule 3')))
|
|
->action(rules_action('scheduler_set_unpublish_date_action', array('data:select' => 'node:node', 'date' => REQUEST_TIME + 1800)))
|
|
->action('drupal_message', array('message' => $message3));
|
|
$rule->access();
|
|
$rule->integrityCheck();
|
|
$rule->save('rule_id_3', $message3);
|
|
|
|
$message4 = 'RULE 4. Remove Unpublish-on date.';
|
|
$rule = rules_reaction_rule();
|
|
$rule->event('node_update')
|
|
->condition(rules_condition('data_is', array('data:select' => 'node:title', 'value' => 'Rule 4')))
|
|
->action(rules_action('scheduler_remove_unpublish_date_action', array('data:select' => 'node:node')))
|
|
->action('drupal_message', array('message' => $message4));
|
|
$rule->access();
|
|
$rule->integrityCheck();
|
|
$rule->save('rule_id_4', $message4);
|
|
|
|
// Edit node without changing title, then reload the node.
|
|
$this->drupalPost('node/' . $node->nid . '/edit', array(), t('Save'));
|
|
$node = node_load($node->nid, NULL, TRUE);
|
|
|
|
// Check that neither of the rules are triggered, no publish and unpublish
|
|
// dates are set and the status is still published.
|
|
$this->assertNoText($message1, '"' . $message1 . '" is not shown');
|
|
$this->assertNoText($message2, '"' . $message2 . '" is not shown');
|
|
$this->assertNoText($message3, '"' . $message3 . '" is not shown');
|
|
$this->assertNoText($message4, '"' . $message4 . '" is not shown');
|
|
$this->assertTrue(empty($node->publish_on), 'Node is not scheduled for publishing.');
|
|
$this->assertTrue(empty($node->unpublish_on), 'Node is not scheduled for unpublishing.');
|
|
$this->assertTrue($node->status, 'Node remains published for title: "' . $node->title . '".');
|
|
|
|
$this->drupalGet('admin/reports/dblog');
|
|
$this->drupalGet('admin/content/scheduler');
|
|
|
|
// Edit the node, triggering rule 1, then reload the node.
|
|
$this->drupalPost('node/' . $node->nid . '/edit', array('title' => 'Rule 1'), t('Save'));
|
|
$node = node_load($node->nid, NULL, TRUE);
|
|
|
|
// Check that only rule 1 is triggered.
|
|
$this->assertText($message1, '"' . $message1 . '" is shown');
|
|
$this->assertNoText($message2, '"' . $message2 . '" is not shown');
|
|
$this->assertNoText($message3, '"' . $message3 . '" is not shown');
|
|
$this->assertNoText($message4, '"' . $message4 . '" is not shown');
|
|
// Check that a publishing date has been set and status is now unpublished.
|
|
$this->assertTrue(!empty($node->publish_on), 'Node is scheduled for publishing.');
|
|
$this->assertTrue(empty($node->unpublish_on), 'Node is not scheduled for unpublishing.');
|
|
$this->assertFalse($node->status, 'Node is now unpublished for title: "' . $node->title . '".');
|
|
|
|
$this->drupalGet('admin/reports/dblog');
|
|
$this->drupalGet('admin/content/scheduler');
|
|
|
|
// Edit the node, triggering rule 2, then reload the node.
|
|
$this->drupalPost('node/' . $node->nid . '/edit', array('title' => 'Rule 2'), t('Save'));
|
|
$node = node_load($node->nid, NULL, TRUE);
|
|
|
|
// Check that only rule 2 is triggered.
|
|
$this->assertNoText($message1, '"' . $message1 . '" is not shown');
|
|
$this->assertText($message2, '"' . $message2 . '" is shown');
|
|
$this->assertNoText($message3, '"' . $message3 . '" is not shown');
|
|
$this->assertNoText($message4, '"' . $message4 . '" is not shown');
|
|
// Check that the publishing date has been removed.
|
|
$this->assertTrue(empty($node->publish_on), 'Node is not scheduled for publishing.');
|
|
$this->assertTrue(empty($node->unpublish_on), 'Node is not scheduled for unpublishing.');
|
|
$this->assertTrue($node->status, 'Node is now published for title: "' . $node->title . '".');
|
|
|
|
$this->drupalGet('admin/reports/dblog');
|
|
$this->drupalGet('admin/content/scheduler');
|
|
|
|
// Edit the node, triggering rule 3, then reload the node.
|
|
$this->drupalPost('node/' . $node->nid . '/edit', array('title' => 'Rule 3'), t('Save'));
|
|
$node = node_load($node->nid, NULL, TRUE);
|
|
|
|
// Check that only rule 3 is triggered.
|
|
$this->assertNoText($message1, '"' . $message1 . '" is not shown');
|
|
$this->assertNoText($message2, '"' . $message2 . '" is not shown');
|
|
$this->assertText($message3, '"' . $message3 . '" is shown');
|
|
$this->assertNoText($message4, '"' . $message4 . '" is not shown');
|
|
// Check that an unpublishing date has been set.
|
|
$this->assertTrue(empty($node->publish_on), 'Node is not scheduled for publishing.');
|
|
$this->assertTrue(!empty($node->unpublish_on), 'Node is scheduled for unpublishing.');
|
|
$this->assertTrue($node->status, 'Node remains published for title: "' . $node->title . '".');
|
|
|
|
$this->drupalGet('admin/reports/dblog');
|
|
$this->drupalGet('admin/content/scheduler');
|
|
|
|
// Edit the node, triggering rule 4, then reload the node.
|
|
$this->drupalPost('node/' . $node->nid . '/edit', array('title' => 'Rule 4'), t('Save'));
|
|
$node = node_load($node->nid, NULL, TRUE);
|
|
|
|
// Check that only rule 4 is triggered.
|
|
$this->assertNoText($message1, '"' . $message1 . '" is not shown');
|
|
$this->assertNoText($message2, '"' . $message2 . '" is not shown');
|
|
$this->assertNoText($message3, '"' . $message3 . '" is not shown');
|
|
$this->assertText($message4, '"' . $message4 . '" is shown');
|
|
// Check that the unpublishing date has been removed.
|
|
$this->assertTrue(empty($node->publish_on), 'Node is not scheduled for publishing.');
|
|
$this->assertTrue(empty($node->unpublish_on), 'Node is not scheduled for unpublishing.');
|
|
$this->assertTrue($node->status, 'Node remains published for title: "' . $node->title . '".');
|
|
|
|
$this->drupalGet('admin/reports/dblog');
|
|
$this->drupalGet('admin/content/scheduler');
|
|
}
|
|
|
|
/**
|
|
* Tests the two conditions for a content type being enabled for scheduling.
|
|
*/
|
|
public function testRulesConditionsNodetypeEnabled() {
|
|
$this->drupalLogin($this->adminUser);
|
|
$node = $this->node;
|
|
|
|
// Create a reaction rule to display a message when viewing a node of a type
|
|
// that is enabled for scheduled publishing.
|
|
// "viewing content" actually means "viewing PUBLISHED content".
|
|
$message1 = 'RULE 1. This node type is enabled for scheduled publishing.';
|
|
$rule = rules_reaction_rule();
|
|
$rule->event('node_view')
|
|
->condition(rules_condition('scheduler_condition_publishing_is_enabled', array('data:select' => 'node:node')))
|
|
->action('drupal_message', array('message' => $message1));
|
|
// Check access and integrity, then save the rule.
|
|
$rule->access();
|
|
$rule->integrityCheck();
|
|
$rule->save('rule_id_1', $message1);
|
|
|
|
// Create a reaction rule to display a message when viewing a node of a type
|
|
// that is enabled for scheduled unpublishing.
|
|
$message2 = 'RULE 2. This node type is enabled for scheduled unpublishing.';
|
|
$rule = rules_reaction_rule();
|
|
$rule->event('node_view')
|
|
->condition(rules_condition('scheduler_condition_unpublishing_is_enabled', array('data:select' => 'node:node')))
|
|
->action('drupal_message', array('message' => $message2));
|
|
$rule->access();
|
|
$rule->integrityCheck();
|
|
$rule->save('rule_id_2', $message2);
|
|
|
|
// Create a reaction rule to display a message when viewing a node of a type
|
|
// that is NOT enabled for scheduled publishing.
|
|
$message3 = 'RULE 3. This node type is not enabled for scheduled publishing.';
|
|
$rule = rules_reaction_rule();
|
|
$rule->event('node_view')
|
|
->condition(rules_condition('scheduler_condition_publishing_is_enabled', array('data:select' => 'node:node'))->negate())
|
|
->action('drupal_message', array('message' => $message3));
|
|
$rule->access();
|
|
$rule->integrityCheck();
|
|
$rule->save('rule_id_3', $message3);
|
|
|
|
// Create a reaction rule to display a message when viewing a node of a type
|
|
// that is not enabled for scheduled unpublishing.
|
|
$message4 = 'RULE 4. This node type is not enabled for scheduled unpublishing.';
|
|
$rule = rules_reaction_rule();
|
|
$rule->event('node_view')
|
|
->condition(rules_condition('scheduler_condition_unpublishing_is_enabled', array('data:select' => 'node:node'))->negate())
|
|
->action('drupal_message', array('message' => $message4));
|
|
$rule->access();
|
|
$rule->integrityCheck();
|
|
$rule->save('rule_id_4', $message4);
|
|
|
|
// View the node and check the default position - that the node type is
|
|
// enabled for both publishing and unpublishing.
|
|
$this->drupalGet('node/' . $node->nid);
|
|
$this->assertText($message1, '"' . $message1 . '" is shown');
|
|
$this->assertText($message2, '"' . $message2 . '" is shown');
|
|
$this->assertNoText($message3, '"' . $message3 . '" is not shown');
|
|
$this->assertNoText($message4, '"' . $message4 . '" is not shown');
|
|
|
|
// Turn off scheduled publishing for the node type and check the rules.
|
|
variable_set('scheduler_publish_enable_page', FALSE);
|
|
$this->drupalGet('node/' . $node->nid);
|
|
$this->assertNoText($message1, '"' . $message1 . '" is not shown');
|
|
$this->assertText($message2, '"' . $message2 . '" is shown');
|
|
$this->assertText($message3, '"' . $message3 . '" is shown');
|
|
$this->assertNoText($message4, '"' . $message4 . '" is not shown');
|
|
|
|
// Turn off scheduled unpublishing for the node type and the check again.
|
|
variable_set('scheduler_unpublish_enable_page', FALSE);
|
|
$this->drupalGet('node/' . $node->nid);
|
|
$this->assertNoText($message1, '"' . $message1 . '" is not shown');
|
|
$this->assertNoText($message2, '"' . $message2 . '" is not shown');
|
|
$this->assertText($message3, '"' . $message3 . '" is shown');
|
|
$this->assertText($message4, '"' . $message4 . '" is shown');
|
|
}
|
|
|
|
/**
|
|
* Tests the two conditions for whether a node is scheduled.
|
|
*/
|
|
public function testRulesConditionsNodeIsScheduled() {
|
|
$this->drupalLogin($this->adminUser);
|
|
$node = $this->node;
|
|
|
|
// Create a reaction rule to display a message when a node is updated and
|
|
// is not scheduled for publishing.
|
|
$message5 = 'RULE 5. This content is not scheduled for publishing.';
|
|
$rule = rules_reaction_rule();
|
|
$rule->event('node_update')
|
|
->condition(rules_condition('scheduler_condition_node_is_scheduled_for_publishing', array('data:select' => 'node:node'))->negate())
|
|
->action('drupal_message', array('message' => $message5));
|
|
$rule->access();
|
|
$rule->integrityCheck();
|
|
$rule->save('rule_id_5', $message5);
|
|
|
|
// Create a reaction rule to display a message when a node is updated and
|
|
// is not scheduled for unpublishing.
|
|
$message6 = 'RULE 6. This content is not scheduled for unpublishing.';
|
|
$rule = rules_reaction_rule();
|
|
$rule->event('node_update')
|
|
->condition(rules_condition('scheduler_condition_node_is_scheduled_for_unpublishing', array('data:select' => 'node:node'))->negate())
|
|
->action('drupal_message', array('message' => $message6));
|
|
$rule->access();
|
|
$rule->integrityCheck();
|
|
$rule->save('rule_id_6', $message6);
|
|
|
|
// Create a reaction rule to display a message when a node is updated and
|
|
// is scheduled for publishing.
|
|
$message7 = 'RULE 7. This content is scheduled for publishing.';
|
|
$rule = rules_reaction_rule();
|
|
$rule->event('node_update')
|
|
->condition(rules_condition('scheduler_condition_node_is_scheduled_for_publishing', array('data:select' => 'node:node')))
|
|
->action('drupal_message', array('message' => $message7));
|
|
$rule->access();
|
|
$rule->integrityCheck();
|
|
$rule->save('rule_id_7', $message7);
|
|
|
|
// Create a reaction rule to display a message when a node is updated and
|
|
// is scheduled for unpublishing.
|
|
$message8 = 'RULE 8. This content is scheduled for unpublishing.';
|
|
$rule = rules_reaction_rule();
|
|
$rule->event('node_update')
|
|
->condition(rules_condition('scheduler_condition_node_is_scheduled_for_unpublishing', array('data:select' => 'node:node')))
|
|
->action('drupal_message', array('message' => $message8));
|
|
$rule->access();
|
|
$rule->integrityCheck();
|
|
$rule->save('rule_id_8', $message8);
|
|
|
|
// Edit the node but do not enter any scheduling dates.
|
|
$this->drupalPost('node/' . $node->nid . '/edit', array(), t('Save'));
|
|
|
|
// Check that the conditions have been met or not as expceted.
|
|
$this->assertText($message5, '"' . $message5 . '" is shown');
|
|
$this->assertText($message6, '"' . $message6 . '" is shown');
|
|
$this->assertNoText($message7, '"' . $message7 . '" is not shown');
|
|
$this->assertNoText($message8, '"' . $message8 . '" is not shown');
|
|
|
|
// Edit the node and set a publish_on date.
|
|
$edit = array(
|
|
'publish_on' => date('Y-m-d H:i:s', strtotime('+1 day', REQUEST_TIME)),
|
|
);
|
|
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
|
|
|
// Check that the conditions have been met (or not) as expected.
|
|
$this->assertNoText($message5, '"' . $message5 . '" is not shown');
|
|
$this->assertText($message6, '"' . $message6 . '" is shown');
|
|
$this->assertText($message7, '"' . $message7 . '" is shown');
|
|
$this->assertNoText($message8, '"' . $message8 . '" is not shown');
|
|
|
|
// Edit the node and set an unpublish_on date.
|
|
$edit = array(
|
|
'unpublish_on' => date('Y-m-d H:i:s', strtotime('+2 day', REQUEST_TIME)),
|
|
);
|
|
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
|
|
|
// Check that the conditions have been met (or not) as expected.
|
|
$this->assertNoText($message5, '"' . $message5 . '" is not shown');
|
|
$this->assertNoText($message6, '"' . $message6 . '" is not shown');
|
|
$this->assertText($message7, '"' . $message7 . '" is shown');
|
|
$this->assertText($message8, '"' . $message8 . '" is shown');
|
|
}
|
|
|
|
/**
|
|
* Helper function to check which events have been triggered.
|
|
*
|
|
* @param array $expected
|
|
* Array of integers to indicate which messages (1-6) should be seen.
|
|
*/
|
|
private function checkEventText(array $expected = array()) {
|
|
for ($i = 1; $i <= 6; $i++) {
|
|
$message = $this->eventMessage[$i];
|
|
if (in_array($i, $expected)) {
|
|
$this->assertText($message, 'Event message "' . $message . '" is shown');
|
|
}
|
|
else {
|
|
$this->assertNoText($message, 'Event message "' . $message . '" is not shown');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tests the six events provided by Scheduler.
|
|
*
|
|
* This class tests all six events provided by Scheduler, by creating six
|
|
* rules which are all active throughout the test. They are all checked in
|
|
* this one test class to make the tests stronger, as this will show not only
|
|
* that the correct events are triggered in the right places, but also
|
|
* that they are not triggered in the wrong places.
|
|
*/
|
|
public function testRulesEvents() {
|
|
|
|
// Create six reaction rules, one for each event that Scheduler triggers.
|
|
$rule_data = array(
|
|
1 => array('scheduler_new_node_is_scheduled_for_publishing_event', 'A new node is created and is scheduled for publishing.'),
|
|
2 => array('scheduler_existing_node_is_scheduled_for_publishing_event', 'An existing node is saved and is scheduled for publishing.'),
|
|
3 => array('scheduler_node_has_been_published_event', 'Scheduler has published this node during cron.'),
|
|
4 => array('scheduler_new_node_is_scheduled_for_unpublishing_event', 'A new node is created and is scheduled for unpublishing.'),
|
|
5 => array('scheduler_existing_node_is_scheduled_for_unpublishing_event', 'An existing node is saved and is scheduled for unpublishing.'),
|
|
6 => array('scheduler_node_has_been_unpublished_event', 'Scheduler has unpublished this node during cron.'),
|
|
);
|
|
foreach ($rule_data as $i => $values) {
|
|
list($event_name, $description) = $values;
|
|
$rule = rules_reaction_rule();
|
|
$this->eventMessage[$i] = 'RULE ' . $i . '. ' . $description;
|
|
$rule->event($event_name)
|
|
->action('drupal_message', array('message' => $this->eventMessage[$i]));
|
|
$rule->access();
|
|
$rule->integrityCheck();
|
|
$rule->save('rule_id_' . $i, $this->eventMessage[$i]);
|
|
}
|
|
|
|
$this->drupalLogin($this->adminUser);
|
|
|
|
// Create a node without any scheduled dates, using node/add/page not
|
|
// drupalCreateNode(), and check that no events are triggered.
|
|
$edit = array(
|
|
'title' => 'Test for no events on creation',
|
|
'body[' . LANGUAGE_NONE . '][0][value]' => $this->randomString(30),
|
|
);
|
|
$this->drupalPost('node/add/page', $edit, t('Save'));
|
|
$node = $this->drupalGetNodeByTitle($edit['title']);
|
|
$this->checkEventText();
|
|
|
|
// Edit the node and check that no events are triggered.
|
|
$edit = array(
|
|
'title' => 'Test for no events on edit',
|
|
'body[' . LANGUAGE_NONE . '][0][value]' => $this->randomString(30),
|
|
);
|
|
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
|
$this->checkEventText();
|
|
|
|
// Create a new node with a publish-on date, and check that only event 1 is
|
|
// triggered. Use time() not REQUEST_TIME to guarantee the datetime is in
|
|
// the future but only by a few seconds.
|
|
$edit = array(
|
|
'title' => 'Create node with publish-on date',
|
|
'publish_on' => date('Y-m-d H:i:s', time() + 3),
|
|
'body[' . LANGUAGE_NONE . '][0][value]' => $this->randomString(30),
|
|
);
|
|
$this->drupalPost('node/add/page', $edit, t('Save'));
|
|
$node = $this->drupalGetNodeByTitle($edit['title']);
|
|
$this->checkEventText(array(1));
|
|
|
|
// Edit this node and check that only event 2 is triggered.
|
|
$edit = array(
|
|
'title' => 'Edit node with publish-on date',
|
|
'body[' . LANGUAGE_NONE . '][0][value]' => $this->randomString(30),
|
|
);
|
|
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
|
$this->checkEventText(array(2));
|
|
|
|
// Delay before running cron to ensure that the date will be in the past, so
|
|
// that the node gets processed. Then assert that only event 3 is triggered.
|
|
sleep(5);
|
|
$this->cronRun();
|
|
$this->drupalGet('admin/reports/dblog');
|
|
$this->checkEventText(array(3));
|
|
|
|
// Create a new node with an unpublish-on date, and check that only event 4
|
|
// is triggered.
|
|
$edit = array(
|
|
'title' => 'Create node with unpublish-on date',
|
|
'unpublish_on' => date('Y-m-d H:i:s', time() + 3),
|
|
'body[' . LANGUAGE_NONE . '][0][value]' => $this->randomString(30),
|
|
);
|
|
$this->drupalPost('node/add/page', $edit, t('Save'));
|
|
$node = $this->drupalGetNodeByTitle($edit['title']);
|
|
$this->checkEventText(array(4));
|
|
|
|
// Edit this node and check that only event 5 is triggered.
|
|
$edit = array(
|
|
'title' => 'Edit node with unpublish-on date',
|
|
'body[' . LANGUAGE_NONE . '][0][value]' => $this->randomString(30),
|
|
);
|
|
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
|
$this->checkEventText(array(5));
|
|
|
|
// Delay before running cron to ensure that the date will be in the past, so
|
|
// that the node gets processed. Then assert that event 6 is triggered.
|
|
sleep(5);
|
|
$this->cronRun();
|
|
$this->drupalGet('admin/reports/dblog');
|
|
$this->checkEventText(array(6));
|
|
|
|
// Create a new node with both publish-on and unpublish-on dates, and check
|
|
// that events 1 and event 4 are both triggered.
|
|
$edit = array(
|
|
'title' => 'Create node with both dates',
|
|
'publish_on' => date('Y-m-d H:i:s', time() + 3),
|
|
'unpublish_on' => date('Y-m-d H:i:s', time() + 4),
|
|
'body[' . LANGUAGE_NONE . '][0][value]' => $this->randomString(30),
|
|
);
|
|
$this->drupalPost('node/add/page', $edit, t('Save'));
|
|
$node = $this->drupalGetNodeByTitle($edit['title']);
|
|
$this->checkEventText(array(1, 4));
|
|
|
|
// Edit this node and check that events 2 and 5 are triggered.
|
|
$edit = array(
|
|
'title' => 'Edit node with both dates',
|
|
'body[' . LANGUAGE_NONE . '][0][value]' => $this->randomString(30),
|
|
);
|
|
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
|
$this->checkEventText(array(2, 5));
|
|
|
|
// Delay before running cron to ensure that the dates will be in the past.
|
|
// Then assert that events 3, 5 & 6 are triggered.
|
|
sleep(6);
|
|
$this->cronRun();
|
|
$this->drupalGet('admin/reports/dblog');
|
|
$this->checkEventText(array(3, 5, 6));
|
|
}
|
|
|
|
}
|