Merge branch 'kernel-remerge' into remerge
commit
1e0223a167
|
@ -669,8 +669,10 @@ function drupal_settings_initialize() {
|
|||
global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $config_directory_name;
|
||||
$conf = array();
|
||||
|
||||
if (file_exists(DRUPAL_ROOT . '/' . conf_path() . '/settings.php')) {
|
||||
include_once DRUPAL_ROOT . '/' . conf_path() . '/settings.php';
|
||||
// Make conf_path() available as local variable in settings.php.
|
||||
$conf_path = conf_path();
|
||||
if (file_exists(DRUPAL_ROOT . '/' . $conf_path . '/settings.php')) {
|
||||
include_once DRUPAL_ROOT . '/' . $conf_path . '/settings.php';
|
||||
}
|
||||
$is_https = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on';
|
||||
|
||||
|
|
|
@ -3969,6 +3969,8 @@ function drupal_region_class($region) {
|
|||
* which drupal_add_js() happened earlier in the page request.
|
||||
* - defer: If set to TRUE, the defer attribute is set on the <script>
|
||||
* tag. Defaults to FALSE.
|
||||
* - async: If set to TRUE, the async attribute is set on the <script>
|
||||
* tag. Defaults to FALSE.
|
||||
* - cache: If set to FALSE, the JavaScript file is loaded anew on every page
|
||||
* call; in other words, it is not cached. Used only when 'type' references
|
||||
* a JavaScript file. Defaults to TRUE.
|
||||
|
@ -4041,6 +4043,7 @@ function drupal_add_js($data = NULL, $options = NULL) {
|
|||
'preprocess' => TRUE,
|
||||
'cache' => TRUE,
|
||||
'defer' => FALSE,
|
||||
'async' => FALSE,
|
||||
'browsers' => array(),
|
||||
),
|
||||
);
|
||||
|
@ -4088,6 +4091,7 @@ function drupal_js_defaults($data = NULL) {
|
|||
'scope' => 'header',
|
||||
'cache' => TRUE,
|
||||
'defer' => FALSE,
|
||||
'async' => FALSE,
|
||||
'preprocess' => TRUE,
|
||||
'version' => NULL,
|
||||
'data' => $data,
|
||||
|
@ -4282,9 +4286,16 @@ function drupal_pre_render_scripts($elements) {
|
|||
break;
|
||||
}
|
||||
|
||||
// The defer attribute must not be specified if src is not defined.
|
||||
if (!empty($item['defer']) && isset($element['#attributes']['src'])) {
|
||||
$element['#attributes']['defer'] = 'defer';
|
||||
// The defer and async attributes must not be specified if the src
|
||||
// attribute is not present.
|
||||
if (!empty($element['#attributes']['src'])) {
|
||||
// Both may be specified for legacy browser fallback purposes.
|
||||
if (!empty($item['async'])) {
|
||||
$element['#attributes']['async'] = 'async';
|
||||
}
|
||||
if (!empty($item['defer'])) {
|
||||
$element['#attributes']['defer'] = 'defer';
|
||||
}
|
||||
}
|
||||
|
||||
$elements[] = $element;
|
||||
|
|
|
@ -3,6 +3,5 @@ description = "Aggregates syndicated content (RSS, RDF, and Atom feeds) from ext
|
|||
package = Core
|
||||
version = VERSION
|
||||
core = 8.x
|
||||
files[] = aggregator.test
|
||||
configure = admin/config/services/aggregator/settings
|
||||
stylesheets[all][] = aggregator.theme.css
|
||||
|
|
|
@ -1,987 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Tests for aggregator.module.
|
||||
*/
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
class AggregatorTestCase extends WebTestBase {
|
||||
function setUp() {
|
||||
parent::setUp(array('node', 'block', 'aggregator', 'aggregator_test'));
|
||||
|
||||
// Create an Article node type.
|
||||
if ($this->profile != 'standard') {
|
||||
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
|
||||
}
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('administer news feeds', 'access news feeds', 'create article content'));
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aggregator feed (simulate form submission on admin/config/services/aggregator/add/feed).
|
||||
*
|
||||
* @param $feed_url
|
||||
* If given, feed will be created with this URL, otherwise /rss.xml will be used.
|
||||
* @return $feed
|
||||
* Full feed object if possible.
|
||||
*
|
||||
* @see getFeedEditArray()
|
||||
*/
|
||||
function createFeed($feed_url = NULL) {
|
||||
$edit = $this->getFeedEditArray($feed_url);
|
||||
$this->drupalPost('admin/config/services/aggregator/add/feed', $edit, t('Save'));
|
||||
$this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title'])), t('The feed !name has been added.', array('!name' => $edit['title'])));
|
||||
|
||||
$feed = db_query("SELECT * FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $edit['title'], ':url' => $edit['url']))->fetch();
|
||||
$this->assertTrue(!empty($feed), t('The feed found in database.'));
|
||||
return $feed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an aggregator feed.
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
*/
|
||||
function deleteFeed($feed) {
|
||||
$this->drupalPost('admin/config/services/aggregator/edit/feed/' . $feed->fid, array(), t('Delete'));
|
||||
$this->assertRaw(t('The feed %title has been deleted.', array('%title' => $feed->title)), t('Feed deleted successfully.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a randomly generated feed edit array.
|
||||
*
|
||||
* @param $feed_url
|
||||
* If given, feed will be created with this URL, otherwise /rss.xml will be used.
|
||||
* @return
|
||||
* A feed array.
|
||||
*/
|
||||
function getFeedEditArray($feed_url = NULL) {
|
||||
$feed_name = $this->randomName(10);
|
||||
if (!$feed_url) {
|
||||
$feed_url = url('rss.xml', array(
|
||||
'query' => array('feed' => $feed_name),
|
||||
'absolute' => TRUE,
|
||||
));
|
||||
}
|
||||
$edit = array(
|
||||
'title' => $feed_name,
|
||||
'url' => $feed_url,
|
||||
'refresh' => '900',
|
||||
);
|
||||
return $edit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of the randomly created feed array.
|
||||
*
|
||||
* @return
|
||||
* Number of feed items on default feed created by createFeed().
|
||||
*/
|
||||
function getDefaultFeedItemCount() {
|
||||
// Our tests are based off of rss.xml, so let's find out how many elements should be related.
|
||||
$feed_count = db_query_range('SELECT COUNT(*) FROM {node} n WHERE n.promote = 1 AND n.status = 1', 0, config('system.rss-publishing')->get('feed_default_items'))->fetchField();
|
||||
return $feed_count > 10 ? 10 : $feed_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update feed items (simulate click to admin/config/services/aggregator/update/$fid).
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
* @param $expected_count
|
||||
* Expected number of feed items.
|
||||
*/
|
||||
function updateFeedItems(&$feed, $expected_count) {
|
||||
// First, let's ensure we can get to the rss xml.
|
||||
$this->drupalGet($feed->url);
|
||||
$this->assertResponse(200, t('!url is reachable.', array('!url' => $feed->url)));
|
||||
|
||||
// Attempt to access the update link directly without an access token.
|
||||
$this->drupalGet('admin/config/services/aggregator/update/' . $feed->fid);
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Refresh the feed (simulated link click).
|
||||
$this->drupalGet('admin/config/services/aggregator');
|
||||
$this->clickLink('update items');
|
||||
|
||||
// Ensure we have the right number of items.
|
||||
$result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid));
|
||||
$items = array();
|
||||
$feed->items = array();
|
||||
foreach ($result as $item) {
|
||||
$feed->items[] = $item->iid;
|
||||
}
|
||||
$feed->item_count = count($feed->items);
|
||||
$this->assertEqual($expected_count, $feed->item_count, t('Total items in feed equal to the total items in database (!val1 != !val2)', array('!val1' => $expected_count, '!val2' => $feed->item_count)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm item removal from a feed.
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
*/
|
||||
function removeFeedItems($feed) {
|
||||
$this->drupalPost('admin/config/services/aggregator/remove/' . $feed->fid, array(), t('Remove items'));
|
||||
$this->assertRaw(t('The news items from %title have been removed.', array('%title' => $feed->title)), t('Feed items removed.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add and remove feed items and ensure that the count is zero.
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
* @param $expected_count
|
||||
* Expected number of feed items.
|
||||
*/
|
||||
function updateAndRemove($feed, $expected_count) {
|
||||
$this->updateFeedItems($feed, $expected_count);
|
||||
$count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
|
||||
$this->assertTrue($count);
|
||||
$this->removeFeedItems($feed);
|
||||
$count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
|
||||
$this->assertTrue($count == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull feed categories from aggregator_category_feed table.
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
*/
|
||||
function getFeedCategories($feed) {
|
||||
// add the categories to the feed so we can use them
|
||||
$result = db_query('SELECT cid FROM {aggregator_category_feed} WHERE fid = :fid', array(':fid' => $feed->fid));
|
||||
foreach ($result as $category) {
|
||||
$feed->categories[] = $category->cid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull categories from aggregator_category table.
|
||||
*/
|
||||
function getCategories() {
|
||||
$categories = array();
|
||||
$result = db_query('SELECT * FROM {aggregator_category}');
|
||||
foreach ($result as $category) {
|
||||
$categories[$category->cid] = $category;
|
||||
}
|
||||
return $categories;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the feed name and url is unique.
|
||||
*
|
||||
* @param $feed_name
|
||||
* String containing the feed name to check.
|
||||
* @param $feed_url
|
||||
* String containing the feed url to check.
|
||||
* @return
|
||||
* TRUE if feed is unique.
|
||||
*/
|
||||
function uniqueFeed($feed_name, $feed_url) {
|
||||
$result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed_name, ':url' => $feed_url))->fetchField();
|
||||
return (1 == $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a valid OPML file from an array of feeds.
|
||||
*
|
||||
* @param $feeds
|
||||
* An array of feeds.
|
||||
* @return
|
||||
* Path to valid OPML file.
|
||||
*/
|
||||
function getValidOpml($feeds) {
|
||||
// Properly escape URLs so that XML parsers don't choke on them.
|
||||
foreach ($feeds as &$feed) {
|
||||
$feed['url'] = htmlspecialchars($feed['url']);
|
||||
}
|
||||
/**
|
||||
* Does not have an XML declaration, must pass the parser.
|
||||
*/
|
||||
$opml = <<<EOF
|
||||
<opml version="1.0">
|
||||
<head></head>
|
||||
<body>
|
||||
<!-- First feed to be imported. -->
|
||||
<outline text="{$feeds[0]['title']}" xmlurl="{$feeds[0]['url']}" />
|
||||
|
||||
<!-- Second feed. Test string delimitation and attribute order. -->
|
||||
<outline xmlurl='{$feeds[1]['url']}' text='{$feeds[1]['title']}'/>
|
||||
|
||||
<!-- Test for duplicate URL and title. -->
|
||||
<outline xmlurl="{$feeds[0]['url']}" text="Duplicate URL"/>
|
||||
<outline xmlurl="http://duplicate.title" text="{$feeds[1]['title']}"/>
|
||||
|
||||
<!-- Test that feeds are only added with required attributes. -->
|
||||
<outline text="{$feeds[2]['title']}" />
|
||||
<outline xmlurl="{$feeds[2]['url']}" />
|
||||
</body>
|
||||
</opml>
|
||||
EOF;
|
||||
|
||||
$path = 'public://valid-opml.xml';
|
||||
return file_unmanaged_save_data($opml, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an invalid OPML file.
|
||||
*
|
||||
* @return
|
||||
* Path to invalid OPML file.
|
||||
*/
|
||||
function getInvalidOpml() {
|
||||
$opml = <<<EOF
|
||||
<opml>
|
||||
<invalid>
|
||||
</opml>
|
||||
EOF;
|
||||
|
||||
$path = 'public://invalid-opml.xml';
|
||||
return file_unmanaged_save_data($opml, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a valid but empty OPML file.
|
||||
*
|
||||
* @return
|
||||
* Path to empty OPML file.
|
||||
*/
|
||||
function getEmptyOpml() {
|
||||
$opml = <<<EOF
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<opml version="1.0">
|
||||
<head></head>
|
||||
<body>
|
||||
<outline text="Sample text" />
|
||||
<outline text="Sample text" url="Sample URL" />
|
||||
</body>
|
||||
</opml>
|
||||
EOF;
|
||||
|
||||
$path = 'public://empty-opml.xml';
|
||||
return file_unmanaged_save_data($opml, $path);
|
||||
}
|
||||
|
||||
function getRSS091Sample() {
|
||||
return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_rss091.xml';
|
||||
}
|
||||
|
||||
function getAtomSample() {
|
||||
// The content of this sample ATOM feed is based directly off of the
|
||||
// example provided in RFC 4287.
|
||||
return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_atom.xml';
|
||||
}
|
||||
|
||||
function getHtmlEntitiesSample() {
|
||||
return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_title_entities.xml';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates sample article nodes.
|
||||
*
|
||||
* @param $count
|
||||
* (optional) The number of nodes to generate.
|
||||
*/
|
||||
function createSampleNodes($count = 5) {
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
// Post $count article nodes.
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName();
|
||||
$edit["body[$langcode][0][value]"] = $this->randomName();
|
||||
$this->drupalPost('node/add/article', $edit, t('Save'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests aggregator configuration settings.
|
||||
*/
|
||||
class AggregatorConfigurationTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Aggregator configuration',
|
||||
'description' => 'Test aggregator settings page.',
|
||||
'group' => 'Aggregator',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the settings form to ensure the correct default values are used.
|
||||
*/
|
||||
function testSettingsPage() {
|
||||
$edit = array(
|
||||
'aggregator_allowed_html_tags' => '<a>',
|
||||
'aggregator_summary_items' => 10,
|
||||
'aggregator_clear' => 3600,
|
||||
'aggregator_category_selector' => 'select',
|
||||
'aggregator_teaser_length' => 200,
|
||||
);
|
||||
$this->drupalPost('admin/config/services/aggregator/settings', $edit, t('Save configuration'));
|
||||
$this->assertText(t('The configuration options have been saved.'));
|
||||
|
||||
foreach ($edit as $name => $value) {
|
||||
$this->assertFieldByName($name, $value, t('"@name" has correct default value.', array('@name' => $name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AddFeedTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Add feed functionality',
|
||||
'description' => 'Add feed test.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feed, ensure that it is unique, check the source, and delete the feed.
|
||||
*/
|
||||
function testAddFeed() {
|
||||
$feed = $this->createFeed();
|
||||
|
||||
// Check feed data.
|
||||
$this->assertEqual($this->getUrl(), url('admin/config/services/aggregator/add/feed', array('absolute' => TRUE)), t('Directed to correct url.'));
|
||||
$this->assertTrue($this->uniqueFeed($feed->title, $feed->url), t('The feed is unique.'));
|
||||
|
||||
// Check feed source.
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(200, t('Feed source exists.'));
|
||||
$this->assertText($feed->title, t('Page title'));
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid . '/categorize');
|
||||
$this->assertResponse(200, t('Feed categorization page exists.'));
|
||||
|
||||
// Delete feed.
|
||||
$this->deleteFeed($feed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests feeds with very long URLs.
|
||||
*/
|
||||
function testAddLongFeed() {
|
||||
// Create a feed with a URL of > 255 characters.
|
||||
$long_url = "https://www.google.com/search?ix=heb&sourceid=chrome&ie=UTF-8&q=angie+byron#sclient=psy-ab&hl=en&safe=off&source=hp&q=angie+byron&pbx=1&oq=angie+byron&aq=f&aqi=&aql=&gs_sm=3&gs_upl=0l0l0l10534l0l0l0l0l0l0l0l0ll0l0&bav=on.2,or.r_gc.r_pw.r_cp.,cf.osb&fp=a70b6b1f0abe28d8&biw=1629&bih=889&ix=heb";
|
||||
$feed = $this->createFeed($long_url);
|
||||
|
||||
// Create a second feed of > 255 characters, where the only difference is
|
||||
// after the 255th character.
|
||||
$long_url_2 = "https://www.google.com/search?ix=heb&sourceid=chrome&ie=UTF-8&q=angie+byron#sclient=psy-ab&hl=en&safe=off&source=hp&q=angie+byron&pbx=1&oq=angie+byron&aq=f&aqi=&aql=&gs_sm=3&gs_upl=0l0l0l10534l0l0l0l0l0l0l0l0ll0l0&bav=on.2,or.r_gc.r_pw.r_cp.,cf.osb&fp=a70b6b1f0abe28d8&biw=1629&bih=889";
|
||||
$feed_2 = $this->createFeed($long_url_2);
|
||||
|
||||
// Check feed data.
|
||||
$this->assertTrue($this->uniqueFeed($feed->title, $feed->url), 'The first long URL feed is unique.');
|
||||
$this->assertTrue($this->uniqueFeed($feed_2->title, $feed_2->url), 'The second long URL feed is unique.');
|
||||
|
||||
// Check feed source.
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(200, 'Long URL feed source exists.');
|
||||
$this->assertText($feed->title, 'Page title');
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid . '/categorize');
|
||||
$this->assertResponse(200, 'Long URL feed categorization page exists.');
|
||||
|
||||
// Delete feeds.
|
||||
$this->deleteFeed($feed);
|
||||
$this->deleteFeed($feed_2);
|
||||
}
|
||||
}
|
||||
|
||||
class CategorizeFeedTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Categorize feed functionality',
|
||||
'description' => 'Categorize feed test.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feed and make sure you can add more than one category to it.
|
||||
*/
|
||||
function testCategorizeFeed() {
|
||||
|
||||
// Create 2 categories.
|
||||
$category_1 = array('title' => $this->randomName(10), 'description' => '');
|
||||
$this->drupalPost('admin/config/services/aggregator/add/category', $category_1, t('Save'));
|
||||
$this->assertRaw(t('The category %title has been added.', array('%title' => $category_1['title'])), t('The category %title has been added.', array('%title' => $category_1['title'])));
|
||||
|
||||
$category_2 = array('title' => $this->randomName(10), 'description' => '');
|
||||
$this->drupalPost('admin/config/services/aggregator/add/category', $category_2, t('Save'));
|
||||
$this->assertRaw(t('The category %title has been added.', array('%title' => $category_2['title'])), t('The category %title has been added.', array('%title' => $category_2['title'])));
|
||||
|
||||
// Get categories from database.
|
||||
$categories = $this->getCategories();
|
||||
|
||||
// Create a feed and assign 2 categories to it.
|
||||
$feed = $this->getFeedEditArray();
|
||||
$feed['block'] = 5;
|
||||
foreach ($categories as $cid => $category) {
|
||||
$feed['category'][$cid] = $cid;
|
||||
}
|
||||
|
||||
// Use aggregator_save_feed() function to save the feed.
|
||||
aggregator_save_feed($feed);
|
||||
$db_feed = db_query("SELECT * FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed['title'], ':url' => $feed['url']))->fetch();
|
||||
|
||||
// Assert the feed has two categories.
|
||||
$this->getFeedCategories($db_feed);
|
||||
$this->assertEqual(count($db_feed->categories), 2, t('Feed has 2 categories'));
|
||||
}
|
||||
}
|
||||
|
||||
class UpdateFeedTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Update feed functionality',
|
||||
'description' => 'Update feed test.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feed and attempt to update it.
|
||||
*/
|
||||
function testUpdateFeed() {
|
||||
$remamining_fields = array('title', 'url', '');
|
||||
foreach ($remamining_fields as $same_field) {
|
||||
$feed = $this->createFeed();
|
||||
|
||||
// Get new feed data array and modify newly created feed.
|
||||
$edit = $this->getFeedEditArray();
|
||||
$edit['refresh'] = 1800; // Change refresh value.
|
||||
if (isset($feed->{$same_field})) {
|
||||
$edit[$same_field] = $feed->{$same_field};
|
||||
}
|
||||
$this->drupalPost('admin/config/services/aggregator/edit/feed/' . $feed->fid, $edit, t('Save'));
|
||||
$this->assertRaw(t('The feed %name has been updated.', array('%name' => $edit['title'])), t('The feed %name has been updated.', array('%name' => $edit['title'])));
|
||||
|
||||
// Check feed data.
|
||||
$this->assertEqual($this->getUrl(), url('admin/config/services/aggregator/', array('absolute' => TRUE)));
|
||||
$this->assertTrue($this->uniqueFeed($edit['title'], $edit['url']), t('The feed is unique.'));
|
||||
|
||||
// Check feed source.
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(200, t('Feed source exists.'));
|
||||
$this->assertText($edit['title'], t('Page title'));
|
||||
|
||||
// Delete feed.
|
||||
$feed->title = $edit['title']; // Set correct title so deleteFeed() will work.
|
||||
$this->deleteFeed($feed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RemoveFeedTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Remove feed functionality',
|
||||
'description' => 'Remove feed test.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a feed and ensure that all it services are removed.
|
||||
*/
|
||||
function testRemoveFeed() {
|
||||
$feed = $this->createFeed();
|
||||
|
||||
// Delete feed.
|
||||
$this->deleteFeed($feed);
|
||||
|
||||
// Check feed source.
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(404, t('Deleted feed source does not exists.'));
|
||||
|
||||
// Check database for feed.
|
||||
$result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed->title, ':url' => $feed->url))->fetchField();
|
||||
$this->assertFalse($result, t('Feed not found in database'));
|
||||
}
|
||||
}
|
||||
|
||||
class UpdateFeedItemTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Update feed item functionality',
|
||||
'description' => 'Update feed items from a feed.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test running "update items" from the 'admin/config/services/aggregator' page.
|
||||
*/
|
||||
function testUpdateFeedItem() {
|
||||
$this->createSampleNodes();
|
||||
|
||||
// Create a feed and test updating feed items if possible.
|
||||
$feed = $this->createFeed();
|
||||
if (!empty($feed)) {
|
||||
$this->updateFeedItems($feed, $this->getDefaultFeedItemCount());
|
||||
$this->removeFeedItems($feed);
|
||||
}
|
||||
|
||||
// Delete feed.
|
||||
$this->deleteFeed($feed);
|
||||
|
||||
// Test updating feed items without valid timestamp information.
|
||||
$edit = array(
|
||||
'title' => "Feed without publish timestamp",
|
||||
'url' => $this->getRSS091Sample(),
|
||||
);
|
||||
|
||||
$this->drupalGet($edit['url']);
|
||||
$this->assertResponse(array(200), t('URL !url is accessible', array('!url' => $edit['url'])));
|
||||
|
||||
$this->drupalPost('admin/config/services/aggregator/add/feed', $edit, t('Save'));
|
||||
$this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title'])), t('The feed !name has been added.', array('!name' => $edit['title'])));
|
||||
|
||||
$feed = db_query("SELECT * FROM {aggregator_feed} WHERE url = :url", array(':url' => $edit['url']))->fetchObject();
|
||||
|
||||
aggregator_refresh($feed);
|
||||
$before = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
|
||||
|
||||
// Sleep for 3 second.
|
||||
sleep(3);
|
||||
db_update('aggregator_feed')
|
||||
->condition('fid', $feed->fid)
|
||||
->fields(array(
|
||||
'checked' => 0,
|
||||
'hash' => '',
|
||||
'etag' => '',
|
||||
'modified' => 0,
|
||||
))
|
||||
->execute();
|
||||
aggregator_refresh($feed);
|
||||
|
||||
$after = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
|
||||
$this->assertTrue($before === $after, t('Publish timestamp of feed item was not updated (!before === !after)', array('!before' => $before, '!after' => $after)));
|
||||
}
|
||||
}
|
||||
|
||||
class RemoveFeedItemTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Remove feed item functionality',
|
||||
'description' => 'Remove feed items from a feed.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test running "remove items" from the 'admin/config/services/aggregator' page.
|
||||
*/
|
||||
function testRemoveFeedItem() {
|
||||
// Create a bunch of test feeds.
|
||||
$feed_urls = array();
|
||||
// No last-modified, no etag.
|
||||
$feed_urls[] = url('aggregator/test-feed', array('absolute' => TRUE));
|
||||
// Last-modified, but no etag.
|
||||
$feed_urls[] = url('aggregator/test-feed/1', array('absolute' => TRUE));
|
||||
// No Last-modified, but etag.
|
||||
$feed_urls[] = url('aggregator/test-feed/0/1', array('absolute' => TRUE));
|
||||
// Last-modified and etag.
|
||||
$feed_urls[] = url('aggregator/test-feed/1/1', array('absolute' => TRUE));
|
||||
|
||||
foreach ($feed_urls as $feed_url) {
|
||||
$feed = $this->createFeed($feed_url);
|
||||
// Update and remove items two times in a row to make sure that removal
|
||||
// resets all 'modified' information (modified, etag, hash) and allows for
|
||||
// immediate update.
|
||||
$this->updateAndRemove($feed, 2);
|
||||
$this->updateAndRemove($feed, 2);
|
||||
$this->updateAndRemove($feed, 2);
|
||||
// Delete feed.
|
||||
$this->deleteFeed($feed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CategorizeFeedItemTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Categorize feed item functionality',
|
||||
'description' => 'Test feed item categorization.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a feed has a category, make sure that the children inherit that
|
||||
* categorization.
|
||||
*/
|
||||
function testCategorizeFeedItem() {
|
||||
$this->createSampleNodes();
|
||||
|
||||
// Simulate form submission on "admin/config/services/aggregator/add/category".
|
||||
$edit = array('title' => $this->randomName(10), 'description' => '');
|
||||
$this->drupalPost('admin/config/services/aggregator/add/category', $edit, t('Save'));
|
||||
$this->assertRaw(t('The category %title has been added.', array('%title' => $edit['title'])), t('The category %title has been added.', array('%title' => $edit['title'])));
|
||||
|
||||
$category = db_query("SELECT * FROM {aggregator_category} WHERE title = :title", array(':title' => $edit['title']))->fetch();
|
||||
$this->assertTrue(!empty($category), t('The category found in database.'));
|
||||
|
||||
$link_path = 'aggregator/categories/' . $category->cid;
|
||||
$menu_link = db_query("SELECT * FROM {menu_links} WHERE link_path = :link_path", array(':link_path' => $link_path))->fetch();
|
||||
$this->assertTrue(!empty($menu_link), t('The menu link associated with the category found in database.'));
|
||||
|
||||
$feed = $this->createFeed();
|
||||
db_insert('aggregator_category_feed')
|
||||
->fields(array(
|
||||
'cid' => $category->cid,
|
||||
'fid' => $feed->fid,
|
||||
))
|
||||
->execute();
|
||||
$this->updateFeedItems($feed, $this->getDefaultFeedItemCount());
|
||||
$this->getFeedCategories($feed);
|
||||
$this->assertTrue(!empty($feed->categories), t('The category found in the feed.'));
|
||||
|
||||
// For each category of a feed, ensure feed items have that category, too.
|
||||
if (!empty($feed->categories) && !empty($feed->items)) {
|
||||
foreach ($feed->categories as $category) {
|
||||
$categorized_count = db_select('aggregator_category_item')
|
||||
->condition('iid', $feed->items, 'IN')
|
||||
->countQuery()
|
||||
->execute()
|
||||
->fetchField();
|
||||
|
||||
$this->assertEqual($feed->item_count, $categorized_count, t('Total items in feed equal to the total categorized feed items in database'));
|
||||
}
|
||||
}
|
||||
|
||||
// Delete feed.
|
||||
$this->deleteFeed($feed);
|
||||
}
|
||||
}
|
||||
|
||||
class ImportOPMLTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Import feeds from OPML functionality',
|
||||
'description' => 'Test OPML import.',
|
||||
'group' => 'Aggregator',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open OPML import form.
|
||||
*/
|
||||
function openImportForm() {
|
||||
db_delete('aggregator_category')->execute();
|
||||
|
||||
$category = $this->randomName(10);
|
||||
$cid = db_insert('aggregator_category')
|
||||
->fields(array(
|
||||
'title' => $category,
|
||||
'description' => '',
|
||||
))
|
||||
->execute();
|
||||
|
||||
$this->drupalGet('admin/config/services/aggregator/add/opml');
|
||||
$this->assertText('A single OPML document may contain a collection of many feeds.', t('Found OPML help text.'));
|
||||
$this->assertField('files[upload]', t('Found file upload field.'));
|
||||
$this->assertField('remote', t('Found Remote URL field.'));
|
||||
$this->assertField('refresh', '', t('Found Refresh field.'));
|
||||
$this->assertFieldByName("category[$cid]", $cid, t('Found category field.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit form filled with invalid fields.
|
||||
*/
|
||||
function validateImportFormFields() {
|
||||
$before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
|
||||
|
||||
$edit = array();
|
||||
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
|
||||
$this->assertRaw(t('You must <em>either</em> upload a file or enter a URL.'), t('Error if no fields are filled.'));
|
||||
|
||||
$path = $this->getEmptyOpml();
|
||||
$edit = array(
|
||||
'files[upload]' => $path,
|
||||
'remote' => file_create_url($path),
|
||||
);
|
||||
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
|
||||
$this->assertRaw(t('You must <em>either</em> upload a file or enter a URL.'), t('Error if both fields are filled.'));
|
||||
|
||||
$edit = array('remote' => 'invalidUrl://empty');
|
||||
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
|
||||
$this->assertText(t('The URL invalidUrl://empty is not valid.'), 'Error if the URL is invalid.');
|
||||
|
||||
$after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
|
||||
$this->assertEqual($before, $after, t('No feeds were added during the three last form submissions.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit form with invalid, empty and valid OPML files.
|
||||
*/
|
||||
function submitImportForm() {
|
||||
$before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
|
||||
|
||||
$form['files[upload]'] = $this->getInvalidOpml();
|
||||
$this->drupalPost('admin/config/services/aggregator/add/opml', $form, t('Import'));
|
||||
$this->assertText(t('No new feed has been added.'), t('Attempting to upload invalid XML.'));
|
||||
|
||||
$edit = array('remote' => file_create_url($this->getEmptyOpml()));
|
||||
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
|
||||
$this->assertText(t('No new feed has been added.'), t('Attempting to load empty OPML from remote URL.'));
|
||||
|
||||
$after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
|
||||
$this->assertEqual($before, $after, t('No feeds were added during the two last form submissions.'));
|
||||
|
||||
db_delete('aggregator_feed')->execute();
|
||||
db_delete('aggregator_category')->execute();
|
||||
db_delete('aggregator_category_feed')->execute();
|
||||
|
||||
$category = $this->randomName(10);
|
||||
db_insert('aggregator_category')
|
||||
->fields(array(
|
||||
'cid' => 1,
|
||||
'title' => $category,
|
||||
'description' => '',
|
||||
))
|
||||
->execute();
|
||||
|
||||
$feeds[0] = $this->getFeedEditArray();
|
||||
$feeds[1] = $this->getFeedEditArray();
|
||||
$feeds[2] = $this->getFeedEditArray();
|
||||
$edit = array(
|
||||
'files[upload]' => $this->getValidOpml($feeds),
|
||||
'refresh' => '900',
|
||||
'category[1]' => $category,
|
||||
);
|
||||
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
|
||||
$this->assertRaw(t('A feed with the URL %url already exists.', array('%url' => $feeds[0]['url'])), t('Verifying that a duplicate URL was identified'));
|
||||
$this->assertRaw(t('A feed named %title already exists.', array('%title' => $feeds[1]['title'])), t('Verifying that a duplicate title was identified'));
|
||||
|
||||
$after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
|
||||
$this->assertEqual($after, 2, t('Verifying that two distinct feeds were added.'));
|
||||
|
||||
$feeds_from_db = db_query("SELECT f.title, f.url, f.refresh, cf.cid FROM {aggregator_feed} f LEFT JOIN {aggregator_category_feed} cf ON f.fid = cf.fid");
|
||||
$refresh = $category = TRUE;
|
||||
foreach ($feeds_from_db as $feed) {
|
||||
$title[$feed->url] = $feed->title;
|
||||
$url[$feed->title] = $feed->url;
|
||||
$category = $category && $feed->cid == 1;
|
||||
$refresh = $refresh && $feed->refresh == 900;
|
||||
}
|
||||
|
||||
$this->assertEqual($title[$feeds[0]['url']], $feeds[0]['title'], t('First feed was added correctly.'));
|
||||
$this->assertEqual($url[$feeds[1]['title']], $feeds[1]['url'], t('Second feed was added correctly.'));
|
||||
$this->assertTrue($refresh, t('Refresh times are correct.'));
|
||||
$this->assertTrue($category, t('Categories are correct.'));
|
||||
}
|
||||
|
||||
function testOPMLImport() {
|
||||
$this->openImportForm();
|
||||
$this->validateImportFormFields();
|
||||
$this->submitImportForm();
|
||||
}
|
||||
}
|
||||
|
||||
class AggregatorCronTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Update on cron functionality',
|
||||
'description' => 'Update feeds on cron.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add feeds update them on cron.
|
||||
*/
|
||||
public function testCron() {
|
||||
// Create feed and test basic updating on cron.
|
||||
global $base_url;
|
||||
$key = config('system.cron')->get('cron_key');
|
||||
$this->createSampleNodes();
|
||||
$feed = $this->createFeed();
|
||||
$this->cronRun();
|
||||
$this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
|
||||
$this->removeFeedItems($feed);
|
||||
$this->assertEqual(0, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
|
||||
$this->cronRun();
|
||||
$this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
|
||||
|
||||
// Test feed locking when queued for update.
|
||||
$this->removeFeedItems($feed);
|
||||
db_update('aggregator_feed')
|
||||
->condition('fid', $feed->fid)
|
||||
->fields(array(
|
||||
'queued' => REQUEST_TIME,
|
||||
))
|
||||
->execute();
|
||||
$this->cronRun();
|
||||
$this->assertEqual(0, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
|
||||
db_update('aggregator_feed')
|
||||
->condition('fid', $feed->fid)
|
||||
->fields(array(
|
||||
'queued' => 0,
|
||||
))
|
||||
->execute();
|
||||
$this->cronRun();
|
||||
$this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
|
||||
}
|
||||
}
|
||||
|
||||
class AggregatorRenderingTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Checks display of aggregator items',
|
||||
'description' => 'Checks display of aggregator items on the page.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a feed block to the page and checks its links.
|
||||
*
|
||||
* TODO: Test the category block as well.
|
||||
*/
|
||||
public function testBlockLinks() {
|
||||
// Create feed.
|
||||
$this->createSampleNodes();
|
||||
$feed = $this->createFeed();
|
||||
$this->updateFeedItems($feed, $this->getDefaultFeedItemCount());
|
||||
|
||||
// Place block on page (@see block.test:moveBlockToRegion())
|
||||
// Need admin user to be able to access block admin.
|
||||
$this->admin_user = $this->drupalCreateUser(array(
|
||||
'administer blocks',
|
||||
'access administration pages',
|
||||
'administer news feeds',
|
||||
'access news feeds',
|
||||
));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Prepare to use the block admin form.
|
||||
$block = array(
|
||||
'module' => 'aggregator',
|
||||
'delta' => 'feed-' . $feed->fid,
|
||||
'title' => $feed->title,
|
||||
);
|
||||
$region = 'footer';
|
||||
$edit = array();
|
||||
$edit['blocks[' . $block['module'] . '_' . $block['delta'] . '][region]'] = $region;
|
||||
// Check the feed block is available in the block list form.
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->assertFieldByName('blocks[' . $block['module'] . '_' . $block['delta'] . '][region]', '', 'Aggregator feed block is available for positioning.');
|
||||
// Position it.
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
$this->assertText(t('The block settings have been updated.'), t('Block successfully moved to %region_name region.', array( '%region_name' => $region)));
|
||||
// Confirm that the block is now being displayed on pages.
|
||||
$this->drupalGet('node');
|
||||
$this->assertText(t($block['title']), t('Feed block is displayed on the page.'));
|
||||
|
||||
// Find the expected read_more link.
|
||||
$href = 'aggregator/sources/' . $feed->fid;
|
||||
$links = $this->xpath('//a[@href = :href]', array(':href' => url($href)));
|
||||
$this->assert(isset($links[0]), t('Link to href %href found.', array('%href' => $href)));
|
||||
|
||||
// Visit that page.
|
||||
$this->drupalGet($href);
|
||||
$correct_titles = $this->xpath('//h1[normalize-space(text())=:title]', array(':title' => $feed->title));
|
||||
$this->assertFalse(empty($correct_titles), t('Aggregator feed page is available and has the correct title.'));
|
||||
|
||||
// Set the number of news items to 0 to test that the block does not show
|
||||
// up.
|
||||
$feed->block = 0;
|
||||
aggregator_save_feed((array) $feed);
|
||||
// It is nescessary to flush the cache after saving the number of items.
|
||||
$this->resetAll();
|
||||
// Check that the block is no longer displayed.
|
||||
$this->drupalGet('node');
|
||||
$this->assertNoText(t($block['title']), 'Feed block is not displayed on the page when number of items is set to 0.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feed and check that feed's page.
|
||||
*/
|
||||
public function testFeedPage() {
|
||||
// Increase the number of items published in the rss.xml feed so we have
|
||||
// enough articles to test paging.
|
||||
$config = config('system.rss-publishing');
|
||||
$config->set('feed_default_items', 30);
|
||||
$config->save();
|
||||
|
||||
// Create a feed with 30 items.
|
||||
$this->createSampleNodes(30);
|
||||
$feed = $this->createFeed();
|
||||
$this->updateFeedItems($feed, 30);
|
||||
|
||||
// Check for the presence of a pager.
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$elements = $this->xpath("//ul[@class=:class]", array(':class' => 'pager'));
|
||||
$this->assertTrue(!empty($elements), t('Individual source page contains a pager.'));
|
||||
|
||||
// Reset the number of items in rss.xml to the default value.
|
||||
$config->set('feed_default_items', 10);
|
||||
$config->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for feed parsing.
|
||||
*/
|
||||
class FeedParserTestCase extends AggregatorTestCase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Feed parser functionality',
|
||||
'description' => 'Test the built-in feed parser with valid feed samples.',
|
||||
'group' => 'Aggregator',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
// Do not remove old aggregator items during these tests, since our sample
|
||||
// feeds have hardcoded dates in them (which may be expired when this test
|
||||
// is run).
|
||||
variable_set('aggregator_clear', AGGREGATOR_CLEAR_NEVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a feed that uses the RSS 0.91 format.
|
||||
*/
|
||||
function testRSS091Sample() {
|
||||
$feed = $this->createFeed($this->getRSS091Sample());
|
||||
aggregator_refresh($feed);
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(200, t('Feed %name exists.', array('%name' => $feed->title)));
|
||||
$this->assertText('First example feed item title');
|
||||
$this->assertLinkByHref('http://example.com/example-turns-one');
|
||||
$this->assertText('First example feed item description.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a feed that uses the Atom format.
|
||||
*/
|
||||
function testAtomSample() {
|
||||
$feed = $this->createFeed($this->getAtomSample());
|
||||
aggregator_refresh($feed);
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(200, t('Feed %name exists.', array('%name' => $feed->title)));
|
||||
$this->assertText('Atom-Powered Robots Run Amok');
|
||||
$this->assertLinkByHref('http://example.org/2003/12/13/atom03');
|
||||
$this->assertText('Some text.');
|
||||
$this->assertEqual('urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a', db_query('SELECT guid FROM {aggregator_item} WHERE link = :link', array(':link' => 'http://example.org/2003/12/13/atom03'))->fetchField(), 'Atom entry id element is parsed correctly.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a feed that uses HTML entities in item titles.
|
||||
*/
|
||||
function testHtmlEntitiesSample() {
|
||||
$feed = $this->createFeed($this->getHtmlEntitiesSample());
|
||||
aggregator_refresh($feed);
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(200, t('Feed %name exists.', array('%name' => $feed->title)));
|
||||
$this->assertRaw("Quote" Amp&");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\aggregator\Tests\AddFeedTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
|
||||
/**
|
||||
* Tests aggregator feed adding.
|
||||
*/
|
||||
class AddFeedTest extends AggregatorTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Add feed functionality',
|
||||
'description' => 'Add feed test.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feed, ensure that it is unique, check the source, and delete the feed.
|
||||
*/
|
||||
function testAddFeed() {
|
||||
$feed = $this->createFeed();
|
||||
|
||||
// Check feed data.
|
||||
$this->assertEqual($this->getUrl(), url('admin/config/services/aggregator/add/feed', array('absolute' => TRUE)), t('Directed to correct url.'));
|
||||
$this->assertTrue($this->uniqueFeed($feed->title, $feed->url), t('The feed is unique.'));
|
||||
|
||||
// Check feed source.
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(200, t('Feed source exists.'));
|
||||
$this->assertText($feed->title, t('Page title'));
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid . '/categorize');
|
||||
$this->assertResponse(200, t('Feed categorization page exists.'));
|
||||
|
||||
// Delete feed.
|
||||
$this->deleteFeed($feed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests feeds with very long URLs.
|
||||
*/
|
||||
function testAddLongFeed() {
|
||||
// Create a feed with a URL of > 255 characters.
|
||||
$long_url = "https://www.google.com/search?ix=heb&sourceid=chrome&ie=UTF-8&q=angie+byron#sclient=psy-ab&hl=en&safe=off&source=hp&q=angie+byron&pbx=1&oq=angie+byron&aq=f&aqi=&aql=&gs_sm=3&gs_upl=0l0l0l10534l0l0l0l0l0l0l0l0ll0l0&bav=on.2,or.r_gc.r_pw.r_cp.,cf.osb&fp=a70b6b1f0abe28d8&biw=1629&bih=889&ix=heb";
|
||||
$feed = $this->createFeed($long_url);
|
||||
|
||||
// Create a second feed of > 255 characters, where the only difference is
|
||||
// after the 255th character.
|
||||
$long_url_2 = "https://www.google.com/search?ix=heb&sourceid=chrome&ie=UTF-8&q=angie+byron#sclient=psy-ab&hl=en&safe=off&source=hp&q=angie+byron&pbx=1&oq=angie+byron&aq=f&aqi=&aql=&gs_sm=3&gs_upl=0l0l0l10534l0l0l0l0l0l0l0l0ll0l0&bav=on.2,or.r_gc.r_pw.r_cp.,cf.osb&fp=a70b6b1f0abe28d8&biw=1629&bih=889";
|
||||
$feed_2 = $this->createFeed($long_url_2);
|
||||
|
||||
// Check feed data.
|
||||
$this->assertTrue($this->uniqueFeed($feed->title, $feed->url), 'The first long URL feed is unique.');
|
||||
$this->assertTrue($this->uniqueFeed($feed_2->title, $feed_2->url), 'The second long URL feed is unique.');
|
||||
|
||||
// Check feed source.
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(200, 'Long URL feed source exists.');
|
||||
$this->assertText($feed->title, 'Page title');
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid . '/categorize');
|
||||
$this->assertResponse(200, 'Long URL feed categorization page exists.');
|
||||
|
||||
// Delete feeds.
|
||||
$this->deleteFeed($feed);
|
||||
$this->deleteFeed($feed_2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\aggregator\Tests\AggregatorConfigurationTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
|
||||
/**
|
||||
* Tests aggregator configuration settings.
|
||||
*/
|
||||
class AggregatorConfigurationTest extends AggregatorTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Aggregator configuration',
|
||||
'description' => 'Test aggregator settings page.',
|
||||
'group' => 'Aggregator',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the settings form to ensure the correct default values are used.
|
||||
*/
|
||||
function testSettingsPage() {
|
||||
$edit = array(
|
||||
'aggregator_allowed_html_tags' => '<a>',
|
||||
'aggregator_summary_items' => 10,
|
||||
'aggregator_clear' => 3600,
|
||||
'aggregator_category_selector' => 'select',
|
||||
'aggregator_teaser_length' => 200,
|
||||
);
|
||||
$this->drupalPost('admin/config/services/aggregator/settings', $edit, t('Save configuration'));
|
||||
$this->assertText(t('The configuration options have been saved.'));
|
||||
|
||||
foreach ($edit as $name => $value) {
|
||||
$this->assertFieldByName($name, $value, t('"@name" has correct default value.', array('@name' => $name)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\aggregator\Tests\AggregatorCronTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
|
||||
class AggregatorCronTest extends AggregatorTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Update on cron functionality',
|
||||
'description' => 'Update feeds on cron.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add feeds update them on cron.
|
||||
*/
|
||||
public function testCron() {
|
||||
// Create feed and test basic updating on cron.
|
||||
global $base_url;
|
||||
$key = config('system.cron')->get('cron_key');
|
||||
$this->createSampleNodes();
|
||||
$feed = $this->createFeed();
|
||||
$this->cronRun();
|
||||
$this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
|
||||
$this->removeFeedItems($feed);
|
||||
$this->assertEqual(0, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
|
||||
$this->cronRun();
|
||||
$this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
|
||||
|
||||
// Test feed locking when queued for update.
|
||||
$this->removeFeedItems($feed);
|
||||
db_update('aggregator_feed')
|
||||
->condition('fid', $feed->fid)
|
||||
->fields(array(
|
||||
'queued' => REQUEST_TIME,
|
||||
))
|
||||
->execute();
|
||||
$this->cronRun();
|
||||
$this->assertEqual(0, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
|
||||
db_update('aggregator_feed')
|
||||
->condition('fid', $feed->fid)
|
||||
->fields(array(
|
||||
'queued' => 0,
|
||||
))
|
||||
->execute();
|
||||
$this->cronRun();
|
||||
$this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\aggregator\Tests\AggregatorRenderingTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
|
||||
class AggregatorRenderingTest extends AggregatorTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Checks display of aggregator items',
|
||||
'description' => 'Checks display of aggregator items on the page.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a feed block to the page and checks its links.
|
||||
*
|
||||
* TODO: Test the category block as well.
|
||||
*/
|
||||
public function testBlockLinks() {
|
||||
// Create feed.
|
||||
$this->createSampleNodes();
|
||||
$feed = $this->createFeed();
|
||||
$this->updateFeedItems($feed, $this->getDefaultFeedItemCount());
|
||||
|
||||
// Place block on page (@see block.test:moveBlockToRegion())
|
||||
// Need admin user to be able to access block admin.
|
||||
$this->admin_user = $this->drupalCreateUser(array(
|
||||
'administer blocks',
|
||||
'access administration pages',
|
||||
'administer news feeds',
|
||||
'access news feeds',
|
||||
));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Prepare to use the block admin form.
|
||||
$block = array(
|
||||
'module' => 'aggregator',
|
||||
'delta' => 'feed-' . $feed->fid,
|
||||
'title' => $feed->title,
|
||||
);
|
||||
$region = 'footer';
|
||||
$edit = array();
|
||||
$edit['blocks[' . $block['module'] . '_' . $block['delta'] . '][region]'] = $region;
|
||||
// Check the feed block is available in the block list form.
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->assertFieldByName('blocks[' . $block['module'] . '_' . $block['delta'] . '][region]', '', 'Aggregator feed block is available for positioning.');
|
||||
// Position it.
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
$this->assertText(t('The block settings have been updated.'), t('Block successfully moved to %region_name region.', array( '%region_name' => $region)));
|
||||
// Confirm that the block is now being displayed on pages.
|
||||
$this->drupalGet('node');
|
||||
$this->assertText(t($block['title']), t('Feed block is displayed on the page.'));
|
||||
|
||||
// Find the expected read_more link.
|
||||
$href = 'aggregator/sources/' . $feed->fid;
|
||||
$links = $this->xpath('//a[@href = :href]', array(':href' => url($href)));
|
||||
$this->assert(isset($links[0]), t('Link to href %href found.', array('%href' => $href)));
|
||||
|
||||
// Visit that page.
|
||||
$this->drupalGet($href);
|
||||
$correct_titles = $this->xpath('//h1[normalize-space(text())=:title]', array(':title' => $feed->title));
|
||||
$this->assertFalse(empty($correct_titles), t('Aggregator feed page is available and has the correct title.'));
|
||||
|
||||
// Set the number of news items to 0 to test that the block does not show
|
||||
// up.
|
||||
$feed->block = 0;
|
||||
aggregator_save_feed((array) $feed);
|
||||
// It is nescessary to flush the cache after saving the number of items.
|
||||
$this->resetAll();
|
||||
// Check that the block is no longer displayed.
|
||||
$this->drupalGet('node');
|
||||
$this->assertNoText(t($block['title']), 'Feed block is not displayed on the page when number of items is set to 0.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feed and check that feed's page.
|
||||
*/
|
||||
public function testFeedPage() {
|
||||
// Increase the number of items published in the rss.xml feed so we have
|
||||
// enough articles to test paging.
|
||||
$config = config('system.rss-publishing');
|
||||
$config->set('feed_default_items', 30);
|
||||
$config->save();
|
||||
|
||||
// Create a feed with 30 items.
|
||||
$this->createSampleNodes(30);
|
||||
$feed = $this->createFeed();
|
||||
$this->updateFeedItems($feed, 30);
|
||||
|
||||
// Check for the presence of a pager.
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$elements = $this->xpath("//ul[@class=:class]", array(':class' => 'pager'));
|
||||
$this->assertTrue(!empty($elements), t('Individual source page contains a pager.'));
|
||||
|
||||
// Reset the number of items in rss.xml to the default value.
|
||||
$config->set('feed_default_items', 10);
|
||||
$config->save();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,307 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\aggregator\Tests\AggregatorTestBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Defines a base class for testing aggregator.module.
|
||||
*/
|
||||
class AggregatorTestBase extends WebTestBase {
|
||||
function setUp() {
|
||||
parent::setUp(array('node', 'block', 'aggregator', 'aggregator_test'));
|
||||
|
||||
// Create an Article node type.
|
||||
if ($this->profile != 'standard') {
|
||||
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
|
||||
}
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('administer news feeds', 'access news feeds', 'create article content'));
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aggregator feed (simulate form submission on admin/config/services/aggregator/add/feed).
|
||||
*
|
||||
* @param $feed_url
|
||||
* If given, feed will be created with this URL, otherwise /rss.xml will be used.
|
||||
* @return $feed
|
||||
* Full feed object if possible.
|
||||
*
|
||||
* @see getFeedEditArray()
|
||||
*/
|
||||
function createFeed($feed_url = NULL) {
|
||||
$edit = $this->getFeedEditArray($feed_url);
|
||||
$this->drupalPost('admin/config/services/aggregator/add/feed', $edit, t('Save'));
|
||||
$this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title'])), t('The feed !name has been added.', array('!name' => $edit['title'])));
|
||||
|
||||
$feed = db_query("SELECT * FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $edit['title'], ':url' => $edit['url']))->fetch();
|
||||
$this->assertTrue(!empty($feed), t('The feed found in database.'));
|
||||
return $feed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an aggregator feed.
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
*/
|
||||
function deleteFeed($feed) {
|
||||
$this->drupalPost('admin/config/services/aggregator/edit/feed/' . $feed->fid, array(), t('Delete'));
|
||||
$this->assertRaw(t('The feed %title has been deleted.', array('%title' => $feed->title)), t('Feed deleted successfully.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a randomly generated feed edit array.
|
||||
*
|
||||
* @param $feed_url
|
||||
* If given, feed will be created with this URL, otherwise /rss.xml will be used.
|
||||
* @return
|
||||
* A feed array.
|
||||
*/
|
||||
function getFeedEditArray($feed_url = NULL) {
|
||||
$feed_name = $this->randomName(10);
|
||||
if (!$feed_url) {
|
||||
$feed_url = url('rss.xml', array(
|
||||
'query' => array('feed' => $feed_name),
|
||||
'absolute' => TRUE,
|
||||
));
|
||||
}
|
||||
$edit = array(
|
||||
'title' => $feed_name,
|
||||
'url' => $feed_url,
|
||||
'refresh' => '900',
|
||||
);
|
||||
return $edit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of the randomly created feed array.
|
||||
*
|
||||
* @return
|
||||
* Number of feed items on default feed created by createFeed().
|
||||
*/
|
||||
function getDefaultFeedItemCount() {
|
||||
// Our tests are based off of rss.xml, so let's find out how many elements should be related.
|
||||
$feed_count = db_query_range('SELECT COUNT(*) FROM {node} n WHERE n.promote = 1 AND n.status = 1', 0, config('system.rss-publishing')->get('feed_default_items'))->fetchField();
|
||||
return $feed_count > 10 ? 10 : $feed_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update feed items (simulate click to admin/config/services/aggregator/update/$fid).
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
* @param $expected_count
|
||||
* Expected number of feed items.
|
||||
*/
|
||||
function updateFeedItems(&$feed, $expected_count) {
|
||||
// First, let's ensure we can get to the rss xml.
|
||||
$this->drupalGet($feed->url);
|
||||
$this->assertResponse(200, t('!url is reachable.', array('!url' => $feed->url)));
|
||||
|
||||
// Attempt to access the update link directly without an access token.
|
||||
$this->drupalGet('admin/config/services/aggregator/update/' . $feed->fid);
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Refresh the feed (simulated link click).
|
||||
$this->drupalGet('admin/config/services/aggregator');
|
||||
$this->clickLink('update items');
|
||||
|
||||
// Ensure we have the right number of items.
|
||||
$result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid));
|
||||
$items = array();
|
||||
$feed->items = array();
|
||||
foreach ($result as $item) {
|
||||
$feed->items[] = $item->iid;
|
||||
}
|
||||
$feed->item_count = count($feed->items);
|
||||
$this->assertEqual($expected_count, $feed->item_count, t('Total items in feed equal to the total items in database (!val1 != !val2)', array('!val1' => $expected_count, '!val2' => $feed->item_count)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm item removal from a feed.
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
*/
|
||||
function removeFeedItems($feed) {
|
||||
$this->drupalPost('admin/config/services/aggregator/remove/' . $feed->fid, array(), t('Remove items'));
|
||||
$this->assertRaw(t('The news items from %title have been removed.', array('%title' => $feed->title)), t('Feed items removed.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add and remove feed items and ensure that the count is zero.
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
* @param $expected_count
|
||||
* Expected number of feed items.
|
||||
*/
|
||||
function updateAndRemove($feed, $expected_count) {
|
||||
$this->updateFeedItems($feed, $expected_count);
|
||||
$count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
|
||||
$this->assertTrue($count);
|
||||
$this->removeFeedItems($feed);
|
||||
$count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
|
||||
$this->assertTrue($count == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull feed categories from aggregator_category_feed table.
|
||||
*
|
||||
* @param $feed
|
||||
* Feed object representing the feed.
|
||||
*/
|
||||
function getFeedCategories($feed) {
|
||||
// add the categories to the feed so we can use them
|
||||
$result = db_query('SELECT cid FROM {aggregator_category_feed} WHERE fid = :fid', array(':fid' => $feed->fid));
|
||||
foreach ($result as $category) {
|
||||
$feed->categories[] = $category->cid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull categories from aggregator_category table.
|
||||
*/
|
||||
function getCategories() {
|
||||
$categories = array();
|
||||
$result = db_query('SELECT * FROM {aggregator_category}');
|
||||
foreach ($result as $category) {
|
||||
$categories[$category->cid] = $category;
|
||||
}
|
||||
return $categories;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the feed name and url is unique.
|
||||
*
|
||||
* @param $feed_name
|
||||
* String containing the feed name to check.
|
||||
* @param $feed_url
|
||||
* String containing the feed url to check.
|
||||
* @return
|
||||
* TRUE if feed is unique.
|
||||
*/
|
||||
function uniqueFeed($feed_name, $feed_url) {
|
||||
$result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed_name, ':url' => $feed_url))->fetchField();
|
||||
return (1 == $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a valid OPML file from an array of feeds.
|
||||
*
|
||||
* @param $feeds
|
||||
* An array of feeds.
|
||||
* @return
|
||||
* Path to valid OPML file.
|
||||
*/
|
||||
function getValidOpml($feeds) {
|
||||
// Properly escape URLs so that XML parsers don't choke on them.
|
||||
foreach ($feeds as &$feed) {
|
||||
$feed['url'] = htmlspecialchars($feed['url']);
|
||||
}
|
||||
/**
|
||||
* Does not have an XML declaration, must pass the parser.
|
||||
*/
|
||||
$opml = <<<EOF
|
||||
<opml version="1.0">
|
||||
<head></head>
|
||||
<body>
|
||||
<!-- First feed to be imported. -->
|
||||
<outline text="{$feeds[0]['title']}" xmlurl="{$feeds[0]['url']}" />
|
||||
|
||||
<!-- Second feed. Test string delimitation and attribute order. -->
|
||||
<outline xmlurl='{$feeds[1]['url']}' text='{$feeds[1]['title']}'/>
|
||||
|
||||
<!-- Test for duplicate URL and title. -->
|
||||
<outline xmlurl="{$feeds[0]['url']}" text="Duplicate URL"/>
|
||||
<outline xmlurl="http://duplicate.title" text="{$feeds[1]['title']}"/>
|
||||
|
||||
<!-- Test that feeds are only added with required attributes. -->
|
||||
<outline text="{$feeds[2]['title']}" />
|
||||
<outline xmlurl="{$feeds[2]['url']}" />
|
||||
</body>
|
||||
</opml>
|
||||
EOF;
|
||||
|
||||
$path = 'public://valid-opml.xml';
|
||||
return file_unmanaged_save_data($opml, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an invalid OPML file.
|
||||
*
|
||||
* @return
|
||||
* Path to invalid OPML file.
|
||||
*/
|
||||
function getInvalidOpml() {
|
||||
$opml = <<<EOF
|
||||
<opml>
|
||||
<invalid>
|
||||
</opml>
|
||||
EOF;
|
||||
|
||||
$path = 'public://invalid-opml.xml';
|
||||
return file_unmanaged_save_data($opml, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a valid but empty OPML file.
|
||||
*
|
||||
* @return
|
||||
* Path to empty OPML file.
|
||||
*/
|
||||
function getEmptyOpml() {
|
||||
$opml = <<<EOF
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<opml version="1.0">
|
||||
<head></head>
|
||||
<body>
|
||||
<outline text="Sample text" />
|
||||
<outline text="Sample text" url="Sample URL" />
|
||||
</body>
|
||||
</opml>
|
||||
EOF;
|
||||
|
||||
$path = 'public://empty-opml.xml';
|
||||
return file_unmanaged_save_data($opml, $path);
|
||||
}
|
||||
|
||||
function getRSS091Sample() {
|
||||
return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_rss091.xml';
|
||||
}
|
||||
|
||||
function getAtomSample() {
|
||||
// The content of this sample ATOM feed is based directly off of the
|
||||
// example provided in RFC 4287.
|
||||
return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_atom.xml';
|
||||
}
|
||||
|
||||
function getHtmlEntitiesSample() {
|
||||
return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_title_entities.xml';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates sample article nodes.
|
||||
*
|
||||
* @param $count
|
||||
* (optional) The number of nodes to generate.
|
||||
*/
|
||||
function createSampleNodes($count = 5) {
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
// Post $count article nodes.
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName();
|
||||
$edit["body[$langcode][0][value]"] = $this->randomName();
|
||||
$this->drupalPost('node/add/article', $edit, t('Save'));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\aggregator\Tests\CategorizeFeedItemTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
|
||||
class CategorizeFeedItemTest extends AggregatorTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Categorize feed item functionality',
|
||||
'description' => 'Test feed item categorization.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a feed has a category, make sure that the children inherit that
|
||||
* categorization.
|
||||
*/
|
||||
function testCategorizeFeedItem() {
|
||||
$this->createSampleNodes();
|
||||
|
||||
// Simulate form submission on "admin/config/services/aggregator/add/category".
|
||||
$edit = array('title' => $this->randomName(10), 'description' => '');
|
||||
$this->drupalPost('admin/config/services/aggregator/add/category', $edit, t('Save'));
|
||||
$this->assertRaw(t('The category %title has been added.', array('%title' => $edit['title'])), t('The category %title has been added.', array('%title' => $edit['title'])));
|
||||
|
||||
$category = db_query("SELECT * FROM {aggregator_category} WHERE title = :title", array(':title' => $edit['title']))->fetch();
|
||||
$this->assertTrue(!empty($category), t('The category found in database.'));
|
||||
|
||||
$link_path = 'aggregator/categories/' . $category->cid;
|
||||
$menu_link = db_query("SELECT * FROM {menu_links} WHERE link_path = :link_path", array(':link_path' => $link_path))->fetch();
|
||||
$this->assertTrue(!empty($menu_link), t('The menu link associated with the category found in database.'));
|
||||
|
||||
$feed = $this->createFeed();
|
||||
db_insert('aggregator_category_feed')
|
||||
->fields(array(
|
||||
'cid' => $category->cid,
|
||||
'fid' => $feed->fid,
|
||||
))
|
||||
->execute();
|
||||
$this->updateFeedItems($feed, $this->getDefaultFeedItemCount());
|
||||
$this->getFeedCategories($feed);
|
||||
$this->assertTrue(!empty($feed->categories), t('The category found in the feed.'));
|
||||
|
||||
// For each category of a feed, ensure feed items have that category, too.
|
||||
if (!empty($feed->categories) && !empty($feed->items)) {
|
||||
foreach ($feed->categories as $category) {
|
||||
$categorized_count = db_select('aggregator_category_item')
|
||||
->condition('iid', $feed->items, 'IN')
|
||||
->countQuery()
|
||||
->execute()
|
||||
->fetchField();
|
||||
|
||||
$this->assertEqual($feed->item_count, $categorized_count, t('Total items in feed equal to the total categorized feed items in database'));
|
||||
}
|
||||
}
|
||||
|
||||
// Delete feed.
|
||||
$this->deleteFeed($feed);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\aggregator\Tests\CategorizeFeedTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
|
||||
class CategorizeFeedTest extends AggregatorTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Categorize feed functionality',
|
||||
'description' => 'Categorize feed test.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feed and make sure you can add more than one category to it.
|
||||
*/
|
||||
function testCategorizeFeed() {
|
||||
|
||||
// Create 2 categories.
|
||||
$category_1 = array('title' => $this->randomName(10), 'description' => '');
|
||||
$this->drupalPost('admin/config/services/aggregator/add/category', $category_1, t('Save'));
|
||||
$this->assertRaw(t('The category %title has been added.', array('%title' => $category_1['title'])), t('The category %title has been added.', array('%title' => $category_1['title'])));
|
||||
|
||||
$category_2 = array('title' => $this->randomName(10), 'description' => '');
|
||||
$this->drupalPost('admin/config/services/aggregator/add/category', $category_2, t('Save'));
|
||||
$this->assertRaw(t('The category %title has been added.', array('%title' => $category_2['title'])), t('The category %title has been added.', array('%title' => $category_2['title'])));
|
||||
|
||||
// Get categories from database.
|
||||
$categories = $this->getCategories();
|
||||
|
||||
// Create a feed and assign 2 categories to it.
|
||||
$feed = $this->getFeedEditArray();
|
||||
$feed['block'] = 5;
|
||||
foreach ($categories as $cid => $category) {
|
||||
$feed['category'][$cid] = $cid;
|
||||
}
|
||||
|
||||
// Use aggregator_save_feed() function to save the feed.
|
||||
aggregator_save_feed($feed);
|
||||
$db_feed = db_query("SELECT * FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed['title'], ':url' => $feed['url']))->fetch();
|
||||
|
||||
// Assert the feed has two categories.
|
||||
$this->getFeedCategories($db_feed);
|
||||
$this->assertEqual(count($db_feed->categories), 2, t('Feed has 2 categories'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\aggregator\Tests\FeedParserTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
|
||||
/**
|
||||
* Tests for feed parsing.
|
||||
*/
|
||||
class FeedParserTest extends AggregatorTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Feed parser functionality',
|
||||
'description' => 'Test the built-in feed parser with valid feed samples.',
|
||||
'group' => 'Aggregator',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
// Do not remove old aggregator items during these tests, since our sample
|
||||
// feeds have hardcoded dates in them (which may be expired when this test
|
||||
// is run).
|
||||
variable_set('aggregator_clear', AGGREGATOR_CLEAR_NEVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a feed that uses the RSS 0.91 format.
|
||||
*/
|
||||
function testRSS091Sample() {
|
||||
$feed = $this->createFeed($this->getRSS091Sample());
|
||||
aggregator_refresh($feed);
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(200, t('Feed %name exists.', array('%name' => $feed->title)));
|
||||
$this->assertText('First example feed item title');
|
||||
$this->assertLinkByHref('http://example.com/example-turns-one');
|
||||
$this->assertText('First example feed item description.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a feed that uses the Atom format.
|
||||
*/
|
||||
function testAtomSample() {
|
||||
$feed = $this->createFeed($this->getAtomSample());
|
||||
aggregator_refresh($feed);
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(200, t('Feed %name exists.', array('%name' => $feed->title)));
|
||||
$this->assertText('Atom-Powered Robots Run Amok');
|
||||
$this->assertLinkByHref('http://example.org/2003/12/13/atom03');
|
||||
$this->assertText('Some text.');
|
||||
$this->assertEqual('urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a', db_query('SELECT guid FROM {aggregator_item} WHERE link = :link', array(':link' => 'http://example.org/2003/12/13/atom03'))->fetchField(), 'Atom entry id element is parsed correctly.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a feed that uses HTML entities in item titles.
|
||||
*/
|
||||
function testHtmlEntitiesSample() {
|
||||
$feed = $this->createFeed($this->getHtmlEntitiesSample());
|
||||
aggregator_refresh($feed);
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(200, t('Feed %name exists.', array('%name' => $feed->title)));
|
||||
$this->assertRaw("Quote" Amp&");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\aggregator\Tests\ImportOpmlTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
|
||||
class ImportOpmlTest extends AggregatorTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Import feeds from OPML functionality',
|
||||
'description' => 'Test OPML import.',
|
||||
'group' => 'Aggregator',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open OPML import form.
|
||||
*/
|
||||
function openImportForm() {
|
||||
db_delete('aggregator_category')->execute();
|
||||
|
||||
$category = $this->randomName(10);
|
||||
$cid = db_insert('aggregator_category')
|
||||
->fields(array(
|
||||
'title' => $category,
|
||||
'description' => '',
|
||||
))
|
||||
->execute();
|
||||
|
||||
$this->drupalGet('admin/config/services/aggregator/add/opml');
|
||||
$this->assertText('A single OPML document may contain a collection of many feeds.', t('Found OPML help text.'));
|
||||
$this->assertField('files[upload]', t('Found file upload field.'));
|
||||
$this->assertField('remote', t('Found Remote URL field.'));
|
||||
$this->assertField('refresh', '', t('Found Refresh field.'));
|
||||
$this->assertFieldByName("category[$cid]", $cid, t('Found category field.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit form filled with invalid fields.
|
||||
*/
|
||||
function validateImportFormFields() {
|
||||
$before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
|
||||
|
||||
$edit = array();
|
||||
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
|
||||
$this->assertRaw(t('You must <em>either</em> upload a file or enter a URL.'), t('Error if no fields are filled.'));
|
||||
|
||||
$path = $this->getEmptyOpml();
|
||||
$edit = array(
|
||||
'files[upload]' => $path,
|
||||
'remote' => file_create_url($path),
|
||||
);
|
||||
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
|
||||
$this->assertRaw(t('You must <em>either</em> upload a file or enter a URL.'), t('Error if both fields are filled.'));
|
||||
|
||||
$edit = array('remote' => 'invalidUrl://empty');
|
||||
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
|
||||
$this->assertText(t('The URL invalidUrl://empty is not valid.'), 'Error if the URL is invalid.');
|
||||
|
||||
$after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
|
||||
$this->assertEqual($before, $after, t('No feeds were added during the three last form submissions.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit form with invalid, empty and valid OPML files.
|
||||
*/
|
||||
function submitImportForm() {
|
||||
$before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
|
||||
|
||||
$form['files[upload]'] = $this->getInvalidOpml();
|
||||
$this->drupalPost('admin/config/services/aggregator/add/opml', $form, t('Import'));
|
||||
$this->assertText(t('No new feed has been added.'), t('Attempting to upload invalid XML.'));
|
||||
|
||||
$edit = array('remote' => file_create_url($this->getEmptyOpml()));
|
||||
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
|
||||
$this->assertText(t('No new feed has been added.'), t('Attempting to load empty OPML from remote URL.'));
|
||||
|
||||
$after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
|
||||
$this->assertEqual($before, $after, t('No feeds were added during the two last form submissions.'));
|
||||
|
||||
db_delete('aggregator_feed')->execute();
|
||||
db_delete('aggregator_category')->execute();
|
||||
db_delete('aggregator_category_feed')->execute();
|
||||
|
||||
$category = $this->randomName(10);
|
||||
db_insert('aggregator_category')
|
||||
->fields(array(
|
||||
'cid' => 1,
|
||||
'title' => $category,
|
||||
'description' => '',
|
||||
))
|
||||
->execute();
|
||||
|
||||
$feeds[0] = $this->getFeedEditArray();
|
||||
$feeds[1] = $this->getFeedEditArray();
|
||||
$feeds[2] = $this->getFeedEditArray();
|
||||
$edit = array(
|
||||
'files[upload]' => $this->getValidOpml($feeds),
|
||||
'refresh' => '900',
|
||||
'category[1]' => $category,
|
||||
);
|
||||
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
|
||||
$this->assertRaw(t('A feed with the URL %url already exists.', array('%url' => $feeds[0]['url'])), t('Verifying that a duplicate URL was identified'));
|
||||
$this->assertRaw(t('A feed named %title already exists.', array('%title' => $feeds[1]['title'])), t('Verifying that a duplicate title was identified'));
|
||||
|
||||
$after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
|
||||
$this->assertEqual($after, 2, t('Verifying that two distinct feeds were added.'));
|
||||
|
||||
$feeds_from_db = db_query("SELECT f.title, f.url, f.refresh, cf.cid FROM {aggregator_feed} f LEFT JOIN {aggregator_category_feed} cf ON f.fid = cf.fid");
|
||||
$refresh = $category = TRUE;
|
||||
foreach ($feeds_from_db as $feed) {
|
||||
$title[$feed->url] = $feed->title;
|
||||
$url[$feed->title] = $feed->url;
|
||||
$category = $category && $feed->cid == 1;
|
||||
$refresh = $refresh && $feed->refresh == 900;
|
||||
}
|
||||
|
||||
$this->assertEqual($title[$feeds[0]['url']], $feeds[0]['title'], t('First feed was added correctly.'));
|
||||
$this->assertEqual($url[$feeds[1]['title']], $feeds[1]['url'], t('Second feed was added correctly.'));
|
||||
$this->assertTrue($refresh, t('Refresh times are correct.'));
|
||||
$this->assertTrue($category, t('Categories are correct.'));
|
||||
}
|
||||
|
||||
function testOpmlImport() {
|
||||
$this->openImportForm();
|
||||
$this->validateImportFormFields();
|
||||
$this->submitImportForm();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\aggregator\Tests\RemoveFeedItemTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
|
||||
class RemoveFeedItemTest extends AggregatorTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Remove feed item functionality',
|
||||
'description' => 'Remove feed items from a feed.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test running "remove items" from the 'admin/config/services/aggregator' page.
|
||||
*/
|
||||
function testRemoveFeedItem() {
|
||||
// Create a bunch of test feeds.
|
||||
$feed_urls = array();
|
||||
// No last-modified, no etag.
|
||||
$feed_urls[] = url('aggregator/test-feed', array('absolute' => TRUE));
|
||||
// Last-modified, but no etag.
|
||||
$feed_urls[] = url('aggregator/test-feed/1', array('absolute' => TRUE));
|
||||
// No Last-modified, but etag.
|
||||
$feed_urls[] = url('aggregator/test-feed/0/1', array('absolute' => TRUE));
|
||||
// Last-modified and etag.
|
||||
$feed_urls[] = url('aggregator/test-feed/1/1', array('absolute' => TRUE));
|
||||
|
||||
foreach ($feed_urls as $feed_url) {
|
||||
$feed = $this->createFeed($feed_url);
|
||||
// Update and remove items two times in a row to make sure that removal
|
||||
// resets all 'modified' information (modified, etag, hash) and allows for
|
||||
// immediate update.
|
||||
$this->updateAndRemove($feed, 2);
|
||||
$this->updateAndRemove($feed, 2);
|
||||
$this->updateAndRemove($feed, 2);
|
||||
// Delete feed.
|
||||
$this->deleteFeed($feed);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\aggregator\Tests\RemoveFeedTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
|
||||
class RemoveFeedTest extends AggregatorTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Remove feed functionality',
|
||||
'description' => 'Remove feed test.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a feed and ensure that all it services are removed.
|
||||
*/
|
||||
function testRemoveFeed() {
|
||||
$feed = $this->createFeed();
|
||||
|
||||
// Delete feed.
|
||||
$this->deleteFeed($feed);
|
||||
|
||||
// Check feed source.
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(404, t('Deleted feed source does not exists.'));
|
||||
|
||||
// Check database for feed.
|
||||
$result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed->title, ':url' => $feed->url))->fetchField();
|
||||
$this->assertFalse($result, t('Feed not found in database'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\aggregator\Tests\UpdateFeedItemTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
|
||||
class UpdateFeedItemTest extends AggregatorTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Update feed item functionality',
|
||||
'description' => 'Update feed items from a feed.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test running "update items" from the 'admin/config/services/aggregator' page.
|
||||
*/
|
||||
function testUpdateFeedItem() {
|
||||
$this->createSampleNodes();
|
||||
|
||||
// Create a feed and test updating feed items if possible.
|
||||
$feed = $this->createFeed();
|
||||
if (!empty($feed)) {
|
||||
$this->updateFeedItems($feed, $this->getDefaultFeedItemCount());
|
||||
$this->removeFeedItems($feed);
|
||||
}
|
||||
|
||||
// Delete feed.
|
||||
$this->deleteFeed($feed);
|
||||
|
||||
// Test updating feed items without valid timestamp information.
|
||||
$edit = array(
|
||||
'title' => "Feed without publish timestamp",
|
||||
'url' => $this->getRSS091Sample(),
|
||||
);
|
||||
|
||||
$this->drupalGet($edit['url']);
|
||||
$this->assertResponse(array(200), t('URL !url is accessible', array('!url' => $edit['url'])));
|
||||
|
||||
$this->drupalPost('admin/config/services/aggregator/add/feed', $edit, t('Save'));
|
||||
$this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title'])), t('The feed !name has been added.', array('!name' => $edit['title'])));
|
||||
|
||||
$feed = db_query("SELECT * FROM {aggregator_feed} WHERE url = :url", array(':url' => $edit['url']))->fetchObject();
|
||||
|
||||
aggregator_refresh($feed);
|
||||
$before = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
|
||||
|
||||
// Sleep for 3 second.
|
||||
sleep(3);
|
||||
db_update('aggregator_feed')
|
||||
->condition('fid', $feed->fid)
|
||||
->fields(array(
|
||||
'checked' => 0,
|
||||
'hash' => '',
|
||||
'etag' => '',
|
||||
'modified' => 0,
|
||||
))
|
||||
->execute();
|
||||
aggregator_refresh($feed);
|
||||
|
||||
$after = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
|
||||
$this->assertTrue($before === $after, t('Publish timestamp of feed item was not updated (!before === !after)', array('!before' => $before, '!after' => $after)));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\aggregator\Tests\UpdateFeedTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\aggregator\Tests;
|
||||
|
||||
class UpdateFeedTest extends AggregatorTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Update feed functionality',
|
||||
'description' => 'Update feed test.',
|
||||
'group' => 'Aggregator'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feed and attempt to update it.
|
||||
*/
|
||||
function testUpdateFeed() {
|
||||
$remamining_fields = array('title', 'url', '');
|
||||
foreach ($remamining_fields as $same_field) {
|
||||
$feed = $this->createFeed();
|
||||
|
||||
// Get new feed data array and modify newly created feed.
|
||||
$edit = $this->getFeedEditArray();
|
||||
$edit['refresh'] = 1800; // Change refresh value.
|
||||
if (isset($feed->{$same_field})) {
|
||||
$edit[$same_field] = $feed->{$same_field};
|
||||
}
|
||||
$this->drupalPost('admin/config/services/aggregator/edit/feed/' . $feed->fid, $edit, t('Save'));
|
||||
$this->assertRaw(t('The feed %name has been updated.', array('%name' => $edit['title'])), t('The feed %name has been updated.', array('%name' => $edit['title'])));
|
||||
|
||||
// Check feed data.
|
||||
$this->assertEqual($this->getUrl(), url('admin/config/services/aggregator/', array('absolute' => TRUE)));
|
||||
$this->assertTrue($this->uniqueFeed($edit['title'], $edit['url']), t('The feed is unique.'));
|
||||
|
||||
// Check feed source.
|
||||
$this->drupalGet('aggregator/sources/' . $feed->fid);
|
||||
$this->assertResponse(200, t('Feed source exists.'));
|
||||
$this->assertText($edit['title'], t('Page title'));
|
||||
|
||||
// Delete feed.
|
||||
$feed->title = $edit['title']; // Set correct title so deleteFeed() will work.
|
||||
$this->deleteFeed($feed);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,5 +3,4 @@ description = Controls the visual building blocks a page is constructed with. Bl
|
|||
package = Core
|
||||
version = VERSION
|
||||
core = 8.x
|
||||
files[] = block.test
|
||||
configure = admin/structure/block
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\block\Tests\BlockAdminThemeTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Test the block system with admin themes.
|
||||
*/
|
||||
class BlockAdminThemeTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Admin theme block admin accessibility',
|
||||
'description' => "Check whether the block administer page for a disabled theme accessible if and only if it's the admin theme.",
|
||||
'group' => 'Block',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('block'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for the accessibility of the admin theme on the block admin page.
|
||||
*/
|
||||
function testAdminTheme() {
|
||||
// Create administrative user.
|
||||
$admin_user = $this->drupalCreateUser(array('administer blocks', 'administer themes'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Ensure that access to block admin page is denied when theme is disabled.
|
||||
$this->drupalGet('admin/structure/block/list/bartik');
|
||||
$this->assertResponse(403, t('The block admin page for a disabled theme can not be accessed'));
|
||||
|
||||
// Enable admin theme and confirm that tab is accessible.
|
||||
$edit['admin_theme'] = 'bartik';
|
||||
$this->drupalPost('admin/appearance', $edit, t('Save configuration'));
|
||||
$this->drupalGet('admin/structure/block/list/bartik');
|
||||
$this->assertResponse(200, t('The block admin page for the admin theme can be accessed'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\block\Tests\BlockCacheTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Test block caching.
|
||||
*/
|
||||
class BlockCacheTest extends WebTestBase {
|
||||
protected $admin_user;
|
||||
protected $normal_user;
|
||||
protected $normal_user_alt;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Block caching',
|
||||
'description' => 'Test block caching.',
|
||||
'group' => 'Block',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('block', 'block_test'));
|
||||
|
||||
// Create an admin user, log in and enable test blocks.
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer blocks', 'access administration pages'));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Create additional users to test caching modes.
|
||||
$this->normal_user = $this->drupalCreateUser();
|
||||
$this->normal_user_alt = $this->drupalCreateUser();
|
||||
// Sync the roles, since drupalCreateUser() creates separate roles for
|
||||
// the same permission sets.
|
||||
$this->normal_user_alt->roles = $this->normal_user->roles;
|
||||
$this->normal_user_alt->save();
|
||||
|
||||
// Enable our test block.
|
||||
$edit['blocks[block_test_test_cache][region]'] = 'sidebar_first';
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test DRUPAL_CACHE_PER_ROLE.
|
||||
*/
|
||||
function testCachePerRole() {
|
||||
$this->setCacheMode(DRUPAL_CACHE_PER_ROLE);
|
||||
|
||||
// Enable our test block. Set some content for it to display.
|
||||
$current_content = $this->randomName();
|
||||
variable_set('block_test_content', $current_content);
|
||||
$this->drupalLogin($this->normal_user);
|
||||
$this->drupalGet('');
|
||||
$this->assertText($current_content, t('Block content displays.'));
|
||||
|
||||
// Change the content, but the cached copy should still be served.
|
||||
$old_content = $current_content;
|
||||
$current_content = $this->randomName();
|
||||
variable_set('block_test_content', $current_content);
|
||||
$this->drupalGet('');
|
||||
$this->assertText($old_content, t('Block is served from the cache.'));
|
||||
|
||||
// Clear the cache and verify that the stale data is no longer there.
|
||||
cache_clear_all();
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText($old_content, t('Block cache clear removes stale cache data.'));
|
||||
$this->assertText($current_content, t('Fresh block content is displayed after clearing the cache.'));
|
||||
|
||||
// Test whether the cached data is served for the correct users.
|
||||
$old_content = $current_content;
|
||||
$current_content = $this->randomName();
|
||||
variable_set('block_test_content', $current_content);
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText($old_content, t('Anonymous user does not see content cached per-role for normal user.'));
|
||||
|
||||
$this->drupalLogin($this->normal_user_alt);
|
||||
$this->drupalGet('');
|
||||
$this->assertText($old_content, t('User with the same roles sees per-role cached content.'));
|
||||
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText($old_content, t('Admin user does not see content cached per-role for normal user.'));
|
||||
|
||||
$this->drupalLogin($this->normal_user);
|
||||
$this->drupalGet('');
|
||||
$this->assertText($old_content, t('Block is served from the per-role cache.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test DRUPAL_CACHE_GLOBAL.
|
||||
*/
|
||||
function testCacheGlobal() {
|
||||
$this->setCacheMode(DRUPAL_CACHE_GLOBAL);
|
||||
$current_content = $this->randomName();
|
||||
variable_set('block_test_content', $current_content);
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->assertText($current_content, t('Block content displays.'));
|
||||
|
||||
$old_content = $current_content;
|
||||
$current_content = $this->randomName();
|
||||
variable_set('block_test_content', $current_content);
|
||||
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('user');
|
||||
$this->assertText($old_content, t('Block content served from global cache.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test DRUPAL_NO_CACHE.
|
||||
*/
|
||||
function testNoCache() {
|
||||
$this->setCacheMode(DRUPAL_NO_CACHE);
|
||||
$current_content = $this->randomName();
|
||||
variable_set('block_test_content', $current_content);
|
||||
|
||||
// If DRUPAL_NO_CACHE has no effect, the next request would be cached.
|
||||
$this->drupalGet('');
|
||||
$this->assertText($current_content, t('Block content displays.'));
|
||||
|
||||
// A cached copy should not be served.
|
||||
$current_content = $this->randomName();
|
||||
variable_set('block_test_content', $current_content);
|
||||
$this->drupalGet('');
|
||||
$this->assertText($current_content, t('DRUPAL_NO_CACHE prevents blocks from being cached.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test DRUPAL_CACHE_PER_USER.
|
||||
*/
|
||||
function testCachePerUser() {
|
||||
$this->setCacheMode(DRUPAL_CACHE_PER_USER);
|
||||
$current_content = $this->randomName();
|
||||
variable_set('block_test_content', $current_content);
|
||||
$this->drupalLogin($this->normal_user);
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->assertText($current_content, t('Block content displays.'));
|
||||
|
||||
$old_content = $current_content;
|
||||
$current_content = $this->randomName();
|
||||
variable_set('block_test_content', $current_content);
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->assertText($old_content, t('Block is served from per-user cache.'));
|
||||
|
||||
$this->drupalLogin($this->normal_user_alt);
|
||||
$this->drupalGet('');
|
||||
$this->assertText($current_content, t('Per-user block cache is not served for other users.'));
|
||||
|
||||
$this->drupalLogin($this->normal_user);
|
||||
$this->drupalGet('');
|
||||
$this->assertText($old_content, t('Per-user block cache is persistent.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test DRUPAL_CACHE_PER_PAGE.
|
||||
*/
|
||||
function testCachePerPage() {
|
||||
$this->setCacheMode(DRUPAL_CACHE_PER_PAGE);
|
||||
$current_content = $this->randomName();
|
||||
variable_set('block_test_content', $current_content);
|
||||
|
||||
$this->drupalGet('node');
|
||||
$this->assertText($current_content, t('Block content displays on the node page.'));
|
||||
|
||||
$old_content = $current_content;
|
||||
$current_content = $this->randomName();
|
||||
variable_set('block_test_content', $current_content);
|
||||
|
||||
$this->drupalGet('user');
|
||||
$this->assertNoText($old_content, t('Block content cached for the node page does not show up for the user page.'));
|
||||
$this->drupalGet('node');
|
||||
$this->assertText($old_content, t('Block content cached for the node page.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Private helper method to set the test block's cache mode.
|
||||
*/
|
||||
private function setCacheMode($cache_mode) {
|
||||
db_update('block')
|
||||
->fields(array('cache' => $cache_mode))
|
||||
->condition('module', 'block_test')
|
||||
->execute();
|
||||
|
||||
$current_mode = db_query("SELECT cache FROM {block} WHERE module = 'block_test'")->fetchField();
|
||||
if ($current_mode != $cache_mode) {
|
||||
$this->fail(t('Unable to set cache mode to %mode. Current mode: %current_mode', array('%mode' => $cache_mode, '%current_mode' => $current_mode)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\block\Tests\BlockHiddenRegionTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests that hidden regions do not inherit blocks when a theme is enabled.
|
||||
*/
|
||||
class BlockHiddenRegionTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Blocks not in hidden region',
|
||||
'description' => 'Checks that a newly enabled theme does not inherit blocks to its hidden regions.',
|
||||
'group' => 'Block',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('block', 'block_test', 'search'));
|
||||
|
||||
// Enable Search block in default theme.
|
||||
db_merge('block')
|
||||
->key(array(
|
||||
'module' => 'search',
|
||||
'delta' => 'form',
|
||||
'theme' => variable_get('theme_default', 'stark'),
|
||||
))
|
||||
->fields(array(
|
||||
'status' => 1,
|
||||
'weight' => -1,
|
||||
'region' => 'sidebar_first',
|
||||
'pages' => '',
|
||||
'cache' => -1,
|
||||
))
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that hidden regions do not inherit blocks when a theme is enabled.
|
||||
*/
|
||||
function testBlockNotInHiddenRegion() {
|
||||
// Create administrative user.
|
||||
$admin_user = $this->drupalCreateUser(array('administer blocks', 'administer themes', 'search content'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Ensure that the search form block is displayed.
|
||||
$this->drupalGet('');
|
||||
$this->assertText('Search', t('Block was displayed on the front page.'));
|
||||
|
||||
// Enable "block_test_theme" and set it as the default theme.
|
||||
$theme = 'block_test_theme';
|
||||
theme_enable(array($theme));
|
||||
variable_set('theme_default', $theme);
|
||||
menu_router_rebuild();
|
||||
|
||||
// Ensure that "block_test_theme" is set as the default theme.
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->assertText('Block test theme(' . t('active tab') . ')', t('Default local task on blocks admin page is the block test theme.'));
|
||||
|
||||
// Ensure that the search form block is displayed.
|
||||
$this->drupalGet('');
|
||||
$this->assertText('Search', t('Block was displayed on the front page.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\block\Tests\BlockHtmlIdTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Test block HTML id validity.
|
||||
*/
|
||||
class BlockHtmlIdTest extends WebTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Block HTML id',
|
||||
'description' => 'Test block HTML id validity.',
|
||||
'group' => 'Block',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('block', 'block_test'));
|
||||
|
||||
// Create an admin user, log in and enable test blocks.
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer blocks', 'access administration pages'));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Enable our test block.
|
||||
$edit['blocks[block_test_test_html_id][region]'] = 'sidebar_first';
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
|
||||
// Make sure the block has some content so it will appear
|
||||
$current_content = $this->randomName();
|
||||
variable_set('block_test_content', $current_content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test valid HTML id.
|
||||
*/
|
||||
function testHtmlId() {
|
||||
$this->drupalGet('');
|
||||
$this->assertRaw('block-block-test-test-html-id', t('HTML id for test block is valid.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\block\Tests\BlockInvalidRegionTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests that a block assigned to an invalid region triggers the warning.
|
||||
*/
|
||||
class BlockInvalidRegionTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Blocks in invalid regions',
|
||||
'description' => 'Checks that an active block assigned to a non-existing region triggers the warning message and is disabled.',
|
||||
'group' => 'Block',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('block', 'block_test'));
|
||||
// Create an admin user.
|
||||
$admin_user = $this->drupalCreateUser(array('administer site configuration', 'access administration pages'));
|
||||
$this->drupalLogin($admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that blocks assigned to invalid regions work correctly.
|
||||
*/
|
||||
function testBlockInInvalidRegion() {
|
||||
// Enable a test block in the default theme and place it in an invalid region.
|
||||
db_merge('block')
|
||||
->key(array(
|
||||
'module' => 'block_test',
|
||||
'delta' => 'test_html_id',
|
||||
'theme' => variable_get('theme_default', 'stark'),
|
||||
))
|
||||
->fields(array(
|
||||
'status' => 1,
|
||||
'region' => 'invalid_region',
|
||||
'cache' => DRUPAL_NO_CACHE,
|
||||
))
|
||||
->execute();
|
||||
|
||||
$warning_message = t('The block %info was assigned to the invalid region %region and has been disabled.', array('%info' => t('Test block html id'), '%region' => 'invalid_region'));
|
||||
|
||||
// Clearing the cache should disable the test block placed in the invalid region.
|
||||
$this->drupalPost('admin/config/development/performance', array(), 'Clear all caches');
|
||||
$this->assertRaw($warning_message, 'Enabled block was in the invalid region and has been disabled.');
|
||||
|
||||
// Clear the cache to check if the warning message is not triggered.
|
||||
$this->drupalPost('admin/config/development/performance', array(), 'Clear all caches');
|
||||
$this->assertNoRaw($warning_message, 'Disabled block in the invalid region will not trigger the warning.');
|
||||
|
||||
// Place disabled test block in the invalid region of the default theme.
|
||||
db_merge('block')
|
||||
->key(array(
|
||||
'module' => 'block_test',
|
||||
'delta' => 'test_html_id',
|
||||
'theme' => variable_get('theme_default', 'stark'),
|
||||
))
|
||||
->fields(array(
|
||||
'region' => 'invalid_region',
|
||||
'cache' => DRUPAL_NO_CACHE,
|
||||
))
|
||||
->execute();
|
||||
|
||||
// Clear the cache to check if the warning message is not triggered.
|
||||
$this->drupalPost('admin/config/development/performance', array(), 'Clear all caches');
|
||||
$this->assertNoRaw($warning_message, 'Disabled block in the invalid region will not trigger the warning.');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,196 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\block\Tests\BlockLanguageTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Functional tests for the language list configuration forms.
|
||||
*/
|
||||
class BlockLanguageTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Language block visibility',
|
||||
'description' => 'Tests if a block can be configure to be only visibile on a particular language.',
|
||||
'group' => 'Block',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('language', 'block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the visibility settings for the blocks based on language.
|
||||
*/
|
||||
public function testLanguageBlockVisibility() {
|
||||
// Create a new user, allow him to manage the blocks and the languages.
|
||||
$admin_user = $this->drupalCreateUser(array(
|
||||
'administer languages', 'administer blocks',
|
||||
));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Add predefined language.
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'fr',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
$this->assertText('French', t('Language added successfully.'));
|
||||
|
||||
// Check if the visibility setting is available.
|
||||
$this->drupalGet('admin/structure/block/add');
|
||||
$this->assertField('langcodes[en]', t('Language visibility field is visible.'));
|
||||
|
||||
// Create a new block.
|
||||
$info_name = $this->randomString(10);
|
||||
$body = '';
|
||||
for ($i = 0; $i <= 100; $i++) {
|
||||
$body .= chr(rand(97, 122));
|
||||
}
|
||||
$edit = array(
|
||||
'regions[stark]' => 'sidebar_first',
|
||||
'info' => $info_name,
|
||||
'title' => 'test',
|
||||
'body[value]' => $body,
|
||||
);
|
||||
$this->drupalPost('admin/structure/block/add', $edit, t('Save block'));
|
||||
|
||||
// Set visibility setting for one language.
|
||||
$edit = array(
|
||||
'langcodes[en]' => TRUE,
|
||||
);
|
||||
$this->drupalPost('admin/structure/block/manage/block/1/configure', $edit, t('Save block'));
|
||||
|
||||
// Change the default language.
|
||||
$edit = array(
|
||||
'site_default' => 'fr',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language', $edit, t('Save configuration'));
|
||||
|
||||
// Reset the static cache of the language list.
|
||||
drupal_static_reset('language_list');
|
||||
|
||||
// Check that a page has a block
|
||||
$this->drupalGet('', array('language' => language_load('en')));
|
||||
$this->assertText($body, t('The body of the custom block appears on the page.'));
|
||||
|
||||
// Check that a page doesn't has a block for the current language anymore
|
||||
$this->drupalGet('', array('language' => language_load('fr')));
|
||||
$this->assertNoText($body, t('The body of the custom block does not appear on the page.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the visibility settings are removed if the language is deleted.
|
||||
*/
|
||||
public function testLanguageBlockVisibilityLanguageDelete() {
|
||||
// Create a new user, allow him to manage the blocks and the languages.
|
||||
$admin_user = $this->drupalCreateUser(array(
|
||||
'administer languages', 'administer blocks',
|
||||
));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Add predefined language.
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'fr',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
$this->assertText('French', t('Language added successfully.'));
|
||||
|
||||
// Create a new block.
|
||||
$info_name = $this->randomString(10);
|
||||
$body = '';
|
||||
for ($i = 0; $i <= 100; $i++) {
|
||||
$body .= chr(rand(97, 122));
|
||||
}
|
||||
$edit = array(
|
||||
'regions[stark]' => 'sidebar_first',
|
||||
'info' => $info_name,
|
||||
'title' => 'test',
|
||||
'body[value]' => $body,
|
||||
);
|
||||
$this->drupalPost('admin/structure/block/add', $edit, t('Save block'));
|
||||
|
||||
// Set visibility setting for one language.
|
||||
$edit = array(
|
||||
'langcodes[fr]' => TRUE,
|
||||
);
|
||||
$this->drupalPost('admin/structure/block/manage/block/1/configure', $edit, t('Save block'));
|
||||
|
||||
// Check that we have an entry in the database after saving the setting.
|
||||
$count = db_query('SELECT COUNT(langcode) FROM {block_language} WHERE module = :module AND delta = :delta', array(
|
||||
':module' => 'block',
|
||||
':delta' => '1'
|
||||
))->fetchField();
|
||||
$this->assertTrue($count == 1, t('The block language visibility has an entry in the database.'));
|
||||
|
||||
// Delete the language.
|
||||
$this->drupalPost('admin/config/regional/language/delete/fr', array(), t('Delete'));
|
||||
|
||||
// Check that the setting related to this language has been deleted.
|
||||
$count = db_query('SELECT COUNT(langcode) FROM {block_language} WHERE module = :module AND delta = :delta', array(
|
||||
':module' => 'block',
|
||||
':delta' => '1'
|
||||
))->fetchField();
|
||||
$this->assertTrue($count == 0, t('The block language visibility do not have an entry in the database.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the visibility settings are removed if the block is deleted.
|
||||
*/
|
||||
public function testLanguageBlockVisibilityBlockDelete() {
|
||||
// Create a new user, allow him to manage the blocks and the languages.
|
||||
$admin_user = $this->drupalCreateUser(array(
|
||||
'administer languages', 'administer blocks',
|
||||
));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Add predefined language.
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'fr',
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
$this->assertText('French', t('Language added successfully.'));
|
||||
|
||||
// Create a new block.
|
||||
$info_name = $this->randomString(10);
|
||||
$body = '';
|
||||
for ($i = 0; $i <= 100; $i++) {
|
||||
$body .= chr(rand(97, 122));
|
||||
}
|
||||
$edit = array(
|
||||
'regions[stark]' => 'sidebar_first',
|
||||
'info' => $info_name,
|
||||
'title' => 'test',
|
||||
'body[value]' => $body,
|
||||
);
|
||||
$this->drupalPost('admin/structure/block/add', $edit, t('Save block'));
|
||||
|
||||
// Set visibility setting for one language.
|
||||
$edit = array(
|
||||
'langcodes[fr]' => TRUE,
|
||||
);
|
||||
$this->drupalPost('admin/structure/block/manage/block/1/configure', $edit, t('Save block'));
|
||||
|
||||
// Check that we have an entry in the database after saving the setting.
|
||||
$count = db_query('SELECT COUNT(langcode) FROM {block_language} WHERE module = :module AND delta = :delta', array(
|
||||
':module' => 'block',
|
||||
':delta' => '1'
|
||||
))->fetchField();
|
||||
$this->assertTrue($count == 1, t('The block language visibility has an entry in the database.'));
|
||||
|
||||
// Delete the custom block.
|
||||
$this->drupalPost('admin/structure/block/manage/block/1/delete', array(), t('Delete'));
|
||||
|
||||
// Check that the setting related to this block has been deleted.
|
||||
$count = db_query('SELECT COUNT(langcode) FROM {block_language} WHERE module = :module AND delta = :delta', array(
|
||||
':module' => 'block',
|
||||
':delta' => '1'
|
||||
))->fetchField();
|
||||
$this->assertTrue($count == 0, t('The block language visibility do not have an entry in the database.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\block\Tests\BlockTemplateSuggestionsUnitTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\UnitTestBase;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Unit tests for template_preprocess_block().
|
||||
*/
|
||||
class BlockTemplateSuggestionsUnitTest extends UnitTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Block template suggestions',
|
||||
'description' => 'Test the template_preprocess_block() function.',
|
||||
'group' => 'Block',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if template_preprocess_block() handles the suggestions right.
|
||||
*/
|
||||
function testBlockThemeHookSuggestions() {
|
||||
// Define block delta with underscore to be preprocessed
|
||||
$block1 = new stdClass();
|
||||
$block1->module = 'block';
|
||||
$block1->delta = 'underscore_test';
|
||||
$block1->region = 'footer';
|
||||
$variables1 = array();
|
||||
$variables1['elements']['#block'] = $block1;
|
||||
$variables1['elements']['#children'] = '';
|
||||
template_preprocess_block($variables1);
|
||||
$this->assertEqual($variables1['theme_hook_suggestions'], array('block__footer', 'block__block', 'block__block__underscore_test'), t('Found expected block suggestions for delta with underscore'));
|
||||
|
||||
// Define block delta with hyphens to be preprocessed. Hyphens should be
|
||||
// replaced with underscores.
|
||||
$block2 = new stdClass();
|
||||
$block2->module = 'block';
|
||||
$block2->delta = 'hyphen-test';
|
||||
$block2->region = 'footer';
|
||||
$variables2 = array();
|
||||
$variables2['elements']['#block'] = $block2;
|
||||
$variables2['elements']['#children'] = '';
|
||||
// Test adding a class to the block content.
|
||||
$variables2['content_attributes_array']['class'][] = 'test-class';
|
||||
template_preprocess_block($variables2);
|
||||
$this->assertEqual($variables2['theme_hook_suggestions'], array('block__footer', 'block__block', 'block__block__hyphen_test'), t('Hyphens (-) in block delta were replaced by underscore (_)'));
|
||||
// Test that the default class and added class are available.
|
||||
$this->assertEqual($variables2['content_attributes_array']['class'], array('test-class', 'content'), t('Default .content class added to block content_attributes_array'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,403 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\block\Tests\BlockTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
class BlockTest extends WebTestBase {
|
||||
protected $regions;
|
||||
protected $admin_user;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Block functionality',
|
||||
'description' => 'Add, edit and delete custom block. Configure and move a module-defined block.',
|
||||
'group' => 'Block',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('block'));
|
||||
|
||||
// Create Full HTML text format.
|
||||
$full_html_format = array(
|
||||
'format' => 'full_html',
|
||||
'name' => 'Full HTML',
|
||||
);
|
||||
$full_html_format = (object) $full_html_format;
|
||||
filter_format_save($full_html_format);
|
||||
$this->checkPermissions(array(), TRUE);
|
||||
|
||||
// Create and log in an administrative user having access to the Full HTML
|
||||
// text format.
|
||||
$this->admin_user = $this->drupalCreateUser(array(
|
||||
'administer blocks',
|
||||
filter_permission_name($full_html_format),
|
||||
'access administration pages',
|
||||
));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Define the existing regions
|
||||
$this->regions = array();
|
||||
$this->regions[] = 'header';
|
||||
$this->regions[] = 'sidebar_first';
|
||||
$this->regions[] = 'content';
|
||||
$this->regions[] = 'sidebar_second';
|
||||
$this->regions[] = 'footer';
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating custom block, moving it to a specific region and then deleting it.
|
||||
*/
|
||||
function testCustomBlock() {
|
||||
// Enable a second theme.
|
||||
theme_enable(array('seven'));
|
||||
|
||||
// Confirm that the add block link appears on block overview pages.
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->assertRaw(l('Add block', 'admin/structure/block/add'), t('Add block link is present on block overview page for default theme.'));
|
||||
$this->drupalGet('admin/structure/block/list/seven');
|
||||
$this->assertRaw(l('Add block', 'admin/structure/block/list/seven/add'), t('Add block link is present on block overview page for non-default theme.'));
|
||||
|
||||
// Confirm that hidden regions are not shown as options for block placement
|
||||
// when adding a new block.
|
||||
theme_enable(array('bartik'));
|
||||
$themes = list_themes();
|
||||
$this->drupalGet('admin/structure/block/add');
|
||||
foreach ($themes as $key => $theme) {
|
||||
if ($theme->status) {
|
||||
foreach ($theme->info['regions_hidden'] as $hidden_region) {
|
||||
$elements = $this->xpath('//select[@id=:id]//option[@value=:value]', array(':id' => 'edit-regions-' . $key, ':value' => $hidden_region));
|
||||
$this->assertFalse(isset($elements[0]), t('The hidden region @region is not available for @theme.', array('@region' => $hidden_region, '@theme' => $key)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new custom block by filling out the input form on the admin/structure/block/add page.
|
||||
$custom_block = array();
|
||||
$custom_block['info'] = $this->randomName(8);
|
||||
$custom_block['title'] = $this->randomName(8);
|
||||
$custom_block['body[value]'] = $this->randomName(32);
|
||||
$this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
|
||||
|
||||
// Confirm that the custom block has been created, and then query the created bid.
|
||||
$this->assertText(t('The block has been created.'), t('Custom block successfully created.'));
|
||||
$bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
|
||||
|
||||
// Check to see if the custom block was created by checking that it's in the database.
|
||||
$this->assertNotNull($bid, t('Custom block found in database'));
|
||||
|
||||
// Check that block_block_view() returns the correct title and content.
|
||||
$data = block_block_view($bid);
|
||||
$format = db_query("SELECT format FROM {block_custom} WHERE bid = :bid", array(':bid' => $bid))->fetchField();
|
||||
$this->assertTrue(array_key_exists('subject', $data) && empty($data['subject']), t('block_block_view() provides an empty block subject, since custom blocks do not have default titles.'));
|
||||
$this->assertEqual(check_markup($custom_block['body[value]'], $format), $data['content'], t('block_block_view() provides correct block content.'));
|
||||
|
||||
// Check whether the block can be moved to all available regions.
|
||||
$custom_block['module'] = 'block';
|
||||
$custom_block['delta'] = $bid;
|
||||
foreach ($this->regions as $region) {
|
||||
$this->moveBlockToRegion($custom_block, $region);
|
||||
}
|
||||
|
||||
// Verify presence of configure and delete links for custom block.
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->assertLinkByHref('admin/structure/block/manage/block/' . $bid . '/configure', 0, t('Custom block configure link found.'));
|
||||
$this->assertLinkByHref('admin/structure/block/manage/block/' . $bid . '/delete', 0, t('Custom block delete link found.'));
|
||||
|
||||
// Set visibility only for authenticated users, to verify delete functionality.
|
||||
$edit = array();
|
||||
$edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = TRUE;
|
||||
$this->drupalPost('admin/structure/block/manage/block/' . $bid . '/configure', $edit, t('Save block'));
|
||||
|
||||
// Delete the created custom block & verify that it's been deleted and no longer appearing on the page.
|
||||
$this->clickLink(t('delete'));
|
||||
$this->drupalPost('admin/structure/block/manage/block/' . $bid . '/delete', array(), t('Delete'));
|
||||
$this->assertRaw(t('The block %title has been removed.', array('%title' => $custom_block['info'])), t('Custom block successfully deleted.'));
|
||||
$this->assertNoText(t($custom_block['title']), t('Custom block no longer appears on page.'));
|
||||
$count = db_query("SELECT 1 FROM {block_role} WHERE module = :module AND delta = :delta", array(':module' => $custom_block['module'], ':delta' => $custom_block['delta']))->fetchField();
|
||||
$this->assertFalse($count, t('Table block_role being cleaned.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating custom block using Full HTML.
|
||||
*/
|
||||
function testCustomBlockFormat() {
|
||||
// Add a new custom block by filling out the input form on the admin/structure/block/add page.
|
||||
$custom_block = array();
|
||||
$custom_block['info'] = $this->randomName(8);
|
||||
$custom_block['title'] = $this->randomName(8);
|
||||
$custom_block['body[value]'] = '<h1>Full HTML</h1>';
|
||||
$full_html_format = filter_format_load('full_html');
|
||||
$custom_block['body[format]'] = $full_html_format->format;
|
||||
$this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
|
||||
|
||||
// Set the created custom block to a specific region.
|
||||
$bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
|
||||
$edit = array();
|
||||
$edit['blocks[block_' . $bid . '][region]'] = $this->regions[1];
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
|
||||
// Confirm that the custom block is being displayed using configured text format.
|
||||
$this->drupalGet('node');
|
||||
$this->assertRaw('<h1>Full HTML</h1>', t('Custom block successfully being displayed using Full HTML.'));
|
||||
|
||||
// Confirm that a user without access to Full HTML can not see the body field,
|
||||
// but can still submit the form without errors.
|
||||
$block_admin = $this->drupalCreateUser(array('administer blocks'));
|
||||
$this->drupalLogin($block_admin);
|
||||
$this->drupalGet('admin/structure/block/manage/block/' . $bid . '/configure');
|
||||
$this->assertFieldByXPath("//textarea[@name='body[value]' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), t('Body field contains denied message'));
|
||||
$this->drupalPost('admin/structure/block/manage/block/' . $bid . '/configure', array(), t('Save block'));
|
||||
$this->assertNoText(t('Ensure that each block description is unique.'));
|
||||
|
||||
// Confirm that the custom block is still being displayed using configured text format.
|
||||
$this->drupalGet('node');
|
||||
$this->assertRaw('<h1>Full HTML</h1>', t('Custom block successfully being displayed using Full HTML.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test block visibility.
|
||||
*/
|
||||
function testBlockVisibility() {
|
||||
// Enable Node module and change the front page path to 'node'.
|
||||
module_enable(array('node'));
|
||||
variable_set('site_frontpage', 'node');
|
||||
|
||||
$block = array();
|
||||
|
||||
// Create a random title for the block
|
||||
$title = $this->randomName(8);
|
||||
|
||||
// Create the custom block
|
||||
$custom_block = array();
|
||||
$custom_block['info'] = $this->randomName(8);
|
||||
$custom_block['title'] = $title;
|
||||
$custom_block['body[value]'] = $this->randomName(32);
|
||||
$this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
|
||||
|
||||
$bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
|
||||
$block['module'] = 'block';
|
||||
$block['delta'] = $bid;
|
||||
$block['title'] = $title;
|
||||
|
||||
// Set the block to be hidden on any user path, and to be shown only to
|
||||
// authenticated users.
|
||||
$edit = array();
|
||||
$edit['pages'] = 'user*';
|
||||
$edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = TRUE;
|
||||
$this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', $edit, t('Save block'));
|
||||
|
||||
// Move block to the first sidebar.
|
||||
$this->moveBlockToRegion($block, $this->regions[1]);
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->assertText($title, t('Block was displayed on the front page.'));
|
||||
|
||||
$this->drupalGet('user');
|
||||
$this->assertNoText($title, t('Block was not displayed according to block visibility rules.'));
|
||||
|
||||
$this->drupalGet('USER/' . $this->admin_user->uid);
|
||||
$this->assertNoText($title, t('Block was not displayed according to block visibility rules regardless of path case.'));
|
||||
|
||||
// Confirm that the block is not displayed to anonymous users.
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText($title, t('Block was not displayed to anonymous users.'));
|
||||
|
||||
// Confirm that an empty block is not displayed.
|
||||
$this->assertNoRaw('block-system-help', t('Empty block not displayed.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test block visibility when using "pages" restriction but leaving
|
||||
* "pages" textarea empty
|
||||
*/
|
||||
function testBlockVisibilityListedEmpty() {
|
||||
$block = array();
|
||||
|
||||
// Create a random title for the block
|
||||
$title = $this->randomName(8);
|
||||
|
||||
// Create the custom block
|
||||
$custom_block = array();
|
||||
$custom_block['info'] = $this->randomName(8);
|
||||
$custom_block['title'] = $title;
|
||||
$custom_block['body[value]'] = $this->randomName(32);
|
||||
$this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
|
||||
|
||||
$bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
|
||||
$block['module'] = 'block';
|
||||
$block['delta'] = $bid;
|
||||
$block['title'] = $title;
|
||||
|
||||
// Move block to the first sidebar.
|
||||
$this->moveBlockToRegion($block, $this->regions[1]);
|
||||
|
||||
// Set the block to be hidden on any user path, and to be shown only to
|
||||
// authenticated users.
|
||||
$edit = array();
|
||||
$edit['visibility'] = BLOCK_VISIBILITY_LISTED;
|
||||
$this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', $edit, t('Save block'));
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText($title, t('Block was not displayed according to block visibility rules.'));
|
||||
|
||||
$this->drupalGet('user');
|
||||
$this->assertNoText($title, t('Block was not displayed according to block visibility rules regardless of path case.'));
|
||||
|
||||
// Confirm that the block is not displayed to anonymous users.
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText($title, t('Block was not displayed to anonymous users.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test user customization of block visibility.
|
||||
*/
|
||||
function testBlockVisibilityPerUser() {
|
||||
$block = array();
|
||||
|
||||
// Create a random title for the block.
|
||||
$title = $this->randomName(8);
|
||||
|
||||
// Create our custom test block.
|
||||
$custom_block = array();
|
||||
$custom_block['info'] = $this->randomName(8);
|
||||
$custom_block['title'] = $title;
|
||||
$custom_block['body[value]'] = $this->randomName(32);
|
||||
$this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
|
||||
|
||||
$bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
|
||||
$block['module'] = 'block';
|
||||
$block['delta'] = $bid;
|
||||
$block['title'] = $title;
|
||||
|
||||
// Move block to the first sidebar.
|
||||
$this->moveBlockToRegion($block, $this->regions[1]);
|
||||
|
||||
// Set the block to be customizable per user, visible by default.
|
||||
$edit = array();
|
||||
$edit['custom'] = BLOCK_CUSTOM_ENABLED;
|
||||
$this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', $edit, t('Save block'));
|
||||
|
||||
// Disable block visibility for the admin user.
|
||||
$edit = array();
|
||||
$edit['block[' . $block['module'] . '][' . $block['delta'] . ']'] = FALSE;
|
||||
$this->drupalPost('user/' . $this->admin_user->uid . '/edit', $edit, t('Save'));
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText($block['title'], t('Block was not displayed according to per user block visibility setting.'));
|
||||
|
||||
// Set the block to be customizable per user, hidden by default.
|
||||
$edit = array();
|
||||
$edit['custom'] = BLOCK_CUSTOM_DISABLED;
|
||||
$this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', $edit, t('Save block'));
|
||||
|
||||
// Enable block visibility for the admin user.
|
||||
$edit = array();
|
||||
$edit['block[' . $block['module'] . '][' . $block['delta'] . ']'] = TRUE;
|
||||
$this->drupalPost('user/' . $this->admin_user->uid . '/edit', $edit, t('Save'));
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->assertText($block['title'], t('Block was displayed according to per user block visibility setting.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test configuring and moving a module-define block to specific regions.
|
||||
*/
|
||||
function testBlock() {
|
||||
// Select the Navigation block to be configured and moved.
|
||||
$block = array();
|
||||
$block['module'] = 'system';
|
||||
$block['delta'] = 'management';
|
||||
$block['title'] = $this->randomName(8);
|
||||
|
||||
// Set block title to confirm that interface works and override any custom titles.
|
||||
$this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', array('title' => $block['title']), t('Save block'));
|
||||
$this->assertText(t('The block configuration has been saved.'), t('Block title set.'));
|
||||
$bid = db_query("SELECT bid FROM {block} WHERE module = :module AND delta = :delta", array(
|
||||
':module' => $block['module'],
|
||||
':delta' => $block['delta'],
|
||||
))->fetchField();
|
||||
|
||||
// Check to see if the block was created by checking that it's in the database.
|
||||
$this->assertNotNull($bid, t('Block found in database'));
|
||||
|
||||
// Check whether the block can be moved to all available regions.
|
||||
foreach ($this->regions as $region) {
|
||||
$this->moveBlockToRegion($block, $region);
|
||||
}
|
||||
|
||||
// Set the block to the disabled region.
|
||||
$edit = array();
|
||||
$edit['blocks[' . $block['module'] . '_' . $block['delta'] . '][region]'] = '-1';
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
|
||||
// Confirm that the block was moved to the proper region.
|
||||
$this->assertText(t('The block settings have been updated.'), t('Block successfully move to disabled region.'));
|
||||
$this->assertNoText(t($block['title']), t('Block no longer appears on page.'));
|
||||
|
||||
// Confirm that the region's xpath is not available.
|
||||
$xpath = $this->buildXPathQuery('//div[@id=:id]/*', array(':id' => 'block-block-' . $bid));
|
||||
$this->assertNoFieldByXPath($xpath, FALSE, t('Custom block found in no regions.'));
|
||||
|
||||
// For convenience of developers, put the navigation block back.
|
||||
$edit = array();
|
||||
$edit['blocks[' . $block['module'] . '_' . $block['delta'] . '][region]'] = $this->regions[1];
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
$this->assertText(t('The block settings have been updated.'), t('Block successfully move to first sidebar region.'));
|
||||
|
||||
$this->drupalPost('admin/structure/block/manage/' . $block['module'] . '/' . $block['delta'] . '/configure', array('title' => 'Navigation'), t('Save block'));
|
||||
$this->assertText(t('The block configuration has been saved.'), t('Block title set.'));
|
||||
}
|
||||
|
||||
function moveBlockToRegion($block, $region) {
|
||||
// Set the created block to a specific region.
|
||||
$edit = array();
|
||||
$edit['blocks[' . $block['module'] . '_' . $block['delta'] . '][region]'] = $region;
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
|
||||
// Confirm that the block was moved to the proper region.
|
||||
$this->assertText(t('The block settings have been updated.'), t('Block successfully moved to %region_name region.', array( '%region_name' => $region)));
|
||||
|
||||
// Confirm that the block is being displayed.
|
||||
$this->drupalGet('node');
|
||||
$this->assertText(t($block['title']), t('Block successfully being displayed on the page.'));
|
||||
|
||||
// Confirm that the custom block was found at the proper region.
|
||||
$xpath = $this->buildXPathQuery('//div[@class=:region-class]//div[@id=:block-id]/*', array(
|
||||
':region-class' => 'region region-' . str_replace('_', '-', $region),
|
||||
':block-id' => 'block-' . $block['module'] . '-' . $block['delta'],
|
||||
));
|
||||
$this->assertFieldByXPath($xpath, NULL, t('Custom block found in %region_name region.', array('%region_name' => $region)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test _block_rehash().
|
||||
*/
|
||||
function testBlockRehash() {
|
||||
module_enable(array('block_test'));
|
||||
$this->assertTrue(module_exists('block_test'), t('Test block module enabled.'));
|
||||
|
||||
// Our new block should be inserted in the database when we visit the
|
||||
// block management page.
|
||||
$this->drupalGet('admin/structure/block');
|
||||
// Our test block's caching should default to DRUPAL_CACHE_PER_ROLE.
|
||||
$current_caching = db_query("SELECT cache FROM {block} WHERE module = 'block_test' AND delta = 'test_cache'")->fetchField();
|
||||
$this->assertEqual($current_caching, DRUPAL_CACHE_PER_ROLE, t('Test block cache mode defaults to DRUPAL_CACHE_PER_ROLE.'));
|
||||
|
||||
// Disable caching for this block.
|
||||
variable_set('block_test_caching', DRUPAL_NO_CACHE);
|
||||
// Flushing all caches should call _block_rehash().
|
||||
$this->resetAll();
|
||||
// Verify that the database is updated with the new caching mode.
|
||||
$current_caching = db_query("SELECT cache FROM {block} WHERE module = 'block_test' AND delta = 'test_cache'")->fetchField();
|
||||
$this->assertEqual($current_caching, DRUPAL_NO_CACHE, t("Test block's database entry updated to DRUPAL_NO_CACHE."));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\block\Tests\BlockUserAccountSettingsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests personalized block settings for user accounts.
|
||||
*/
|
||||
class BlockUserAccountSettingsTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Personalized block settings',
|
||||
'description' => 'Tests the block settings in user accounts.',
|
||||
'group' => 'Block',
|
||||
);
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp(array('block', 'field_ui'));
|
||||
$admin_user = $this->drupalCreateUser(array('administer users'));
|
||||
$this->drupalLogin($admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the personalized block is shown.
|
||||
*/
|
||||
function testAccountSettingsPage() {
|
||||
$this->drupalGet('admin/config/people/accounts/fields');
|
||||
$this->assertText(t('Personalize blocks'), 'Personalized block is present.');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\block\Tests\NewDefaultThemeBlocksTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Test blocks correctly initialized when picking a new default theme.
|
||||
*/
|
||||
class NewDefaultThemeBlocksTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'New default theme blocks',
|
||||
'description' => 'Checks that the new default theme gets blocks.',
|
||||
'group' => 'Block',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('block'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the enabled Bartik blocks are correctly copied over.
|
||||
*/
|
||||
function testNewDefaultThemeBlocks() {
|
||||
// Create administrative user.
|
||||
$admin_user = $this->drupalCreateUser(array('administer themes'));
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Ensure no other theme's blocks are in the block table yet.
|
||||
$themes = array();
|
||||
$themes['default'] = variable_get('theme_default', 'stark');
|
||||
if ($admin_theme = variable_get('admin_theme')) {
|
||||
$themes['admin'] = $admin_theme;
|
||||
}
|
||||
$count = db_query_range('SELECT 1 FROM {block} WHERE theme NOT IN (:themes)', 0, 1, array(':themes' => $themes))->fetchField();
|
||||
$this->assertFalse($count, t('Only the default theme and the admin theme have blocks.'));
|
||||
|
||||
// Populate list of all blocks for matching against new theme.
|
||||
$blocks = array();
|
||||
$result = db_query('SELECT * FROM {block} WHERE theme = :theme', array(':theme' => $themes['default']));
|
||||
foreach ($result as $block) {
|
||||
// $block->theme and $block->bid will not match, so remove them.
|
||||
unset($block->theme, $block->bid);
|
||||
$blocks[$block->module][$block->delta] = $block;
|
||||
}
|
||||
|
||||
// Turn on a new theme and ensure that it contains all of the blocks
|
||||
// the default theme had.
|
||||
$new_theme = 'bartik';
|
||||
theme_enable(array($new_theme));
|
||||
variable_set('theme_default', $new_theme);
|
||||
$result = db_query('SELECT * FROM {block} WHERE theme = :theme', array(':theme' => $new_theme));
|
||||
foreach ($result as $block) {
|
||||
unset($block->theme, $block->bid);
|
||||
$this->assertEqual($blocks[$block->module][$block->delta], $block, t('Block %name matched', array('%name' => $block->module . '-' . $block->delta)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\block\Tests\NonDefaultBlockAdminTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
class NonDefaultBlockAdminTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Non default theme admin',
|
||||
'description' => 'Check the administer page for non default theme.',
|
||||
'group' => 'Block',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('block'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test non-default theme admin.
|
||||
*/
|
||||
function testNonDefaultBlockAdmin() {
|
||||
$admin_user = $this->drupalCreateUser(array('administer blocks', 'administer themes'));
|
||||
$this->drupalLogin($admin_user);
|
||||
$new_theme = 'bartik';
|
||||
theme_enable(array($new_theme));
|
||||
$this->drupalGet('admin/structure/block/list/' . $new_theme);
|
||||
}
|
||||
}
|
|
@ -6,6 +6,5 @@ core = 8.x
|
|||
dependencies[] = node
|
||||
dependencies[] = text
|
||||
dependencies[] = entity
|
||||
files[] = comment.test
|
||||
configure = admin/content/comment
|
||||
stylesheets[all][] = comment.theme.css
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\comment\Tests\CommentActionsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
/**
|
||||
* Tests actions provided by the Comment module.
|
||||
*/
|
||||
class CommentActionsTest extends CommentTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Comment actions',
|
||||
'description' => 'Test actions provided by the comment module.',
|
||||
'group' => 'Comment',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests comment publish and unpublish actions.
|
||||
*/
|
||||
function testCommentPublishUnpublishActions() {
|
||||
$this->drupalLogin($this->web_user);
|
||||
$comment_text = $this->randomName();
|
||||
$subject = $this->randomName();
|
||||
$comment = $this->postComment($this->node, $comment_text, $subject);
|
||||
$comment = comment_load($comment->id);
|
||||
|
||||
// Unpublish a comment (direct form: doesn't actually save the comment).
|
||||
comment_unpublish_action($comment);
|
||||
$this->assertEqual($comment->status, COMMENT_NOT_PUBLISHED, t('Comment was unpublished'));
|
||||
$this->assertWatchdogMessage('Unpublished comment %subject.', array('%subject' => $subject), t('Found watchdog message'));
|
||||
$this->clearWatchdog();
|
||||
|
||||
// Unpublish a comment (indirect form: modify the comment in the database).
|
||||
comment_unpublish_action(NULL, array('cid' => $comment->cid));
|
||||
$this->assertEqual(comment_load($comment->cid)->status, COMMENT_NOT_PUBLISHED, t('Comment was unpublished'));
|
||||
$this->assertWatchdogMessage('Unpublished comment %subject.', array('%subject' => $subject), t('Found watchdog message'));
|
||||
|
||||
// Publish a comment (direct form: doesn't actually save the comment).
|
||||
comment_publish_action($comment);
|
||||
$this->assertEqual($comment->status, COMMENT_PUBLISHED, t('Comment was published'));
|
||||
$this->assertWatchdogMessage('Published comment %subject.', array('%subject' => $subject), t('Found watchdog message'));
|
||||
$this->clearWatchdog();
|
||||
|
||||
// Publish a comment (indirect form: modify the comment in the database).
|
||||
comment_publish_action(NULL, array('cid' => $comment->cid));
|
||||
$this->assertEqual(comment_load($comment->cid)->status, COMMENT_PUBLISHED, t('Comment was published'));
|
||||
$this->assertWatchdogMessage('Published comment %subject.', array('%subject' => $subject), t('Found watchdog message'));
|
||||
$this->clearWatchdog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a watchdog message has been entered.
|
||||
*
|
||||
* @param $watchdog_message
|
||||
* The watchdog message.
|
||||
* @param $variables
|
||||
* The array of variables passed to watchdog().
|
||||
* @param $message
|
||||
* The assertion message.
|
||||
*/
|
||||
function assertWatchdogMessage($watchdog_message, $variables, $message) {
|
||||
$status = (bool) db_query_range("SELECT 1 FROM {watchdog} WHERE message = :message AND variables = :variables", 0, 1, array(':message' => $watchdog_message, ':variables' => serialize($variables)))->fetchField();
|
||||
return $this->assert($status, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears watchdog.
|
||||
*/
|
||||
function clearWatchdog() {
|
||||
db_truncate('watchdog')->execute();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\comment\Tests\CommentAnonymousTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
/**
|
||||
* Tests anonymous commenting.
|
||||
*/
|
||||
class CommentAnonymousTest extends CommentTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Anonymous comments',
|
||||
'description' => 'Test anonymous comments.',
|
||||
'group' => 'Comment',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
variable_set('user_register', USER_REGISTER_VISITORS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests anonymous comment functionality.
|
||||
*/
|
||||
function testAnonymous() {
|
||||
$this->drupalLogin($this->admin_user);
|
||||
// Enabled anonymous user comments.
|
||||
user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
|
||||
'access comments' => TRUE,
|
||||
'post comments' => TRUE,
|
||||
'skip comment approval' => TRUE,
|
||||
));
|
||||
$this->setCommentAnonymous('0'); // Ensure that doesn't require contact info.
|
||||
$this->drupalLogout();
|
||||
|
||||
// Post anonymous comment without contact info.
|
||||
$anonymous_comment1 = $this->postComment($this->node, $this->randomName(), $this->randomName());
|
||||
$this->assertTrue($this->commentExists($anonymous_comment1), t('Anonymous comment without contact info found.'));
|
||||
|
||||
// Allow contact info.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentAnonymous('1');
|
||||
|
||||
// Attempt to edit anonymous comment.
|
||||
$this->drupalGet('comment/' . $anonymous_comment1->id . '/edit');
|
||||
$edited_comment = $this->postComment(NULL, $this->randomName(), $this->randomName());
|
||||
$this->assertTrue($this->commentExists($edited_comment, FALSE), t('Modified reply found.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Post anonymous comment with contact info (optional).
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid);
|
||||
$this->assertTrue($this->commentContactInfoAvailable(), t('Contact information available.'));
|
||||
|
||||
$anonymous_comment2 = $this->postComment($this->node, $this->randomName(), $this->randomName());
|
||||
$this->assertTrue($this->commentExists($anonymous_comment2), t('Anonymous comment with contact info (optional) found.'));
|
||||
|
||||
// Ensure anonymous users cannot post in the name of registered users.
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$edit = array(
|
||||
'name' => $this->admin_user->name,
|
||||
'mail' => $this->randomName() . '@example.com',
|
||||
'subject' => $this->randomName(),
|
||||
"comment_body[$langcode][0][value]" => $this->randomName(),
|
||||
);
|
||||
$this->drupalPost('comment/reply/' . $this->node->nid, $edit, t('Save'));
|
||||
$this->assertText(t('The name you used belongs to a registered user.'));
|
||||
|
||||
// Require contact info.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentAnonymous('2');
|
||||
$this->drupalLogout();
|
||||
|
||||
// Try to post comment with contact info (required).
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid);
|
||||
$this->assertTrue($this->commentContactInfoAvailable(), t('Contact information available.'));
|
||||
|
||||
$anonymous_comment3 = $this->postComment($this->node, $this->randomName(), $this->randomName(), TRUE);
|
||||
$this->assertText(t('E-mail field is required.'), t('E-mail required.')); // Name should have 'Anonymous' for value by default.
|
||||
$this->assertFalse($this->commentExists($anonymous_comment3), t('Anonymous comment with contact info (required) not found.'));
|
||||
|
||||
// Post comment with contact info (required).
|
||||
$author_name = $this->randomName();
|
||||
$author_mail = $this->randomName() . '@example.com';
|
||||
$anonymous_comment3 = $this->postComment($this->node, $this->randomName(), $this->randomName(), array('name' => $author_name, 'mail' => $author_mail));
|
||||
$this->assertTrue($this->commentExists($anonymous_comment3), t('Anonymous comment with contact info (required) found.'));
|
||||
|
||||
// Make sure the user data appears correctly when editing the comment.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->drupalGet('comment/' . $anonymous_comment3->id . '/edit');
|
||||
$this->assertRaw($author_name, t("The anonymous user's name is correct when editing the comment."));
|
||||
$this->assertRaw($author_mail, t("The anonymous user's e-mail address is correct when editing the comment."));
|
||||
|
||||
// Unpublish comment.
|
||||
$this->performCommentOperation($anonymous_comment3, 'unpublish');
|
||||
|
||||
$this->drupalGet('admin/content/comment/approval');
|
||||
$this->assertRaw('comments[' . $anonymous_comment3->id . ']', t('Comment was unpublished.'));
|
||||
|
||||
// Publish comment.
|
||||
$this->performCommentOperation($anonymous_comment3, 'publish', TRUE);
|
||||
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->assertRaw('comments[' . $anonymous_comment3->id . ']', t('Comment was published.'));
|
||||
|
||||
// Delete comment.
|
||||
$this->performCommentOperation($anonymous_comment3, 'delete');
|
||||
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->assertNoRaw('comments[' . $anonymous_comment3->id . ']', t('Comment was deleted.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Reset.
|
||||
user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
|
||||
'access comments' => FALSE,
|
||||
'post comments' => FALSE,
|
||||
'skip comment approval' => FALSE,
|
||||
));
|
||||
|
||||
// Attempt to view comments while disallowed.
|
||||
// NOTE: if authenticated user has permission to post comments, then a
|
||||
// "Login or register to post comments" type link may be shown.
|
||||
$this->drupalGet('node/' . $this->node->nid);
|
||||
$this->assertNoPattern('@<h2[^>]*>Comments</h2>@', t('Comments were not displayed.'));
|
||||
$this->assertNoLink('Add new comment', t('Link to add comment was found.'));
|
||||
|
||||
// Attempt to view node-comment form while disallowed.
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid);
|
||||
$this->assertText('You are not authorized to post comments', t('Error attempting to post comment.'));
|
||||
$this->assertNoFieldByName('subject', '', t('Subject field not found.'));
|
||||
$this->assertNoFieldByName("comment_body[$langcode][0][value]", '', t('Comment field not found.'));
|
||||
|
||||
user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
|
||||
'access comments' => TRUE,
|
||||
'post comments' => FALSE,
|
||||
'skip comment approval' => FALSE,
|
||||
));
|
||||
$this->drupalGet('node/' . $this->node->nid);
|
||||
$this->assertPattern('@<h2[^>]*>Comments</h2>@', t('Comments were displayed.'));
|
||||
$this->assertLink('Log in', 1, t('Link to log in was found.'));
|
||||
$this->assertLink('register', 1, t('Link to register was found.'));
|
||||
|
||||
user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
|
||||
'access comments' => FALSE,
|
||||
'post comments' => TRUE,
|
||||
'skip comment approval' => TRUE,
|
||||
));
|
||||
$this->drupalGet('node/' . $this->node->nid);
|
||||
$this->assertNoPattern('@<h2[^>]*>Comments</h2>@', t('Comments were not displayed.'));
|
||||
$this->assertFieldByName('subject', '', t('Subject field found.'));
|
||||
$this->assertFieldByName("comment_body[$langcode][0][value]", '', t('Comment field found.'));
|
||||
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $anonymous_comment3->id);
|
||||
$this->assertText('You are not authorized to view comments', t('Error attempting to post reply.'));
|
||||
$this->assertNoText($author_name, t('Comment not displayed.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\comment\Tests\CommentApprovalTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
/**
|
||||
* Tests comment approval functionality.
|
||||
*/
|
||||
class CommentApprovalTest extends CommentTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Comment approval',
|
||||
'description' => 'Test comment approval functionality.',
|
||||
'group' => 'Comment',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test comment approval functionality through admin/content/comment.
|
||||
*/
|
||||
function testApprovalAdminInterface() {
|
||||
// Set anonymous comments to require approval.
|
||||
user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
|
||||
'access comments' => TRUE,
|
||||
'post comments' => TRUE,
|
||||
'skip comment approval' => FALSE,
|
||||
));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentAnonymous('0'); // Ensure that doesn't require contact info.
|
||||
|
||||
// Test that the comments page loads correctly when there are no comments
|
||||
$this->drupalGet('admin/content/comment');
|
||||
$this->assertText(t('No comments available.'));
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Post anonymous comment without contact info.
|
||||
$subject = $this->randomName();
|
||||
$body = $this->randomName();
|
||||
$this->postComment($this->node, $body, $subject, TRUE); // Set $contact to true so that it won't check for id and message.
|
||||
$this->assertText(t('Your comment has been queued for review by site administrators and will be published after approval.'), t('Comment requires approval.'));
|
||||
|
||||
// Get unapproved comment id.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$anonymous_comment4 = $this->getUnapprovedComment($subject);
|
||||
$anonymous_comment4 = entity_create('comment', array('id' => $anonymous_comment4, 'subject' => $subject, 'comment' => $body));
|
||||
$this->drupalLogout();
|
||||
|
||||
$this->assertFalse($this->commentExists($anonymous_comment4), t('Anonymous comment was not published.'));
|
||||
|
||||
// Approve comment.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->performCommentOperation($anonymous_comment4, 'publish', TRUE);
|
||||
$this->drupalLogout();
|
||||
|
||||
$this->drupalGet('node/' . $this->node->nid);
|
||||
$this->assertTrue($this->commentExists($anonymous_comment4), t('Anonymous comment visible.'));
|
||||
|
||||
// Post 2 anonymous comments without contact info.
|
||||
$comments[] = $this->postComment($this->node, $this->randomName(), $this->randomName(), TRUE);
|
||||
$comments[] = $this->postComment($this->node, $this->randomName(), $this->randomName(), TRUE);
|
||||
|
||||
// Publish multiple comments in one operation.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->drupalGet('admin/content/comment/approval');
|
||||
$this->assertText(t('Unapproved comments (@count)', array('@count' => 2)), t('Two unapproved comments waiting for approval.'));
|
||||
$edit = array(
|
||||
"comments[{$comments[0]->id}]" => 1,
|
||||
"comments[{$comments[1]->id}]" => 1,
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Update'));
|
||||
$this->assertText(t('Unapproved comments (@count)', array('@count' => 0)), t('All comments were approved.'));
|
||||
|
||||
// Delete multiple comments in one operation.
|
||||
$edit = array(
|
||||
'operation' => 'delete',
|
||||
"comments[{$comments[0]->id}]" => 1,
|
||||
"comments[{$comments[1]->id}]" => 1,
|
||||
"comments[{$anonymous_comment4->id}]" => 1,
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Update'));
|
||||
$this->assertText(t('Are you sure you want to delete these comments and all their children?'), t('Confirmation required.'));
|
||||
$this->drupalPost(NULL, $edit, t('Delete comments'));
|
||||
$this->assertText(t('No comments available.'), t('All comments were deleted.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests comment approval functionality through the node interface.
|
||||
*/
|
||||
function testApprovalNodeInterface() {
|
||||
// Set anonymous comments to require approval.
|
||||
user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
|
||||
'access comments' => TRUE,
|
||||
'post comments' => TRUE,
|
||||
'skip comment approval' => FALSE,
|
||||
));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentAnonymous('0'); // Ensure that doesn't require contact info.
|
||||
$this->drupalLogout();
|
||||
|
||||
// Post anonymous comment without contact info.
|
||||
$subject = $this->randomName();
|
||||
$body = $this->randomName();
|
||||
$this->postComment($this->node, $body, $subject, TRUE); // Set $contact to true so that it won't check for id and message.
|
||||
$this->assertText(t('Your comment has been queued for review by site administrators and will be published after approval.'), t('Comment requires approval.'));
|
||||
|
||||
// Get unapproved comment id.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$anonymous_comment4 = $this->getUnapprovedComment($subject);
|
||||
$anonymous_comment4 = entity_create('comment', array('id' => $anonymous_comment4, 'subject' => $subject, 'comment' => $body));
|
||||
$this->drupalLogout();
|
||||
|
||||
$this->assertFalse($this->commentExists($anonymous_comment4), t('Anonymous comment was not published.'));
|
||||
|
||||
// Approve comment.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->drupalGet('comment/1/approve');
|
||||
$this->assertResponse(403, t('Forged comment approval was denied.'));
|
||||
$this->drupalGet('comment/1/approve', array('query' => array('token' => 'forged')));
|
||||
$this->assertResponse(403, t('Forged comment approval was denied.'));
|
||||
$this->drupalGet('node/' . $this->node->nid);
|
||||
$this->clickLink(t('approve'));
|
||||
$this->drupalLogout();
|
||||
|
||||
$this->drupalGet('node/' . $this->node->nid);
|
||||
$this->assertTrue($this->commentExists($anonymous_comment4), t('Anonymous comment visible.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\comment\Tests\CommentBlockTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
/**
|
||||
* Tests the Comment module blocks.
|
||||
*/
|
||||
class CommentBlockTest extends CommentTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Comment blocks',
|
||||
'description' => 'Test comment block functionality.',
|
||||
'group' => 'Comment',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the recent comments block.
|
||||
*/
|
||||
function testRecentCommentBlock() {
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Set the block to a region to confirm block is available.
|
||||
$edit = array(
|
||||
'blocks[comment_recent][region]' => 'sidebar_first',
|
||||
);
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
$this->assertText(t('The block settings have been updated.'), t('Block saved to first sidebar region.'));
|
||||
|
||||
// Set block title and variables.
|
||||
$block = array(
|
||||
'title' => $this->randomName(),
|
||||
'comment_block_count' => 2,
|
||||
);
|
||||
$this->drupalPost('admin/structure/block/manage/comment/recent/configure', $block, t('Save block'));
|
||||
$this->assertText(t('The block configuration has been saved.'), t('Block saved.'));
|
||||
|
||||
// Add some test comments, one without a subject.
|
||||
$comment1 = $this->postComment($this->node, $this->randomName(), $this->randomName());
|
||||
$comment2 = $this->postComment($this->node, $this->randomName(), $this->randomName());
|
||||
$comment3 = $this->postComment($this->node, $this->randomName());
|
||||
|
||||
// Test that a user without the 'access comments' permission cannot see the
|
||||
// block.
|
||||
$this->drupalLogout();
|
||||
user_role_revoke_permissions(DRUPAL_ANONYMOUS_RID, array('access comments'));
|
||||
// drupalCreateNode() does not automatically flush content caches unlike
|
||||
// posting a node from a node form.
|
||||
cache_clear_all();
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText($block['title'], t('Block was not found.'));
|
||||
user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access comments'));
|
||||
|
||||
// Test that a user with the 'access comments' permission can see the
|
||||
// block.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('');
|
||||
$this->assertText($block['title'], t('Block was found.'));
|
||||
|
||||
// Test the only the 2 latest comments are shown and in the proper order.
|
||||
$this->assertNoText($comment1->subject, t('Comment not found in block.'));
|
||||
$this->assertText($comment2->subject, t('Comment found in block.'));
|
||||
$this->assertText($comment3->comment, t('Comment found in block.'));
|
||||
$this->assertTrue(strpos($this->drupalGetContent(), $comment3->comment) < strpos($this->drupalGetContent(), $comment2->subject), t('Comments were ordered correctly in block.'));
|
||||
|
||||
// Set the number of recent comments to show to 10.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$block = array(
|
||||
'comment_block_count' => 10,
|
||||
);
|
||||
$this->drupalPost('admin/structure/block/manage/comment/recent/configure', $block, t('Save block'));
|
||||
$this->assertText(t('The block configuration has been saved.'), t('Block saved.'));
|
||||
|
||||
// Post an additional comment.
|
||||
$comment4 = $this->postComment($this->node, $this->randomName(), $this->randomName());
|
||||
|
||||
// Test that all four comments are shown.
|
||||
$this->assertText($comment1->subject, t('Comment found in block.'));
|
||||
$this->assertText($comment2->subject, t('Comment found in block.'));
|
||||
$this->assertText($comment3->comment, t('Comment found in block.'));
|
||||
$this->assertText($comment4->subject, t('Comment found in block.'));
|
||||
|
||||
// Test that links to comments work when comments are across pages.
|
||||
$this->setCommentsPerPage(1);
|
||||
$this->drupalGet('');
|
||||
$this->clickLink($comment1->subject);
|
||||
$this->assertText($comment1->subject, t('Comment link goes to correct page.'));
|
||||
$this->drupalGet('');
|
||||
$this->clickLink($comment2->subject);
|
||||
$this->assertText($comment2->subject, t('Comment link goes to correct page.'));
|
||||
$this->clickLink($comment4->subject);
|
||||
$this->assertText($comment4->subject, t('Comment link goes to correct page.'));
|
||||
// Check that when viewing a comment page from a link to the comment, that
|
||||
// rel="canonical" is added to the head of the document.
|
||||
$this->assertRaw('<link rel="canonical"', t('Canonical URL was found in the HTML head'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\comment\Tests\CommentContentRebuildTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
/**
|
||||
* Tests comment content rebuilding.
|
||||
*/
|
||||
class CommentContentRebuildTest extends CommentTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Comment Rebuild',
|
||||
'description' => 'Test to make sure the comment content is rebuilt.',
|
||||
'group' => 'Comment',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the rebuilding of comment's content arrays on calling comment_view().
|
||||
*/
|
||||
function testCommentRebuild() {
|
||||
// Update the comment settings so preview isn't required.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentSubject(TRUE);
|
||||
$this->setCommentPreview(DRUPAL_OPTIONAL);
|
||||
$this->drupalLogout();
|
||||
|
||||
// Log in as the web user and add the comment.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$subject_text = $this->randomName();
|
||||
$comment_text = $this->randomName();
|
||||
$comment = $this->postComment($this->node, $comment_text, $subject_text, TRUE);
|
||||
$comment_loaded = comment_load($comment->id);
|
||||
$this->assertTrue($this->commentExists($comment), t('Comment found.'));
|
||||
|
||||
// Add the property to the content array and then see if it still exists on build.
|
||||
$comment_loaded->content['test_property'] = array('#value' => $this->randomString());
|
||||
$built_content = comment_view($comment_loaded, $this->node);
|
||||
|
||||
// This means that the content was rebuilt as the added test property no longer exists.
|
||||
$this->assertFalse(isset($built_content['test_property']), t('Comment content was emptied before being built.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\comment\Tests\CommentFieldsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
/**
|
||||
* Tests fields on comments.
|
||||
*/
|
||||
class CommentFieldsTest extends CommentTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Comment fields',
|
||||
'description' => 'Tests fields on comments.',
|
||||
'group' => 'Comment',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the default 'comment_body' field is correctly added.
|
||||
*/
|
||||
function testCommentDefaultFields() {
|
||||
// Do not make assumptions on default node types created by the test
|
||||
// install profile, and create our own.
|
||||
$this->drupalCreateContentType(array('type' => 'test_node_type'));
|
||||
|
||||
// Check that the 'comment_body' field is present on all comment bundles.
|
||||
$instances = field_info_instances('comment');
|
||||
foreach (node_type_get_types() as $type_name => $info) {
|
||||
$this->assertTrue(isset($instances['comment_node_' . $type_name]['comment_body']), t('The comment_body field is present for comments on type @type', array('@type' => $type_name)));
|
||||
|
||||
// Delete the instance along the way.
|
||||
field_delete_instance($instances['comment_node_' . $type_name]['comment_body']);
|
||||
}
|
||||
|
||||
// Check that the 'comment_body' field is deleted.
|
||||
$field = field_info_field('comment_body');
|
||||
$this->assertTrue(empty($field), t('The comment_body field was deleted'));
|
||||
|
||||
// Create a new content type.
|
||||
$type_name = 'test_node_type_2';
|
||||
$this->drupalCreateContentType(array('type' => $type_name));
|
||||
|
||||
// Check that the 'comment_body' field exists and has an instance on the
|
||||
// new comment bundle.
|
||||
$field = field_info_field('comment_body');
|
||||
$this->assertTrue($field, t('The comment_body field exists'));
|
||||
$instances = field_info_instances('comment');
|
||||
$this->assertTrue(isset($instances['comment_node_' . $type_name]['comment_body']), t('The comment_body field is present for comments on type @type', array('@type' => $type_name)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that comment module works when enabled after a content module.
|
||||
*/
|
||||
function testCommentEnable() {
|
||||
// Create a user to do module administration.
|
||||
$this->admin_user = $this->drupalCreateUser(array('access administration pages', 'administer modules'));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Disable the comment module.
|
||||
$edit = array();
|
||||
$edit['modules[Core][comment][enable]'] = FALSE;
|
||||
$this->drupalPost('admin/modules', $edit, t('Save configuration'));
|
||||
$this->resetAll();
|
||||
$this->assertFalse(module_exists('comment'), t('Comment module disabled.'));
|
||||
|
||||
// Enable core content type modules (book, and poll).
|
||||
$edit = array();
|
||||
$edit['modules[Core][book][enable]'] = 'book';
|
||||
$edit['modules[Core][poll][enable]'] = 'poll';
|
||||
$this->drupalPost('admin/modules', $edit, t('Save configuration'));
|
||||
|
||||
// Now enable the comment module.
|
||||
$edit = array();
|
||||
$edit['modules[Core][comment][enable]'] = 'comment';
|
||||
$this->drupalPost('admin/modules', $edit, t('Save configuration'));
|
||||
$this->resetAll();
|
||||
$this->assertTrue(module_exists('comment'), t('Comment module enabled.'));
|
||||
|
||||
// Create nodes of each type.
|
||||
$book_node = $this->drupalCreateNode(array('type' => 'book'));
|
||||
$poll_node = $this->drupalCreateNode(array('type' => 'poll', 'active' => 1, 'runtime' => 0, 'choice' => array(array('chtext' => ''))));
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Try to post a comment on each node. A failure will be triggered if the
|
||||
// comment body is missing on one of these forms, due to postComment()
|
||||
// asserting that the body is actually posted correctly.
|
||||
$this->web_user = $this->drupalCreateUser(array('access content', 'access comments', 'post comments', 'skip comment approval'));
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->postComment($book_node, $this->randomName(), $this->randomName());
|
||||
$this->postComment($poll_node, $this->randomName(), $this->randomName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that comment module works correctly with plain text format.
|
||||
*/
|
||||
function testCommentFormat() {
|
||||
// Disable text processing for comments.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$edit = array('instance[settings][text_processing]' => 0);
|
||||
$this->drupalPost('admin/structure/types/manage/article/comment/fields/comment_body', $edit, t('Save settings'));
|
||||
|
||||
// Post a comment without an explicit subject.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$edit = array('comment_body[und][0][value]' => $this->randomName(8));
|
||||
$this->drupalPost('node/' . $this->node->nid, $edit, t('Save'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,702 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\comment\Tests\CommentInterfaceTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
class CommentInterfaceTest extends CommentTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Comment interface',
|
||||
'description' => 'Test comment user interfaces.',
|
||||
'group' => 'Comment',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the comment interface.
|
||||
*/
|
||||
function testCommentInterface() {
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
// Set comments to have subject and preview disabled.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentPreview(DRUPAL_DISABLED);
|
||||
$this->setCommentForm(TRUE);
|
||||
$this->setCommentSubject(FALSE);
|
||||
$this->setCommentSettings('comment_default_mode', COMMENT_MODE_THREADED, t('Comment paging changed.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Post comment #1 without subject or preview.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$comment_text = $this->randomName();
|
||||
$comment = $this->postComment($this->node, $comment_text);
|
||||
$comment_loaded = comment_load($comment->id);
|
||||
$this->assertTrue($this->commentExists($comment), t('Comment found.'));
|
||||
|
||||
// Set comments to have subject and preview to required.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentSubject(TRUE);
|
||||
$this->setCommentPreview(DRUPAL_REQUIRED);
|
||||
$this->drupalLogout();
|
||||
|
||||
// Create comment #2 that allows subject and requires preview.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$subject_text = $this->randomName();
|
||||
$comment_text = $this->randomName();
|
||||
$comment = $this->postComment($this->node, $comment_text, $subject_text, TRUE);
|
||||
$comment_loaded = comment_load($comment->id);
|
||||
$this->assertTrue($this->commentExists($comment), t('Comment found.'));
|
||||
|
||||
// Check comment display.
|
||||
$this->drupalGet('node/' . $this->node->nid . '/' . $comment->id);
|
||||
$this->assertText($subject_text, t('Individual comment subject found.'));
|
||||
$this->assertText($comment_text, t('Individual comment body found.'));
|
||||
|
||||
// Set comments to have subject and preview to optional.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentSubject(TRUE);
|
||||
$this->setCommentPreview(DRUPAL_OPTIONAL);
|
||||
|
||||
// Test changing the comment author to "Anonymous".
|
||||
$this->drupalGet('comment/' . $comment->id . '/edit');
|
||||
$comment = $this->postComment(NULL, $comment->comment, $comment->subject, array('name' => ''));
|
||||
$comment_loaded = comment_load($comment->id);
|
||||
$this->assertTrue(empty($comment_loaded->name) && $comment_loaded->uid == 0, t('Comment author successfully changed to anonymous.'));
|
||||
|
||||
// Test changing the comment author to an unverified user.
|
||||
$random_name = $this->randomName();
|
||||
$this->drupalGet('comment/' . $comment->id . '/edit');
|
||||
$comment = $this->postComment(NULL, $comment->comment, $comment->subject, array('name' => $random_name));
|
||||
$this->drupalGet('node/' . $this->node->nid);
|
||||
$this->assertText($random_name . ' (' . t('not verified') . ')', t('Comment author successfully changed to an unverified user.'));
|
||||
|
||||
// Test changing the comment author to a verified user.
|
||||
$this->drupalGet('comment/' . $comment->id . '/edit');
|
||||
$comment = $this->postComment(NULL, $comment->comment, $comment->subject, array('name' => $this->web_user->name));
|
||||
$comment_loaded = comment_load($comment->id);
|
||||
$this->assertTrue($comment_loaded->name == $this->web_user->name && $comment_loaded->uid == $this->web_user->uid, t('Comment author successfully changed to a registered user.'));
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Reply to comment #2 creating comment #3 with optional preview and no
|
||||
// subject though field enabled.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id);
|
||||
$this->assertText($subject_text, t('Individual comment-reply subject found.'));
|
||||
$this->assertText($comment_text, t('Individual comment-reply body found.'));
|
||||
$reply = $this->postComment(NULL, $this->randomName(), '', TRUE);
|
||||
$reply_loaded = comment_load($reply->id);
|
||||
$this->assertTrue($this->commentExists($reply, TRUE), t('Reply found.'));
|
||||
$this->assertEqual($comment->id, $reply_loaded->pid, t('Pid of a reply to a comment is set correctly.'));
|
||||
$this->assertEqual(rtrim($comment_loaded->thread, '/') . '.00/', $reply_loaded->thread, t('Thread of reply grows correctly.'));
|
||||
|
||||
// Second reply to comment #3 creating comment #4.
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id);
|
||||
$this->assertText($subject_text, t('Individual comment-reply subject found.'));
|
||||
$this->assertText($comment_text, t('Individual comment-reply body found.'));
|
||||
$reply = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
$reply_loaded = comment_load($reply->id);
|
||||
$this->assertTrue($this->commentExists($reply, TRUE), t('Second reply found.'));
|
||||
$this->assertEqual(rtrim($comment_loaded->thread, '/') . '.01/', $reply_loaded->thread, t('Thread of second reply grows correctly.'));
|
||||
|
||||
// Edit reply.
|
||||
$this->drupalGet('comment/' . $reply->id . '/edit');
|
||||
$reply = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
$this->assertTrue($this->commentExists($reply, TRUE), t('Modified reply found.'));
|
||||
|
||||
// Correct link count
|
||||
$this->drupalGet('node');
|
||||
$this->assertRaw('4 comments', t('Link to the 4 comments exist.'));
|
||||
|
||||
// Confirm a new comment is posted to the correct page.
|
||||
$this->setCommentsPerPage(2);
|
||||
$comment_new_page = $this->postComment($this->node, $this->randomName(), $this->randomName(), TRUE);
|
||||
$this->assertTrue($this->commentExists($comment_new_page), t('Page one exists. %s'));
|
||||
$this->drupalGet('node/' . $this->node->nid, array('query' => array('page' => 1)));
|
||||
$this->assertTrue($this->commentExists($reply, TRUE), t('Page two exists. %s'));
|
||||
$this->setCommentsPerPage(50);
|
||||
|
||||
// Attempt to reply to an unpublished comment.
|
||||
$reply_loaded->status = COMMENT_NOT_PUBLISHED;
|
||||
$reply_loaded->save();
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $reply_loaded->cid);
|
||||
$this->assertText(t('The comment you are replying to does not exist.'), 'Replying to an unpublished comment');
|
||||
|
||||
// Attempt to post to node with comments disabled.
|
||||
$this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => COMMENT_NODE_HIDDEN));
|
||||
$this->assertTrue($this->node, t('Article node created.'));
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid);
|
||||
$this->assertText('This discussion is closed', t('Posting to node with comments disabled'));
|
||||
$this->assertNoField('edit-comment', t('Comment body field found.'));
|
||||
|
||||
// Attempt to post to node with read-only comments.
|
||||
$this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => COMMENT_NODE_CLOSED));
|
||||
$this->assertTrue($this->node, t('Article node created.'));
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid);
|
||||
$this->assertText('This discussion is closed', t('Posting to node with comments read-only'));
|
||||
$this->assertNoField('edit-comment', t('Comment body field found.'));
|
||||
|
||||
// Attempt to post to node with comments enabled (check field names etc).
|
||||
$this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => COMMENT_NODE_OPEN));
|
||||
$this->assertTrue($this->node, t('Article node created.'));
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid);
|
||||
$this->assertNoText('This discussion is closed', t('Posting to node with comments enabled'));
|
||||
$this->assertField('edit-comment-body-' . $langcode . '-0-value', t('Comment body field found.'));
|
||||
|
||||
// Delete comment and make sure that reply is also removed.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->deleteComment($comment);
|
||||
$this->deleteComment($comment_new_page);
|
||||
|
||||
$this->drupalGet('node/' . $this->node->nid);
|
||||
$this->assertFalse($this->commentExists($comment), t('Comment not found.'));
|
||||
$this->assertFalse($this->commentExists($reply, TRUE), t('Reply not found.'));
|
||||
|
||||
// Enabled comment form on node page.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentForm(TRUE);
|
||||
$this->drupalLogout();
|
||||
|
||||
// Submit comment through node form.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('node/' . $this->node->nid);
|
||||
$form_comment = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
$this->assertTrue($this->commentExists($form_comment), t('Form comment found.'));
|
||||
|
||||
// Disable comment form on node page.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentForm(FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests new comment marker.
|
||||
*/
|
||||
public function testCommentNewCommentsIndicator() {
|
||||
// Test if the right links are displayed when no comment is present for the
|
||||
// node.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'comment' => COMMENT_NODE_OPEN));
|
||||
$this->drupalGet('node');
|
||||
$this->assertNoLink(t('@count comments', array('@count' => 0)));
|
||||
$this->assertNoLink(t('@count new comments', array('@count' => 0)));
|
||||
$this->assertLink(t('Read more'));
|
||||
$count = $this->xpath('//div[@id=:id]/div[@class=:class]/ul/li', array(':id' => 'node-' . $this->node->nid, ':class' => 'link-wrapper'));
|
||||
$this->assertTrue(count($count) == 1, t('One child found'));
|
||||
|
||||
// Create a new comment. This helper function may be run with different
|
||||
// comment settings so use comment_save() to avoid complex setup.
|
||||
$comment = entity_create('comment', array(
|
||||
'cid' => NULL,
|
||||
'nid' => $this->node->nid,
|
||||
'node_type' => $this->node->type,
|
||||
'pid' => 0,
|
||||
'uid' => $this->loggedInUser->uid,
|
||||
'status' => COMMENT_PUBLISHED,
|
||||
'subject' => $this->randomName(),
|
||||
'hostname' => ip_address(),
|
||||
'langcode' => LANGUAGE_NOT_SPECIFIED,
|
||||
'comment_body' => array(LANGUAGE_NOT_SPECIFIED => array($this->randomName())),
|
||||
));
|
||||
comment_save($comment);
|
||||
$this->drupalLogout();
|
||||
|
||||
// Log in with 'web user' and check comment links.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('node');
|
||||
$this->assertLink(t('1 new comment'));
|
||||
$this->clickLink(t('1 new comment'));
|
||||
$this->assertRaw('<a id="new"></a>', t('Found "new" marker.'));
|
||||
$this->assertTrue($this->xpath('//a[@id=:new]/following-sibling::a[1][@id=:comment_id]', array(':new' => 'new', ':comment_id' => 'comment-1')), t('The "new" anchor is positioned at the right comment.'));
|
||||
|
||||
// Test if "new comment" link is correctly removed.
|
||||
$this->drupalGet('node');
|
||||
$this->assertLink(t('1 comment'));
|
||||
$this->assertLink(t('Read more'));
|
||||
$this->assertNoLink(t('1 new comment'));
|
||||
$this->assertNoLink(t('@count new comments', array('@count' => 0)));
|
||||
$count = $this->xpath('//div[@id=:id]/div[@class=:class]/ul/li', array(':id' => 'node-' . $this->node->nid, ':class' => 'link-wrapper'));
|
||||
$this->assertTrue(count($count) == 2, print_r($count, TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests CSS classes on comments.
|
||||
*/
|
||||
function testCommentClasses() {
|
||||
// Create all permutations for comments, users, and nodes.
|
||||
$parameters = array(
|
||||
'node_uid' => array(0, $this->web_user->uid),
|
||||
'comment_uid' => array(0, $this->web_user->uid, $this->admin_user->uid),
|
||||
'comment_status' => array(COMMENT_PUBLISHED, COMMENT_NOT_PUBLISHED),
|
||||
'user' => array('anonymous', 'authenticated', 'admin'),
|
||||
);
|
||||
$permutations = $this->generatePermutations($parameters);
|
||||
|
||||
foreach ($permutations as $case) {
|
||||
// Create a new node.
|
||||
$node = $this->drupalCreateNode(array('type' => 'article', 'uid' => $case['node_uid']));
|
||||
|
||||
// Add a comment.
|
||||
$comment = entity_create('comment', array(
|
||||
'nid' => $node->nid,
|
||||
'uid' => $case['comment_uid'],
|
||||
'status' => $case['comment_status'],
|
||||
'subject' => $this->randomName(),
|
||||
'language' => LANGUAGE_NOT_SPECIFIED,
|
||||
'comment_body' => array(LANGUAGE_NOT_SPECIFIED => array($this->randomName())),
|
||||
));
|
||||
comment_save($comment);
|
||||
|
||||
// Adjust the current/viewing user.
|
||||
switch ($case['user']) {
|
||||
case 'anonymous':
|
||||
if ($this->loggedInUser) {
|
||||
$this->drupalLogout();
|
||||
}
|
||||
$case['user_uid'] = 0;
|
||||
break;
|
||||
|
||||
case 'authenticated':
|
||||
$this->drupalLogin($this->web_user);
|
||||
$case['user_uid'] = $this->web_user->uid;
|
||||
break;
|
||||
|
||||
case 'admin':
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$case['user_uid'] = $this->admin_user->uid;
|
||||
break;
|
||||
}
|
||||
// Request the node with the comment.
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
|
||||
// Verify classes if the comment is visible for the current user.
|
||||
if ($case['comment_status'] == COMMENT_PUBLISHED || $case['user'] == 'admin') {
|
||||
// Verify the by-anonymous class.
|
||||
$comments = $this->xpath('//*[contains(@class, "comment") and contains(@class, "by-anonymous")]');
|
||||
if ($case['comment_uid'] == 0) {
|
||||
$this->assertTrue(count($comments) == 1, 'by-anonymous class found.');
|
||||
}
|
||||
else {
|
||||
$this->assertFalse(count($comments), 'by-anonymous class not found.');
|
||||
}
|
||||
|
||||
// Verify the by-node-author class.
|
||||
$comments = $this->xpath('//*[contains(@class, "comment") and contains(@class, "by-node-author")]');
|
||||
if ($case['comment_uid'] > 0 && $case['comment_uid'] == $case['node_uid']) {
|
||||
$this->assertTrue(count($comments) == 1, 'by-node-author class found.');
|
||||
}
|
||||
else {
|
||||
$this->assertFalse(count($comments), 'by-node-author class not found.');
|
||||
}
|
||||
|
||||
// Verify the by-viewer class.
|
||||
$comments = $this->xpath('//*[contains(@class, "comment") and contains(@class, "by-viewer")]');
|
||||
if ($case['comment_uid'] > 0 && $case['comment_uid'] == $case['user_uid']) {
|
||||
$this->assertTrue(count($comments) == 1, 'by-viewer class found.');
|
||||
}
|
||||
else {
|
||||
$this->assertFalse(count($comments), 'by-viewer class not found.');
|
||||
}
|
||||
}
|
||||
|
||||
// Verify the unpublished class.
|
||||
$comments = $this->xpath('//*[contains(@class, "comment") and contains(@class, "unpublished")]');
|
||||
if ($case['comment_status'] == COMMENT_NOT_PUBLISHED && $case['user'] == 'admin') {
|
||||
$this->assertTrue(count($comments) == 1, 'unpublished class found.');
|
||||
}
|
||||
else {
|
||||
$this->assertFalse(count($comments), 'unpublished class not found.');
|
||||
}
|
||||
|
||||
// Verify the new class.
|
||||
if ($case['comment_status'] == COMMENT_PUBLISHED || $case['user'] == 'admin') {
|
||||
$comments = $this->xpath('//*[contains(@class, "comment") and contains(@class, "new")]');
|
||||
if ($case['user'] != 'anonymous') {
|
||||
$this->assertTrue(count($comments) == 1, 'new class found.');
|
||||
|
||||
// Request the node again. The new class should disappear.
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$comments = $this->xpath('//*[contains(@class, "comment") and contains(@class, "new")]');
|
||||
$this->assertFalse(count($comments), 'new class not found.');
|
||||
}
|
||||
else {
|
||||
$this->assertFalse(count($comments), 'new class not found.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the node comment statistics.
|
||||
*/
|
||||
function testCommentNodeCommentStatistics() {
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
// Set comments to have subject and preview disabled.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentPreview(DRUPAL_DISABLED);
|
||||
$this->setCommentForm(TRUE);
|
||||
$this->setCommentSubject(FALSE);
|
||||
$this->setCommentSettings('comment_default_mode', COMMENT_MODE_THREADED, t('Comment paging changed.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Creates a second user to post comments.
|
||||
$this->web_user2 = $this->drupalCreateUser(array('access comments', 'post comments', 'create article content', 'edit own comments'));
|
||||
|
||||
// Checks the initial values of node comment statistics with no comment.
|
||||
$node = node_load($this->node->nid);
|
||||
$this->assertEqual($node->last_comment_timestamp, $this->node->created, t('The initial value of node last_comment_timestamp is the node created date.'));
|
||||
$this->assertEqual($node->last_comment_name, NULL, t('The initial value of node last_comment_name is NULL.'));
|
||||
$this->assertEqual($node->last_comment_uid, $this->web_user->uid, t('The initial value of node last_comment_uid is the node uid.'));
|
||||
$this->assertEqual($node->comment_count, 0, t('The initial value of node comment_count is zero.'));
|
||||
|
||||
// Post comment #1 as web_user2.
|
||||
$this->drupalLogin($this->web_user2);
|
||||
$comment_text = $this->randomName();
|
||||
$comment = $this->postComment($this->node, $comment_text);
|
||||
$comment_loaded = comment_load($comment->id);
|
||||
|
||||
// Checks the new values of node comment statistics with comment #1.
|
||||
// The node needs to be reloaded with a node_load_multiple cache reset.
|
||||
$node = node_load($this->node->nid, NULL, TRUE);
|
||||
$this->assertEqual($node->last_comment_name, NULL, t('The value of node last_comment_name is NULL.'));
|
||||
$this->assertEqual($node->last_comment_uid, $this->web_user2->uid, t('The value of node last_comment_uid is the comment #1 uid.'));
|
||||
$this->assertEqual($node->comment_count, 1, t('The value of node comment_count is 1.'));
|
||||
|
||||
// Prepare for anonymous comment submission (comment approval enabled).
|
||||
variable_set('user_register', USER_REGISTER_VISITORS);
|
||||
$this->drupalLogin($this->admin_user);
|
||||
user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
|
||||
'access comments' => TRUE,
|
||||
'post comments' => TRUE,
|
||||
'skip comment approval' => FALSE,
|
||||
));
|
||||
// Ensure that the poster can leave some contact info.
|
||||
$this->setCommentAnonymous('1');
|
||||
$this->drupalLogout();
|
||||
|
||||
// Post comment #2 as anonymous (comment approval enabled).
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid);
|
||||
$anonymous_comment = $this->postComment($this->node, $this->randomName(), '', TRUE);
|
||||
$comment_unpublished_loaded = comment_load($anonymous_comment->id);
|
||||
|
||||
// Checks the new values of node comment statistics with comment #2 and
|
||||
// ensure they haven't changed since the comment has not been moderated.
|
||||
// The node needs to be reloaded with a node_load_multiple cache reset.
|
||||
$node = node_load($this->node->nid, NULL, TRUE);
|
||||
$this->assertEqual($node->last_comment_name, NULL, t('The value of node last_comment_name is still NULL.'));
|
||||
$this->assertEqual($node->last_comment_uid, $this->web_user2->uid, t('The value of node last_comment_uid is still the comment #1 uid.'));
|
||||
$this->assertEqual($node->comment_count, 1, t('The value of node comment_count is still 1.'));
|
||||
|
||||
// Prepare for anonymous comment submission (no approval required).
|
||||
$this->drupalLogin($this->admin_user);
|
||||
user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
|
||||
'access comments' => TRUE,
|
||||
'post comments' => TRUE,
|
||||
'skip comment approval' => TRUE,
|
||||
));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Post comment #3 as anonymous.
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid);
|
||||
$anonymous_comment = $this->postComment($this->node, $this->randomName(), '', array('name' => $this->randomName()));
|
||||
$comment_loaded = comment_load($anonymous_comment->id);
|
||||
|
||||
// Checks the new values of node comment statistics with comment #3.
|
||||
// The node needs to be reloaded with a node_load_multiple cache reset.
|
||||
$node = node_load($this->node->nid, NULL, TRUE);
|
||||
$this->assertEqual($node->last_comment_name, $comment_loaded->name, t('The value of node last_comment_name is the name of the anonymous user.'));
|
||||
$this->assertEqual($node->last_comment_uid, 0, t('The value of node last_comment_uid is zero.'));
|
||||
$this->assertEqual($node->comment_count, 2, t('The value of node comment_count is 2.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests comment links.
|
||||
*
|
||||
* The output of comment links depends on various environment conditions:
|
||||
* - Various Comment module configuration settings, user registration
|
||||
* settings, and user access permissions.
|
||||
* - Whether the user is authenticated or not, and whether any comments exist.
|
||||
*
|
||||
* To account for all possible cases, this test creates permutations of all
|
||||
* possible conditions and tests the expected appearance of comment links in
|
||||
* each environment.
|
||||
*/
|
||||
function testCommentLinks() {
|
||||
// Bartik theme alters comment links, so use a different theme.
|
||||
theme_enable(array('stark'));
|
||||
variable_set('theme_default', 'stark');
|
||||
|
||||
// Remove additional user permissions from $this->web_user added by setUp(),
|
||||
// since this test is limited to anonymous and authenticated roles only.
|
||||
user_role_delete(key($this->web_user->roles));
|
||||
|
||||
// Matrix of possible environmental conditions and configuration settings.
|
||||
// See setEnvironment() for details.
|
||||
$conditions = array(
|
||||
'authenticated' => array(FALSE, TRUE),
|
||||
'comment count' => array(FALSE, TRUE),
|
||||
'access comments' => array(0, 1),
|
||||
'post comments' => array(0, 1),
|
||||
'form' => array(COMMENT_FORM_BELOW, COMMENT_FORM_SEPARATE_PAGE),
|
||||
// USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL is irrelevant for this
|
||||
// test; there is only a difference between open and closed registration.
|
||||
'user_register' => array(USER_REGISTER_VISITORS, USER_REGISTER_ADMINISTRATORS_ONLY),
|
||||
// @todo Complete test coverage for:
|
||||
//'comments' => array(COMMENT_NODE_OPEN, COMMENT_NODE_CLOSED, COMMENT_NODE_HIDDEN),
|
||||
//// COMMENT_ANONYMOUS_MUST_CONTACT is irrelevant for this test.
|
||||
//'contact ' => array(COMMENT_ANONYMOUS_MAY_CONTACT, COMMENT_ANONYMOUS_MAYNOT_CONTACT),
|
||||
);
|
||||
|
||||
$environments = $this->generatePermutations($conditions);
|
||||
foreach ($environments as $info) {
|
||||
$this->assertCommentLinks($info);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-configures the environment, module settings, and user permissions.
|
||||
*
|
||||
* @param $info
|
||||
* An associative array describing the environment to setup:
|
||||
* - Environment conditions:
|
||||
* - authenticated: Boolean whether to test with $this->web_user or
|
||||
* anonymous.
|
||||
* - comment count: Boolean whether to test with a new/unread comment on
|
||||
* $this->node or no comments.
|
||||
* - Configuration settings:
|
||||
* - form: COMMENT_FORM_BELOW or COMMENT_FORM_SEPARATE_PAGE.
|
||||
* - user_register: USER_REGISTER_ADMINISTRATORS_ONLY or
|
||||
* USER_REGISTER_VISITORS.
|
||||
* - contact: COMMENT_ANONYMOUS_MAY_CONTACT or
|
||||
* COMMENT_ANONYMOUS_MAYNOT_CONTACT.
|
||||
* - comments: COMMENT_NODE_OPEN, COMMENT_NODE_CLOSED, or
|
||||
* COMMENT_NODE_HIDDEN.
|
||||
* - User permissions:
|
||||
* These are granted or revoked for the user, according to the
|
||||
* 'authenticated' flag above. Pass 0 or 1 as parameter values. See
|
||||
* user_role_change_permissions().
|
||||
* - access comments
|
||||
* - post comments
|
||||
* - skip comment approval
|
||||
* - edit own comments
|
||||
*/
|
||||
function setEnvironment(array $info) {
|
||||
static $current;
|
||||
|
||||
// Apply defaults to initial environment.
|
||||
if (!isset($current)) {
|
||||
$current = array(
|
||||
'authenticated' => FALSE,
|
||||
'comment count' => FALSE,
|
||||
'form' => COMMENT_FORM_BELOW,
|
||||
'user_register' => USER_REGISTER_VISITORS,
|
||||
'contact' => COMMENT_ANONYMOUS_MAY_CONTACT,
|
||||
'comments' => COMMENT_NODE_OPEN,
|
||||
'access comments' => 0,
|
||||
'post comments' => 0,
|
||||
// Enabled by default, because it's irrelevant for this test.
|
||||
'skip comment approval' => 1,
|
||||
'edit own comments' => 0,
|
||||
);
|
||||
}
|
||||
// Complete new environment with current environment.
|
||||
$info = array_merge($current, $info);
|
||||
|
||||
// Change environment conditions.
|
||||
if ($current['authenticated'] != $info['authenticated']) {
|
||||
if ($this->loggedInUser) {
|
||||
$this->drupalLogout();
|
||||
}
|
||||
else {
|
||||
$this->drupalLogin($this->web_user);
|
||||
}
|
||||
}
|
||||
if ($current['comment count'] != $info['comment count']) {
|
||||
if ($info['comment count']) {
|
||||
// Create a comment via CRUD API functionality, since
|
||||
// $this->postComment() relies on actual user permissions.
|
||||
$comment = entity_create('comment', array(
|
||||
'cid' => NULL,
|
||||
'nid' => $this->node->nid,
|
||||
'node_type' => $this->node->type,
|
||||
'pid' => 0,
|
||||
'uid' => 0,
|
||||
'status' => COMMENT_PUBLISHED,
|
||||
'subject' => $this->randomName(),
|
||||
'hostname' => ip_address(),
|
||||
'langcode' => LANGUAGE_NOT_SPECIFIED,
|
||||
'comment_body' => array(LANGUAGE_NOT_SPECIFIED => array($this->randomName())),
|
||||
));
|
||||
comment_save($comment);
|
||||
$this->comment = $comment;
|
||||
|
||||
// comment_num_new() relies on node_last_viewed(), so ensure that no one
|
||||
// has seen the node of this comment.
|
||||
db_delete('history')->condition('nid', $this->node->nid)->execute();
|
||||
}
|
||||
else {
|
||||
$cids = db_query("SELECT cid FROM {comment}")->fetchCol();
|
||||
comment_delete_multiple($cids);
|
||||
unset($this->comment);
|
||||
}
|
||||
}
|
||||
|
||||
// Change comment settings.
|
||||
variable_set('comment_form_location_' . $this->node->type, $info['form']);
|
||||
variable_set('comment_anonymous_' . $this->node->type, $info['contact']);
|
||||
if ($this->node->comment != $info['comments']) {
|
||||
$this->node->comment = $info['comments'];
|
||||
node_save($this->node);
|
||||
}
|
||||
|
||||
// Change user settings.
|
||||
variable_set('user_register', $info['user_register']);
|
||||
|
||||
// Change user permissions.
|
||||
$rid = ($this->loggedInUser ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID);
|
||||
$perms = array_intersect_key($info, array('access comments' => 1, 'post comments' => 1, 'skip comment approval' => 1, 'edit own comments' => 1));
|
||||
user_role_change_permissions($rid, $perms);
|
||||
|
||||
// Output verbose debugging information.
|
||||
// @see Drupal\simpletest\TestBase::error()
|
||||
$t_form = array(
|
||||
COMMENT_FORM_BELOW => 'below',
|
||||
COMMENT_FORM_SEPARATE_PAGE => 'separate page',
|
||||
);
|
||||
$t_contact = array(
|
||||
COMMENT_ANONYMOUS_MAY_CONTACT => 'optional',
|
||||
COMMENT_ANONYMOUS_MAYNOT_CONTACT => 'disabled',
|
||||
COMMENT_ANONYMOUS_MUST_CONTACT => 'required',
|
||||
);
|
||||
$t_comments = array(
|
||||
COMMENT_NODE_OPEN => 'open',
|
||||
COMMENT_NODE_CLOSED => 'closed',
|
||||
COMMENT_NODE_HIDDEN => 'hidden',
|
||||
);
|
||||
$verbose = $info;
|
||||
$verbose['form'] = $t_form[$info['form']];
|
||||
$verbose['contact'] = $t_contact[$info['contact']];
|
||||
$verbose['comments'] = $t_comments[$info['comments']];
|
||||
$message = t('Changed environment:<pre>@verbose</pre>', array(
|
||||
'@verbose' => var_export($verbose, TRUE),
|
||||
));
|
||||
$this->assert('debug', $message, 'Debug');
|
||||
|
||||
// Update current environment.
|
||||
$current = $info;
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that comment links appear according to the passed environment.
|
||||
*
|
||||
* @param $info
|
||||
* An associative array describing the environment to pass to
|
||||
* setEnvironment().
|
||||
*/
|
||||
function assertCommentLinks(array $info) {
|
||||
$info = $this->setEnvironment($info);
|
||||
|
||||
$nid = $this->node->nid;
|
||||
|
||||
foreach (array('', "node/$nid") as $path) {
|
||||
$this->drupalGet($path);
|
||||
|
||||
// User is allowed to view comments.
|
||||
if ($info['access comments']) {
|
||||
if ($path == '') {
|
||||
// In teaser view, a link containing the comment count is always
|
||||
// expected.
|
||||
if ($info['comment count']) {
|
||||
$this->assertLink(t('1 comment'));
|
||||
|
||||
// For logged in users, a link containing the amount of new/unread
|
||||
// comments is expected.
|
||||
// See important note about comment_num_new() below.
|
||||
if ($this->loggedInUser && isset($this->comment) && !isset($this->comment->seen)) {
|
||||
$this->assertLink(t('1 new comment'));
|
||||
$this->comment->seen = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->assertNoLink(t('1 comment'));
|
||||
$this->assertNoLink(t('1 new comment'));
|
||||
}
|
||||
// comment_num_new() is based on node views, so comments are marked as
|
||||
// read when a node is viewed, regardless of whether we have access to
|
||||
// comments.
|
||||
if ($path == "node/$nid" && $this->loggedInUser && isset($this->comment)) {
|
||||
$this->comment->seen = TRUE;
|
||||
}
|
||||
|
||||
// User is not allowed to post comments.
|
||||
if (!$info['post comments']) {
|
||||
$this->assertNoLink('Add new comment');
|
||||
|
||||
// Anonymous users should see a note to log in or register in case
|
||||
// authenticated users are allowed to post comments.
|
||||
// @see theme_comment_post_forbidden()
|
||||
if (!$this->loggedInUser) {
|
||||
if (user_access('post comments', $this->web_user)) {
|
||||
// The note depends on whether users are actually able to register.
|
||||
if ($info['user_register']) {
|
||||
$this->assertText('Log in or register to post comments');
|
||||
}
|
||||
else {
|
||||
$this->assertText('Log in to post comments');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->assertNoText('Log in or register to post comments');
|
||||
$this->assertNoText('Log in to post comments');
|
||||
}
|
||||
}
|
||||
}
|
||||
// User is allowed to post comments.
|
||||
else {
|
||||
$this->assertNoText('Log in or register to post comments');
|
||||
|
||||
// "Add new comment" is always expected, except when there are no
|
||||
// comments or if the user cannot see them.
|
||||
if ($path == "node/$nid" && $info['form'] == COMMENT_FORM_BELOW && (!$info['comment count'] || !$info['access comments'])) {
|
||||
$this->assertNoLink('Add new comment');
|
||||
}
|
||||
else {
|
||||
$this->assertLink('Add new comment');
|
||||
|
||||
// Verify that the "Add new comment" link points to the correct URL
|
||||
// based on the comment form location configuration.
|
||||
if ($info['form'] == COMMENT_FORM_SEPARATE_PAGE) {
|
||||
$this->assertLinkByHref("comment/reply/$nid#comment-form", 0, 'Comment form link destination is on a separate page.');
|
||||
$this->assertNoLinkByHref("node/$nid#comment-form");
|
||||
}
|
||||
else {
|
||||
$this->assertLinkByHref("node/$nid#comment-form", 0, 'Comment form link destination is on node.');
|
||||
$this->assertNoLinkByHref("comment/reply/$nid#comment-form");
|
||||
}
|
||||
}
|
||||
|
||||
// Also verify that the comment form appears according to the configured
|
||||
// location.
|
||||
if ($path == "node/$nid") {
|
||||
$elements = $this->xpath('//form[@id=:id]', array(':id' => 'comment-form'));
|
||||
if ($info['form'] == COMMENT_FORM_BELOW) {
|
||||
$this->assertTrue(count($elements), t('Comment form found below.'));
|
||||
}
|
||||
else {
|
||||
$this->assertFalse(count($elements), t('Comment form not found below.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\comment\Tests\CommentNodeAccessTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests comments with node access.
|
||||
*
|
||||
* See http://drupal.org/node/886752 -- verify there is no PostgreSQL error when
|
||||
* viewing a node with threaded comments (a comment and a reply), if a node
|
||||
* access module is in use.
|
||||
*/
|
||||
class CommentNodeAccessTest extends CommentTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Comment node access',
|
||||
'description' => 'Test comment viewing with node access.',
|
||||
'group' => 'Comment',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
WebTestBase::setUp('comment', 'search', 'node_access_test');
|
||||
node_access_rebuild();
|
||||
|
||||
// Create users and test node.
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer comments', 'administer blocks'));
|
||||
$this->web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'create article content', 'edit own comments', 'node test view'));
|
||||
$this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'uid' => $this->web_user->uid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that threaded comments can be viewed.
|
||||
*/
|
||||
function testThreadedCommentView() {
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
// Set comments to have subject required and preview disabled.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentPreview(DRUPAL_DISABLED);
|
||||
$this->setCommentForm(TRUE);
|
||||
$this->setCommentSubject(TRUE);
|
||||
$this->setCommentSettings('comment_default_mode', COMMENT_MODE_THREADED, t('Comment paging changed.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Post comment.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$comment_text = $this->randomName();
|
||||
$comment_subject = $this->randomName();
|
||||
$comment = $this->postComment($this->node, $comment_text, $comment_subject);
|
||||
$comment_loaded = comment_load($comment->id);
|
||||
$this->assertTrue($this->commentExists($comment), t('Comment found.'));
|
||||
|
||||
// Check comment display.
|
||||
$this->drupalGet('node/' . $this->node->nid . '/' . $comment->id);
|
||||
$this->assertText($comment_subject, t('Individual comment subject found.'));
|
||||
$this->assertText($comment_text, t('Individual comment body found.'));
|
||||
|
||||
// Reply to comment, creating second comment.
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id);
|
||||
$reply_text = $this->randomName();
|
||||
$reply_subject = $this->randomName();
|
||||
$reply = $this->postComment(NULL, $reply_text, $reply_subject, TRUE);
|
||||
$reply_loaded = comment_load($reply->id);
|
||||
$this->assertTrue($this->commentExists($reply, TRUE), t('Reply found.'));
|
||||
|
||||
// Go to the node page and verify comment and reply are visible.
|
||||
$this->drupalGet('node/' . $this->node->nid);
|
||||
$this->assertText($comment_text);
|
||||
$this->assertText($comment_subject);
|
||||
$this->assertText($reply_text);
|
||||
$this->assertText($reply_subject);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,273 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\comment\Tests\CommentPagerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
/**
|
||||
* Verifies pagination of comments.
|
||||
*/
|
||||
class CommentPagerTest extends CommentTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Comment paging settings',
|
||||
'description' => 'Test paging of comments and their settings.',
|
||||
'group' => 'Comment',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms comment paging works correctly with flat and threaded comments.
|
||||
*/
|
||||
function testCommentPaging() {
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Set comment variables.
|
||||
$this->setCommentForm(TRUE);
|
||||
$this->setCommentSubject(TRUE);
|
||||
$this->setCommentPreview(DRUPAL_DISABLED);
|
||||
|
||||
// Create a node and three comments.
|
||||
$node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
|
||||
$comments = array();
|
||||
$comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE);
|
||||
$comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE);
|
||||
$comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE);
|
||||
|
||||
$this->setCommentSettings('comment_default_mode', COMMENT_MODE_FLAT, t('Comment paging changed.'));
|
||||
|
||||
// Set comments to one per page so that we are able to test paging without
|
||||
// needing to insert large numbers of comments.
|
||||
$this->setCommentsPerPage(1);
|
||||
|
||||
// Check the first page of the node, and confirm the correct comments are
|
||||
// shown.
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertRaw(t('next'), t('Paging links found.'));
|
||||
$this->assertTrue($this->commentExists($comments[0]), t('Comment 1 appears on page 1.'));
|
||||
$this->assertFalse($this->commentExists($comments[1]), t('Comment 2 does not appear on page 1.'));
|
||||
$this->assertFalse($this->commentExists($comments[2]), t('Comment 3 does not appear on page 1.'));
|
||||
|
||||
// Check the second page.
|
||||
$this->drupalGet('node/' . $node->nid, array('query' => array('page' => 1)));
|
||||
$this->assertTrue($this->commentExists($comments[1]), t('Comment 2 appears on page 2.'));
|
||||
$this->assertFalse($this->commentExists($comments[0]), t('Comment 1 does not appear on page 2.'));
|
||||
$this->assertFalse($this->commentExists($comments[2]), t('Comment 3 does not appear on page 2.'));
|
||||
|
||||
// Check the third page.
|
||||
$this->drupalGet('node/' . $node->nid, array('query' => array('page' => 2)));
|
||||
$this->assertTrue($this->commentExists($comments[2]), t('Comment 3 appears on page 3.'));
|
||||
$this->assertFalse($this->commentExists($comments[0]), t('Comment 1 does not appear on page 3.'));
|
||||
$this->assertFalse($this->commentExists($comments[1]), t('Comment 2 does not appear on page 3.'));
|
||||
|
||||
// Post a reply to the oldest comment and test again.
|
||||
$replies = array();
|
||||
$oldest_comment = reset($comments);
|
||||
$this->drupalGet('comment/reply/' . $node->nid . '/' . $oldest_comment->id);
|
||||
$reply = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
|
||||
$this->setCommentsPerPage(2);
|
||||
// We are still in flat view - the replies should not be on the first page,
|
||||
// even though they are replies to the oldest comment.
|
||||
$this->drupalGet('node/' . $node->nid, array('query' => array('page' => 0)));
|
||||
$this->assertFalse($this->commentExists($reply, TRUE), t('In flat mode, reply does not appear on page 1.'));
|
||||
|
||||
// If we switch to threaded mode, the replies on the oldest comment
|
||||
// should be bumped to the first page and comment 6 should be bumped
|
||||
// to the second page.
|
||||
$this->setCommentSettings('comment_default_mode', COMMENT_MODE_THREADED, t('Switched to threaded mode.'));
|
||||
$this->drupalGet('node/' . $node->nid, array('query' => array('page' => 0)));
|
||||
$this->assertTrue($this->commentExists($reply, TRUE), t('In threaded mode, reply appears on page 1.'));
|
||||
$this->assertFalse($this->commentExists($comments[1]), t('In threaded mode, comment 2 has been bumped off of page 1.'));
|
||||
|
||||
// If (# replies > # comments per page) in threaded expanded view,
|
||||
// the overage should be bumped.
|
||||
$reply2 = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
$this->drupalGet('node/' . $node->nid, array('query' => array('page' => 0)));
|
||||
$this->assertFalse($this->commentExists($reply2, TRUE), t('In threaded mode where # replies > # comments per page, the newest reply does not appear on page 1.'));
|
||||
|
||||
$this->drupalLogout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests comment ordering and threading.
|
||||
*/
|
||||
function testCommentOrderingThreading() {
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Set comment variables.
|
||||
$this->setCommentForm(TRUE);
|
||||
$this->setCommentSubject(TRUE);
|
||||
$this->setCommentPreview(DRUPAL_DISABLED);
|
||||
|
||||
// Display all the comments on the same page.
|
||||
$this->setCommentsPerPage(1000);
|
||||
|
||||
// Create a node and three comments.
|
||||
$node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
|
||||
$comments = array();
|
||||
$comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE);
|
||||
$comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE);
|
||||
$comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE);
|
||||
|
||||
// Post a reply to the second comment.
|
||||
$this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[1]->id);
|
||||
$comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
|
||||
// Post a reply to the first comment.
|
||||
$this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[0]->id);
|
||||
$comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
|
||||
// Post a reply to the last comment.
|
||||
$this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[2]->id);
|
||||
$comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
|
||||
// Post a reply to the second comment.
|
||||
$this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[3]->id);
|
||||
$comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
|
||||
// At this point, the comment tree is:
|
||||
// - 0
|
||||
// - 4
|
||||
// - 1
|
||||
// - 3
|
||||
// - 6
|
||||
// - 2
|
||||
// - 5
|
||||
|
||||
$this->setCommentSettings('comment_default_mode', COMMENT_MODE_FLAT, t('Comment paging changed.'));
|
||||
|
||||
$expected_order = array(
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
);
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertCommentOrder($comments, $expected_order);
|
||||
|
||||
$this->setCommentSettings('comment_default_mode', COMMENT_MODE_THREADED, t('Switched to threaded mode.'));
|
||||
|
||||
$expected_order = array(
|
||||
0,
|
||||
4,
|
||||
1,
|
||||
3,
|
||||
6,
|
||||
2,
|
||||
5,
|
||||
);
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertCommentOrder($comments, $expected_order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the comments are displayed in the correct order.
|
||||
*
|
||||
* @param $comments
|
||||
* And array of comments.
|
||||
* @param $expected_order
|
||||
* An array of keys from $comments describing the expected order.
|
||||
*/
|
||||
function assertCommentOrder(array $comments, array $expected_order) {
|
||||
$expected_cids = array();
|
||||
|
||||
// First, rekey the expected order by cid.
|
||||
foreach ($expected_order as $key) {
|
||||
$expected_cids[] = $comments[$key]->id;
|
||||
}
|
||||
|
||||
$comment_anchors = $this->xpath('//a[starts-with(@id,"comment-")]');
|
||||
$result_order = array();
|
||||
foreach ($comment_anchors as $anchor) {
|
||||
$result_order[] = substr($anchor['id'], 8);
|
||||
}
|
||||
|
||||
return $this->assertIdentical($expected_cids, $result_order, t('Comment order: expected @expected, returned @returned.', array('@expected' => implode(',', $expected_cids), '@returned' => implode(',', $result_order))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests comment_new_page_count().
|
||||
*/
|
||||
function testCommentNewPageIndicator() {
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Set comment variables.
|
||||
$this->setCommentForm(TRUE);
|
||||
$this->setCommentSubject(TRUE);
|
||||
$this->setCommentPreview(DRUPAL_DISABLED);
|
||||
|
||||
// Set comments to one per page so that we are able to test paging without
|
||||
// needing to insert large numbers of comments.
|
||||
$this->setCommentsPerPage(1);
|
||||
|
||||
// Create a node and three comments.
|
||||
$node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
|
||||
$comments = array();
|
||||
$comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE);
|
||||
$comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE);
|
||||
$comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE);
|
||||
|
||||
// Post a reply to the second comment.
|
||||
$this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[1]->id);
|
||||
$comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
|
||||
// Post a reply to the first comment.
|
||||
$this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[0]->id);
|
||||
$comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
|
||||
// Post a reply to the last comment.
|
||||
$this->drupalGet('comment/reply/' . $node->nid . '/' . $comments[2]->id);
|
||||
$comments[] = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
|
||||
// At this point, the comment tree is:
|
||||
// - 0
|
||||
// - 4
|
||||
// - 1
|
||||
// - 3
|
||||
// - 2
|
||||
// - 5
|
||||
|
||||
$this->setCommentSettings('comment_default_mode', COMMENT_MODE_FLAT, t('Comment paging changed.'));
|
||||
|
||||
$expected_pages = array(
|
||||
1 => 5, // Page of comment 5
|
||||
2 => 4, // Page of comment 4
|
||||
3 => 3, // Page of comment 3
|
||||
4 => 2, // Page of comment 2
|
||||
5 => 1, // Page of comment 1
|
||||
6 => 0, // Page of comment 0
|
||||
);
|
||||
|
||||
$node = node_load($node->nid);
|
||||
foreach ($expected_pages as $new_replies => $expected_page) {
|
||||
$returned = comment_new_page_count($node->comment_count, $new_replies, $node);
|
||||
$returned_page = is_array($returned) ? $returned['page'] : 0;
|
||||
$this->assertIdentical($expected_page, $returned_page, t('Flat mode, @new replies: expected page @expected, returned page @returned.', array('@new' => $new_replies, '@expected' => $expected_page, '@returned' => $returned_page)));
|
||||
}
|
||||
|
||||
$this->setCommentSettings('comment_default_mode', COMMENT_MODE_THREADED, t('Switched to threaded mode.'));
|
||||
|
||||
$expected_pages = array(
|
||||
1 => 5, // Page of comment 5
|
||||
2 => 1, // Page of comment 4
|
||||
3 => 1, // Page of comment 4
|
||||
4 => 1, // Page of comment 4
|
||||
5 => 1, // Page of comment 4
|
||||
6 => 0, // Page of comment 0
|
||||
);
|
||||
|
||||
$node = node_load($node->nid);
|
||||
foreach ($expected_pages as $new_replies => $expected_page) {
|
||||
$returned = comment_new_page_count($node->comment_count, $new_replies, $node);
|
||||
$returned_page = is_array($returned) ? $returned['page'] : 0;
|
||||
$this->assertEqual($expected_page, $returned_page, t('Threaded mode, @new replies: expected page @expected, returned page @returned.', array('@new' => $new_replies, '@expected' => $expected_page, '@returned' => $returned_page)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\comment\Tests\CommentPreviewTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
/**
|
||||
* Tests previewing comments.
|
||||
*/
|
||||
class CommentPreviewTest extends CommentTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Comment preview',
|
||||
'description' => 'Test comment preview.',
|
||||
'group' => 'Comment',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests comment preview.
|
||||
*/
|
||||
function testCommentPreview() {
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
|
||||
// As admin user, configure comment settings.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentPreview(DRUPAL_OPTIONAL);
|
||||
$this->setCommentForm(TRUE);
|
||||
$this->setCommentSubject(TRUE);
|
||||
$this->setCommentSettings('comment_default_mode', COMMENT_MODE_THREADED, t('Comment paging changed.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Login as web user and add a signature and a user picture.
|
||||
$this->drupalLogin($this->web_user);
|
||||
variable_set('user_signatures', 1);
|
||||
variable_set('user_pictures', 1);
|
||||
$test_signature = $this->randomName();
|
||||
$edit['signature[value]'] = '<a href="http://example.com/">' . $test_signature. '</a>';
|
||||
$edit['signature[format]'] = 'filtered_html';
|
||||
$image = current($this->drupalGetTestFiles('image'));
|
||||
$edit['files[picture_upload]'] = drupal_realpath($image->uri);
|
||||
$this->drupalPost('user/' . $this->web_user->uid . '/edit', $edit, t('Save'));
|
||||
|
||||
// As the web user, fill in the comment form and preview the comment.
|
||||
$edit = array();
|
||||
$edit['subject'] = $this->randomName(8);
|
||||
$edit['comment_body[' . $langcode . '][0][value]'] = $this->randomName(16);
|
||||
$this->drupalPost('node/' . $this->node->nid, $edit, t('Preview'));
|
||||
|
||||
// Check that the preview is displaying the title and body.
|
||||
$this->assertTitle(t('Preview comment | Drupal'), t('Page title is "Preview comment".'));
|
||||
$this->assertText($edit['subject'], t('Subject displayed.'));
|
||||
$this->assertText($edit['comment_body[' . $langcode . '][0][value]'], t('Comment displayed.'));
|
||||
|
||||
// Check that the title and body fields are displayed with the correct values.
|
||||
$this->assertFieldByName('subject', $edit['subject'], t('Subject field displayed.'));
|
||||
$this->assertFieldByName('comment_body[' . $langcode . '][0][value]', $edit['comment_body[' . $langcode . '][0][value]'], t('Comment field displayed.'));
|
||||
|
||||
// Check that the signature is displaying with the correct text format.
|
||||
$this->assertLink($test_signature);
|
||||
|
||||
// Check that the user picture is displayed.
|
||||
$this->assertFieldByXPath("//div[contains(@class, 'preview')]//div[contains(@class, 'user-picture')]//img", NULL, 'User picture displayed.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests comment edit, preview, and save.
|
||||
*/
|
||||
function testCommentEditPreviewSave() {
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'skip comment approval'));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentPreview(DRUPAL_OPTIONAL);
|
||||
$this->setCommentForm(TRUE);
|
||||
$this->setCommentSubject(TRUE);
|
||||
$this->setCommentSettings('comment_default_mode', COMMENT_MODE_THREADED, t('Comment paging changed.'));
|
||||
|
||||
$edit = array();
|
||||
$edit['subject'] = $this->randomName(8);
|
||||
$edit['comment_body[' . $langcode . '][0][value]'] = $this->randomName(16);
|
||||
$edit['name'] = $web_user->name;
|
||||
$edit['date'] = '2008-03-02 17:23 +0300';
|
||||
$raw_date = strtotime($edit['date']);
|
||||
$expected_text_date = format_date($raw_date);
|
||||
$expected_form_date = format_date($raw_date, 'custom', 'Y-m-d H:i O');
|
||||
$comment = $this->postComment($this->node, $edit['subject'], $edit['comment_body[' . $langcode . '][0][value]'], TRUE);
|
||||
$this->drupalPost('comment/' . $comment->id . '/edit', $edit, t('Preview'));
|
||||
|
||||
// Check that the preview is displaying the subject, comment, author and date correctly.
|
||||
$this->assertTitle(t('Preview comment | Drupal'), t('Page title is "Preview comment".'));
|
||||
$this->assertText($edit['subject'], t('Subject displayed.'));
|
||||
$this->assertText($edit['comment_body[' . $langcode . '][0][value]'], t('Comment displayed.'));
|
||||
$this->assertText($edit['name'], t('Author displayed.'));
|
||||
$this->assertText($expected_text_date, t('Date displayed.'));
|
||||
|
||||
// Check that the subject, comment, author and date fields are displayed with the correct values.
|
||||
$this->assertFieldByName('subject', $edit['subject'], t('Subject field displayed.'));
|
||||
$this->assertFieldByName('comment_body[' . $langcode . '][0][value]', $edit['comment_body[' . $langcode . '][0][value]'], t('Comment field displayed.'));
|
||||
$this->assertFieldByName('name', $edit['name'], t('Author field displayed.'));
|
||||
$this->assertFieldByName('date', $edit['date'], t('Date field displayed.'));
|
||||
|
||||
// Check that saving a comment produces a success message.
|
||||
$this->drupalPost('comment/' . $comment->id . '/edit', $edit, t('Save'));
|
||||
$this->assertText(t('Your comment has been posted.'), t('Comment posted.'));
|
||||
|
||||
// Check that the comment fields are correct after loading the saved comment.
|
||||
$this->drupalGet('comment/' . $comment->id . '/edit');
|
||||
$this->assertFieldByName('subject', $edit['subject'], t('Subject field displayed.'));
|
||||
$this->assertFieldByName('comment_body[' . $langcode . '][0][value]', $edit['comment_body[' . $langcode . '][0][value]'], t('Comment field displayed.'));
|
||||
$this->assertFieldByName('name', $edit['name'], t('Author field displayed.'));
|
||||
$this->assertFieldByName('date', $expected_form_date, t('Date field displayed.'));
|
||||
|
||||
// Submit the form using the displayed values.
|
||||
$displayed = array();
|
||||
$displayed['subject'] = (string) current($this->xpath("//input[@id='edit-subject']/@value"));
|
||||
$displayed['comment_body[' . $langcode . '][0][value]'] = (string) current($this->xpath("//textarea[@id='edit-comment-body-" . $langcode . "-0-value']"));
|
||||
$displayed['name'] = (string) current($this->xpath("//input[@id='edit-name']/@value"));
|
||||
$displayed['date'] = (string) current($this->xpath("//input[@id='edit-date']/@value"));
|
||||
$this->drupalPost('comment/' . $comment->id . '/edit', $displayed, t('Save'));
|
||||
|
||||
// Check that the saved comment is still correct.
|
||||
$comment_loaded = comment_load($comment->id);
|
||||
$this->assertEqual($comment_loaded->subject, $edit['subject'], t('Subject loaded.'));
|
||||
$this->assertEqual($comment_loaded->comment_body[$langcode][0]['value'], $edit['comment_body[' . $langcode . '][0][value]'], t('Comment body loaded.'));
|
||||
$this->assertEqual($comment_loaded->name, $edit['name'], t('Name loaded.'));
|
||||
$this->assertEqual($comment_loaded->created, $raw_date, t('Date loaded.'));
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\comment\Tests\CommentRssTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
/**
|
||||
* Tests for Comment module integration with RSS feeds.
|
||||
*/
|
||||
class CommentRssTest extends CommentTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Comment RSS',
|
||||
'description' => 'Test comments as part of an RSS feed.',
|
||||
'group' => 'Comment',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests comments as part of an RSS feed.
|
||||
*/
|
||||
function testCommentRss() {
|
||||
// Find comment in RSS feed.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$comment = $this->postComment($this->node, $this->randomName(), $this->randomName());
|
||||
$this->drupalGet('rss.xml');
|
||||
$raw = '<comments>' . url('node/' . $this->node->nid, array('fragment' => 'comments', 'absolute' => TRUE)) . '</comments>';
|
||||
$this->assertRaw($raw, t('Comments as part of RSS feed.'));
|
||||
|
||||
// Hide comments from RSS feed and check presence.
|
||||
$this->node->comment = COMMENT_NODE_HIDDEN;
|
||||
node_save($this->node);
|
||||
$this->drupalGet('rss.xml');
|
||||
$this->assertNoRaw($raw, t('Hidden comments is not a part of RSS feed.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\comment\Tests\CommentThreadingTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
/**
|
||||
* Tests comment threading.
|
||||
*/
|
||||
class CommentThreadingTest extends CommentTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Comment Threading',
|
||||
'description' => 'Test to make sure the comment number increments properly.',
|
||||
'group' => 'Comment',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the comment threading.
|
||||
*/
|
||||
function testCommentThreading() {
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
// Set comments to have a subject with preview disabled.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->setCommentPreview(DRUPAL_DISABLED);
|
||||
$this->setCommentForm(TRUE);
|
||||
$this->setCommentSubject(TRUE);
|
||||
$this->setCommentSettings('comment_default_mode', COMMENT_MODE_THREADED, t('Comment paging changed.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Create a node.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'uid' => $this->web_user->uid));
|
||||
|
||||
// Post comment #1.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$subject_text = $this->randomName();
|
||||
$comment_text = $this->randomName();
|
||||
$comment = $this->postComment($this->node, $comment_text, $subject_text, TRUE);
|
||||
$comment_loaded = comment_load($comment->id);
|
||||
$this->assertTrue($this->commentExists($comment), 'Comment #1. Comment found.');
|
||||
$this->assertEqual($comment_loaded->thread, '01/');
|
||||
|
||||
// Reply to comment #1 creating comment #2.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id);
|
||||
$reply = $this->postComment(NULL, $this->randomName(), '', TRUE);
|
||||
$reply_loaded = comment_load($reply->id);
|
||||
$this->assertTrue($this->commentExists($reply, TRUE), 'Comment #2. Reply found.');
|
||||
$this->assertEqual($reply_loaded->thread, '01.00/');
|
||||
|
||||
// Reply to comment #2 creating comment #3.
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $reply->id);
|
||||
$reply = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
$reply_loaded = comment_load($reply->id);
|
||||
$this->assertTrue($this->commentExists($reply, TRUE), 'Comment #3. Second reply found.');
|
||||
$this->assertEqual($reply_loaded->thread, '01.00.00/');
|
||||
|
||||
// Reply to comment #1 creating comment #4.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id);
|
||||
$reply = $this->postComment(NULL, $this->randomName(), '', TRUE);
|
||||
$reply_loaded = comment_load($reply->id);
|
||||
$this->assertTrue($this->commentExists($comment), 'Comment #4. Third reply found.');
|
||||
$this->assertEqual($reply_loaded->thread, '01.01/');
|
||||
|
||||
// Post comment #2 overall comment #5.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$subject_text = $this->randomName();
|
||||
$comment_text = $this->randomName();
|
||||
$comment = $this->postComment($this->node, $comment_text, $subject_text, TRUE);
|
||||
$comment_loaded = comment_load($comment->id);
|
||||
$this->assertTrue($this->commentExists($comment), 'Comment #5. Second comment found.');
|
||||
$this->assertEqual($comment_loaded->thread, '02/');
|
||||
|
||||
// Reply to comment #5 creating comment #6.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id);
|
||||
$reply = $this->postComment(NULL, $this->randomName(), '', TRUE);
|
||||
$reply_loaded = comment_load($reply->id);
|
||||
$this->assertTrue($this->commentExists($reply, TRUE), 'Comment #6. Reply found.');
|
||||
$this->assertEqual($reply_loaded->thread, '02.00/');
|
||||
|
||||
// Reply to comment #6 creating comment #7.
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $reply->id);
|
||||
$reply = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
|
||||
$reply_loaded = comment_load($reply->id);
|
||||
$this->assertTrue($this->commentExists($reply, TRUE), 'Comment #7. Second reply found.');
|
||||
$this->assertEqual($reply_loaded->thread, '02.00.00/');
|
||||
|
||||
// Reply to comment #5 creating comment #8.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id);
|
||||
$reply = $this->postComment(NULL, $this->randomName(), '', TRUE);
|
||||
$reply_loaded = comment_load($reply->id);
|
||||
$this->assertTrue($this->commentExists($comment), 'Comment #8. Third reply found.');
|
||||
$this->assertEqual($reply_loaded->thread, '02.01/');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\comment\Tests\CommentTokenReplaceTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\comment\Tests;
|
||||
|
||||
/**
|
||||
* Tests comment token replacement in strings.
|
||||
*/
|
||||
class CommentTokenReplaceTest extends CommentTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Comment token replacement',
|
||||
'description' => 'Generates text using placeholders for dummy content to check comment token replacement.',
|
||||
'group' => 'Comment',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a comment, then tests the tokens generated from it.
|
||||
*/
|
||||
function testCommentTokenReplacement() {
|
||||
global $language_interface;
|
||||
$url_options = array(
|
||||
'absolute' => TRUE,
|
||||
'language' => $language_interface,
|
||||
);
|
||||
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Set comment variables.
|
||||
$this->setCommentSubject(TRUE);
|
||||
|
||||
// Create a node and a comment.
|
||||
$node = $this->drupalCreateNode(array('type' => 'article'));
|
||||
$parent_comment = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE);
|
||||
|
||||
// Post a reply to the comment.
|
||||
$this->drupalGet('comment/reply/' . $node->nid . '/' . $parent_comment->id);
|
||||
$child_comment = $this->postComment(NULL, $this->randomName(), $this->randomName());
|
||||
$comment = comment_load($child_comment->id);
|
||||
$comment->homepage = 'http://example.org/';
|
||||
|
||||
// Add HTML to ensure that sanitation of some fields tested directly.
|
||||
$comment->subject = '<blink>Blinking Comment</blink>';
|
||||
$instance = field_info_instance('comment', 'body', 'comment_body');
|
||||
|
||||
// Generate and test sanitized tokens.
|
||||
$tests = array();
|
||||
$tests['[comment:cid]'] = $comment->cid;
|
||||
$tests['[comment:hostname]'] = check_plain($comment->hostname);
|
||||
$tests['[comment:name]'] = filter_xss($comment->name);
|
||||
$tests['[comment:mail]'] = check_plain($this->admin_user->mail);
|
||||
$tests['[comment:homepage]'] = check_url($comment->homepage);
|
||||
$tests['[comment:title]'] = filter_xss($comment->subject);
|
||||
$tests['[comment:body]'] = _text_sanitize($instance, LANGUAGE_NOT_SPECIFIED, $comment->comment_body[LANGUAGE_NOT_SPECIFIED][0], 'value');
|
||||
$tests['[comment:url]'] = url('comment/' . $comment->cid, $url_options + array('fragment' => 'comment-' . $comment->cid));
|
||||
$tests['[comment:edit-url]'] = url('comment/' . $comment->cid . '/edit', $url_options);
|
||||
$tests['[comment:created:since]'] = format_interval(REQUEST_TIME - $comment->created, 2, $language_interface->langcode);
|
||||
$tests['[comment:changed:since]'] = format_interval(REQUEST_TIME - $comment->changed, 2, $language_interface->langcode);
|
||||
$tests['[comment:parent:cid]'] = $comment->pid;
|
||||
$tests['[comment:parent:title]'] = check_plain($parent_comment->subject);
|
||||
$tests['[comment:node:nid]'] = $comment->nid;
|
||||
$tests['[comment:node:title]'] = check_plain($node->title);
|
||||
$tests['[comment:author:uid]'] = $comment->uid;
|
||||
$tests['[comment:author:name]'] = check_plain($this->admin_user->name);
|
||||
|
||||
// Test to make sure that we generated something for each token.
|
||||
$this->assertFalse(in_array(0, array_map('strlen', $tests)), t('No empty tokens generated.'));
|
||||
|
||||
foreach ($tests as $input => $expected) {
|
||||
$output = token_replace($input, array('comment' => $comment), array('language' => $language_interface));
|
||||
$this->assertEqual($output, $expected, t('Sanitized comment token %token replaced.', array('%token' => $input)));
|
||||
}
|
||||
|
||||
// Generate and test unsanitized tokens.
|
||||
$tests['[comment:hostname]'] = $comment->hostname;
|
||||
$tests['[comment:name]'] = $comment->name;
|
||||
$tests['[comment:mail]'] = $this->admin_user->mail;
|
||||
$tests['[comment:homepage]'] = $comment->homepage;
|
||||
$tests['[comment:title]'] = $comment->subject;
|
||||
$tests['[comment:body]'] = $comment->comment_body[LANGUAGE_NOT_SPECIFIED][0]['value'];
|
||||
$tests['[comment:parent:title]'] = $parent_comment->subject;
|
||||
$tests['[comment:node:title]'] = $node->title;
|
||||
$tests['[comment:author:name]'] = $this->admin_user->name;
|
||||
|
||||
foreach ($tests as $input => $expected) {
|
||||
$output = token_replace($input, array('comment' => $comment), array('language' => $language_interface, 'sanitize' => FALSE));
|
||||
$this->assertEqual($output, $expected, t('Unsanitized comment token %token replaced.', array('%token' => $input)));
|
||||
}
|
||||
|
||||
// Load node so comment_count gets computed.
|
||||
$node = node_load($node->nid);
|
||||
|
||||
// Generate comment tokens for the node (it has 2 comments, both new).
|
||||
$tests = array();
|
||||
$tests['[node:comment-count]'] = 2;
|
||||
$tests['[node:comment-count-new]'] = 2;
|
||||
|
||||
foreach ($tests as $input => $expected) {
|
||||
$output = token_replace($input, array('node' => $node), array('language' => $language_interface));
|
||||
$this->assertEqual($output, $expected, t('Node comment token %token replaced.', array('%token' => $input)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,5 +3,4 @@ description = Enables the use of both personal and site-wide contact forms.
|
|||
package = Core
|
||||
version = VERSION
|
||||
core = 8.x
|
||||
files[] = contact.test
|
||||
configure = admin/structure/contact
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\contact\Tests\ContactPersonalTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests the personal contact form.
|
||||
*/
|
||||
class ContactPersonalTest extends WebTestBase {
|
||||
private $admin_user;
|
||||
private $web_user;
|
||||
private $contact_user;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Personal contact form',
|
||||
'description' => 'Tests personal contact form functionality.',
|
||||
'group' => 'Contact',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('contact');
|
||||
|
||||
// Create an admin user.
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer contact forms', 'administer users'));
|
||||
|
||||
// Create some normal users with their contact forms enabled by default.
|
||||
variable_set('contact_default_status', TRUE);
|
||||
$this->web_user = $this->drupalCreateUser(array('access user contact forms'));
|
||||
$this->contact_user = $this->drupalCreateUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests access to the personal contact form.
|
||||
*/
|
||||
function testPersonalContactAccess() {
|
||||
// Test allowed access to user with contact form enabled.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Test denied access to the user's own contact form.
|
||||
$this->drupalGet('user/' . $this->web_user->uid . '/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test always denied access to the anonymous user contact form.
|
||||
$this->drupalGet('user/0/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test that anonymous users can access the contact form.
|
||||
$this->drupalLogout();
|
||||
user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access user contact forms'));
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Revoke the personal contact permission for the anonymous user.
|
||||
user_role_revoke_permissions(DRUPAL_ANONYMOUS_RID, array('access user contact forms'));
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Disable the personal contact form.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$edit = array('contact_default_status' => FALSE);
|
||||
$this->drupalPost('admin/config/people/accounts', $edit, t('Save configuration'));
|
||||
$this->assertText(t('The configuration options have been saved.'), t('Setting successfully saved.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Re-create our contacted user with personal contact forms disabled by
|
||||
// default.
|
||||
$this->contact_user = $this->drupalCreateUser();
|
||||
|
||||
// Test denied access to a user with contact form disabled.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test allowed access for admin user to a user with contact form disabled.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Re-create our contacted user as a blocked user.
|
||||
$this->contact_user = $this->drupalCreateUser();
|
||||
$this->contact_user->status = 0;
|
||||
$this->contact_user->save();
|
||||
|
||||
// Test that blocked users can still be contacted by admin.
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Test that blocked users cannot be contacted by non-admins.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(403);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the personal contact form flood protection.
|
||||
*/
|
||||
function testPersonalContactFlood() {
|
||||
$flood_limit = 3;
|
||||
variable_set('contact_threshold_limit', $flood_limit);
|
||||
|
||||
// Clear flood table in preparation for flood test and allow other checks to complete.
|
||||
db_delete('flood')->execute();
|
||||
$num_records_flood = db_query("SELECT COUNT(*) FROM {flood}")->fetchField();
|
||||
$this->assertIdentical($num_records_flood, '0', 'Flood table emptied.');
|
||||
|
||||
$this->drupalLogin($this->web_user);
|
||||
|
||||
// Submit contact form with correct values and check flood interval.
|
||||
for ($i = 0; $i < $flood_limit; $i++) {
|
||||
$this->submitPersonalContact($this->contact_user);
|
||||
$this->assertText(t('Your message has been sent.'), 'Message sent.');
|
||||
}
|
||||
|
||||
// Submit contact form one over limit.
|
||||
$this->drupalGet('user/' . $this->contact_user->uid. '/contact');
|
||||
$this->assertRaw(t('You cannot send more than %number messages in @interval. Try again later.', array('%number' => $flood_limit, '@interval' => format_interval(variable_get('contact_threshold_window', 3600)))), 'Normal user denied access to flooded contact form.');
|
||||
|
||||
// Test that the admin user can still access the contact form even though
|
||||
// the flood limit was reached.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->assertNoText('Try again later.', 'Admin user not denied access to flooded contact form.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills out a user's personal contact form and submits it.
|
||||
*
|
||||
* @param $account
|
||||
* A user object of the user being contacted.
|
||||
* @param $message
|
||||
* An optional array with the form fields being used.
|
||||
*/
|
||||
protected function submitPersonalContact($account, array $message = array()) {
|
||||
$message += array(
|
||||
'subject' => $this->randomName(16),
|
||||
'message' => $this->randomName(64),
|
||||
);
|
||||
$this->drupalPost('user/' . $account->uid . '/contact', $message, t('Send message'));
|
||||
}
|
||||
}
|
|
@ -1,15 +1,18 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Tests for the Contact module.
|
||||
* Definition of Drupal\contact\Tests\ContactSitewideTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\contact\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests the site-wide contact form.
|
||||
*/
|
||||
class ContactSitewideTestCase extends WebTestBase {
|
||||
class ContactSitewideTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Site-wide contact form',
|
||||
|
@ -296,142 +299,3 @@ class ContactSitewideTestCase extends WebTestBase {
|
|||
return $categories;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the personal contact form.
|
||||
*/
|
||||
class ContactPersonalTestCase extends WebTestBase {
|
||||
private $admin_user;
|
||||
private $web_user;
|
||||
private $contact_user;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Personal contact form',
|
||||
'description' => 'Tests personal contact form functionality.',
|
||||
'group' => 'Contact',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('contact');
|
||||
|
||||
// Create an admin user.
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer contact forms', 'administer users'));
|
||||
|
||||
// Create some normal users with their contact forms enabled by default.
|
||||
variable_set('contact_default_status', TRUE);
|
||||
$this->web_user = $this->drupalCreateUser(array('access user contact forms'));
|
||||
$this->contact_user = $this->drupalCreateUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests access to the personal contact form.
|
||||
*/
|
||||
function testPersonalContactAccess() {
|
||||
// Test allowed access to user with contact form enabled.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Test denied access to the user's own contact form.
|
||||
$this->drupalGet('user/' . $this->web_user->uid . '/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test always denied access to the anonymous user contact form.
|
||||
$this->drupalGet('user/0/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test that anonymous users can access the contact form.
|
||||
$this->drupalLogout();
|
||||
user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access user contact forms'));
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Revoke the personal contact permission for the anonymous user.
|
||||
user_role_revoke_permissions(DRUPAL_ANONYMOUS_RID, array('access user contact forms'));
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Disable the personal contact form.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$edit = array('contact_default_status' => FALSE);
|
||||
$this->drupalPost('admin/config/people/accounts', $edit, t('Save configuration'));
|
||||
$this->assertText(t('The configuration options have been saved.'), t('Setting successfully saved.'));
|
||||
$this->drupalLogout();
|
||||
|
||||
// Re-create our contacted user with personal contact forms disabled by
|
||||
// default.
|
||||
$this->contact_user = $this->drupalCreateUser();
|
||||
|
||||
// Test denied access to a user with contact form disabled.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Test allowed access for admin user to a user with contact form disabled.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Re-create our contacted user as a blocked user.
|
||||
$this->contact_user = $this->drupalCreateUser();
|
||||
$this->contact_user->status = 0;
|
||||
$this->contact_user->save();
|
||||
|
||||
// Test that blocked users can still be contacted by admin.
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Test that blocked users cannot be contacted by non-admins.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('user/' . $this->contact_user->uid . '/contact');
|
||||
$this->assertResponse(403);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the personal contact form flood protection.
|
||||
*/
|
||||
function testPersonalContactFlood() {
|
||||
$flood_limit = 3;
|
||||
variable_set('contact_threshold_limit', $flood_limit);
|
||||
|
||||
// Clear flood table in preparation for flood test and allow other checks to complete.
|
||||
db_delete('flood')->execute();
|
||||
$num_records_flood = db_query("SELECT COUNT(*) FROM {flood}")->fetchField();
|
||||
$this->assertIdentical($num_records_flood, '0', 'Flood table emptied.');
|
||||
|
||||
$this->drupalLogin($this->web_user);
|
||||
|
||||
// Submit contact form with correct values and check flood interval.
|
||||
for ($i = 0; $i < $flood_limit; $i++) {
|
||||
$this->submitPersonalContact($this->contact_user);
|
||||
$this->assertText(t('Your message has been sent.'), 'Message sent.');
|
||||
}
|
||||
|
||||
// Submit contact form one over limit.
|
||||
$this->drupalGet('user/' . $this->contact_user->uid. '/contact');
|
||||
$this->assertRaw(t('You cannot send more than %number messages in @interval. Try again later.', array('%number' => $flood_limit, '@interval' => format_interval(variable_get('contact_threshold_window', 3600)))), 'Normal user denied access to flooded contact form.');
|
||||
|
||||
// Test that the admin user can still access the contact form even though
|
||||
// the flood limit was reached.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->assertNoText('Try again later.', 'Admin user not denied access to flooded contact form.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills out a user's personal contact form and submits it.
|
||||
*
|
||||
* @param $account
|
||||
* A user object of the user being contacted.
|
||||
* @param $message
|
||||
* An optional array with the form fields being used.
|
||||
*/
|
||||
protected function submitPersonalContact($account, array $message = array()) {
|
||||
$message += array(
|
||||
'subject' => $this->randomName(16),
|
||||
'message' => $this->randomName(64),
|
||||
);
|
||||
$this->drupalPost('user/' . $account->uid . '/contact', $message, t('Send message'));
|
||||
}
|
||||
}
|
|
@ -3,4 +3,3 @@ description = Provides contextual links to perform actions related to elements o
|
|||
package = Core
|
||||
version = VERSION
|
||||
core = 8.x
|
||||
files[] = contextual.test
|
||||
|
|
|
@ -2,15 +2,17 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Tests for contextual.module.
|
||||
* Definition of Drupal\contextual\Tests\ContextualDynamicContextTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\contextual\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests accessible links after inaccessible links on dynamic context.
|
||||
*/
|
||||
class ContextualDynamicContextTestCase extends WebTestBase {
|
||||
class ContextualDynamicContextTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Contextual links on node lists',
|
|
@ -3,6 +3,5 @@ description = Filters content in preparation for display.
|
|||
package = Core
|
||||
version = VERSION
|
||||
core = 8.x
|
||||
files[] = filter.test
|
||||
required = TRUE
|
||||
configure = admin/config/content/formats
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,265 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\filter\Tests\FilterAdminTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\filter\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
class FilterAdminTest extends WebTestBase {
|
||||
protected $profile = 'standard';
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Filter administration functionality',
|
||||
'description' => 'Thoroughly test the administrative interface of the filter module.',
|
||||
'group' => 'Filter',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create users.
|
||||
$filtered_html_format = filter_format_load('filtered_html');
|
||||
$full_html_format = filter_format_load('full_html');
|
||||
$this->admin_user = $this->drupalCreateUser(array(
|
||||
'administer filters',
|
||||
filter_permission_name($filtered_html_format),
|
||||
filter_permission_name($full_html_format),
|
||||
));
|
||||
|
||||
$this->web_user = $this->drupalCreateUser(array('create page content', 'edit own page content'));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
|
||||
function testFormatAdmin() {
|
||||
// Add text format.
|
||||
$this->drupalGet('admin/config/content/formats');
|
||||
$this->clickLink('Add text format');
|
||||
$format_id = drupal_strtolower($this->randomName());
|
||||
$name = $this->randomName();
|
||||
$edit = array(
|
||||
'format' => $format_id,
|
||||
'name' => $name,
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Save configuration'));
|
||||
|
||||
// Verify default weight of the text format.
|
||||
$this->drupalGet('admin/config/content/formats');
|
||||
$this->assertFieldByName("formats[$format_id][weight]", 0, t('Text format weight was saved.'));
|
||||
|
||||
// Change the weight of the text format.
|
||||
$edit = array(
|
||||
"formats[$format_id][weight]" => 5,
|
||||
);
|
||||
$this->drupalPost('admin/config/content/formats', $edit, t('Save changes'));
|
||||
$this->assertFieldByName("formats[$format_id][weight]", 5, t('Text format weight was saved.'));
|
||||
|
||||
// Edit text format.
|
||||
$this->drupalGet('admin/config/content/formats');
|
||||
$this->assertLinkByHref('admin/config/content/formats/' . $format_id);
|
||||
$this->drupalGet('admin/config/content/formats/' . $format_id);
|
||||
$this->drupalPost(NULL, array(), t('Save configuration'));
|
||||
|
||||
// Verify that the custom weight of the text format has been retained.
|
||||
$this->drupalGet('admin/config/content/formats');
|
||||
$this->assertFieldByName("formats[$format_id][weight]", 5, t('Text format weight was retained.'));
|
||||
|
||||
// Disable text format.
|
||||
$this->assertLinkByHref('admin/config/content/formats/' . $format_id . '/disable');
|
||||
$this->drupalGet('admin/config/content/formats/' . $format_id . '/disable');
|
||||
$this->drupalPost(NULL, array(), t('Disable'));
|
||||
|
||||
// Verify that disabled text format no longer exists.
|
||||
$this->drupalGet('admin/config/content/formats/' . $format_id);
|
||||
$this->assertResponse(404, t('Disabled text format no longer exists.'));
|
||||
|
||||
// Attempt to create a format of the same machine name as the disabled
|
||||
// format but with a different human readable name.
|
||||
$edit = array(
|
||||
'format' => $format_id,
|
||||
'name' => 'New format',
|
||||
);
|
||||
$this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
|
||||
$this->assertText('The machine-readable name is already in use. It must be unique.');
|
||||
|
||||
// Attempt to create a format of the same human readable name as the
|
||||
// disabled format but with a different machine name.
|
||||
$edit = array(
|
||||
'format' => 'new_format',
|
||||
'name' => $name,
|
||||
);
|
||||
$this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
|
||||
$this->assertRaw(t('Text format names must be unique. A format named %name already exists.', array(
|
||||
'%name' => $name,
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test filter administration functionality.
|
||||
*/
|
||||
function testFilterAdmin() {
|
||||
// URL filter.
|
||||
$first_filter = 'filter_url';
|
||||
// Line filter.
|
||||
$second_filter = 'filter_autop';
|
||||
|
||||
$filtered = 'filtered_html';
|
||||
$full = 'full_html';
|
||||
$plain = 'plain_text';
|
||||
|
||||
// Check that the fallback format exists and cannot be disabled.
|
||||
$this->assertTrue($plain == filter_fallback_format(), t('The fallback format is set to plain text.'));
|
||||
$this->drupalGet('admin/config/content/formats');
|
||||
$this->assertNoRaw('admin/config/content/formats/' . $plain . '/disable', t('Disable link for the fallback format not found.'));
|
||||
$this->drupalGet('admin/config/content/formats/' . $plain . '/disable');
|
||||
$this->assertResponse(403, t('The fallback format cannot be disabled.'));
|
||||
|
||||
// Verify access permissions to Full HTML format.
|
||||
$this->assertTrue(filter_access(filter_format_load($full), $this->admin_user), t('Admin user may use Full HTML.'));
|
||||
$this->assertFalse(filter_access(filter_format_load($full), $this->web_user), t('Web user may not use Full HTML.'));
|
||||
|
||||
// Add an additional tag.
|
||||
$edit = array();
|
||||
$edit['filters[filter_html][settings][allowed_html]'] = '<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <quote>';
|
||||
$this->drupalPost('admin/config/content/formats/' . $filtered, $edit, t('Save configuration'));
|
||||
$this->assertFieldByName('filters[filter_html][settings][allowed_html]', $edit['filters[filter_html][settings][allowed_html]'], t('Allowed HTML tag added.'));
|
||||
|
||||
$result = db_query('SELECT * FROM {cache_filter}')->fetchObject();
|
||||
$this->assertFalse($result, t('Cache cleared.'));
|
||||
|
||||
$elements = $this->xpath('//select[@name=:first]/following::select[@name=:second]', array(
|
||||
':first' => 'filters[' . $first_filter . '][weight]',
|
||||
':second' => 'filters[' . $second_filter . '][weight]',
|
||||
));
|
||||
$this->assertTrue(!empty($elements), t('Order confirmed in admin interface.'));
|
||||
|
||||
// Reorder filters.
|
||||
$edit = array();
|
||||
$edit['filters[' . $second_filter . '][weight]'] = 1;
|
||||
$edit['filters[' . $first_filter . '][weight]'] = 2;
|
||||
$this->drupalPost(NULL, $edit, t('Save configuration'));
|
||||
$this->assertFieldByName('filters[' . $second_filter . '][weight]', 1, t('Order saved successfully.'));
|
||||
$this->assertFieldByName('filters[' . $first_filter . '][weight]', 2, t('Order saved successfully.'));
|
||||
|
||||
$elements = $this->xpath('//select[@name=:first]/following::select[@name=:second]', array(
|
||||
':first' => 'filters[' . $second_filter . '][weight]',
|
||||
':second' => 'filters[' . $first_filter . '][weight]',
|
||||
));
|
||||
$this->assertTrue(!empty($elements), t('Reorder confirmed in admin interface.'));
|
||||
|
||||
$result = db_query('SELECT * FROM {filter} WHERE format = :format ORDER BY weight ASC', array(':format' => $filtered));
|
||||
$filters = array();
|
||||
foreach ($result as $filter) {
|
||||
if ($filter->name == $second_filter || $filter->name == $first_filter) {
|
||||
$filters[] = $filter;
|
||||
}
|
||||
}
|
||||
$this->assertTrue(($filters[0]->name == $second_filter && $filters[1]->name == $first_filter), t('Order confirmed in database.'));
|
||||
|
||||
// Add format.
|
||||
$edit = array();
|
||||
$edit['format'] = drupal_strtolower($this->randomName());
|
||||
$edit['name'] = $this->randomName();
|
||||
$edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = 1;
|
||||
$edit['filters[' . $second_filter . '][status]'] = TRUE;
|
||||
$edit['filters[' . $first_filter . '][status]'] = TRUE;
|
||||
$this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
|
||||
$this->assertRaw(t('Added text format %format.', array('%format' => $edit['name'])), t('New filter created.'));
|
||||
|
||||
drupal_static_reset('filter_formats');
|
||||
$format = filter_format_load($edit['format']);
|
||||
$this->assertNotNull($format, t('Format found in database.'));
|
||||
|
||||
$this->assertFieldByName('roles[' . DRUPAL_AUTHENTICATED_RID . ']', '', t('Role found.'));
|
||||
$this->assertFieldByName('filters[' . $second_filter . '][status]', '', t('Line break filter found.'));
|
||||
$this->assertFieldByName('filters[' . $first_filter . '][status]', '', t('Url filter found.'));
|
||||
|
||||
// Disable new filter.
|
||||
$this->drupalPost('admin/config/content/formats/' . $format->format . '/disable', array(), t('Disable'));
|
||||
$this->assertRaw(t('Disabled text format %format.', array('%format' => $edit['name'])), t('Format successfully disabled.'));
|
||||
|
||||
// Allow authenticated users on full HTML.
|
||||
$format = filter_format_load($full);
|
||||
$edit = array();
|
||||
$edit['roles[' . DRUPAL_ANONYMOUS_RID . ']'] = 0;
|
||||
$edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = 1;
|
||||
$this->drupalPost('admin/config/content/formats/' . $full, $edit, t('Save configuration'));
|
||||
$this->assertRaw(t('The text format %format has been updated.', array('%format' => $format->name)), t('Full HTML format successfully updated.'));
|
||||
|
||||
// Switch user.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->web_user);
|
||||
|
||||
$this->drupalGet('node/add/page');
|
||||
$this->assertRaw('<option value="' . $full . '">Full HTML</option>', t('Full HTML filter accessible.'));
|
||||
|
||||
// Use filtered HTML and see if it removes tags that are not allowed.
|
||||
$body = '<em>' . $this->randomName() . '</em>';
|
||||
$extra_text = 'text';
|
||||
$text = $body . '<random>' . $extra_text . '</random>';
|
||||
|
||||
$edit = array();
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$edit["title"] = $this->randomName();
|
||||
$edit["body[$langcode][0][value]"] = $text;
|
||||
$edit["body[$langcode][0][format]"] = $filtered;
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
$this->assertRaw(t('Basic page %title has been created.', array('%title' => $edit["title"])), t('Filtered node created.'));
|
||||
|
||||
$node = $this->drupalGetNodeByTitle($edit["title"]);
|
||||
$this->assertTrue($node, t('Node found in database.'));
|
||||
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertRaw($body . $extra_text, t('Filter removed invalid tag.'));
|
||||
|
||||
// Use plain text and see if it escapes all tags, whether allowed or not.
|
||||
$edit = array();
|
||||
$edit["body[$langcode][0][format]"] = $plain;
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertText(check_plain($text), t('The "Plain text" text format escapes all HTML tags.'));
|
||||
|
||||
// Switch user.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Clean up.
|
||||
// Allowed tags.
|
||||
$edit = array();
|
||||
$edit['filters[filter_html][settings][allowed_html]'] = '<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>';
|
||||
$this->drupalPost('admin/config/content/formats/' . $filtered, $edit, t('Save configuration'));
|
||||
$this->assertFieldByName('filters[filter_html][settings][allowed_html]', $edit['filters[filter_html][settings][allowed_html]'], t('Changes reverted.'));
|
||||
|
||||
// Full HTML.
|
||||
$edit = array();
|
||||
$edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = FALSE;
|
||||
$this->drupalPost('admin/config/content/formats/' . $full, $edit, t('Save configuration'));
|
||||
$this->assertRaw(t('The text format %format has been updated.', array('%format' => $format->name)), t('Full HTML format successfully reverted.'));
|
||||
$this->assertFieldByName('roles[' . DRUPAL_AUTHENTICATED_RID . ']', $edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'], t('Changes reverted.'));
|
||||
|
||||
// Filter order.
|
||||
$edit = array();
|
||||
$edit['filters[' . $second_filter . '][weight]'] = 2;
|
||||
$edit['filters[' . $first_filter . '][weight]'] = 1;
|
||||
$this->drupalPost('admin/config/content/formats/' . $filtered, $edit, t('Save configuration'));
|
||||
$this->assertFieldByName('filters[' . $second_filter . '][weight]', $edit['filters[' . $second_filter . '][weight]'], t('Changes reverted.'));
|
||||
$this->assertFieldByName('filters[' . $first_filter . '][weight]', $edit['filters[' . $first_filter . '][weight]'], t('Changes reverted.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the URL filter settings form is properly validated.
|
||||
*/
|
||||
function testUrlFilterAdmin() {
|
||||
// The form does not save with an invalid filter URL length.
|
||||
$edit = array(
|
||||
'filters[filter_url][settings][filter_url_length]' => $this->randomName(4),
|
||||
);
|
||||
$this->drupalPost('admin/config/content/formats/filtered_html', $edit, t('Save configuration'));
|
||||
$this->assertNoRaw(t('The text format %format has been updated.', array('%format' => 'Filtered HTML')));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\filter\Tests\FilterCrudTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\filter\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Tests for text format and filter CRUD operations.
|
||||
*/
|
||||
class FilterCrudTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Filter CRUD operations',
|
||||
'description' => 'Test creation, loading, updating, deleting of text formats and filters.',
|
||||
'group' => 'Filter',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('filter_test');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test CRUD operations for text formats and filters.
|
||||
*/
|
||||
function testTextFormatCrud() {
|
||||
// Add a text format with minimum data only.
|
||||
$format = new stdClass();
|
||||
$format->format = 'empty_format';
|
||||
$format->name = 'Empty format';
|
||||
filter_format_save($format);
|
||||
$this->verifyTextFormat($format);
|
||||
$this->verifyFilters($format);
|
||||
|
||||
// Add another text format specifying all possible properties.
|
||||
$format = new stdClass();
|
||||
$format->format = 'custom_format';
|
||||
$format->name = 'Custom format';
|
||||
$format->filters = array(
|
||||
'filter_url' => array(
|
||||
'status' => 1,
|
||||
'settings' => array(
|
||||
'filter_url_length' => 30,
|
||||
),
|
||||
),
|
||||
);
|
||||
filter_format_save($format);
|
||||
$this->verifyTextFormat($format);
|
||||
$this->verifyFilters($format);
|
||||
|
||||
// Alter some text format properties and save again.
|
||||
$format->name = 'Altered format';
|
||||
$format->filters['filter_url']['status'] = 0;
|
||||
$format->filters['filter_autop']['status'] = 1;
|
||||
filter_format_save($format);
|
||||
$this->verifyTextFormat($format);
|
||||
$this->verifyFilters($format);
|
||||
|
||||
// Add a uncacheable filter and save again.
|
||||
$format->filters['filter_test_uncacheable']['status'] = 1;
|
||||
filter_format_save($format);
|
||||
$this->verifyTextFormat($format);
|
||||
$this->verifyFilters($format);
|
||||
|
||||
// Disable the text format.
|
||||
filter_format_disable($format);
|
||||
|
||||
$db_format = db_query("SELECT * FROM {filter_format} WHERE format = :format", array(':format' => $format->format))->fetchObject();
|
||||
$this->assertFalse($db_format->status, t('Database: Disabled text format is marked as disabled.'));
|
||||
$formats = filter_formats();
|
||||
$this->assertTrue(!isset($formats[$format->format]), t('filter_formats: Disabled text format no longer exists.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that a text format is properly stored.
|
||||
*/
|
||||
function verifyTextFormat($format) {
|
||||
$t_args = array('%format' => $format->name);
|
||||
// Verify text format database record.
|
||||
$db_format = db_select('filter_format', 'ff')
|
||||
->fields('ff')
|
||||
->condition('format', $format->format)
|
||||
->execute()
|
||||
->fetchObject();
|
||||
$this->assertEqual($db_format->format, $format->format, t('Database: Proper format id for text format %format.', $t_args));
|
||||
$this->assertEqual($db_format->name, $format->name, t('Database: Proper title for text format %format.', $t_args));
|
||||
$this->assertEqual($db_format->cache, $format->cache, t('Database: Proper cache indicator for text format %format.', $t_args));
|
||||
$this->assertEqual($db_format->weight, $format->weight, t('Database: Proper weight for text format %format.', $t_args));
|
||||
|
||||
// Verify filter_format_load().
|
||||
$filter_format = filter_format_load($format->format);
|
||||
$this->assertEqual($filter_format->format, $format->format, t('filter_format_load: Proper format id for text format %format.', $t_args));
|
||||
$this->assertEqual($filter_format->name, $format->name, t('filter_format_load: Proper title for text format %format.', $t_args));
|
||||
$this->assertEqual($filter_format->cache, $format->cache, t('filter_format_load: Proper cache indicator for text format %format.', $t_args));
|
||||
$this->assertEqual($filter_format->weight, $format->weight, t('filter_format_load: Proper weight for text format %format.', $t_args));
|
||||
|
||||
// Verify the 'cache' text format property according to enabled filters.
|
||||
$filter_info = filter_get_filters();
|
||||
$filters = filter_list_format($filter_format->format);
|
||||
$cacheable = TRUE;
|
||||
foreach ($filters as $name => $filter) {
|
||||
// If this filter is not cacheable, update $cacheable accordingly, so we
|
||||
// can verify $format->cache after iterating over all filters.
|
||||
if ($filter->status && isset($filter_info[$name]['cache']) && !$filter_info[$name]['cache']) {
|
||||
$cacheable = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->assertEqual($filter_format->cache, $cacheable, t('Text format contains proper cache property.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that filters are properly stored for a text format.
|
||||
*/
|
||||
function verifyFilters($format) {
|
||||
// Verify filter database records.
|
||||
$filters = db_query("SELECT * FROM {filter} WHERE format = :format", array(':format' => $format->format))->fetchAllAssoc('name');
|
||||
$format_filters = $format->filters;
|
||||
foreach ($filters as $name => $filter) {
|
||||
$t_args = array('%format' => $format->name, '%filter' => $name);
|
||||
|
||||
// Verify that filter status is properly stored.
|
||||
$this->assertEqual($filter->status, $format_filters[$name]['status'], t('Database: Proper status for %filter in text format %format.', $t_args));
|
||||
|
||||
// Verify that filter settings were properly stored.
|
||||
$this->assertEqual(unserialize($filter->settings), isset($format_filters[$name]['settings']) ? $format_filters[$name]['settings'] : array(), t('Database: Proper filter settings for %filter in text format %format.', $t_args));
|
||||
|
||||
// Verify that each filter has a module name assigned.
|
||||
$this->assertTrue(!empty($filter->module), t('Database: Proper module name for %filter in text format %format.', $t_args));
|
||||
|
||||
// Remove the filter from the copy of saved $format to check whether all
|
||||
// filters have been processed later.
|
||||
unset($format_filters[$name]);
|
||||
}
|
||||
// Verify that all filters have been processed.
|
||||
$this->assertTrue(empty($format_filters), t('Database contains values for all filters in the saved format.'));
|
||||
|
||||
// Verify filter_list_format().
|
||||
$filters = filter_list_format($format->format);
|
||||
$format_filters = $format->filters;
|
||||
foreach ($filters as $name => $filter) {
|
||||
$t_args = array('%format' => $format->name, '%filter' => $name);
|
||||
|
||||
// Verify that filter status is properly stored.
|
||||
$this->assertEqual($filter->status, $format_filters[$name]['status'], t('filter_list_format: Proper status for %filter in text format %format.', $t_args));
|
||||
|
||||
// Verify that filter settings were properly stored.
|
||||
$this->assertEqual($filter->settings, isset($format_filters[$name]['settings']) ? $format_filters[$name]['settings'] : array(), t('filter_list_format: Proper filter settings for %filter in text format %format.', $t_args));
|
||||
|
||||
// Verify that each filter has a module name assigned.
|
||||
$this->assertTrue(!empty($filter->module), t('filter_list_format: Proper module name for %filter in text format %format.', $t_args));
|
||||
|
||||
// Remove the filter from the copy of saved $format to check whether all
|
||||
// filters have been processed later.
|
||||
unset($format_filters[$name]);
|
||||
}
|
||||
// Verify that all filters have been processed.
|
||||
$this->assertTrue(empty($format_filters), t('filter_list_format: Loaded filters contain values for all filters in the saved format.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\filter\Tests\FilterDefaultFormatTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\filter\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
class FilterDefaultFormatTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Default text format functionality',
|
||||
'description' => 'Test the default text formats for different users.',
|
||||
'group' => 'Filter',
|
||||
);
|
||||
}
|
||||
|
||||
function testDefaultTextFormats() {
|
||||
// Create two text formats, and two users. The first user has access to
|
||||
// both formats, but the second user only has access to the second one.
|
||||
$admin_user = $this->drupalCreateUser(array('administer filters'));
|
||||
$this->drupalLogin($admin_user);
|
||||
$formats = array();
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$edit = array(
|
||||
'format' => drupal_strtolower($this->randomName()),
|
||||
'name' => $this->randomName(),
|
||||
);
|
||||
$this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
|
||||
$this->resetFilterCaches();
|
||||
$formats[] = filter_format_load($edit['format']);
|
||||
}
|
||||
list($first_format, $second_format) = $formats;
|
||||
$first_user = $this->drupalCreateUser(array(filter_permission_name($first_format), filter_permission_name($second_format)));
|
||||
$second_user = $this->drupalCreateUser(array(filter_permission_name($second_format)));
|
||||
|
||||
// Adjust the weights so that the first and second formats (in that order)
|
||||
// are the two lowest weighted formats available to any user.
|
||||
$minimum_weight = db_query("SELECT MIN(weight) FROM {filter_format}")->fetchField();
|
||||
$edit = array();
|
||||
$edit['formats[' . $first_format->format . '][weight]'] = $minimum_weight - 2;
|
||||
$edit['formats[' . $second_format->format . '][weight]'] = $minimum_weight - 1;
|
||||
$this->drupalPost('admin/config/content/formats', $edit, t('Save changes'));
|
||||
$this->resetFilterCaches();
|
||||
|
||||
// Check that each user's default format is the lowest weighted format that
|
||||
// the user has access to.
|
||||
$this->assertEqual(filter_default_format($first_user), $first_format->format, t("The first user's default format is the lowest weighted format that the user has access to."));
|
||||
$this->assertEqual(filter_default_format($second_user), $second_format->format, t("The second user's default format is the lowest weighted format that the user has access to, and is different than the first user's."));
|
||||
|
||||
// Reorder the two formats, and check that both users now have the same
|
||||
// default.
|
||||
$edit = array();
|
||||
$edit['formats[' . $second_format->format . '][weight]'] = $minimum_weight - 3;
|
||||
$this->drupalPost('admin/config/content/formats', $edit, t('Save changes'));
|
||||
$this->resetFilterCaches();
|
||||
$this->assertEqual(filter_default_format($first_user), filter_default_format($second_user), t('After the formats are reordered, both users have the same default format.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild text format and permission caches in the thread running the tests.
|
||||
*/
|
||||
protected function resetFilterCaches() {
|
||||
filter_formats_reset();
|
||||
$this->checkPermissions(array(), TRUE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\filter\Tests\FilterFormatAccessTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\filter\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
class FilterFormatAccessTest extends WebTestBase {
|
||||
protected $admin_user;
|
||||
protected $filter_admin_user;
|
||||
protected $web_user;
|
||||
protected $allowed_format;
|
||||
protected $disallowed_format;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Filter format access',
|
||||
'description' => 'Tests access to text formats.',
|
||||
'group' => 'Filter',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
|
||||
|
||||
// Create a user who can administer text formats, but does not have
|
||||
// specific permission to use any of them.
|
||||
$this->filter_admin_user = $this->drupalCreateUser(array(
|
||||
'administer filters',
|
||||
'create page content',
|
||||
'edit any page content',
|
||||
));
|
||||
|
||||
// Create two text formats.
|
||||
$this->drupalLogin($this->filter_admin_user);
|
||||
$formats = array();
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$edit = array(
|
||||
'format' => drupal_strtolower($this->randomName()),
|
||||
'name' => $this->randomName(),
|
||||
);
|
||||
$this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
|
||||
$this->resetFilterCaches();
|
||||
$formats[] = filter_format_load($edit['format']);
|
||||
}
|
||||
list($this->allowed_format, $this->disallowed_format) = $formats;
|
||||
$this->drupalLogout();
|
||||
|
||||
// Create a regular user with access to one of the formats.
|
||||
$this->web_user = $this->drupalCreateUser(array(
|
||||
'create page content',
|
||||
'edit any page content',
|
||||
filter_permission_name($this->allowed_format),
|
||||
));
|
||||
|
||||
// Create an administrative user who has access to use both formats.
|
||||
$this->admin_user = $this->drupalCreateUser(array(
|
||||
'administer filters',
|
||||
'create page content',
|
||||
'edit any page content',
|
||||
filter_permission_name($this->allowed_format),
|
||||
filter_permission_name($this->disallowed_format),
|
||||
));
|
||||
}
|
||||
|
||||
function testFormatPermissions() {
|
||||
// Make sure that a regular user only has access to the text format they
|
||||
// were granted access to, as well to the fallback format.
|
||||
$this->assertTrue(filter_access($this->allowed_format, $this->web_user), t('A regular user has access to a text format they were granted access to.'));
|
||||
$this->assertFalse(filter_access($this->disallowed_format, $this->web_user), t('A regular user does not have access to a text format they were not granted access to.'));
|
||||
$this->assertTrue(filter_access(filter_format_load(filter_fallback_format()), $this->web_user), t('A regular user has access to the fallback format.'));
|
||||
|
||||
// Perform similar checks as above, but now against the entire list of
|
||||
// available formats for this user.
|
||||
$this->assertTrue(in_array($this->allowed_format->format, array_keys(filter_formats($this->web_user))), t('The allowed format appears in the list of available formats for a regular user.'));
|
||||
$this->assertFalse(in_array($this->disallowed_format->format, array_keys(filter_formats($this->web_user))), t('The disallowed format does not appear in the list of available formats for a regular user.'));
|
||||
$this->assertTrue(in_array(filter_fallback_format(), array_keys(filter_formats($this->web_user))), t('The fallback format appears in the list of available formats for a regular user.'));
|
||||
|
||||
// Make sure that a regular user only has permission to use the format
|
||||
// they were granted access to.
|
||||
$this->assertTrue(user_access(filter_permission_name($this->allowed_format), $this->web_user), t('A regular user has permission to use the allowed text format.'));
|
||||
$this->assertFalse(user_access(filter_permission_name($this->disallowed_format), $this->web_user), t('A regular user does not have permission to use the disallowed text format.'));
|
||||
|
||||
// Make sure that the allowed format appears on the node form and that
|
||||
// the disallowed format does not.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('node/add/page');
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$elements = $this->xpath('//select[@name=:name]/option', array(
|
||||
':name' => "body[$langcode][0][format]",
|
||||
':option' => $this->allowed_format->format,
|
||||
));
|
||||
$options = array();
|
||||
foreach ($elements as $element) {
|
||||
$options[(string) $element['value']] = $element;
|
||||
}
|
||||
$this->assertTrue(isset($options[$this->allowed_format->format]), t('The allowed text format appears as an option when adding a new node.'));
|
||||
$this->assertFalse(isset($options[$this->disallowed_format->format]), t('The disallowed text format does not appear as an option when adding a new node.'));
|
||||
$this->assertTrue(isset($options[filter_fallback_format()]), t('The fallback format appears as an option when adding a new node.'));
|
||||
}
|
||||
|
||||
function testFormatRoles() {
|
||||
// Get the role ID assigned to the regular user; it must be the maximum.
|
||||
$rid = max(array_keys($this->web_user->roles));
|
||||
|
||||
// Check that this role appears in the list of roles that have access to an
|
||||
// allowed text format, but does not appear in the list of roles that have
|
||||
// access to a disallowed text format.
|
||||
$this->assertTrue(in_array($rid, array_keys(filter_get_roles_by_format($this->allowed_format))), t('A role which has access to a text format appears in the list of roles that have access to that format.'));
|
||||
$this->assertFalse(in_array($rid, array_keys(filter_get_roles_by_format($this->disallowed_format))), t('A role which does not have access to a text format does not appear in the list of roles that have access to that format.'));
|
||||
|
||||
// Check that the correct text format appears in the list of formats
|
||||
// available to that role.
|
||||
$this->assertTrue(in_array($this->allowed_format->format, array_keys(filter_get_formats_by_role($rid))), t('A text format which a role has access to appears in the list of formats available to that role.'));
|
||||
$this->assertFalse(in_array($this->disallowed_format->format, array_keys(filter_get_formats_by_role($rid))), t('A text format which a role does not have access to does not appear in the list of formats available to that role.'));
|
||||
|
||||
// Check that the fallback format is always allowed.
|
||||
$this->assertEqual(filter_get_roles_by_format(filter_format_load(filter_fallback_format())), user_roles(), t('All roles have access to the fallback format.'));
|
||||
$this->assertTrue(in_array(filter_fallback_format(), array_keys(filter_get_formats_by_role($rid))), t('The fallback format appears in the list of allowed formats for any role.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test editing a page using a disallowed text format.
|
||||
*
|
||||
* Verifies that regular users and administrators are able to edit a page,
|
||||
* but not allowed to change the fields which use an inaccessible text
|
||||
* format. Also verifies that fields which use a text format that does not
|
||||
* exist can be edited by administrators only, but that the administrator is
|
||||
* forced to choose a new format before saving the page.
|
||||
*/
|
||||
function testFormatWidgetPermissions() {
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$title_key = "title";
|
||||
$body_value_key = "body[$langcode][0][value]";
|
||||
$body_format_key = "body[$langcode][0][format]";
|
||||
|
||||
// Create node to edit.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName(8);
|
||||
$edit[$body_value_key] = $this->randomName(16);
|
||||
$edit[$body_format_key] = $this->disallowed_format->format;
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
$node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
|
||||
// Try to edit with a less privileged user.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->clickLink(t('Edit'));
|
||||
|
||||
// Verify that body field is read-only and contains replacement value.
|
||||
$this->assertFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), t('Text format access denied message found.'));
|
||||
|
||||
// Verify that title can be changed, but preview displays original body.
|
||||
$new_edit = array();
|
||||
$new_edit['title'] = $this->randomName(8);
|
||||
$this->drupalPost(NULL, $new_edit, t('Preview'));
|
||||
$this->assertText($edit[$body_value_key], t('Old body found in preview.'));
|
||||
|
||||
// Save and verify that only the title was changed.
|
||||
$this->drupalPost(NULL, $new_edit, t('Save'));
|
||||
$this->assertNoText($edit['title'], t('Old title not found.'));
|
||||
$this->assertText($new_edit['title'], t('New title found.'));
|
||||
$this->assertText($edit[$body_value_key], t('Old body found.'));
|
||||
|
||||
// Check that even an administrator with "administer filters" permission
|
||||
// cannot edit the body field if they do not have specific permission to
|
||||
// use its stored format. (This must be disallowed so that the
|
||||
// administrator is never forced to switch the text format to something
|
||||
// else.)
|
||||
$this->drupalLogin($this->filter_admin_user);
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
$this->assertFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), t('Text format access denied message found.'));
|
||||
|
||||
// Disable the text format used above.
|
||||
filter_format_disable($this->disallowed_format);
|
||||
$this->resetFilterCaches();
|
||||
|
||||
// Log back in as the less privileged user and verify that the body field
|
||||
// is still disabled, since the less privileged user should not be able to
|
||||
// edit content that does not have an assigned format.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
$this->assertFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", t('This field has been disabled because you do not have sufficient permissions to edit it.'), t('Text format access denied message found.'));
|
||||
|
||||
// Log back in as the filter administrator and verify that the body field
|
||||
// can be edited.
|
||||
$this->drupalLogin($this->filter_admin_user);
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
$this->assertNoFieldByXPath("//textarea[@name='$body_value_key' and @disabled='disabled']", NULL, t('Text format access denied message not found.'));
|
||||
$this->assertFieldByXPath("//select[@name='$body_format_key']", NULL, t('Text format selector found.'));
|
||||
|
||||
// Verify that trying to save the node without selecting a new text format
|
||||
// produces an error message, and does not result in the node being saved.
|
||||
$old_title = $new_edit['title'];
|
||||
$new_title = $this->randomName(8);
|
||||
$edit = array('title' => $new_title);
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$this->assertText(t('!name field is required.', array('!name' => t('Text format'))), t('Error message is displayed.'));
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertText($old_title, t('Old title found.'));
|
||||
$this->assertNoText($new_title, t('New title not found.'));
|
||||
|
||||
// Now select a new text format and make sure the node can be saved.
|
||||
$edit[$body_format_key] = filter_fallback_format();
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$this->assertUrl('node/' . $node->nid);
|
||||
$this->assertText($new_title, t('New title found.'));
|
||||
$this->assertNoText($old_title, t('Old title not found.'));
|
||||
|
||||
// Switch the text format to a new one, then disable that format and all
|
||||
// other formats on the site (leaving only the fallback format).
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$edit = array($body_format_key => $this->allowed_format->format);
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$this->assertUrl('node/' . $node->nid);
|
||||
foreach (filter_formats() as $format) {
|
||||
if ($format->format != filter_fallback_format()) {
|
||||
filter_format_disable($format);
|
||||
}
|
||||
}
|
||||
|
||||
// Since there is now only one available text format, the widget for
|
||||
// selecting a text format would normally not display when the content is
|
||||
// edited. However, we need to verify that the filter administrator still
|
||||
// is forced to make a conscious choice to reassign the text to a different
|
||||
// format.
|
||||
$this->drupalLogin($this->filter_admin_user);
|
||||
$old_title = $new_title;
|
||||
$new_title = $this->randomName(8);
|
||||
$edit = array('title' => $new_title);
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$this->assertText(t('!name field is required.', array('!name' => t('Text format'))), t('Error message is displayed.'));
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertText($old_title, t('Old title found.'));
|
||||
$this->assertNoText($new_title, t('New title not found.'));
|
||||
$edit[$body_format_key] = filter_fallback_format();
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$this->assertUrl('node/' . $node->nid);
|
||||
$this->assertText($new_title, t('New title found.'));
|
||||
$this->assertNoText($old_title, t('Old title not found.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild text format and permission caches in the thread running the tests.
|
||||
*/
|
||||
protected function resetFilterCaches() {
|
||||
filter_formats_reset();
|
||||
$this->checkPermissions(array(), TRUE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\filter\Tests\FilterHooksTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\filter\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests for filter hook invocation.
|
||||
*/
|
||||
class FilterHooksTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Filter format hooks',
|
||||
'description' => 'Test hooks for text formats insert/update/disable.',
|
||||
'group' => 'Filter',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('block', 'filter_test');
|
||||
$admin_user = $this->drupalCreateUser(array('administer filters', 'administer blocks'));
|
||||
$this->drupalLogin($admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that hooks run correctly on creating, editing, and deleting a text format.
|
||||
*/
|
||||
function testFilterHooks() {
|
||||
// Add a text format.
|
||||
$name = $this->randomName();
|
||||
$edit = array();
|
||||
$edit['format'] = drupal_strtolower($this->randomName());
|
||||
$edit['name'] = $name;
|
||||
$edit['roles[' . DRUPAL_ANONYMOUS_RID . ']'] = 1;
|
||||
$this->drupalPost('admin/config/content/formats/add', $edit, t('Save configuration'));
|
||||
$this->assertRaw(t('Added text format %format.', array('%format' => $name)), t('New format created.'));
|
||||
$this->assertText('hook_filter_format_insert invoked.', t('hook_filter_format_insert was invoked.'));
|
||||
|
||||
$format_id = $edit['format'];
|
||||
|
||||
// Update text format.
|
||||
$edit = array();
|
||||
$edit['roles[' . DRUPAL_AUTHENTICATED_RID . ']'] = 1;
|
||||
$this->drupalPost('admin/config/content/formats/' . $format_id, $edit, t('Save configuration'));
|
||||
$this->assertRaw(t('The text format %format has been updated.', array('%format' => $name)), t('Format successfully updated.'));
|
||||
$this->assertText('hook_filter_format_update invoked.', t('hook_filter_format_update() was invoked.'));
|
||||
|
||||
// Add a new custom block.
|
||||
$custom_block = array();
|
||||
$custom_block['info'] = $this->randomName(8);
|
||||
$custom_block['title'] = $this->randomName(8);
|
||||
$custom_block['body[value]'] = $this->randomName(32);
|
||||
// Use the format created.
|
||||
$custom_block['body[format]'] = $format_id;
|
||||
$this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
|
||||
$this->assertText(t('The block has been created.'), t('New block successfully created.'));
|
||||
|
||||
// Verify the new block is in the database.
|
||||
$bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
|
||||
$this->assertNotNull($bid, t('New block found in database'));
|
||||
|
||||
// Disable the text format.
|
||||
$this->drupalPost('admin/config/content/formats/' . $format_id . '/disable', array(), t('Disable'));
|
||||
$this->assertRaw(t('Disabled text format %format.', array('%format' => $name)), t('Format successfully disabled.'));
|
||||
$this->assertText('hook_filter_format_disable invoked.', t('hook_filter_format_disable() was invoked.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\filter\Tests\FilterNoFormatTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\filter\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
class FilterNoFormatTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Unassigned text format functionality',
|
||||
'description' => 'Test the behavior of check_markup() when it is called without a text format.',
|
||||
'group' => 'Filter',
|
||||
);
|
||||
}
|
||||
|
||||
function testCheckMarkupNoFormat() {
|
||||
// Create some text. Include some HTML and line breaks, so we get a good
|
||||
// test of the filtering that is applied to it.
|
||||
$text = "<strong>" . $this->randomName(32) . "</strong>\n\n<div>" . $this->randomName(32) . "</div>";
|
||||
|
||||
// Make sure that when this text is run through check_markup() with no text
|
||||
// format, it is filtered as though it is in the fallback format.
|
||||
$this->assertEqual(check_markup($text), check_markup($text, filter_fallback_format()), t('Text with no format is filtered the same as text in the fallback format.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\filter\Tests\FilterSecurityTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\filter\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Security tests for missing/vanished text formats or filters.
|
||||
*/
|
||||
class FilterSecurityTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Security',
|
||||
'description' => 'Test the behavior of check_markup() when a filter or text format vanishes.',
|
||||
'group' => 'Filter',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('node', 'php', 'filter_test'));
|
||||
|
||||
// Create Basic page node type.
|
||||
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
|
||||
|
||||
// Create Filtered HTML format.
|
||||
$filtered_html_format = array(
|
||||
'format' => 'filtered_html',
|
||||
'name' => 'Filtered HTML',
|
||||
);
|
||||
$filtered_html_format = (object) $filtered_html_format;
|
||||
filter_format_save($filtered_html_format);
|
||||
|
||||
$filtered_html_permission = filter_permission_name($filtered_html_format);
|
||||
user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array($filtered_html_permission));
|
||||
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer modules', 'administer filters', 'administer site configuration'));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that filtered content is emptied when an actively used filter module is disabled.
|
||||
*/
|
||||
function testDisableFilterModule() {
|
||||
// Create a new node.
|
||||
$node = $this->drupalCreateNode(array('promote' => 1));
|
||||
$body_raw = $node->body[LANGUAGE_NOT_SPECIFIED][0]['value'];
|
||||
$format_id = $node->body[LANGUAGE_NOT_SPECIFIED][0]['format'];
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertText($body_raw, t('Node body found.'));
|
||||
|
||||
// Enable the filter_test_replace filter.
|
||||
$edit = array(
|
||||
'filters[filter_test_replace][status]' => 1,
|
||||
);
|
||||
$this->drupalPost('admin/config/content/formats/' . $format_id, $edit, t('Save configuration'));
|
||||
|
||||
// Verify that filter_test_replace filter replaced the content.
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertNoText($body_raw, t('Node body not found.'));
|
||||
$this->assertText('Filter: Testing filter', t('Testing filter output found.'));
|
||||
|
||||
// Disable the text format entirely.
|
||||
$this->drupalPost('admin/config/content/formats/' . $format_id . '/disable', array(), t('Disable'));
|
||||
|
||||
// Verify that the content is empty, because the text format does not exist.
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertNoText($body_raw, t('Node body not found.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\filter\Tests\FilterSettingsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\filter\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests filter settings.
|
||||
*/
|
||||
class FilterSettingsTest extends WebTestBase {
|
||||
protected $profile = 'testing';
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Filter settings',
|
||||
'description' => 'Tests filter settings.',
|
||||
'group' => 'Filter',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests explicit and implicit default settings for filters.
|
||||
*/
|
||||
function testFilterDefaults() {
|
||||
$filter_info = filter_filter_info();
|
||||
$filters = array_fill_keys(array_keys($filter_info), array());
|
||||
|
||||
// Create text format using filter default settings.
|
||||
$filter_defaults_format = (object) array(
|
||||
'format' => 'filter_defaults',
|
||||
'name' => 'Filter defaults',
|
||||
'filters' => $filters,
|
||||
);
|
||||
filter_format_save($filter_defaults_format);
|
||||
|
||||
// Verify that default weights defined in hook_filter_info() were applied.
|
||||
$saved_settings = array();
|
||||
foreach ($filter_defaults_format->filters as $name => $settings) {
|
||||
$expected_weight = (isset($filter_info[$name]['weight']) ? $filter_info[$name]['weight'] : 0);
|
||||
$this->assertEqual($settings['weight'], $expected_weight, format_string('@name filter weight %saved equals %default', array(
|
||||
'@name' => $name,
|
||||
'%saved' => $settings['weight'],
|
||||
'%default' => $expected_weight,
|
||||
)));
|
||||
$saved_settings[$name]['weight'] = $expected_weight;
|
||||
}
|
||||
|
||||
// Re-save the text format.
|
||||
filter_format_save($filter_defaults_format);
|
||||
// Reload it from scratch.
|
||||
filter_formats_reset();
|
||||
$filter_defaults_format = filter_format_load($filter_defaults_format->format);
|
||||
$filter_defaults_format->filters = filter_list_format($filter_defaults_format->format);
|
||||
|
||||
// Verify that saved filter settings have not been changed.
|
||||
foreach ($filter_defaults_format->filters as $name => $settings) {
|
||||
$this->assertEqual($settings->weight, $saved_settings[$name]['weight'], format_string('@name filter weight %saved equals %previous', array(
|
||||
'@name' => $name,
|
||||
'%saved' => $settings->weight,
|
||||
'%previous' => $saved_settings[$name]['weight'],
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\menu\Tests\MenuNodeTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Test menu settings for nodes.
|
||||
*/
|
||||
class MenuNodeTest extends WebTestBase {
|
||||
protected $profile = 'standard';
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Menu settings for nodes',
|
||||
'description' => 'Add, edit, and delete a node with menu link.',
|
||||
'group' => 'Menu',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('menu');
|
||||
|
||||
$this->admin_user = $this->drupalCreateUser(array(
|
||||
'access administration pages',
|
||||
'administer content types',
|
||||
'administer menu',
|
||||
'create page content',
|
||||
'edit any page content',
|
||||
'delete any page content',
|
||||
));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating, editing, deleting menu links via node form widget.
|
||||
*/
|
||||
function testMenuNodeFormWidget() {
|
||||
// Enable Navigation menu as available menu.
|
||||
$edit = array(
|
||||
'menu_options[navigation]' => 1,
|
||||
);
|
||||
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
// Change default parent item to Navigation menu, so we can assert more
|
||||
// easily.
|
||||
$edit = array(
|
||||
'menu_parent' => 'navigation:0',
|
||||
);
|
||||
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
|
||||
// Create a node.
|
||||
$node_title = $this->randomName();
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$edit = array(
|
||||
"title" => $node_title,
|
||||
"body[$langcode][0][value]" => $this->randomString(),
|
||||
);
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
$node = $this->drupalGetNodeByTitle($node_title);
|
||||
// Assert that there is no link for the node.
|
||||
$this->drupalGet('');
|
||||
$this->assertNoLink($node_title);
|
||||
|
||||
// Edit the node, enable the menu link setting, but skip the link title.
|
||||
$edit = array(
|
||||
'menu[enabled]' => 1,
|
||||
);
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
// Assert that there is no link for the node.
|
||||
$this->drupalGet('');
|
||||
$this->assertNoLink($node_title);
|
||||
|
||||
// Edit the node and create a menu link.
|
||||
$edit = array(
|
||||
'menu[enabled]' => 1,
|
||||
'menu[link_title]' => $node_title,
|
||||
'menu[weight]' => 17,
|
||||
);
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
// Assert that the link exists.
|
||||
$this->drupalGet('');
|
||||
$this->assertLink($node_title);
|
||||
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
$this->assertOptionSelected('edit-menu-weight', 17, t('Menu weight correct in edit form'));
|
||||
|
||||
// Edit the node and remove the menu link.
|
||||
$edit = array(
|
||||
'menu[enabled]' => FALSE,
|
||||
);
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
// Assert that there is no link for the node.
|
||||
$this->drupalGet('');
|
||||
$this->assertNoLink($node_title);
|
||||
|
||||
// Add a menu link to the Management menu.
|
||||
$item = array(
|
||||
'link_path' => 'node/' . $node->nid,
|
||||
'link_title' => $this->randomName(16),
|
||||
'menu_name' => 'management',
|
||||
);
|
||||
menu_link_save($item);
|
||||
|
||||
// Assert that disabled Management menu is not shown on the node/$nid/edit page.
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
$this->assertText('Provide a menu link', t('Link in not allowed menu not shown in node edit form'));
|
||||
// Assert that the link is still in the management menu after save.
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$link = menu_link_load($item['mlid']);
|
||||
$this->assertTrue($link, t('Link in not allowed menu still exists after saving node'));
|
||||
|
||||
// Move the menu link back to the Navigation menu.
|
||||
$item['menu_name'] = 'navigation';
|
||||
menu_link_save($item);
|
||||
// Create a second node.
|
||||
$child_node = $this->drupalCreateNode(array('type' => 'article'));
|
||||
// Assign a menu link to the second node, being a child of the first one.
|
||||
$child_item = array(
|
||||
'link_path' => 'node/'. $child_node->nid,
|
||||
'link_title' => $this->randomName(16),
|
||||
'plid' => $item['mlid'],
|
||||
);
|
||||
menu_link_save($child_item);
|
||||
// Edit the first node.
|
||||
$this->drupalGet('node/'. $node->nid .'/edit');
|
||||
// Assert that it is not possible to set the parent of the first node to itself or the second node.
|
||||
$this->assertNoOption('edit-menu-parent', 'navigation:'. $item['mlid']);
|
||||
$this->assertNoOption('edit-menu-parent', 'navigation:'. $child_item['mlid']);
|
||||
// Assert that unallowed Management menu is not available in options.
|
||||
$this->assertNoOption('edit-menu-parent', 'management:0');
|
||||
}
|
||||
}
|
|
@ -2,12 +2,14 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* Tests for menu.module.
|
||||
* Definition of Drupal\menu\Tests\MenuTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\menu\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
class MenuTestCase extends WebTestBase {
|
||||
class MenuTest extends WebTestBase {
|
||||
protected $profile = 'standard';
|
||||
|
||||
protected $big_user;
|
||||
|
@ -581,130 +583,3 @@ class MenuTestCase extends WebTestBase {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test menu settings for nodes.
|
||||
*/
|
||||
class MenuNodeTestCase extends WebTestBase {
|
||||
protected $profile = 'standard';
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Menu settings for nodes',
|
||||
'description' => 'Add, edit, and delete a node with menu link.',
|
||||
'group' => 'Menu',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('menu');
|
||||
|
||||
$this->admin_user = $this->drupalCreateUser(array(
|
||||
'access administration pages',
|
||||
'administer content types',
|
||||
'administer menu',
|
||||
'create page content',
|
||||
'edit any page content',
|
||||
'delete any page content',
|
||||
));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating, editing, deleting menu links via node form widget.
|
||||
*/
|
||||
function testMenuNodeFormWidget() {
|
||||
// Enable Navigation menu as available menu.
|
||||
$edit = array(
|
||||
'menu_options[navigation]' => 1,
|
||||
);
|
||||
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
// Change default parent item to Navigation menu, so we can assert more
|
||||
// easily.
|
||||
$edit = array(
|
||||
'menu_parent' => 'navigation:0',
|
||||
);
|
||||
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
|
||||
// Create a node.
|
||||
$node_title = $this->randomName();
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$edit = array(
|
||||
"title" => $node_title,
|
||||
"body[$langcode][0][value]" => $this->randomString(),
|
||||
);
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
$node = $this->drupalGetNodeByTitle($node_title);
|
||||
// Assert that there is no link for the node.
|
||||
$this->drupalGet('');
|
||||
$this->assertNoLink($node_title);
|
||||
|
||||
// Edit the node, enable the menu link setting, but skip the link title.
|
||||
$edit = array(
|
||||
'menu[enabled]' => 1,
|
||||
);
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
// Assert that there is no link for the node.
|
||||
$this->drupalGet('');
|
||||
$this->assertNoLink($node_title);
|
||||
|
||||
// Edit the node and create a menu link.
|
||||
$edit = array(
|
||||
'menu[enabled]' => 1,
|
||||
'menu[link_title]' => $node_title,
|
||||
'menu[weight]' => 17,
|
||||
);
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
// Assert that the link exists.
|
||||
$this->drupalGet('');
|
||||
$this->assertLink($node_title);
|
||||
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
$this->assertOptionSelected('edit-menu-weight', 17, t('Menu weight correct in edit form'));
|
||||
|
||||
// Edit the node and remove the menu link.
|
||||
$edit = array(
|
||||
'menu[enabled]' => FALSE,
|
||||
);
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
// Assert that there is no link for the node.
|
||||
$this->drupalGet('');
|
||||
$this->assertNoLink($node_title);
|
||||
|
||||
// Add a menu link to the Management menu.
|
||||
$item = array(
|
||||
'link_path' => 'node/' . $node->nid,
|
||||
'link_title' => $this->randomName(16),
|
||||
'menu_name' => 'management',
|
||||
);
|
||||
menu_link_save($item);
|
||||
|
||||
// Assert that disabled Management menu is not shown on the node/$nid/edit page.
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
$this->assertText('Provide a menu link', t('Link in not allowed menu not shown in node edit form'));
|
||||
// Assert that the link is still in the management menu after save.
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$link = menu_link_load($item['mlid']);
|
||||
$this->assertTrue($link, t('Link in not allowed menu still exists after saving node'));
|
||||
|
||||
// Move the menu link back to the Navigation menu.
|
||||
$item['menu_name'] = 'navigation';
|
||||
menu_link_save($item);
|
||||
// Create a second node.
|
||||
$child_node = $this->drupalCreateNode(array('type' => 'article'));
|
||||
// Assign a menu link to the second node, being a child of the first one.
|
||||
$child_item = array(
|
||||
'link_path' => 'node/'. $child_node->nid,
|
||||
'link_title' => $this->randomName(16),
|
||||
'plid' => $item['mlid'],
|
||||
);
|
||||
menu_link_save($child_item);
|
||||
// Edit the first node.
|
||||
$this->drupalGet('node/'. $node->nid .'/edit');
|
||||
// Assert that it is not possible to set the parent of the first node to itself or the second node.
|
||||
$this->assertNoOption('edit-menu-parent', 'navigation:'. $item['mlid']);
|
||||
$this->assertNoOption('edit-menu-parent', 'navigation:'. $child_item['mlid']);
|
||||
// Assert that unallowed Management menu is not available in options.
|
||||
$this->assertNoOption('edit-menu-parent', 'management:0');
|
||||
}
|
||||
}
|
|
@ -3,5 +3,4 @@ description = Allows administrators to customize the site navigation menu.
|
|||
package = Core
|
||||
version = VERSION
|
||||
core = 8.x
|
||||
files[] = menu.test
|
||||
configure = admin/structure/menu
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\MultiStepNodeFormBasicOptionsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Test multistep node forms basic options.
|
||||
*/
|
||||
class MultiStepNodeFormBasicOptionsTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Multistep node form basic options',
|
||||
'description' => 'Test the persistence of basic options through multiple steps.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('poll');
|
||||
$web_user = $this->drupalCreateUser(array('administer nodes', 'create poll content'));
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the default values of basic options to ensure they persist.
|
||||
*/
|
||||
function testMultiStepNodeFormBasicOptions() {
|
||||
$edit = array(
|
||||
'title' => 'a',
|
||||
'status' => FALSE,
|
||||
'promote' => FALSE,
|
||||
'sticky' => 1,
|
||||
'choice[new:0][chtext]' => 'a',
|
||||
'choice[new:1][chtext]' => 'a',
|
||||
);
|
||||
$this->drupalPost('node/add/poll', $edit, t('Add another choice'));
|
||||
$this->assertNoFieldChecked('edit-status', 'status stayed unchecked');
|
||||
$this->assertNoFieldChecked('edit-promote', 'promote stayed unchecked');
|
||||
$this->assertFieldChecked('edit-sticky', 'sticky stayed checked');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeAccessBaseTableTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests for Node Access with a non-node base table.
|
||||
*/
|
||||
class NodeAccessBaseTableTest extends NodeTestBase {
|
||||
// Requires tags taxonomy field.
|
||||
protected $profile = 'standard';
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node access on any table',
|
||||
'description' => 'Checks behavior of the node access subsystem if the base table is not node.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable modules and create user with specific permissions.
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp('node_access_test');
|
||||
node_access_rebuild();
|
||||
variable_set('node_access_test_private', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the "private" node access.
|
||||
*
|
||||
* - Create 2 users with "access content" and "create article" permissions.
|
||||
* - Each user creates one private and one not private article.
|
||||
*
|
||||
* - Test that each user can view the other user's non-private article.
|
||||
* - Test that each user cannot view the other user's private article.
|
||||
* - Test that each user finds only appropriate (non-private + own private)
|
||||
* in taxonomy listing.
|
||||
* - Create another user with 'view any private content'.
|
||||
* - Test that user 4 can view all content created above.
|
||||
* - Test that user 4 can view all content on taxonomy listing.
|
||||
*/
|
||||
function testNodeAccessBasic() {
|
||||
$num_simple_users = 2;
|
||||
$simple_users = array();
|
||||
|
||||
// nodes keyed by uid and nid: $nodes[$uid][$nid] = $is_private;
|
||||
$this->nodesByUser = array();
|
||||
$titles = array(); // Titles keyed by nid
|
||||
$private_nodes = array(); // Array of nids marked private.
|
||||
for ($i = 0; $i < $num_simple_users; $i++) {
|
||||
$simple_users[$i] = $this->drupalCreateUser(array('access content', 'create article content'));
|
||||
}
|
||||
foreach ($simple_users as $this->webUser) {
|
||||
$this->drupalLogin($this->webUser);
|
||||
foreach (array(0 => 'Public', 1 => 'Private') as $is_private => $type) {
|
||||
$edit = array(
|
||||
'title' => t('@private_public Article created by @user', array('@private_public' => $type, '@user' => $this->webUser->name)),
|
||||
);
|
||||
if ($is_private) {
|
||||
$edit['private'] = TRUE;
|
||||
$edit['body[und][0][value]'] = 'private node';
|
||||
$edit['field_tags[und]'] = 'private';
|
||||
}
|
||||
else {
|
||||
$edit['body[und][0][value]'] = 'public node';
|
||||
$edit['field_tags[und]'] = 'public';
|
||||
}
|
||||
|
||||
$this->drupalPost('node/add/article', $edit, t('Save'));
|
||||
$nid = db_query('SELECT nid FROM {node} WHERE title = :title', array(':title' => $edit['title']))->fetchField();
|
||||
$private_status = db_query('SELECT private FROM {node_access_test} where nid = :nid', array(':nid' => $nid))->fetchField();
|
||||
$this->assertTrue($is_private == $private_status, t('The private status of the node was properly set in the node_access_test table.'));
|
||||
if ($is_private) {
|
||||
$private_nodes[] = $nid;
|
||||
}
|
||||
$titles[$nid] = $edit['title'];
|
||||
$this->nodesByUser[$this->webUser->uid][$nid] = $is_private;
|
||||
}
|
||||
}
|
||||
$this->publicTid = db_query('SELECT tid FROM {taxonomy_term_data} WHERE name = :name', array(':name' => 'public'))->fetchField();
|
||||
$this->privateTid = db_query('SELECT tid FROM {taxonomy_term_data} WHERE name = :name', array(':name' => 'private'))->fetchField();
|
||||
$this->assertTrue($this->publicTid, t('Public tid was found'));
|
||||
$this->assertTrue($this->privateTid, t('Private tid was found'));
|
||||
foreach ($simple_users as $this->webUser) {
|
||||
$this->drupalLogin($this->webUser);
|
||||
// Check own nodes to see that all are readable.
|
||||
foreach ($this->nodesByUser as $uid => $data) {
|
||||
foreach ($data as $nid => $is_private) {
|
||||
$this->drupalGet('node/' . $nid);
|
||||
if ($is_private) {
|
||||
$should_be_visible = $uid == $this->webUser->uid;
|
||||
}
|
||||
else {
|
||||
$should_be_visible = TRUE;
|
||||
}
|
||||
$this->assertResponse($should_be_visible ? 200 : 403, strtr('A %private node by user %uid is %visible for user %current_uid.', array(
|
||||
'%private' => $is_private ? 'private' : 'public',
|
||||
'%uid' => $uid,
|
||||
'%visible' => $should_be_visible ? 'visible' : 'not visible',
|
||||
'%current_uid' => $this->webUser->uid,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see that the correct nodes are shown on taxonomy/private
|
||||
// and taxonomy/public.
|
||||
$this->assertTaxonomyPage(FALSE);
|
||||
}
|
||||
|
||||
// Now test that a user with 'access any private content' can view content.
|
||||
$access_user = $this->drupalCreateUser(array('access content', 'create article content', 'node test view', 'search content'));
|
||||
$this->drupalLogin($access_user);
|
||||
|
||||
foreach ($this->nodesByUser as $uid => $private_status) {
|
||||
foreach ($private_status as $nid => $is_private) {
|
||||
$this->drupalGet('node/' . $nid);
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
}
|
||||
|
||||
// This user should be able to see all of the nodes on the relevant
|
||||
// taxonomy pages.
|
||||
$this->assertTaxonomyPage(TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks taxonomy/term listings to ensure only accessible nodes are listed.
|
||||
*
|
||||
* @param $is_admin
|
||||
* A boolean indicating whether the current user is an administrator. If
|
||||
* TRUE, all nodes should be listed. If FALSE, only public nodes and the
|
||||
* user's own private nodes should be listed.
|
||||
*/
|
||||
protected function assertTaxonomyPage($is_admin) {
|
||||
foreach (array($this->publicTid, $this->privateTid) as $tid_is_private => $tid) {
|
||||
$this->drupalGet("taxonomy/term/$tid");
|
||||
$this->nids_visible = array();
|
||||
foreach ($this->xpath("//a[text()='Read more']") as $link) {
|
||||
$this->assertTrue(preg_match('|node/(\d+)$|', (string) $link['href'], $matches), 'Read more points to a node');
|
||||
$this->nids_visible[$matches[1]] = TRUE;
|
||||
}
|
||||
foreach ($this->nodesByUser as $uid => $data) {
|
||||
foreach ($data as $nid => $is_private) {
|
||||
// Private nodes should be visible on the private term page,
|
||||
// public nodes should be visible on the public term page.
|
||||
$should_be_visible = $tid_is_private == $is_private;
|
||||
// Non-administrators can only see their own nodes on the private
|
||||
// term page.
|
||||
if (!$is_admin && $tid_is_private) {
|
||||
$should_be_visible = $should_be_visible && $uid == $this->webUser->uid;
|
||||
}
|
||||
$this->assertIdentical(isset($this->nids_visible[$nid]), $should_be_visible, strtr('A %private node by user %uid is %visible for user %current_uid on the %tid_is_private page.', array(
|
||||
'%private' => $is_private ? 'private' : 'public',
|
||||
'%uid' => $uid,
|
||||
'%visible' => isset($this->nids_visible[$nid]) ? 'visible' : 'not visible',
|
||||
'%current_uid' => $this->webUser->uid,
|
||||
'%tid_is_private' => $tid_is_private ? 'private' : 'public',
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeAccessFieldTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests the interaction of the node access system with fields.
|
||||
*/
|
||||
class NodeAccessFieldTest extends NodeTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node access and fields',
|
||||
'description' => 'Tests the interaction of the node access system with fields.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp('node_access_test', 'field_ui');
|
||||
node_access_rebuild();
|
||||
|
||||
// Create some users.
|
||||
$this->admin_user = $this->drupalCreateUser(array('access content', 'bypass node access'));
|
||||
$this->content_admin_user = $this->drupalCreateUser(array('access content', 'administer content types'));
|
||||
|
||||
// Add a custom field to the page content type.
|
||||
$this->field_name = drupal_strtolower($this->randomName() . '_field_name');
|
||||
$this->field = field_create_field(array('field_name' => $this->field_name, 'type' => 'text'));
|
||||
$this->instance = field_create_instance(array(
|
||||
'field_name' => $this->field_name,
|
||||
'entity_type' => 'node',
|
||||
'bundle' => 'page',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests administering fields when node access is restricted.
|
||||
*/
|
||||
function testNodeAccessAdministerField() {
|
||||
// Create a page node.
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$field_data = array();
|
||||
$value = $field_data[$langcode][0]['value'] = $this->randomName();
|
||||
$node = $this->drupalCreateNode(array($this->field_name => $field_data));
|
||||
|
||||
// Log in as the administrator and confirm that the field value is present.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$this->drupalGet("node/{$node->nid}");
|
||||
$this->assertText($value, 'The saved field value is visible to an administrator.');
|
||||
|
||||
// Log in as the content admin and try to view the node.
|
||||
$this->drupalLogin($this->content_admin_user);
|
||||
$this->drupalGet("node/{$node->nid}");
|
||||
$this->assertText('Access denied', 'Access is denied for the content admin.');
|
||||
|
||||
// Modify the field default as the content admin.
|
||||
$edit = array();
|
||||
$default = 'Sometimes words have two meanings';
|
||||
$edit["{$this->field_name}[$langcode][0][value]"] = $default;
|
||||
$this->drupalPost(
|
||||
"admin/structure/types/manage/page/fields/{$this->field_name}",
|
||||
$edit,
|
||||
t('Save settings')
|
||||
);
|
||||
|
||||
// Log in as the administrator.
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Confirm that the existing node still has the correct field value.
|
||||
$this->drupalGet("node/{$node->nid}");
|
||||
$this->assertText($value, 'The original field value is visible to an administrator.');
|
||||
|
||||
// Confirm that the new default value appears when creating a new node.
|
||||
$this->drupalGet('node/add/page');
|
||||
$this->assertRaw($default, 'The updated default value is displayed when creating a new node.');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeAccessPagerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests pagination with a node access module enabled.
|
||||
*/
|
||||
class NodeAccessPagerTest extends WebTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node access pagination',
|
||||
'description' => 'Test access controlled node views have the right amount of comment pages.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp('node_access_test', 'comment', 'forum');
|
||||
node_access_rebuild();
|
||||
$this->web_user = $this->drupalCreateUser(array('access content', 'access comments', 'node test view'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the comment pager for nodes with multiple grants per realm.
|
||||
*/
|
||||
public function testCommentPager() {
|
||||
// Create a node.
|
||||
$node = $this->drupalCreateNode();
|
||||
|
||||
// Create 60 comments.
|
||||
for ($i = 0; $i < 60; $i++) {
|
||||
$comment = entity_create('comment', array(
|
||||
'nid' => $node->nid,
|
||||
'subject' => $this->randomName(),
|
||||
'comment_body' => array(
|
||||
LANGUAGE_NOT_SPECIFIED => array(
|
||||
array('value' => $this->randomName()),
|
||||
),
|
||||
),
|
||||
));
|
||||
$comment->save();
|
||||
}
|
||||
|
||||
$this->drupalLogin($this->web_user);
|
||||
|
||||
// View the node page. With the default 50 comments per page there should
|
||||
// be two pages (0, 1) but no third (2) page.
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertText($node->title, t('Node title found.'));
|
||||
$this->assertText(t('Comments'), t('Has a comments section.'));
|
||||
$this->assertRaw('page=1', t('Secound page exists.'));
|
||||
$this->assertNoRaw('page=2', t('No third page exists.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the forum node pager for nodes with multiple grants per realm.
|
||||
*/
|
||||
public function testForumPager() {
|
||||
// Lookup the forums vocabulary vid.
|
||||
$vid = variable_get('forum_nav_vocabulary', 0);
|
||||
$this->assertTrue($vid, t('Forum navigation vocabulary found.'));
|
||||
|
||||
// Lookup the general discussion term.
|
||||
$tree = taxonomy_get_tree($vid, 0, 1);
|
||||
$tid = reset($tree)->tid;
|
||||
$this->assertTrue($tid, t('General discussion term found.'));
|
||||
|
||||
// Create 30 nodes.
|
||||
for ($i = 0; $i < 30; $i++) {
|
||||
$this->drupalCreateNode(array(
|
||||
'nid' => NULL,
|
||||
'type' => 'forum',
|
||||
'taxonomy_forums' => array(
|
||||
LANGUAGE_NOT_SPECIFIED => array(
|
||||
array('tid' => $tid, 'vid' => $vid, 'vocabulary_machine_name' => 'forums'),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
// View the general discussion forum page. With the default 25 nodes per
|
||||
// page there should be two pages for 30 nodes, no more.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('forum/' . $tid);
|
||||
$this->assertRaw('page=1', t('Secound page exists.'));
|
||||
$this->assertNoRaw('page=2', t('No third page exists.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeAccessRebuildTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Rebuild the node_access table.
|
||||
*/
|
||||
class NodeAccessRebuildTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node access rebuild',
|
||||
'description' => 'Ensures that node access rebuild functions work correctly.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('administer site configuration', 'access administration pages', 'access site reports'));
|
||||
$this->drupalLogin($web_user);
|
||||
$this->web_user = $web_user;
|
||||
}
|
||||
|
||||
function testNodeAccessRebuild() {
|
||||
$this->drupalGet('admin/reports/status');
|
||||
$this->clickLink(t('Rebuild permissions'));
|
||||
$this->drupalPost(NULL, array(), t('Rebuild permissions'));
|
||||
$this->assertText(t('Content permissions have been rebuilt.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeAccessRecordsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Test case to verify hook_node_access_records functionality.
|
||||
*/
|
||||
class NodeAccessRecordsTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node access records',
|
||||
'description' => 'Test hook_node_access_records when acquiring grants.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
// Enable dummy module that implements hook_node_grants(),
|
||||
// hook_node_access_records(), hook_node_grants_alter() and
|
||||
// hook_node_access_records_alter().
|
||||
parent::setUp('node_test');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a node and test the creation of node access rules.
|
||||
*/
|
||||
function testNodeAccessRecords() {
|
||||
// Create an article node.
|
||||
$node1 = $this->drupalCreateNode(array('type' => 'article'));
|
||||
$this->assertTrue(node_load($node1->nid), t('Article node created.'));
|
||||
|
||||
// Check to see if grants added by node_test_node_access_records made it in.
|
||||
$records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node1->nid))->fetchAll();
|
||||
$this->assertEqual(count($records), 1, t('Returned the correct number of rows.'));
|
||||
$this->assertEqual($records[0]->realm, 'test_article_realm', t('Grant with article_realm acquired for node without alteration.'));
|
||||
$this->assertEqual($records[0]->gid, 1, t('Grant with gid = 1 acquired for node without alteration.'));
|
||||
|
||||
// Create an unpromoted "Basic page" node.
|
||||
$node2 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0));
|
||||
$this->assertTrue(node_load($node2->nid), t('Unpromoted basic page node created.'));
|
||||
|
||||
// Check to see if grants added by node_test_node_access_records made it in.
|
||||
$records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node2->nid))->fetchAll();
|
||||
$this->assertEqual(count($records), 1, t('Returned the correct number of rows.'));
|
||||
$this->assertEqual($records[0]->realm, 'test_page_realm', t('Grant with page_realm acquired for node without alteration.'));
|
||||
$this->assertEqual($records[0]->gid, 1, t('Grant with gid = 1 acquired for node without alteration.'));
|
||||
|
||||
// Create an unpromoted, unpublished "Basic page" node.
|
||||
$node3 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0, 'status' => 0));
|
||||
$this->assertTrue(node_load($node3->nid), t('Unpromoted, unpublished basic page node created.'));
|
||||
|
||||
// Check to see if grants added by node_test_node_access_records made it in.
|
||||
$records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node3->nid))->fetchAll();
|
||||
$this->assertEqual(count($records), 1, t('Returned the correct number of rows.'));
|
||||
$this->assertEqual($records[0]->realm, 'test_page_realm', t('Grant with page_realm acquired for node without alteration.'));
|
||||
$this->assertEqual($records[0]->gid, 1, t('Grant with gid = 1 acquired for node without alteration.'));
|
||||
|
||||
// Create a promoted "Basic page" node.
|
||||
$node4 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1));
|
||||
$this->assertTrue(node_load($node4->nid), t('Promoted basic page node created.'));
|
||||
|
||||
// Check to see if grant added by node_test_node_access_records was altered
|
||||
// by node_test_node_access_records_alter.
|
||||
$records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node4->nid))->fetchAll();
|
||||
$this->assertEqual(count($records), 1, t('Returned the correct number of rows.'));
|
||||
$this->assertEqual($records[0]->realm, 'test_alter_realm', t('Altered grant with alter_realm acquired for node.'));
|
||||
$this->assertEqual($records[0]->gid, 2, t('Altered grant with gid = 2 acquired for node.'));
|
||||
|
||||
// Check to see if we can alter grants with hook_node_grants_alter().
|
||||
$operations = array('view', 'update', 'delete');
|
||||
// Create a user that is allowed to access content.
|
||||
$web_user = $this->drupalCreateUser(array('access content'));
|
||||
foreach ($operations as $op) {
|
||||
$grants = node_test_node_grants($op, $web_user);
|
||||
$altered_grants = $grants;
|
||||
drupal_alter('node_grants', $altered_grants, $web_user, $op);
|
||||
$this->assertNotEqual($grants, $altered_grants, t('Altered the %op grant for a user.', array('%op' => $op)));
|
||||
}
|
||||
|
||||
// Check that core does not grant access to an unpublished node when an
|
||||
// empty $grants array is returned.
|
||||
$node6 = $this->drupalCreateNode(array('status' => 0, 'disable_node_access' => TRUE));
|
||||
$records = db_query('SELECT realm, gid FROM {node_access} WHERE nid = :nid', array(':nid' => $node6->nid))->fetchAll();
|
||||
$this->assertEqual(count($records), 0, t('Returned no records for unpublished node.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeAccessTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Test case to verify basic node_access functionality.
|
||||
* @todo Cover hook_node_access in a separate test class.
|
||||
* hook_node_access_records is covered in another test class.
|
||||
*/
|
||||
class NodeAccessTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node access',
|
||||
'description' => 'Test node_access function',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts node_access correctly grants or denies access.
|
||||
*/
|
||||
function assertNodeAccess($ops, $node, $account) {
|
||||
foreach ($ops as $op => $result) {
|
||||
$msg = t("node_access returns @result with operation '@op'.", array('@result' => $result ? 'true' : 'false', '@op' => $op));
|
||||
$this->assertEqual($result, node_access($op, $node, $account), $msg);
|
||||
}
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
// Clear permissions for authenticated users.
|
||||
db_delete('role_permission')
|
||||
->condition('rid', DRUPAL_AUTHENTICATED_RID)
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs basic tests for node_access function.
|
||||
*/
|
||||
function testNodeAccess() {
|
||||
// Ensures user without 'access content' permission can do nothing.
|
||||
$web_user1 = $this->drupalCreateUser(array('create page content', 'edit any page content', 'delete any page content'));
|
||||
$node1 = $this->drupalCreateNode(array('type' => 'page'));
|
||||
$this->assertNodeAccess(array('create' => FALSE), 'page', $web_user1);
|
||||
$this->assertNodeAccess(array('view' => FALSE, 'update' => FALSE, 'delete' => FALSE), $node1, $web_user1);
|
||||
|
||||
// Ensures user with 'bypass node access' permission can do everything.
|
||||
$web_user2 = $this->drupalCreateUser(array('bypass node access'));
|
||||
$node2 = $this->drupalCreateNode(array('type' => 'page'));
|
||||
$this->assertNodeAccess(array('create' => TRUE), 'page', $web_user2);
|
||||
$this->assertNodeAccess(array('view' => TRUE, 'update' => TRUE, 'delete' => TRUE), $node2, $web_user2);
|
||||
|
||||
// User cannot 'view own unpublished content'.
|
||||
$web_user3 = $this->drupalCreateUser(array('access content'));
|
||||
$node3 = $this->drupalCreateNode(array('status' => 0, 'uid' => $web_user3->uid));
|
||||
$this->assertNodeAccess(array('view' => FALSE), $node3, $web_user3);
|
||||
|
||||
// User cannot create content without permission.
|
||||
$this->assertNodeAccess(array('create' => FALSE), 'page', $web_user3);
|
||||
|
||||
// User can 'view own unpublished content', but another user cannot.
|
||||
$web_user4 = $this->drupalCreateUser(array('access content', 'view own unpublished content'));
|
||||
$web_user5 = $this->drupalCreateUser(array('access content', 'view own unpublished content'));
|
||||
$node4 = $this->drupalCreateNode(array('status' => 0, 'uid' => $web_user4->uid));
|
||||
$this->assertNodeAccess(array('view' => TRUE, 'update' => FALSE), $node4, $web_user4);
|
||||
$this->assertNodeAccess(array('view' => FALSE), $node4, $web_user5);
|
||||
|
||||
// Tests the default access provided for a published node.
|
||||
$node5 = $this->drupalCreateNode();
|
||||
$this->assertNodeAccess(array('view' => TRUE, 'update' => FALSE, 'delete' => FALSE), $node5, $web_user3);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeAdminTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Test node administration page functionality.
|
||||
*/
|
||||
class NodeAdminTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node administration',
|
||||
'description' => 'Test node administration page functionality.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Remove the "view own unpublished content" permission which is set
|
||||
// by default for authenticated users so we can test this permission
|
||||
// correctly.
|
||||
user_role_revoke_permissions(DRUPAL_AUTHENTICATED_RID, array('view own unpublished content'));
|
||||
|
||||
$this->admin_user = $this->drupalCreateUser(array('access administration pages', 'access content overview', 'administer nodes', 'bypass node access'));
|
||||
$this->base_user_1 = $this->drupalCreateUser(array('access content overview'));
|
||||
$this->base_user_2 = $this->drupalCreateUser(array('access content overview', 'view own unpublished content'));
|
||||
$this->base_user_3 = $this->drupalCreateUser(array('access content overview', 'bypass node access'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the table sorting works on the content admin pages.
|
||||
*/
|
||||
function testContentAdminSort() {
|
||||
$this->drupalLogin($this->admin_user);
|
||||
foreach (array('dd', 'aa', 'DD', 'bb', 'cc', 'CC', 'AA', 'BB') as $prefix) {
|
||||
$this->drupalCreateNode(array('title' => $prefix . $this->randomName(6)));
|
||||
}
|
||||
|
||||
// Test that the default sort by node.changed DESC actually fires properly.
|
||||
$nodes_query = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->orderBy('changed', 'DESC')
|
||||
->execute()
|
||||
->fetchCol();
|
||||
|
||||
$nodes_form = array();
|
||||
$this->drupalGet('admin/content');
|
||||
foreach ($this->xpath('//table/tbody/tr/td/div/input/@value') as $input) {
|
||||
$nodes_form[] = $input;
|
||||
}
|
||||
$this->assertEqual($nodes_query, $nodes_form, 'Nodes are sorted in the form according to the default query.');
|
||||
|
||||
// Compare the rendered HTML node list to a query for the nodes ordered by
|
||||
// title to account for possible database-dependent sort order.
|
||||
$nodes_query = db_select('node', 'n')
|
||||
->fields('n', array('nid'))
|
||||
->orderBy('title')
|
||||
->execute()
|
||||
->fetchCol();
|
||||
|
||||
$nodes_form = array();
|
||||
$this->drupalGet('admin/content', array('query' => array('sort' => 'asc', 'order' => 'Title')));
|
||||
foreach ($this->xpath('//table/tbody/tr/td/div/input/@value') as $input) {
|
||||
$nodes_form[] = $input;
|
||||
}
|
||||
$this->assertEqual($nodes_query, $nodes_form, 'Nodes are sorted in the form the same as they are in the query.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests content overview with different user permissions.
|
||||
*
|
||||
* Taxonomy filters are tested separately.
|
||||
* @see TaxonomyNodeFilterTestCase
|
||||
*/
|
||||
function testContentAdminPages() {
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
$nodes['published_page'] = $this->drupalCreateNode(array('type' => 'page'));
|
||||
$nodes['published_article'] = $this->drupalCreateNode(array('type' => 'article'));
|
||||
$nodes['unpublished_page_1'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->base_user_1->uid, 'status' => 0));
|
||||
$nodes['unpublished_page_2'] = $this->drupalCreateNode(array('type' => 'page', 'uid' => $this->base_user_2->uid, 'status' => 0));
|
||||
|
||||
// Verify view, edit, and delete links for any content.
|
||||
$this->drupalGet('admin/content');
|
||||
$this->assertResponse(200);
|
||||
foreach ($nodes as $node) {
|
||||
$this->assertLinkByHref('node/' . $node->nid);
|
||||
$this->assertLinkByHref('node/' . $node->nid . '/edit');
|
||||
$this->assertLinkByHref('node/' . $node->nid . '/delete');
|
||||
// Verify tableselect.
|
||||
$this->assertFieldByName('nodes[' . $node->nid . ']', '', t('Tableselect found.'));
|
||||
}
|
||||
|
||||
// Verify filtering by publishing status.
|
||||
$edit = array(
|
||||
'status' => 'status-1',
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Filter'));
|
||||
|
||||
$this->assertRaw(t('where %property is %value', array('%property' => t('status'), '%value' => 'published')), t('Content list is filtered by status.'));
|
||||
|
||||
$this->assertLinkByHref('node/' . $nodes['published_page']->nid . '/edit');
|
||||
$this->assertLinkByHref('node/' . $nodes['published_article']->nid . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/edit');
|
||||
|
||||
// Verify filtering by status and content type.
|
||||
$edit = array(
|
||||
'type' => 'page',
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Refine'));
|
||||
|
||||
$this->assertRaw(t('where %property is %value', array('%property' => t('status'), '%value' => 'published')), t('Content list is filtered by status.'));
|
||||
$this->assertRaw(t('and where %property is %value', array('%property' => t('type'), '%value' => 'Basic page')), t('Content list is filtered by content type.'));
|
||||
|
||||
$this->assertLinkByHref('node/' . $nodes['published_page']->nid . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['published_article']->nid . '/edit');
|
||||
|
||||
// Verify no operation links are displayed for regular users.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->base_user_1);
|
||||
$this->drupalGet('admin/content');
|
||||
$this->assertResponse(200);
|
||||
$this->assertLinkByHref('node/' . $nodes['published_page']->nid);
|
||||
$this->assertLinkByHref('node/' . $nodes['published_article']->nid);
|
||||
$this->assertNoLinkByHref('node/' . $nodes['published_page']->nid . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['published_page']->nid . '/delete');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['published_article']->nid . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['published_article']->nid . '/delete');
|
||||
|
||||
// Verify no unpublished content is displayed without permission.
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid);
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/delete');
|
||||
|
||||
// Verify no tableselect.
|
||||
$this->assertNoFieldByName('nodes[' . $nodes['published_page']->nid . ']', '', t('No tableselect found.'));
|
||||
|
||||
// Verify unpublished content is displayed with permission.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->base_user_2);
|
||||
$this->drupalGet('admin/content');
|
||||
$this->assertResponse(200);
|
||||
$this->assertLinkByHref('node/' . $nodes['unpublished_page_2']->nid);
|
||||
// Verify no operation links are displayed.
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_2']->nid . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_2']->nid . '/delete');
|
||||
|
||||
// Verify user cannot see unpublished content of other users.
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid);
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/edit');
|
||||
$this->assertNoLinkByHref('node/' . $nodes['unpublished_page_1']->nid . '/delete');
|
||||
|
||||
// Verify no tableselect.
|
||||
$this->assertNoFieldByName('nodes[' . $nodes['unpublished_page_2']->nid . ']', '', t('No tableselect found.'));
|
||||
|
||||
// Verify node access can be bypassed.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->base_user_3);
|
||||
$this->drupalGet('admin/content');
|
||||
$this->assertResponse(200);
|
||||
foreach ($nodes as $node) {
|
||||
$this->assertLinkByHref('node/' . $node->nid);
|
||||
$this->assertLinkByHref('node/' . $node->nid . '/edit');
|
||||
$this->assertLinkByHref('node/' . $node->nid . '/delete');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeBlockFunctionalTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Functional tests for the node module blocks.
|
||||
*/
|
||||
class NodeBlockFunctionalTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node blocks',
|
||||
'description' => 'Test node block functionality.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('block'));
|
||||
|
||||
// Create users and test node.
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer nodes', 'administer blocks'));
|
||||
$this->web_user = $this->drupalCreateUser(array('access content', 'create article content'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the recent comments block.
|
||||
*/
|
||||
function testRecentNodeBlock() {
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Disallow anonymous users to view content.
|
||||
user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
|
||||
'access content' => FALSE,
|
||||
));
|
||||
|
||||
// Set the block to a region to confirm block is available.
|
||||
$edit = array(
|
||||
'blocks[node_recent][region]' => 'sidebar_first',
|
||||
);
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
$this->assertText(t('The block settings have been updated.'), t('Block saved to first sidebar region.'));
|
||||
|
||||
// Set block title and variables.
|
||||
$block = array(
|
||||
'title' => $this->randomName(),
|
||||
'node_recent_block_count' => 2,
|
||||
);
|
||||
$this->drupalPost('admin/structure/block/manage/node/recent/configure', $block, t('Save block'));
|
||||
$this->assertText(t('The block configuration has been saved.'), t('Block saved.'));
|
||||
|
||||
// Test that block is not visible without nodes
|
||||
$this->drupalGet('');
|
||||
$this->assertText(t('No content available.'), t('Block with "No content available." found.'));
|
||||
|
||||
// Add some test nodes.
|
||||
$default_settings = array('uid' => $this->web_user->uid, 'type' => 'article');
|
||||
$node1 = $this->drupalCreateNode($default_settings);
|
||||
$node2 = $this->drupalCreateNode($default_settings);
|
||||
$node3 = $this->drupalCreateNode($default_settings);
|
||||
|
||||
// Change the changed time for node so that we can test ordering.
|
||||
db_update('node')
|
||||
->fields(array(
|
||||
'changed' => $node1->changed + 100,
|
||||
))
|
||||
->condition('nid', $node2->nid)
|
||||
->execute();
|
||||
db_update('node')
|
||||
->fields(array(
|
||||
'changed' => $node1->changed + 200,
|
||||
))
|
||||
->condition('nid', $node3->nid)
|
||||
->execute();
|
||||
|
||||
// Test that a user without the 'access content' permission cannot
|
||||
// see the block.
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText($block['title'], t('Block was not found.'));
|
||||
|
||||
// Test that only the 2 latest nodes are shown.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->assertNoText($node1->title, t('Node not found in block.'));
|
||||
$this->assertText($node2->title, t('Node found in block.'));
|
||||
$this->assertText($node3->title, t('Node found in block.'));
|
||||
|
||||
// Check to make sure nodes are in the right order.
|
||||
$this->assertTrue($this->xpath('//div[@id="block-node-recent"]/div/table/tbody/tr[position() = 1]/td/div/a[text() = "' . $node3->title . '"]'), t('Nodes were ordered correctly in block.'));
|
||||
|
||||
// Set the number of recent nodes to show to 10.
|
||||
$this->drupalLogout();
|
||||
$this->drupalLogin($this->admin_user);
|
||||
$block = array(
|
||||
'node_recent_block_count' => 10,
|
||||
);
|
||||
$this->drupalPost('admin/structure/block/manage/node/recent/configure', $block, t('Save block'));
|
||||
$this->assertText(t('The block configuration has been saved.'), t('Block saved.'));
|
||||
|
||||
// Post an additional node.
|
||||
$node4 = $this->drupalCreateNode($default_settings);
|
||||
// drupalCreateNode() does not automatically flush content caches unlike
|
||||
// posting a node from a node form.
|
||||
cache_clear_all();
|
||||
|
||||
// Test that all four nodes are shown.
|
||||
$this->drupalGet('');
|
||||
$this->assertText($node1->title, t('Node found in block.'));
|
||||
$this->assertText($node2->title, t('Node found in block.'));
|
||||
$this->assertText($node3->title, t('Node found in block.'));
|
||||
$this->assertText($node4->title, t('Node found in block.'));
|
||||
|
||||
// Create the custom block.
|
||||
$custom_block = array();
|
||||
$custom_block['info'] = $this->randomName();
|
||||
$custom_block['title'] = $this->randomName();
|
||||
$custom_block['types[article]'] = TRUE;
|
||||
$custom_block['body[value]'] = $this->randomName(32);
|
||||
$custom_block['regions[' . variable_get('theme_default', 'stark') . ']'] = 'content';
|
||||
if ($admin_theme = variable_get('admin_theme')) {
|
||||
$custom_block['regions[' . $admin_theme . ']'] = 'content';
|
||||
}
|
||||
$this->drupalPost('admin/structure/block/add', $custom_block, t('Save block'));
|
||||
|
||||
$bid = db_query("SELECT bid FROM {block_custom} WHERE info = :info", array(':info' => $custom_block['info']))->fetchField();
|
||||
$this->assertTrue($bid, t('Custom block with visibility rule was created.'));
|
||||
|
||||
// Verify visibility rules.
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText($custom_block['title'], t('Block was displayed on the front page.'));
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertText($custom_block['title'], t('Block was displayed on the node/add/article page.'));
|
||||
$this->drupalGet('node/' . $node1->nid);
|
||||
$this->assertText($custom_block['title'], t('Block was displayed on the node/N.'));
|
||||
|
||||
// Delete the created custom block & verify that it's been deleted.
|
||||
$this->drupalPost('admin/structure/block/manage/block/' . $bid . '/delete', array(), t('Delete'));
|
||||
$bid = db_query("SELECT 1 FROM {block_node_type} WHERE module = 'block' AND delta = :delta", array(':delta' => $bid))->fetchField();
|
||||
$this->assertFalse($bid, t('Custom block was deleted.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeBlockTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
class NodeBlockTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Block availability',
|
||||
'description' => 'Check if the syndicate block is available.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('block'));
|
||||
|
||||
// Create and login user
|
||||
$admin_user = $this->drupalCreateUser(array('administer blocks'));
|
||||
$this->drupalLogin($admin_user);
|
||||
}
|
||||
|
||||
function testSearchFormBlock() {
|
||||
// Set block title to confirm that the interface is available.
|
||||
$this->drupalPost('admin/structure/block/manage/node/syndicate/configure', array('title' => $this->randomName(8)), t('Save block'));
|
||||
$this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
|
||||
|
||||
// Set the block to a region to confirm block is available.
|
||||
$edit = array();
|
||||
$edit['blocks[node_syndicate][region]'] = 'footer';
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
$this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeBuildContentTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Test to ensure that a node's content is always rebuilt.
|
||||
*/
|
||||
class NodeBuildContentTest extends NodeTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Rebuild content',
|
||||
'description' => 'Test the rebuilding of content for different build modes.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to ensure that a node's content array is rebuilt on every call to node_build_content().
|
||||
*/
|
||||
function testNodeRebuildContent() {
|
||||
$node = $this->drupalCreateNode();
|
||||
|
||||
// Set a property in the content array so we can test for its existence later on.
|
||||
$node->content['test_content_property'] = array('#value' => $this->randomString());
|
||||
$content = node_build_content($node);
|
||||
|
||||
// If the property doesn't exist it means the node->content was rebuilt.
|
||||
$this->assertFalse(isset($content['test_content_property']), t('Node content was emptied prior to being built.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeCreationTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\Core\Database\Database;
|
||||
use Exception;
|
||||
|
||||
class NodeCreationTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node creation',
|
||||
'description' => 'Create a node and test saving it.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
// Enable dummy module that implements hook_node_insert for exceptions.
|
||||
parent::setUp(array('node_test_exception', 'dblog'));
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('create page content', 'edit own page content'));
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a "Basic page" node and verify its consistency in the database.
|
||||
*/
|
||||
function testNodeCreation() {
|
||||
// Create a node.
|
||||
$edit = array();
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$edit["title"] = $this->randomName(8);
|
||||
$edit["body[$langcode][0][value]"] = $this->randomName(16);
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the Basic page has been created.
|
||||
$this->assertRaw(t('!post %title has been created.', array('!post' => 'Basic page', '%title' => $edit["title"])), t('Basic page created.'));
|
||||
|
||||
// Check that the node exists in the database.
|
||||
$node = $this->drupalGetNodeByTitle($edit["title"]);
|
||||
$this->assertTrue($node, t('Node found in database.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a page node and verify that a transaction rolls back the failed creation
|
||||
*/
|
||||
function testFailedPageCreation() {
|
||||
// Create a node.
|
||||
$edit = array(
|
||||
'uid' => $this->loggedInUser->uid,
|
||||
'name' => $this->loggedInUser->name,
|
||||
'type' => 'page',
|
||||
'langcode' => LANGUAGE_NOT_SPECIFIED,
|
||||
'title' => 'testing_transaction_exception',
|
||||
);
|
||||
|
||||
try {
|
||||
entity_create('node', $edit)->save();
|
||||
$this->fail(t('Expected exception has not been thrown.'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->pass(t('Expected exception has been thrown.'));
|
||||
}
|
||||
|
||||
if (Database::getConnection()->supportsTransactions()) {
|
||||
// Check that the node does not exist in the database.
|
||||
$node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
$this->assertFalse($node, t('Transactions supported, and node not found in database.'));
|
||||
}
|
||||
else {
|
||||
// Check that the node exists in the database.
|
||||
$node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
$this->assertTrue($node, t('Transactions not supported, and node found in database.'));
|
||||
|
||||
// Check that the failed rollback was logged.
|
||||
$records = db_query("SELECT wid FROM {watchdog} WHERE message LIKE 'Explicit rollback failed%'")->fetchAll();
|
||||
$this->assertTrue(count($records) > 0, t('Transactions not supported, and rollback error logged to watchdog.'));
|
||||
}
|
||||
|
||||
// Check that the rollback error was logged.
|
||||
$records = db_query("SELECT wid FROM {watchdog} WHERE variables LIKE '%Test exception for rollback.%'")->fetchAll();
|
||||
$this->assertTrue(count($records) > 0, t('Rollback explanatory error logged to watchdog.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeEntityFieldQueryAlterTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests node_query_entity_field_access_alter().
|
||||
*/
|
||||
class NodeEntityFieldQueryAlterTest extends NodeTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node entity query alter',
|
||||
'description' => 'Test that node access entity queries are properly altered by the node module.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* User with permission to view content.
|
||||
*/
|
||||
protected $accessUser;
|
||||
|
||||
/**
|
||||
* User without permission to view content.
|
||||
*/
|
||||
protected $noAccessUser;
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('node_access_test');
|
||||
node_access_rebuild();
|
||||
|
||||
// Creating 4 nodes with an entity field so we can test that sort of query
|
||||
// alter. All field values starts with 'A' so we can identify and fetch them
|
||||
// in the node_access_test module.
|
||||
$settings = array('langcode' => LANGUAGE_NOT_SPECIFIED);
|
||||
for ($i = 0; $i < 4; $i++) {
|
||||
$body = array(
|
||||
'value' => 'A' . $this->randomName(32),
|
||||
'format' => filter_default_format(),
|
||||
);
|
||||
$settings['body'][LANGUAGE_NOT_SPECIFIED][0] = $body;
|
||||
$this->drupalCreateNode($settings);
|
||||
}
|
||||
|
||||
// Create user with simple node access permission. The 'node test view'
|
||||
// permission is implemented and granted by the node_access_test module.
|
||||
$this->accessUser = $this->drupalCreateUser(array('access content', 'node test view'));
|
||||
$this->noAccessUser = $this->drupalCreateUser(array('access content'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that node access permissions are followed.
|
||||
*/
|
||||
function testNodeQueryAlterWithUI() {
|
||||
// Verify that a user with access permission can see at least one node.
|
||||
$this->drupalLogin($this->accessUser);
|
||||
$this->drupalGet('node_access_entity_test_page');
|
||||
$this->assertText('Yes, 4 nodes', "4 nodes were found for access user");
|
||||
$this->assertNoText('Exception', "No database exception");
|
||||
|
||||
// Verify that a user with no access permission cannot see nodes.
|
||||
$this->drupalLogin($this->noAccessUser);
|
||||
$this->drupalGet('node_access_entity_test_page');
|
||||
$this->assertText('No nodes', "No nodes were found for no access user");
|
||||
$this->assertNoText('Exception', "No database exception");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeFeedTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Test the node_feed() functionality.
|
||||
*/
|
||||
class NodeFeedTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node feed',
|
||||
'description' => 'Ensures that node_feed() functions correctly.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that node_feed accepts and prints extra channel elements.
|
||||
*/
|
||||
function testNodeFeedExtraChannelElements() {
|
||||
$response = node_feed(array(), array('copyright' => 'Drupal is a registered trademark of Dries Buytaert.'));
|
||||
$this->assertTrue(strpos($response->getContent(), '<copyright>Drupal is a registered trademark of Dries Buytaert.</copyright>') !== FALSE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeLoadHooksTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests for the hooks invoked during node_load().
|
||||
*/
|
||||
class NodeLoadHooksTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node load hooks',
|
||||
'description' => 'Test the hooks invoked when a node is being loaded.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('node_test');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that hook_node_load() is invoked correctly.
|
||||
*/
|
||||
function testHookNodeLoad() {
|
||||
// Create some sample articles and pages.
|
||||
$node1 = $this->drupalCreateNode(array('type' => 'article', 'status' => NODE_PUBLISHED));
|
||||
$node2 = $this->drupalCreateNode(array('type' => 'article', 'status' => NODE_PUBLISHED));
|
||||
$node3 = $this->drupalCreateNode(array('type' => 'article', 'status' => NODE_NOT_PUBLISHED));
|
||||
$node4 = $this->drupalCreateNode(array('type' => 'page', 'status' => NODE_NOT_PUBLISHED));
|
||||
|
||||
// Check that when a set of nodes that only contains articles is loaded,
|
||||
// the properties added to the node by node_test_load_node() correctly
|
||||
// reflect the expected values.
|
||||
$nodes = node_load_multiple(array(), array('status' => NODE_PUBLISHED));
|
||||
$loaded_node = end($nodes);
|
||||
$this->assertEqual($loaded_node->node_test_loaded_nids, array($node1->nid, $node2->nid), t('hook_node_load() received the correct list of node IDs the first time it was called.'));
|
||||
$this->assertEqual($loaded_node->node_test_loaded_types, array('article'), t('hook_node_load() received the correct list of node types the first time it was called.'));
|
||||
|
||||
// Now, as part of the same page request, load a set of nodes that contain
|
||||
// both articles and pages, and make sure the parameters passed to
|
||||
// node_test_node_load() are correctly updated.
|
||||
$nodes = node_load_multiple(array(), array('status' => NODE_NOT_PUBLISHED));
|
||||
$loaded_node = end($nodes);
|
||||
$this->assertEqual($loaded_node->node_test_loaded_nids, array($node3->nid, $node4->nid), t('hook_node_load() received the correct list of node IDs the second time it was called.'));
|
||||
$this->assertEqual($loaded_node->node_test_loaded_types, array('article', 'page'), t('hook_node_load() received the correct list of node types the second time it was called.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeLoadMultipleTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests the node_load_multiple() function.
|
||||
*/
|
||||
class NodeLoadMultipleTest extends NodeTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Load multiple nodes',
|
||||
'description' => 'Test the loading of multiple nodes.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
$web_user = $this->drupalCreateUser(array('create article content', 'create page content'));
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates four nodes and ensures that they are loaded correctly.
|
||||
*/
|
||||
function testNodeMultipleLoad() {
|
||||
$node1 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
|
||||
$node2 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
|
||||
$node3 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 0));
|
||||
$node4 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0));
|
||||
|
||||
// Confirm that promoted nodes appear in the default node listing.
|
||||
$this->drupalGet('node');
|
||||
$this->assertText($node1->title, t('Node title appears on the default listing.'));
|
||||
$this->assertText($node2->title, t('Node title appears on the default listing.'));
|
||||
$this->assertNoText($node3->title, t('Node title does not appear in the default listing.'));
|
||||
$this->assertNoText($node4->title, t('Node title does not appear in the default listing.'));
|
||||
|
||||
// Load nodes with only a condition. Nodes 3 and 4 will be loaded.
|
||||
$nodes = node_load_multiple(FALSE, array('promote' => 0));
|
||||
$this->assertEqual($node3->title, $nodes[$node3->nid]->title, t('Node was loaded.'));
|
||||
$this->assertEqual($node4->title, $nodes[$node4->nid]->title, t('Node was loaded.'));
|
||||
$count = count($nodes);
|
||||
$this->assertTrue($count == 2, t('@count nodes loaded.', array('@count' => $count)));
|
||||
|
||||
// Load nodes by nid. Nodes 1, 2 and 4 will be loaded.
|
||||
$nodes = node_load_multiple(array(1, 2, 4));
|
||||
$count = count($nodes);
|
||||
$this->assertTrue(count($nodes) == 3, t('@count nodes loaded', array('@count' => $count)));
|
||||
$this->assertTrue(isset($nodes[$node1->nid]), t('Node is correctly keyed in the array'));
|
||||
$this->assertTrue(isset($nodes[$node2->nid]), t('Node is correctly keyed in the array'));
|
||||
$this->assertTrue(isset($nodes[$node4->nid]), t('Node is correctly keyed in the array'));
|
||||
foreach ($nodes as $node) {
|
||||
$this->assertTrue(is_object($node), t('Node is an object'));
|
||||
}
|
||||
|
||||
// Load nodes by nid, where type = article. Nodes 1, 2 and 3 will be loaded.
|
||||
$nodes = node_load_multiple(array(1, 2, 3, 4), array('type' => 'article'));
|
||||
$count = count($nodes);
|
||||
$this->assertTrue($count == 3, t('@count nodes loaded', array('@count' => $count)));
|
||||
$this->assertEqual($nodes[$node1->nid]->title, $node1->title, t('Node successfully loaded.'));
|
||||
$this->assertEqual($nodes[$node2->nid]->title, $node2->title, t('Node successfully loaded.'));
|
||||
$this->assertEqual($nodes[$node3->nid]->title, $node3->title, t('Node successfully loaded.'));
|
||||
$this->assertFalse(isset($nodes[$node4->nid]));
|
||||
|
||||
// Now that all nodes have been loaded into the static cache, ensure that
|
||||
// they are loaded correctly again when a condition is passed.
|
||||
$nodes = node_load_multiple(array(1, 2, 3, 4), array('type' => 'article'));
|
||||
$count = count($nodes);
|
||||
$this->assertTrue($count == 3, t('@count nodes loaded.', array('@count' => $count)));
|
||||
$this->assertEqual($nodes[$node1->nid]->title, $node1->title, t('Node successfully loaded'));
|
||||
$this->assertEqual($nodes[$node2->nid]->title, $node2->title, t('Node successfully loaded'));
|
||||
$this->assertEqual($nodes[$node3->nid]->title, $node3->title, t('Node successfully loaded'));
|
||||
$this->assertFalse(isset($nodes[$node4->nid]), t('Node was not loaded'));
|
||||
|
||||
// Load nodes by nid, where type = article and promote = 0.
|
||||
$nodes = node_load_multiple(array(1, 2, 3, 4), array('type' => 'article', 'promote' => 0));
|
||||
$count = count($nodes);
|
||||
$this->assertTrue($count == 1, t('@count node loaded', array('@count' => $count)));
|
||||
$this->assertEqual($nodes[$node3->nid]->title, $node3->title, t('Node successfully loaded.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodePostSettingsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Check that the post information displays when enabled for a content type.
|
||||
*/
|
||||
class NodePostSettingsTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node post information display',
|
||||
'description' => 'Check that the post information (submitted by Username on date) text displays appropriately.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('create page content', 'administer content types', 'access user profiles'));
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set "Basic page" content type to display post information and confirm its presence on a new node.
|
||||
*/
|
||||
function testPagePostInfo() {
|
||||
|
||||
// Set "Basic page" content type to display post information.
|
||||
$edit = array();
|
||||
$edit['node_submitted'] = TRUE;
|
||||
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
|
||||
// Create a node.
|
||||
$edit = array();
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$edit["title"] = $this->randomName(8);
|
||||
$edit["body[$langcode][0][value]"] = $this->randomName(16);
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the post information is displayed.
|
||||
$node = $this->drupalGetNodeByTitle($edit["title"]);
|
||||
$elements = $this->xpath('//*[contains(@class,:class)]', array(':class' => 'submitted'));
|
||||
$this->assertEqual(count($elements), 1, t('Post information is displayed.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set "Basic page" content type to not display post information and confirm its absence on a new node.
|
||||
*/
|
||||
function testPageNotPostInfo() {
|
||||
|
||||
// Set "Basic page" content type to display post information.
|
||||
$edit = array();
|
||||
$edit['node_submitted'] = FALSE;
|
||||
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
|
||||
// Create a node.
|
||||
$edit = array();
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$edit["title"] = $this->randomName(8);
|
||||
$edit["body[$langcode][0][value]"] = $this->randomName(16);
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the post information is displayed.
|
||||
$node = $this->drupalGetNodeByTitle($edit["title"]);
|
||||
$this->assertNoRaw('<span class="submitted">', t('Post information is not displayed.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeQueryAlterTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Tests node_query_node_access_alter().
|
||||
*/
|
||||
class NodeQueryAlterTest extends NodeTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node query alter',
|
||||
'description' => 'Test that node access queries are properly altered by the node module.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* User with permission to view content.
|
||||
*/
|
||||
protected $accessUser;
|
||||
|
||||
/**
|
||||
* User without permission to view content.
|
||||
*/
|
||||
protected $noAccessUser;
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('node_access_test');
|
||||
node_access_rebuild();
|
||||
|
||||
// Create some content.
|
||||
$this->drupalCreateNode();
|
||||
$this->drupalCreateNode();
|
||||
$this->drupalCreateNode();
|
||||
$this->drupalCreateNode();
|
||||
|
||||
// Create user with simple node access permission. The 'node test view'
|
||||
// permission is implemented and granted by the node_access_test module.
|
||||
$this->accessUser = $this->drupalCreateUser(array('access content', 'node test view'));
|
||||
$this->noAccessUser = $this->drupalCreateUser(array('access content'));
|
||||
$this->noAccessUser2 = $this->drupalCreateUser(array('access content'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that node access permissions are followed.
|
||||
*/
|
||||
function testNodeQueryAlterWithUI() {
|
||||
// Verify that a user with access permission can see at least one node.
|
||||
$this->drupalLogin($this->accessUser);
|
||||
$this->drupalGet('node_access_test_page');
|
||||
$this->assertText('Yes, 4 nodes', "4 nodes were found for access user");
|
||||
$this->assertNoText('Exception', "No database exception");
|
||||
|
||||
// Verify that a user with no access permission cannot see nodes.
|
||||
$this->drupalLogin($this->noAccessUser);
|
||||
$this->drupalGet('node_access_test_page');
|
||||
$this->assertText('No nodes', "No nodes were found for no access user");
|
||||
$this->assertNoText('Exception', "No database exception");
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower-level test of 'node_access' query alter, for user with access.
|
||||
*
|
||||
* Verifies that a non-standard table alias can be used, and that a
|
||||
* user with node access can view the nodes.
|
||||
*/
|
||||
function testNodeQueryAlterLowLevelWithAccess() {
|
||||
// User with access should be able to view 4 nodes.
|
||||
try {
|
||||
$query = db_select('node', 'mytab')
|
||||
->fields('mytab');
|
||||
$query->addTag('node_access');
|
||||
$query->addMetaData('op', 'view');
|
||||
$query->addMetaData('account', $this->accessUser);
|
||||
|
||||
$result = $query->execute()->fetchAll();
|
||||
$this->assertEqual(count($result), 4, t('User with access can see correct nodes'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->fail(t('Altered query is malformed'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower-level test of 'node_access' query alter, for user without access.
|
||||
*
|
||||
* Verifies that a non-standard table alias can be used, and that a
|
||||
* user without node access cannot view the nodes.
|
||||
*/
|
||||
function testNodeQueryAlterLowLevelNoAccess() {
|
||||
// User without access should be able to view 0 nodes.
|
||||
try {
|
||||
$query = db_select('node', 'mytab')
|
||||
->fields('mytab');
|
||||
$query->addTag('node_access');
|
||||
$query->addMetaData('op', 'view');
|
||||
$query->addMetaData('account', $this->noAccessUser);
|
||||
|
||||
$result = $query->execute()->fetchAll();
|
||||
$this->assertEqual(count($result), 0, t('User with no access cannot see nodes'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->fail(t('Altered query is malformed'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower-level test of 'node_access' query alter, for edit access.
|
||||
*
|
||||
* Verifies that a non-standard table alias can be used, and that a
|
||||
* user with view-only node access cannot edit the nodes.
|
||||
*/
|
||||
function testNodeQueryAlterLowLevelEditAccess() {
|
||||
// User with view-only access should not be able to edit nodes.
|
||||
try {
|
||||
$query = db_select('node', 'mytab')
|
||||
->fields('mytab');
|
||||
$query->addTag('node_access');
|
||||
$query->addMetaData('op', 'update');
|
||||
$query->addMetaData('account', $this->accessUser);
|
||||
|
||||
$result = $query->execute()->fetchAll();
|
||||
$this->assertEqual(count($result), 0, t('User with view-only access cannot edit nodes'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->fail($e->getMessage());
|
||||
$this->fail((string) $query);
|
||||
$this->fail(t('Altered query is malformed'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower-level test of 'node_access' query alter override.
|
||||
*
|
||||
* Verifies that node_access_view_all_nodes() is called from
|
||||
* node_query_node_access_alter(). We do this by checking that
|
||||
* a user which normally would not have view privileges is able
|
||||
* to view the nodes when we add a record to {node_access} paired
|
||||
* with a corresponding privilege in hook_node_grants().
|
||||
*/
|
||||
function testNodeQueryAlterOverride() {
|
||||
$record = array(
|
||||
'nid' => 0,
|
||||
'gid' => 0,
|
||||
'realm' => 'node_access_all',
|
||||
'grant_view' => 1,
|
||||
'grant_update' => 0,
|
||||
'grant_delete' => 0,
|
||||
);
|
||||
drupal_write_record('node_access', $record);
|
||||
|
||||
// Test that the noAccessUser still doesn't have the 'view'
|
||||
// privilege after adding the node_access record.
|
||||
drupal_static_reset('node_access_view_all_nodes');
|
||||
try {
|
||||
$query = db_select('node', 'mytab')
|
||||
->fields('mytab');
|
||||
$query->addTag('node_access');
|
||||
$query->addMetaData('op', 'view');
|
||||
$query->addMetaData('account', $this->noAccessUser);
|
||||
|
||||
$result = $query->execute()->fetchAll();
|
||||
$this->assertEqual(count($result), 0, t('User view privileges are not overridden'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->fail(t('Altered query is malformed'));
|
||||
}
|
||||
|
||||
// Have node_test_node_grants return a node_access_all privilege,
|
||||
// to grant the noAccessUser 'view' access. To verify that
|
||||
// node_access_view_all_nodes is properly checking the specified
|
||||
// $account instead of the global $user, we will log in as
|
||||
// noAccessUser2.
|
||||
$this->drupalLogin($this->noAccessUser2);
|
||||
variable_set('node_test_node_access_all_uid', $this->noAccessUser->uid);
|
||||
drupal_static_reset('node_access_view_all_nodes');
|
||||
try {
|
||||
$query = db_select('node', 'mytab')
|
||||
->fields('mytab');
|
||||
$query->addTag('node_access');
|
||||
$query->addMetaData('op', 'view');
|
||||
$query->addMetaData('account', $this->noAccessUser);
|
||||
|
||||
$result = $query->execute()->fetchAll();
|
||||
$this->assertEqual(count($result), 4, t('User view privileges are overridden'));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->fail(t('Altered query is malformed'));
|
||||
}
|
||||
variable_del('node_test_node_access_all_uid');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeRSSContentTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Ensure that data added to nodes by other modules appears in RSS feeds.
|
||||
*
|
||||
* Create a node, enable the node_test module to ensure that extra data is
|
||||
* added to the node->content array, then verify that the data appears on the
|
||||
* sitewide RSS feed at rss.xml.
|
||||
*/
|
||||
class NodeRSSContentTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node RSS Content',
|
||||
'description' => 'Ensure that data added to nodes by other modules appears in RSS feeds.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
// Enable dummy module that implements hook_node_view.
|
||||
parent::setUp('node_test');
|
||||
|
||||
// Use bypass node access permission here, because the test class uses
|
||||
// hook_grants_alter() to deny access to everyone on node_access
|
||||
// queries.
|
||||
$user = $this->drupalCreateUser(array('bypass node access', 'access content', 'create article content'));
|
||||
$this->drupalLogin($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new node and ensure that it includes the custom data when added
|
||||
* to an RSS feed.
|
||||
*/
|
||||
function testNodeRSSContent() {
|
||||
// Create a node.
|
||||
$node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
|
||||
|
||||
$this->drupalGet('rss.xml');
|
||||
|
||||
// Check that content added in 'rss' view mode appear in RSS feed.
|
||||
$rss_only_content = t('Extra data that should appear only in the RSS feed for node !nid.', array('!nid' => $node->nid));
|
||||
$this->assertText($rss_only_content, t('Node content designated for RSS appear in RSS feed.'));
|
||||
|
||||
// Check that content added in view modes other than 'rss' doesn't
|
||||
// appear in RSS feed.
|
||||
$non_rss_content = t('Extra data that should appear everywhere except the RSS feed for node !nid.', array('!nid' => $node->nid));
|
||||
$this->assertNoText($non_rss_content, t('Node content not designed for RSS doesn\'t appear in RSS feed.'));
|
||||
|
||||
// Check that extra RSS elements and namespaces are added to RSS feed.
|
||||
$test_element = array(
|
||||
'key' => 'testElement',
|
||||
'value' => t('Value of testElement RSS element for node !nid.', array('!nid' => $node->nid)),
|
||||
);
|
||||
$test_ns = 'xmlns:drupaltest="http://example.com/test-namespace"';
|
||||
$this->assertRaw(format_xml_elements(array($test_element)), t('Extra RSS elements appear in RSS feed.'));
|
||||
$this->assertRaw($test_ns, t('Extra namespaces appear in RSS feed.'));
|
||||
|
||||
// Check that content added in 'rss' view mode doesn't appear when
|
||||
// viewing node.
|
||||
$this->drupalGet("node/$node->nid");
|
||||
$this->assertNoText($rss_only_content, t('Node content designed for RSS doesn\'t appear when viewing node.'));
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeRevisionPermissionsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests user permissions for node revisions.
|
||||
*/
|
||||
class NodeRevisionPermissionsTest extends NodeTestBase {
|
||||
protected $node_revisions = array();
|
||||
protected $accounts = array();
|
||||
|
||||
// Map revision permission names to node revision access ops.
|
||||
protected $map = array(
|
||||
'view' => 'view revisions',
|
||||
'update' => 'revert revisions',
|
||||
'delete' => 'delete revisions',
|
||||
);
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node revision permissions',
|
||||
'description' => 'Tests user permissions for node revision operations.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create a node with several revisions.
|
||||
$node = $this->drupalCreateNode();
|
||||
$this->node_revisions[] = $node;
|
||||
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
// Create a revision for the same nid and settings with a random log.
|
||||
$revision = clone $node;
|
||||
$revision->revision = 1;
|
||||
$revision->log = $this->randomName(32);
|
||||
node_save($revision);
|
||||
$this->node_revisions[] = $revision;
|
||||
}
|
||||
|
||||
// Create three users, one with each revision permission.
|
||||
foreach ($this->map as $op => $permission) {
|
||||
// Create the user.
|
||||
$account = $this->drupalCreateUser(
|
||||
array(
|
||||
'access content',
|
||||
'edit any page content',
|
||||
'delete any page content',
|
||||
$permission,
|
||||
)
|
||||
);
|
||||
$account->op = $op;
|
||||
$this->accounts[] = $account;
|
||||
}
|
||||
|
||||
// Create an admin account (returns TRUE for all revision permissions).
|
||||
$admin_account = $this->drupalCreateUser(array('access content', 'administer nodes'));
|
||||
$admin_account->is_admin = TRUE;
|
||||
$this->accounts['admin'] = $admin_account;
|
||||
|
||||
// Create a normal account (returns FALSE for all revision permissions).
|
||||
$normal_account = $this->drupalCreateUser();
|
||||
$normal_account->op = FALSE;
|
||||
$this->accounts[] = $normal_account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the _node_revision_access() function.
|
||||
*/
|
||||
function testNodeRevisionAccess() {
|
||||
$revision = $this->node_revisions[1];
|
||||
|
||||
$parameters = array(
|
||||
'op' => array_keys($this->map),
|
||||
'account' => $this->accounts,
|
||||
);
|
||||
|
||||
$permutations = $this->generatePermutations($parameters);
|
||||
foreach ($permutations as $case) {
|
||||
if (!empty($case['account']->is_admin) || $case['op'] == $case['account']->op) {
|
||||
$this->assertTrue(_node_revision_access($revision, $case['op'], $case['account']), "{$this->map[$case['op']]} granted.");
|
||||
}
|
||||
else {
|
||||
$this->assertFalse(_node_revision_access($revision, $case['op'], $case['account']), "{$this->map[$case['op']]} not granted.");
|
||||
}
|
||||
}
|
||||
|
||||
// Test that access is FALSE for a node administrator with an invalid $node
|
||||
// or $op parameters.
|
||||
$admin_account = $this->accounts['admin'];
|
||||
$this->assertFalse(_node_revision_access($revision, 'invalid-op', $admin_account), '_node_revision_access() returns FALSE with an invalid op.');
|
||||
|
||||
// Test that the $account parameter defaults to the "logged in" user.
|
||||
$original_user = $GLOBALS['user'];
|
||||
$GLOBALS['user'] = $admin_account;
|
||||
$this->assertTrue(_node_revision_access($revision, 'view'), '_node_revision_access() returns TRUE when used with global user.');
|
||||
$GLOBALS['user'] = $original_user;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeRevisionsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
class NodeRevisionsTest extends NodeTestBase {
|
||||
protected $nodes;
|
||||
protected $logs;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node revisions',
|
||||
'description' => 'Create a node with revisions and test viewing, saving, reverting, and deleting revisions.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create and login user.
|
||||
$web_user = $this->drupalCreateUser(array('view revisions', 'revert revisions', 'edit any page content',
|
||||
'delete revisions', 'delete any page content'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Create initial node.
|
||||
$node = $this->drupalCreateNode();
|
||||
$settings = get_object_vars($node);
|
||||
$settings['revision'] = 1;
|
||||
|
||||
$nodes = array();
|
||||
$logs = array();
|
||||
|
||||
// Get original node.
|
||||
$nodes[] = $node;
|
||||
|
||||
// Create three revisions.
|
||||
$revision_count = 3;
|
||||
for ($i = 0; $i < $revision_count; $i++) {
|
||||
$logs[] = $settings['log'] = $this->randomName(32);
|
||||
|
||||
// Create revision with random title and body and update variables.
|
||||
$this->drupalCreateNode($settings);
|
||||
$node = node_load($node->nid); // Make sure we get revision information.
|
||||
$settings = get_object_vars($node);
|
||||
|
||||
$nodes[] = $node;
|
||||
}
|
||||
|
||||
$this->nodes = $nodes;
|
||||
$this->logs = $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check node revision related operations.
|
||||
*/
|
||||
function testRevisions() {
|
||||
$nodes = $this->nodes;
|
||||
$logs = $this->logs;
|
||||
|
||||
// Get last node for simple checks.
|
||||
$node = $nodes[3];
|
||||
|
||||
// Confirm the correct revision text appears on "view revisions" page.
|
||||
$this->drupalGet("node/$node->nid/revisions/$node->vid/view");
|
||||
$this->assertText($node->body[LANGUAGE_NOT_SPECIFIED][0]['value'], t('Correct text displays for version.'));
|
||||
|
||||
// Confirm the correct log message appears on "revisions overview" page.
|
||||
$this->drupalGet("node/$node->nid/revisions");
|
||||
foreach ($logs as $log) {
|
||||
$this->assertText($log, t('Log message found.'));
|
||||
}
|
||||
|
||||
// Confirm that revisions revert properly.
|
||||
$this->drupalPost("node/$node->nid/revisions/{$nodes[1]->vid}/revert", array(), t('Revert'));
|
||||
$this->assertRaw(t('@type %title has been reverted back to the revision from %revision-date.',
|
||||
array('@type' => 'Basic page', '%title' => $nodes[1]->title,
|
||||
'%revision-date' => format_date($nodes[1]->revision_timestamp))), t('Revision reverted.'));
|
||||
$reverted_node = node_load($node->nid);
|
||||
$this->assertTrue(($nodes[1]->body[LANGUAGE_NOT_SPECIFIED][0]['value'] == $reverted_node->body[LANGUAGE_NOT_SPECIFIED][0]['value']), t('Node reverted correctly.'));
|
||||
|
||||
// Confirm revisions delete properly.
|
||||
$this->drupalPost("node/$node->nid/revisions/{$nodes[1]->vid}/delete", array(), t('Delete'));
|
||||
$this->assertRaw(t('Revision from %revision-date of @type %title has been deleted.',
|
||||
array('%revision-date' => format_date($nodes[1]->revision_timestamp),
|
||||
'@type' => 'Basic page', '%title' => $nodes[1]->title)), t('Revision deleted.'));
|
||||
$this->assertTrue(db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid and vid = :vid', array(':nid' => $node->nid, ':vid' => $nodes[1]->vid))->fetchField() == 0, t('Revision not found.'));
|
||||
|
||||
// Set the revision timestamp to an older date to make sure that the
|
||||
// confirmation message correctly displays the stored revision date.
|
||||
$old_revision_date = REQUEST_TIME - 86400;
|
||||
db_update('node_revision')
|
||||
->condition('vid', $nodes[2]->vid)
|
||||
->fields(array(
|
||||
'timestamp' => $old_revision_date,
|
||||
))
|
||||
->execute();
|
||||
$this->drupalPost("node/$node->nid/revisions/{$nodes[2]->vid}/revert", array(), t('Revert'));
|
||||
$this->assertRaw(t('@type %title has been reverted back to the revision from %revision-date.', array(
|
||||
'@type' => 'Basic page',
|
||||
'%title' => $nodes[2]->title,
|
||||
'%revision-date' => format_date($old_revision_date),
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that revisions are correctly saved without log messages.
|
||||
*/
|
||||
function testNodeRevisionWithoutLogMessage() {
|
||||
// Create a node with an initial log message.
|
||||
$log = $this->randomName(10);
|
||||
$node = $this->drupalCreateNode(array('log' => $log));
|
||||
|
||||
// Save over the same revision and explicitly provide an empty log message
|
||||
// (for example, to mimic the case of a node form submitted with no text in
|
||||
// the "log message" field), and check that the original log message is
|
||||
// preserved.
|
||||
$new_title = $this->randomName(10) . 'testNodeRevisionWithoutLogMessage1';
|
||||
|
||||
$node = clone $node;
|
||||
$node->title = $new_title;
|
||||
$node->log = '';
|
||||
$node->revision = FALSE;
|
||||
|
||||
$node->save();
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertText($new_title, t('New node title appears on the page.'));
|
||||
$node_revision = node_load($node->nid, NULL, TRUE);
|
||||
$this->assertEqual($node_revision->log, $log, t('After an existing node revision is re-saved without a log message, the original log message is preserved.'));
|
||||
|
||||
// Create another node with an initial log message.
|
||||
$node = $this->drupalCreateNode(array('log' => $log));
|
||||
|
||||
// Save a new node revision without providing a log message, and check that
|
||||
// this revision has an empty log message.
|
||||
$new_title = $this->randomName(10) . 'testNodeRevisionWithoutLogMessage2';
|
||||
|
||||
$node = clone $node;
|
||||
$node->title = $new_title;
|
||||
$node->revision = TRUE;
|
||||
$node->log = NULL;
|
||||
|
||||
$node->save();
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertText($new_title, 'New node title appears on the page.');
|
||||
$node_revision = node_load($node->nid, NULL, TRUE);
|
||||
$this->assertTrue(empty($node_revision->log), 'After a new node revision is saved with an empty log message, the log message for the node is empty.');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeSaveTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Test case to check node save related functionality, including import-save
|
||||
*/
|
||||
class NodeSaveTest extends NodeTestBase {
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node save',
|
||||
'description' => 'Test $node->save() for saving content.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp('node_test');
|
||||
// Create a user that is allowed to post; we'll use this to test the submission.
|
||||
$web_user = $this->drupalCreateUser(array('create article content'));
|
||||
$this->drupalLogin($web_user);
|
||||
$this->web_user = $web_user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import test, to check if custom node ids are saved properly.
|
||||
* Workflow:
|
||||
* - first create a piece of content
|
||||
* - save the content
|
||||
* - check if node exists
|
||||
*/
|
||||
function testImport() {
|
||||
// Node ID must be a number that is not in the database.
|
||||
$max_nid = db_query('SELECT MAX(nid) FROM {node}')->fetchField();
|
||||
$test_nid = $max_nid + mt_rand(1000, 1000000);
|
||||
$title = $this->randomName(8);
|
||||
$node = array(
|
||||
'title' => $title,
|
||||
'body' => array(LANGUAGE_NOT_SPECIFIED => array(array('value' => $this->randomName(32)))),
|
||||
'uid' => $this->web_user->uid,
|
||||
'type' => 'article',
|
||||
'nid' => $test_nid,
|
||||
'enforceIsNew' => TRUE,
|
||||
);
|
||||
$node = node_submit(entity_create('node', $node));
|
||||
|
||||
// Verify that node_submit did not overwrite the user ID.
|
||||
$this->assertEqual($node->uid, $this->web_user->uid, t('Function node_submit() preserves user ID'));
|
||||
|
||||
$node->save();
|
||||
// Test the import.
|
||||
$node_by_nid = node_load($test_nid);
|
||||
$this->assertTrue($node_by_nid, t('Node load by node ID.'));
|
||||
|
||||
$node_by_title = $this->drupalGetNodeByTitle($title);
|
||||
$this->assertTrue($node_by_title, t('Node load by node title.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the "created" and "changed" timestamps are set correctly when
|
||||
* saving a new node or updating an existing node.
|
||||
*/
|
||||
function testTimestamps() {
|
||||
// Use the default timestamps.
|
||||
$edit = array(
|
||||
'uid' => $this->web_user->uid,
|
||||
'type' => 'article',
|
||||
'title' => $this->randomName(8),
|
||||
);
|
||||
|
||||
entity_create('node', $edit)->save();
|
||||
$node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
$this->assertEqual($node->created, REQUEST_TIME, t('Creating a node sets default "created" timestamp.'));
|
||||
$this->assertEqual($node->changed, REQUEST_TIME, t('Creating a node sets default "changed" timestamp.'));
|
||||
|
||||
// Store the timestamps.
|
||||
$created = $node->created;
|
||||
$changed = $node->changed;
|
||||
|
||||
$node->save();
|
||||
$node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
|
||||
$this->assertEqual($node->created, $created, t('Updating a node preserves "created" timestamp.'));
|
||||
|
||||
// Programmatically set the timestamps using hook_node_presave.
|
||||
$node->title = 'testing_node_presave';
|
||||
|
||||
$node->save();
|
||||
$node = $this->drupalGetNodeByTitle('testing_node_presave', TRUE);
|
||||
$this->assertEqual($node->created, 280299600, t('Saving a node uses "created" timestamp set in presave hook.'));
|
||||
$this->assertEqual($node->changed, 979534800, t('Saving a node uses "changed" timestamp set in presave hook.'));
|
||||
|
||||
// Programmatically set the timestamps on the node.
|
||||
$edit = array(
|
||||
'uid' => $this->web_user->uid,
|
||||
'type' => 'article',
|
||||
'title' => $this->randomName(8),
|
||||
'created' => 280299600, // Sun, 19 Nov 1978 05:00:00 GMT
|
||||
'changed' => 979534800, // Drupal 1.0 release.
|
||||
);
|
||||
|
||||
entity_create('node', $edit)->save();
|
||||
$node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
$this->assertEqual($node->created, 280299600, t('Creating a node uses user-set "created" timestamp.'));
|
||||
$this->assertNotEqual($node->changed, 979534800, t('Creating a node doesn\'t use user-set "changed" timestamp.'));
|
||||
|
||||
// Update the timestamps.
|
||||
$node->created = 979534800;
|
||||
$node->changed = 280299600;
|
||||
|
||||
$node->save();
|
||||
$node = $this->drupalGetNodeByTitle($edit['title'], TRUE);
|
||||
$this->assertEqual($node->created, 979534800, t('Updating a node uses user-set "created" timestamp.'));
|
||||
$this->assertNotEqual($node->changed, 280299600, t('Updating a node doesn\'t use user-set "changed" timestamp.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests determing changes in hook_node_presave() and verifies the static node
|
||||
* load cache is cleared upon save.
|
||||
*/
|
||||
function testDeterminingChanges() {
|
||||
// Initial creation.
|
||||
$node = entity_create('node', array(
|
||||
'uid' => $this->web_user->uid,
|
||||
'type' => 'article',
|
||||
'title' => 'test_changes',
|
||||
));
|
||||
$node->save();
|
||||
|
||||
// Update the node without applying changes.
|
||||
$node->save();
|
||||
$this->assertEqual($node->title, 'test_changes', 'No changes have been determined.');
|
||||
|
||||
// Apply changes.
|
||||
$node->title = 'updated';
|
||||
$node->save();
|
||||
|
||||
// The hook implementations node_test_node_presave() and
|
||||
// node_test_node_update() determine changes and change the title.
|
||||
$this->assertEqual($node->title, 'updated_presave_update', 'Changes have been determined.');
|
||||
|
||||
// Test the static node load cache to be cleared.
|
||||
$node = node_load($node->nid);
|
||||
$this->assertEqual($node->title, 'updated_presave', 'Static cache has been cleared.');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeTestBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
class NodeTestBase extends WebTestBase {
|
||||
function setUp() {
|
||||
$modules = func_get_args();
|
||||
if (isset($modules[0]) && is_array($modules[0])) {
|
||||
$modules = $modules[0];
|
||||
}
|
||||
$modules[] = 'node';
|
||||
parent::setUp($modules);
|
||||
|
||||
// Create Basic page and Article node types.
|
||||
if ($this->profile != 'standard') {
|
||||
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
|
||||
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeTitleTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Test node title.
|
||||
*/
|
||||
class NodeTitleTest extends NodeTestBase {
|
||||
protected $admin_user;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node title',
|
||||
'description' => 'Test node title.',
|
||||
'group' => 'Node'
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('comment'));
|
||||
$this->admin_user = $this->drupalCreateUser(array('administer nodes', 'create article content', 'create page content', 'post comments'));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create one node and test if the node title has the correct value.
|
||||
*/
|
||||
function testNodeTitle() {
|
||||
// Create "Basic page" content with title.
|
||||
// Add the node to the frontpage so we can test if teaser links are clickable.
|
||||
$settings = array(
|
||||
'title' => $this->randomName(8),
|
||||
'promote' => 1,
|
||||
);
|
||||
$node = $this->drupalCreateNode($settings);
|
||||
|
||||
// Test <title> tag.
|
||||
$this->drupalGet("node/$node->nid");
|
||||
$xpath = '//title';
|
||||
$this->assertEqual(current($this->xpath($xpath)), $node->title .' | Drupal', 'Page title is equal to node title.', 'Node');
|
||||
|
||||
// Test breadcrumb in comment preview.
|
||||
$this->drupalGet("comment/reply/$node->nid");
|
||||
$xpath = '//nav[@class="breadcrumb"]/ol/li[last()]/a';
|
||||
$this->assertEqual(current($this->xpath($xpath)), $node->title, 'Node breadcrumb is equal to node title.', 'Node');
|
||||
|
||||
// Test node title in comment preview.
|
||||
$this->assertEqual(current($this->xpath('//article[@id=:id]/h2/a', array(':id' => 'node-' . $node->nid))), $node->title, 'Node preview title is equal to node title.', 'Node');
|
||||
|
||||
// Test node title is clickable on teaser list (/node).
|
||||
$this->drupalGet('node');
|
||||
$this->clickLink($node->title);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeTitleXSSTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
class NodeTitleXSSTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node title XSS filtering',
|
||||
'description' => 'Create a node with dangerous tags in its title and test that they are escaped.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function testNodeTitleXSS() {
|
||||
// Prepare a user to do the stuff.
|
||||
$web_user = $this->drupalCreateUser(array('create page content', 'edit any page content'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
$xss = '<script>alert("xss")</script>';
|
||||
$title = $xss . $this->randomName();
|
||||
$edit = array("title" => $title);
|
||||
|
||||
$this->drupalPost('node/add/page', $edit, t('Preview'));
|
||||
$this->assertNoRaw($xss, t('Harmful tags are escaped when previewing a node.'));
|
||||
|
||||
$settings = array('title' => $title);
|
||||
$node = $this->drupalCreateNode($settings);
|
||||
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
// assertTitle() decodes HTML-entities inside the <title> element.
|
||||
$this->assertTitle($edit["title"] . ' | Drupal', t('Title is diplayed when viewing a node.'));
|
||||
$this->assertNoRaw($xss, t('Harmful tags are escaped when viewing a node.'));
|
||||
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
$this->assertNoRaw($xss, t('Harmful tags are escaped when editing a node.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeTokenReplaceTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Test node token replacement in strings.
|
||||
*/
|
||||
class NodeTokenReplaceTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node token replacement',
|
||||
'description' => 'Generates text using placeholders for dummy content to check node token replacement.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a node, then tests the tokens generated from it.
|
||||
*/
|
||||
function testNodeTokenReplacement() {
|
||||
$language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
|
||||
$url_options = array(
|
||||
'absolute' => TRUE,
|
||||
'language' => $language_interface,
|
||||
);
|
||||
|
||||
// Create a user and a node.
|
||||
$account = $this->drupalCreateUser();
|
||||
$settings = array(
|
||||
'type' => 'article',
|
||||
'uid' => $account->uid,
|
||||
'title' => '<blink>Blinking Text</blink>',
|
||||
'body' => array(LANGUAGE_NOT_SPECIFIED => array(array('value' => $this->randomName(32), 'summary' => $this->randomName(16)))),
|
||||
);
|
||||
$node = $this->drupalCreateNode($settings);
|
||||
|
||||
// Load node so that the body and summary fields are structured properly.
|
||||
$node = node_load($node->nid);
|
||||
$instance = field_info_instance('node', 'body', $node->type);
|
||||
|
||||
// Generate and test sanitized tokens.
|
||||
$tests = array();
|
||||
$tests['[node:nid]'] = $node->nid;
|
||||
$tests['[node:vid]'] = $node->vid;
|
||||
$tests['[node:tnid]'] = $node->tnid;
|
||||
$tests['[node:type]'] = 'article';
|
||||
$tests['[node:type-name]'] = 'Article';
|
||||
$tests['[node:title]'] = check_plain($node->title);
|
||||
$tests['[node:body]'] = _text_sanitize($instance, $node->langcode, $node->body[$node->langcode][0], 'value');
|
||||
$tests['[node:summary]'] = _text_sanitize($instance, $node->langcode, $node->body[$node->langcode][0], 'summary');
|
||||
$tests['[node:langcode]'] = check_plain($node->langcode);
|
||||
$tests['[node:url]'] = url('node/' . $node->nid, $url_options);
|
||||
$tests['[node:edit-url]'] = url('node/' . $node->nid . '/edit', $url_options);
|
||||
$tests['[node:author]'] = check_plain(user_format_name($account));
|
||||
$tests['[node:author:uid]'] = $node->uid;
|
||||
$tests['[node:author:name]'] = check_plain(user_format_name($account));
|
||||
$tests['[node:created:since]'] = format_interval(REQUEST_TIME - $node->created, 2, $language_interface->langcode);
|
||||
$tests['[node:changed:since]'] = format_interval(REQUEST_TIME - $node->changed, 2, $language_interface->langcode);
|
||||
|
||||
// Test to make sure that we generated something for each token.
|
||||
$this->assertFalse(in_array(0, array_map('strlen', $tests)), t('No empty tokens generated.'));
|
||||
|
||||
foreach ($tests as $input => $expected) {
|
||||
$output = token_replace($input, array('node' => $node), array('language' => $language_interface));
|
||||
$this->assertEqual($output, $expected, t('Sanitized node token %token replaced.', array('%token' => $input)));
|
||||
}
|
||||
|
||||
// Generate and test unsanitized tokens.
|
||||
$tests['[node:title]'] = $node->title;
|
||||
$tests['[node:body]'] = $node->body[$node->langcode][0]['value'];
|
||||
$tests['[node:summary]'] = $node->body[$node->langcode][0]['summary'];
|
||||
$tests['[node:langcode]'] = $node->langcode;
|
||||
$tests['[node:author:name]'] = user_format_name($account);
|
||||
|
||||
foreach ($tests as $input => $expected) {
|
||||
$output = token_replace($input, array('node' => $node), array('language' => $language_interface, 'sanitize' => FALSE));
|
||||
$this->assertEqual($output, $expected, t('Unsanitized node token %token replaced.', array('%token' => $input)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeTypePersistenceTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Test node type customizations persistence.
|
||||
*/
|
||||
class NodeTypePersistenceTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node type persist',
|
||||
'description' => 'Ensures that node type customization survives module enabling and disabling.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test node type customizations persist through disable and uninstall.
|
||||
*/
|
||||
function testNodeTypeCustomizationPersistence() {
|
||||
$web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer modules'));
|
||||
$this->drupalLogin($web_user);
|
||||
$poll_key = 'modules[Core][poll][enable]';
|
||||
$poll_enable = array($poll_key => "1");
|
||||
$poll_disable = array($poll_key => FALSE);
|
||||
|
||||
// Enable poll and verify that the node type is in the DB and is not
|
||||
// disabled.
|
||||
$this->drupalPost('admin/modules', $poll_enable, t('Save configuration'));
|
||||
$disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
|
||||
$this->assertNotIdentical($disabled, FALSE, t('Poll node type found in the database'));
|
||||
$this->assertEqual($disabled, 0, t('Poll node type is not disabled'));
|
||||
|
||||
// Check that poll node type (uncustomized) shows up.
|
||||
$this->drupalGet('node/add');
|
||||
$this->assertText('poll', t('poll type is found on node/add'));
|
||||
|
||||
// Customize poll description.
|
||||
$description = $this->randomName();
|
||||
$edit = array('description' => $description);
|
||||
$this->drupalPost('admin/structure/types/manage/poll', $edit, t('Save content type'));
|
||||
|
||||
// Check that poll node type customization shows up.
|
||||
$this->drupalGet('node/add');
|
||||
$this->assertText($description, t('Customized description found'));
|
||||
|
||||
// Disable poll and check that the node type gets disabled.
|
||||
$this->drupalPost('admin/modules', $poll_disable, t('Save configuration'));
|
||||
$disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
|
||||
$this->assertEqual($disabled, 1, t('Poll node type is disabled'));
|
||||
$this->drupalGet('node/add');
|
||||
$this->assertNoText('poll', t('poll type is not found on node/add'));
|
||||
|
||||
// Reenable poll and check that the customization survived the module
|
||||
// disable.
|
||||
$this->drupalPost('admin/modules', $poll_enable, t('Save configuration'));
|
||||
$disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
|
||||
$this->assertNotIdentical($disabled, FALSE, t('Poll node type found in the database'));
|
||||
$this->assertEqual($disabled, 0, t('Poll node type is not disabled'));
|
||||
$this->drupalGet('node/add');
|
||||
$this->assertText($description, t('Customized description found'));
|
||||
|
||||
// Disable and uninstall poll.
|
||||
$this->drupalPost('admin/modules', $poll_disable, t('Save configuration'));
|
||||
$edit = array('uninstall[poll]' => 'poll');
|
||||
$this->drupalPost('admin/modules/uninstall', $edit, t('Uninstall'));
|
||||
$this->drupalPost(NULL, array(), t('Uninstall'));
|
||||
$disabled = db_query('SELECT disabled FROM {node_type} WHERE type = :type', array(':type' => 'poll'))->fetchField();
|
||||
$this->assertTrue($disabled, t('Poll node type is in the database and is disabled'));
|
||||
$this->drupalGet('node/add');
|
||||
$this->assertNoText('poll', t('poll type is no longer found on node/add'));
|
||||
|
||||
// Reenable poll and check that the customization survived the module
|
||||
// uninstall.
|
||||
$this->drupalPost('admin/modules', $poll_enable, t('Save configuration'));
|
||||
$this->drupalGet('node/add');
|
||||
$this->assertText($description, t('Customized description is found even after uninstall and reenable.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\NodeTypeTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
/**
|
||||
* Tests related to node types.
|
||||
*/
|
||||
class NodeTypeTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node types',
|
||||
'description' => 'Ensures that node type functions work correctly.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('field_ui'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that node type functions (node_type_get_*) work correctly.
|
||||
*
|
||||
* Load available node types and validate the returned data.
|
||||
*/
|
||||
function testNodeTypeGetFunctions() {
|
||||
$node_types = node_type_get_types();
|
||||
$node_names = node_type_get_names();
|
||||
|
||||
$this->assertTrue(isset($node_types['article']), t('Node type article is available.'));
|
||||
$this->assertTrue(isset($node_types['page']), t('Node type basic page is available.'));
|
||||
|
||||
$this->assertEqual($node_types['article']->name, $node_names['article'], t('Correct node type base has been returned.'));
|
||||
|
||||
$this->assertEqual($node_types['article'], node_type_load('article'), t('Correct node type has been returned.'));
|
||||
$this->assertEqual($node_types['article']->name, node_type_get_name('article'), t('Correct node type name has been returned.'));
|
||||
$this->assertEqual($node_types['page']->base, node_type_get_base('page'), t('Correct node type base has been returned.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating a content type programmatically and via a form.
|
||||
*/
|
||||
function testNodeTypeCreation() {
|
||||
// Create a content type programmaticaly.
|
||||
$type = $this->drupalCreateContentType();
|
||||
|
||||
$type_exists = db_query('SELECT 1 FROM {node_type} WHERE type = :type', array(':type' => $type->type))->fetchField();
|
||||
$this->assertTrue($type_exists, 'The new content type has been created in the database.');
|
||||
|
||||
// Login a test user.
|
||||
$web_user = $this->drupalCreateUser(array('create ' . $type->name . ' content'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
$this->drupalGet('node/add/' . $type->type);
|
||||
$this->assertResponse(200, 'The new content type can be accessed at node/add.');
|
||||
|
||||
// Create a content type via the user interface.
|
||||
$web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types'));
|
||||
$this->drupalLogin($web_user);
|
||||
$edit = array(
|
||||
'name' => 'foo',
|
||||
'title_label' => 'title for foo',
|
||||
'type' => 'foo',
|
||||
);
|
||||
$this->drupalPost('admin/structure/types/add', $edit, t('Save content type'));
|
||||
$type_exists = db_query('SELECT 1 FROM {node_type} WHERE type = :type', array(':type' => 'foo'))->fetchField();
|
||||
$this->assertTrue($type_exists, 'The new content type has been created in the database.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test editing a node type using the UI.
|
||||
*/
|
||||
function testNodeTypeEditing() {
|
||||
$web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
$instance = field_info_instance('node', 'body', 'page');
|
||||
$this->assertEqual($instance['label'], 'Body', t('Body field was found.'));
|
||||
|
||||
// Verify that title and body fields are displayed.
|
||||
$this->drupalGet('node/add/page');
|
||||
$this->assertRaw('Title', t('Title field was found.'));
|
||||
$this->assertRaw('Body', t('Body field was found.'));
|
||||
|
||||
// Rename the title field.
|
||||
$edit = array(
|
||||
'title_label' => 'Foo',
|
||||
);
|
||||
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
// Refresh the field information for the rest of the test.
|
||||
field_info_cache_clear();
|
||||
|
||||
$this->drupalGet('node/add/page');
|
||||
$this->assertRaw('Foo', t('New title label was displayed.'));
|
||||
$this->assertNoRaw('Title', t('Old title label was not displayed.'));
|
||||
|
||||
// Change the name, machine name and description.
|
||||
$edit = array(
|
||||
'name' => 'Bar',
|
||||
'type' => 'bar',
|
||||
'description' => 'Lorem ipsum.',
|
||||
);
|
||||
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
field_info_cache_clear();
|
||||
|
||||
$this->drupalGet('node/add');
|
||||
$this->assertRaw('Bar', t('New name was displayed.'));
|
||||
$this->assertRaw('Lorem ipsum', t('New description was displayed.'));
|
||||
$this->clickLink('Bar');
|
||||
$this->assertEqual(url('node/add/bar', array('absolute' => TRUE)), $this->getUrl(), t('New machine name was used in URL.'));
|
||||
$this->assertRaw('Foo', t('Title field was found.'));
|
||||
$this->assertRaw('Body', t('Body field was found.'));
|
||||
|
||||
// Remove the body field.
|
||||
$this->drupalPost('admin/structure/types/manage/bar/fields/body/delete', array(), t('Delete'));
|
||||
// Resave the settings for this type.
|
||||
$this->drupalPost('admin/structure/types/manage/bar', array(), t('Save content type'));
|
||||
// Check that the body field doesn't exist.
|
||||
$this->drupalGet('node/add/bar');
|
||||
$this->assertNoRaw('Body', t('Body field was not found.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that node_types_rebuild() correctly handles the 'disabled' flag.
|
||||
*/
|
||||
function testNodeTypeStatus() {
|
||||
// Enable all core node modules, and all types should be active.
|
||||
module_enable(array('book', 'poll'), FALSE);
|
||||
node_types_rebuild();
|
||||
$types = node_type_get_types();
|
||||
foreach (array('book', 'poll', 'article', 'page') as $type) {
|
||||
$this->assertTrue(isset($types[$type]), t('%type is found in node types.', array('%type' => $type)));
|
||||
$this->assertTrue(isset($types[$type]->disabled) && empty($types[$type]->disabled), t('%type type is enabled.', array('%type' => $type)));
|
||||
}
|
||||
|
||||
// Disable poll module and the respective type should be marked as disabled.
|
||||
module_disable(array('poll'), FALSE);
|
||||
node_types_rebuild();
|
||||
$types = node_type_get_types();
|
||||
$this->assertTrue(!empty($types['poll']->disabled), t("Poll module's node type disabled."));
|
||||
|
||||
// Disable book module and the respective type should still be active, since
|
||||
// it is not provided by hook_node_info().
|
||||
module_disable(array('book'), FALSE);
|
||||
node_types_rebuild();
|
||||
$types = node_type_get_types();
|
||||
$this->assertTrue(isset($types['book']) && empty($types['book']->disabled), t("Book module's node type still active."));
|
||||
$this->assertTrue(!empty($types['poll']->disabled), t("Poll module's node type still disabled."));
|
||||
$this->assertTrue(isset($types['article']) && empty($types['article']->disabled), t("Article node type still active."));
|
||||
$this->assertTrue(isset($types['page']) && empty($types['page']->disabled), t("Basic page node type still active."));
|
||||
|
||||
// Re-enable the modules and verify that the types are active again.
|
||||
module_enable(array('book', 'poll'), FALSE);
|
||||
node_types_rebuild();
|
||||
$types = node_type_get_types();
|
||||
foreach (array('book', 'poll', 'article', 'page') as $type) {
|
||||
$this->assertTrue(isset($types[$type]), t('%type is found in node types.', array('%type' => $type)));
|
||||
$this->assertTrue(isset($types[$type]->disabled) && empty($types[$type]->disabled), t('%type type is enabled.', array('%type' => $type)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\PageEditTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
class PageEditTest extends NodeTestBase {
|
||||
protected $web_user;
|
||||
protected $admin_user;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node edit',
|
||||
'description' => 'Create a node and test node edit functionality.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->web_user = $this->drupalCreateUser(array('edit own page content', 'create page content'));
|
||||
$this->admin_user = $this->drupalCreateUser(array('bypass node access', 'administer nodes'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check node edit functionality.
|
||||
*/
|
||||
function testPageEdit() {
|
||||
$this->drupalLogin($this->web_user);
|
||||
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$title_key = "title";
|
||||
$body_key = "body[$langcode][0][value]";
|
||||
// Create node to edit.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $this->randomName(8);
|
||||
$edit[$body_key] = $this->randomName(16);
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the node exists in the database.
|
||||
$node = $this->drupalGetNodeByTitle($edit[$title_key]);
|
||||
$this->assertTrue($node, t('Node found in database.'));
|
||||
|
||||
// Check that "edit" link points to correct page.
|
||||
$this->clickLink(t('Edit'));
|
||||
$edit_url = url("node/$node->nid/edit", array('absolute' => TRUE));
|
||||
$actual_url = $this->getURL();
|
||||
$this->assertEqual($edit_url, $actual_url, t('On edit page.'));
|
||||
|
||||
// Check that the title and body fields are displayed with the correct values.
|
||||
$active = '<span class="element-invisible">' . t('(active tab)') . '</span>';
|
||||
$link_text = t('!local-task-title!active', array('!local-task-title' => t('Edit'), '!active' => $active));
|
||||
$this->assertText(strip_tags($link_text), 0, t('Edit tab found and marked active.'));
|
||||
$this->assertFieldByName($title_key, $edit[$title_key], t('Title field displayed.'));
|
||||
$this->assertFieldByName($body_key, $edit[$body_key], t('Body field displayed.'));
|
||||
|
||||
// Edit the content of the node.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $this->randomName(8);
|
||||
$edit[$body_key] = $this->randomName(16);
|
||||
// Stay on the current page, without reloading.
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
|
||||
// Check that the title and body fields are displayed with the updated values.
|
||||
$this->assertText($edit[$title_key], t('Title displayed.'));
|
||||
$this->assertText($edit[$body_key], t('Body displayed.'));
|
||||
|
||||
// Login as a second administrator user.
|
||||
$second_web_user = $this->drupalCreateUser(array('administer nodes', 'edit any page content'));
|
||||
$this->drupalLogin($second_web_user);
|
||||
// Edit the same node, creating a new revision.
|
||||
$this->drupalGet("node/$node->nid/edit");
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName(8);
|
||||
$edit[$body_key] = $this->randomName(16);
|
||||
$edit['revision'] = TRUE;
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
|
||||
// Ensure that the node revision has been created.
|
||||
$revised_node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
$this->assertNotIdentical($node->vid, $revised_node->vid, 'A new revision has been created.');
|
||||
// Ensure that the node author is preserved when it was not changed in the
|
||||
// edit form.
|
||||
$this->assertIdentical($node->uid, $revised_node->uid, 'The node author has been preserved.');
|
||||
// Ensure that the revision authors are different since the revisions were
|
||||
// made by different users.
|
||||
$first_node_version = node_load($node->nid, $node->vid);
|
||||
$second_node_version = node_load($node->nid, $revised_node->vid);
|
||||
$this->assertNotIdentical($first_node_version->revision_uid, $second_node_version->revision_uid, 'Each revision has a distinct user.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check changing node authored by fields.
|
||||
*/
|
||||
function testPageAuthoredBy() {
|
||||
$this->drupalLogin($this->admin_user);
|
||||
|
||||
// Create node to edit.
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$body_key = "body[$langcode][0][value]";
|
||||
$edit = array();
|
||||
$edit['title'] = $this->randomName(8);
|
||||
$edit[$body_key] = $this->randomName(16);
|
||||
$this->drupalPost('node/add/page', $edit, t('Save'));
|
||||
|
||||
// Check that the node was authored by the currently logged in user.
|
||||
$node = $this->drupalGetNodeByTitle($edit['title']);
|
||||
$this->assertIdentical($node->uid, $this->admin_user->uid, 'Node authored by admin user.');
|
||||
|
||||
// Try to change the 'authored by' field to an invalid user name.
|
||||
$edit = array(
|
||||
'name' => 'invalid-name',
|
||||
);
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$this->assertText('The username invalid-name does not exist.');
|
||||
|
||||
// Change the authored by field to an empty string, which should assign
|
||||
// authorship to the anonymous user (uid 0).
|
||||
$edit['name'] = '';
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$node = node_load($node->nid, NULL, TRUE);
|
||||
$this->assertIdentical($node->uid, '0', 'Node authored by anonymous user.');
|
||||
|
||||
// Change the authored by field to another user's name (that is not
|
||||
// logged in).
|
||||
$edit['name'] = $this->web_user->name;
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$node = node_load($node->nid, NULL, TRUE);
|
||||
$this->assertIdentical($node->uid, $this->web_user->uid, 'Node authored by normal user.');
|
||||
|
||||
// Check that normal users cannot change the authored by information.
|
||||
$this->drupalLogin($this->web_user);
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
$this->assertNoFieldByName('name');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\PagePreviewTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
class PagePreviewTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node preview',
|
||||
'description' => 'Test node preview functionality.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$web_user = $this->drupalCreateUser(array('edit own page content', 'create page content'));
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the node preview functionality.
|
||||
*/
|
||||
function testPagePreview() {
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$title_key = "title";
|
||||
$body_key = "body[$langcode][0][value]";
|
||||
|
||||
// Fill in node creation form and preview node.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $this->randomName(8);
|
||||
$edit[$body_key] = $this->randomName(16);
|
||||
$this->drupalPost('node/add/page', $edit, t('Preview'));
|
||||
|
||||
// Check that the preview is displaying the title and body.
|
||||
$this->assertTitle(t('Preview | Drupal'), t('Basic page title is preview.'));
|
||||
$this->assertText($edit[$title_key], t('Title displayed.'));
|
||||
$this->assertText($edit[$body_key], t('Body displayed.'));
|
||||
|
||||
// Check that the title and body fields are displayed with the correct values.
|
||||
$this->assertFieldByName($title_key, $edit[$title_key], t('Title field displayed.'));
|
||||
$this->assertFieldByName($body_key, $edit[$body_key], t('Body field displayed.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the node preview functionality, when using revisions.
|
||||
*/
|
||||
function testPagePreviewWithRevisions() {
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$title_key = "title";
|
||||
$body_key = "body[$langcode][0][value]";
|
||||
// Force revision on "Basic page" content.
|
||||
variable_set('node_options_page', array('status', 'revision'));
|
||||
|
||||
// Fill in node creation form and preview node.
|
||||
$edit = array();
|
||||
$edit[$title_key] = $this->randomName(8);
|
||||
$edit[$body_key] = $this->randomName(16);
|
||||
$edit['log'] = $this->randomName(32);
|
||||
$this->drupalPost('node/add/page', $edit, t('Preview'));
|
||||
|
||||
// Check that the preview is displaying the title and body.
|
||||
$this->assertTitle(t('Preview | Drupal'), t('Basic page title is preview.'));
|
||||
$this->assertText($edit[$title_key], t('Title displayed.'));
|
||||
$this->assertText($edit[$body_key], t('Body displayed.'));
|
||||
|
||||
// Check that the title and body fields are displayed with the correct values.
|
||||
$this->assertFieldByName($title_key, $edit[$title_key], t('Title field displayed.'));
|
||||
$this->assertFieldByName($body_key, $edit[$body_key], t('Body field displayed.'));
|
||||
|
||||
// Check that the log field has the correct value.
|
||||
$this->assertFieldByName('log', $edit['log'], t('Log field displayed.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\PageViewTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
class PageViewTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Node edit permissions',
|
||||
'description' => 'Create a node and test edit permissions.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a node and then an anonymous and unpermissioned user attempt to edit the node.
|
||||
*/
|
||||
function testPageView() {
|
||||
// Create a node to view.
|
||||
$node = $this->drupalCreateNode();
|
||||
$this->assertTrue(node_load($node->nid), t('Node created.'));
|
||||
|
||||
// Try to edit with anonymous user.
|
||||
$html = $this->drupalGet("node/$node->nid/edit");
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Create a user without permission to edit node.
|
||||
$web_user = $this->drupalCreateUser(array('access content'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Attempt to access edit page.
|
||||
$this->drupalGet("node/$node->nid/edit");
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Create user with permission to edit node.
|
||||
$web_user = $this->drupalCreateUser(array('bypass node access'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Attempt to access edit page.
|
||||
$this->drupalGet("node/$node->nid/edit");
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\node\Tests\SummaryLengthTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\node\Tests;
|
||||
|
||||
class SummaryLengthTest extends NodeTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Summary length',
|
||||
'description' => 'Test summary length.',
|
||||
'group' => 'Node',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a node and then an anonymous and unpermissioned user attempt to edit the node.
|
||||
*/
|
||||
function testSummaryLength() {
|
||||
// Create a node to view.
|
||||
$settings = array(
|
||||
'body' => array(LANGUAGE_NOT_SPECIFIED => array(array('value' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vitae arcu at leo cursus laoreet. Curabitur dui tortor, adipiscing malesuada tempor in, bibendum ac diam. Cras non tellus a libero pellentesque condimentum. What is a Drupalism? Suspendisse ac lacus libero. Ut non est vel nisl faucibus interdum nec sed leo. Pellentesque sem risus, vulputate eu semper eget, auctor in libero. Ut fermentum est vitae metus convallis scelerisque. Phasellus pellentesque rhoncus tellus, eu dignissim purus posuere id. Quisque eu fringilla ligula. Morbi ullamcorper, lorem et mattis egestas, tortor neque pretium velit, eget eleifend odio turpis eu purus. Donec vitae metus quis leo pretium tincidunt a pulvinar sem. Morbi adipiscing laoreet mauris vel placerat. Nullam elementum, nisl sit amet scelerisque malesuada, dolor nunc hendrerit quam, eu ultrices erat est in orci. Curabitur feugiat egestas nisl sed accumsan.'))),
|
||||
'promote' => 1,
|
||||
);
|
||||
$node = $this->drupalCreateNode($settings);
|
||||
$this->assertTrue(node_load($node->nid), t('Node created.'));
|
||||
|
||||
// Create user with permission to view the node.
|
||||
$web_user = $this->drupalCreateUser(array('access content', 'administer content types'));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Attempt to access the front page.
|
||||
$this->drupalGet("node");
|
||||
// The node teaser when it has 600 characters in length
|
||||
$expected = 'What is a Drupalism?';
|
||||
$this->assertRaw($expected, t('Check that the summary is 600 characters in length'), 'Node');
|
||||
|
||||
// Change the teaser length for "Basic page" content type.
|
||||
$instance = field_info_instance('node', 'body', $node->type);
|
||||
$instance['display']['teaser']['settings']['trim_length'] = 200;
|
||||
field_update_instance($instance);
|
||||
|
||||
// Attempt to access the front page again and check if the summary is now only 200 characters in length.
|
||||
$this->drupalGet("node");
|
||||
$this->assertNoRaw($expected, t('Check that the summary is not longer than 200 characters'), 'Node');
|
||||
}
|
||||
}
|
|
@ -3,7 +3,5 @@ description = Allows content to be submitted to the site and displayed on pages.
|
|||
package = Core
|
||||
version = VERSION
|
||||
core = 8.x
|
||||
files[] = node.module
|
||||
files[] = node.test
|
||||
dependencies[] = entity
|
||||
configure = admin/structure/types
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\php\Tests\PhpAccessTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\php\Tests;
|
||||
|
||||
/**
|
||||
* Tests to make sure access to the PHP filter is properly restricted.
|
||||
*/
|
||||
class PhpAccessTest extends PhpTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'PHP filter access check',
|
||||
'description' => 'Make sure that users who don\'t have access to the PHP filter can\'t see it.',
|
||||
'group' => 'PHP',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that the user can't use the PHP filter when not given access.
|
||||
*/
|
||||
function testNoPrivileges() {
|
||||
// Create node with PHP filter enabled.
|
||||
$web_user = $this->drupalCreateUser(array('access content', 'create page content', 'edit own page content'));
|
||||
$this->drupalLogin($web_user);
|
||||
$node = $this->createNodeWithCode();
|
||||
|
||||
// Make sure that the PHP code shows up as text.
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertText('print', t('PHP code was not evaluated.'));
|
||||
|
||||
// Make sure that user doesn't have access to filter.
|
||||
$this->drupalGet('node/' . $node->nid . '/edit');
|
||||
$this->assertNoRaw('<option value="' . $this->php_code_format->format . '">', t('PHP code format not available.'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of Drupal\php\Tests\PhpFilterTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\php\Tests;
|
||||
|
||||
/**
|
||||
* Tests to make sure the PHP filter actually evaluates PHP code when used.
|
||||
*/
|
||||
class PhpFilterTest extends PhpTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'PHP filter functionality',
|
||||
'description' => 'Make sure that PHP filter properly evaluates PHP code when enabled.',
|
||||
'group' => 'PHP',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that the PHP filter evaluates PHP code when used.
|
||||
*/
|
||||
function testPhpFilter() {
|
||||
// Log in as a user with permission to use the PHP code text format.
|
||||
$php_code_permission = filter_permission_name(filter_format_load('php_code'));
|
||||
$web_user = $this->drupalCreateUser(array('access content', 'create page content', 'edit own page content', $php_code_permission));
|
||||
$this->drupalLogin($web_user);
|
||||
|
||||
// Create a node with PHP code in it.
|
||||
$node = $this->createNodeWithCode();
|
||||
|
||||
// Make sure that the PHP code shows up as text.
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->assertText('php print');
|
||||
|
||||
// Change filter to PHP filter and see that PHP code is evaluated.
|
||||
$edit = array();
|
||||
$langcode = LANGUAGE_NOT_SPECIFIED;
|
||||
$edit["body[$langcode][0][format]"] = $this->php_code_format->format;
|
||||
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
|
||||
$this->assertRaw(t('Basic page %title has been updated.', array('%title' => $node->title)), t('PHP code filter turned on.'));
|
||||
|
||||
// Make sure that the PHP code shows up as text.
|
||||
$this->assertNoText('print "SimpleTest PHP was executed!"', t("PHP code isn't displayed."));
|
||||
$this->assertText('SimpleTest PHP was executed!', t('PHP code has been evaluated.'));
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue