Newer
Older
<?php
Dries Buytaert
committed
* Tests for aggregator.module.
class AggregatorTestCase extends DrupalWebTestCase {
function setUp() {
parent::setUp('aggregator', 'aggregator_test');
$web_user = $this->drupalCreateUser(array('administer news feeds', 'access news feeds', 'create article content'));
$this->drupalLogin($web_user);
}
/**
Angie Byron
committed
* 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);
Angie Byron
committed
$this->drupalPost('admin/config/services/aggregator/add/feed', $edit, t('Save'));
Jennifer Hodgdon
committed
$this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title'])), format_string('The feed !name has been added.', array('!name' => $edit['title'])));
Dries Buytaert
committed
$feed = db_query("SELECT * FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $edit['title'], ':url' => $edit['url']))->fetch();
Jennifer Hodgdon
committed
$this->assertTrue(!empty($feed), 'The feed found in database.');
return $feed;
}
/**
* Delete an aggregator feed.
*
* @param $feed
* Feed object representing the feed.
*/
function deleteFeed($feed) {
Angie Byron
committed
$this->drupalPost('admin/config/services/aggregator/edit/feed/' . $feed->fid, array(), t('Delete'));
Jennifer Hodgdon
committed
$this->assertRaw(t('The feed %title has been deleted.', array('%title' => $feed->title)), '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) {
Dries Buytaert
committed
$feed_name = $this->randomName(10);
if (!$feed_url) {
Dries Buytaert
committed
$feed_url = url('rss.xml', array(
Dries Buytaert
committed
'query' => array('feed' => $feed_name),
Dries Buytaert
committed
'absolute' => TRUE,
));
$edit = array(
'title' => $feed_name,
'url' => $feed_url,
'refresh' => '900',
);
return $edit;
}
/**
* Return the count of the randomly created feed array.
* 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, variable_get('feed_default_items', 10))->fetchField();
return $feed_count > 10 ? 10 : $feed_count;
}
/**
Angie Byron
committed
* 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);
Jennifer Hodgdon
committed
$this->assertResponse(200, format_string('!url is reachable.', array('!url' => $feed->url)));
// Attempt to access the update link directly without an access token.
Angie Byron
committed
$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.
Dries Buytaert
committed
$result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid));
$items = array();
$feed->items = array();
Dries Buytaert
committed
foreach ($result as $item) {
$feed->items[] = $item->iid;
}
$feed->item_count = count($feed->items);
Jennifer Hodgdon
committed
$this->assertEqual($expected_count, $feed->item_count, format_string('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) {
Angie Byron
committed
$this->drupalPost('admin/config/services/aggregator/remove/' . $feed->fid, array(), t('Remove items'));
Jennifer Hodgdon
committed
$this->assertRaw(t('The news items from %title have been removed.', array('%title' => $feed->title)), '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);
Dries Buytaert
committed
$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
Dries Buytaert
committed
$result = db_query('SELECT cid FROM {aggregator_category_feed} WHERE fid = :fid', array(':fid' => $feed->fid));
foreach ($result as $category) {
$feed->categories[] = $category->cid;
}
}
Dries Buytaert
committed
/**
* 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;
}
/**
Jennifer Hodgdon
committed
* Check if the feed name and URL is unique.
*
* @param $feed_name
* String containing the feed name to check.
* @param $feed_url
Jennifer Hodgdon
committed
* String containing the feed URL to check.
* @return
* TRUE if feed is unique.
*/
function uniqueFeed($feed_name, $feed_url) {
Dries Buytaert
committed
$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);
}
Dries Buytaert
committed
/**
* 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) {
Dries Buytaert
committed
// Properly escape URLs so that XML parsers don't choke on them.
foreach ($feeds as &$feed) {
$feed['url'] = htmlspecialchars($feed['url']);
}
Dries Buytaert
committed
/**
* 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);
Dries Buytaert
committed
}
/**
* 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);
Dries Buytaert
committed
}
/**
* 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);
Dries Buytaert
committed
}
function getRSS091Sample() {
return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_rss091.xml';
}
Dries Buytaert
committed
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';
}
Angie Byron
committed
/**
* Creates sample article nodes.
*
* @param $count
* (optional) The number of nodes to generate.
*/
function createSampleNodes($count = 5) {
$langcode = LANGUAGE_NONE;
Angie Byron
committed
// Post $count article nodes.
for ($i = 0; $i < $count; $i++) {
$edit = array();
$edit['title'] = $this->randomName();
Angie Byron
committed
$edit["body[$langcode][0][value]"] = $this->randomName();
$this->drupalPost('node/add/article', $edit, t('Save'));
}
}
}
Angie Byron
committed
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
/**
* 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) {
Jennifer Hodgdon
committed
$this->assertFieldByName($name, $value, format_string('"@name" has correct default value.', array('@name' => $name)));
Angie Byron
committed
}
}
}
class AddFeedTestCase extends AggregatorTestCase {
Angie Byron
committed
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.
Jennifer Hodgdon
committed
$this->assertEqual($this->getUrl(), url('admin/config/services/aggregator/add/feed', array('absolute' => TRUE)), 'Directed to correct url.');
$this->assertTrue($this->uniqueFeed($feed->title, $feed->url), 'The feed is unique.');
// Check feed source.
$this->drupalGet('aggregator/sources/' . $feed->fid);
Jennifer Hodgdon
committed
$this->assertResponse(200, 'Feed source exists.');
$this->assertText($feed->title, 'Page title');
Dries Buytaert
committed
$this->drupalGet('aggregator/sources/' . $feed->fid . '/categorize');
Jennifer Hodgdon
committed
$this->assertResponse(200, 'Feed categorization page exists.');
// Delete feed.
$this->deleteFeed($feed);
}
Angie Byron
committed
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
/**
* 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);
}
}
Dries Buytaert
committed
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'));
Jennifer Hodgdon
committed
$this->assertRaw(t('The category %title has been added.', array('%title' => $category_1['title'])), format_string('The category %title has been added.', array('%title' => $category_1['title'])));
Dries Buytaert
committed
$category_2 = array('title' => $this->randomName(10), 'description' => '');
$this->drupalPost('admin/config/services/aggregator/add/category', $category_2, t('Save'));
Jennifer Hodgdon
committed
$this->assertRaw(t('The category %title has been added.', array('%title' => $category_2['title'])), format_string('The category %title has been added.', array('%title' => $category_2['title'])));
Dries Buytaert
committed
// 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);
Jennifer Hodgdon
committed
$this->assertEqual(count($db_feed->categories), 2, 'Feed has 2 categories');
Dries Buytaert
committed
}
}
class UpdateFeedTestCase extends AggregatorTestCase {
Angie Byron
committed
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};
}
Angie Byron
committed
$this->drupalPost('admin/config/services/aggregator/edit/feed/' . $feed->fid, $edit, t('Save'));
Jennifer Hodgdon
committed
$this->assertRaw(t('The feed %name has been updated.', array('%name' => $edit['title'])), format_string('The feed %name has been updated.', array('%name' => $edit['title'])));
// Check feed data.
Angie Byron
committed
$this->assertEqual($this->getUrl(), url('admin/config/services/aggregator/', array('absolute' => TRUE)));
Jennifer Hodgdon
committed
$this->assertTrue($this->uniqueFeed($edit['title'], $edit['url']), 'The feed is unique.');
// Check feed source.
$this->drupalGet('aggregator/sources/' . $feed->fid);
Jennifer Hodgdon
committed
$this->assertResponse(200, 'Feed source exists.');
$this->assertText($edit['title'], 'Page title');
// Delete feed.
$feed->title = $edit['title']; // Set correct title so deleteFeed() will work.
$this->deleteFeed($feed);
}
}
}
class RemoveFeedTestCase extends AggregatorTestCase {
Angie Byron
committed
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);
Jennifer Hodgdon
committed
$this->assertResponse(404, 'Deleted feed source does not exists.');
// Check database for feed.
Dries Buytaert
committed
$result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed->title, ':url' => $feed->url))->fetchField();
Jennifer Hodgdon
committed
$this->assertFalse($result, 'Feed not found in database');
}
}
class UpdateFeedItemTestCase extends AggregatorTestCase {
Angie Byron
committed
public static function getInfo() {
return array(
'name' => 'Update feed item functionality',
'description' => 'Update feed items from a feed.',
'group' => 'Aggregator'
);
}
/**
Angie Byron
committed
* 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']);
Jennifer Hodgdon
committed
$this->assertResponse(array(200), format_string('URL !url is accessible', array('!url' => $edit['url'])));
Angie Byron
committed
$this->drupalPost('admin/config/services/aggregator/add/feed', $edit, t('Save'));
Jennifer Hodgdon
committed
$this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title'])), format_string('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();
Dries Buytaert
committed
$before = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
// Sleep for 3 second.
sleep(3);
Dries Buytaert
committed
db_update('aggregator_feed')
->condition('fid', $feed->fid)
->fields(array(
'checked' => 0,
'hash' => '',
'etag' => '',
'modified' => 0,
))
->execute();
Dries Buytaert
committed
$after = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
Jennifer Hodgdon
committed
$this->assertTrue($before === $after, format_string('Publish timestamp of feed item was not updated (!before === !after)', array('!before' => $before, '!after' => $after)));
}
}
class RemoveFeedItemTestCase extends AggregatorTestCase {
Angie Byron
committed
public static function getInfo() {
return array(
'name' => 'Remove feed item functionality',
'description' => 'Remove feed items from a feed.',
'group' => 'Aggregator'
);
}
/**
Angie Byron
committed
* 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.
Angie Byron
committed
$this->updateAndRemove($feed, 4);
$this->updateAndRemove($feed, 4);
$this->updateAndRemove($feed, 4);
// Delete feed.
$this->deleteFeed($feed);
}
}
}
class CategorizeFeedItemTestCase extends AggregatorTestCase {
Angie Byron
committed
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();
Angie Byron
committed
// Simulate form submission on "admin/config/services/aggregator/add/category".
Dries Buytaert
committed
$edit = array('title' => $this->randomName(10), 'description' => '');
Angie Byron
committed
$this->drupalPost('admin/config/services/aggregator/add/category', $edit, t('Save'));
Jennifer Hodgdon
committed
$this->assertRaw(t('The category %title has been added.', array('%title' => $edit['title'])), format_string('The category %title has been added.', array('%title' => $edit['title'])));
Dries Buytaert
committed
$category = db_query("SELECT * FROM {aggregator_category} WHERE title = :title", array(':title' => $edit['title']))->fetch();
Jennifer Hodgdon
committed
$this->assertTrue(!empty($category), 'The category found in database.');
$link_path = 'aggregator/categories/' . $category->cid;
Dries Buytaert
committed
$menu_link = db_query("SELECT * FROM {menu_links} WHERE link_path = :link_path", array(':link_path' => $link_path))->fetch();
Jennifer Hodgdon
committed
$this->assertTrue(!empty($menu_link), '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);
Jennifer Hodgdon
committed
$this->assertTrue(!empty($feed->categories), '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) {
Dries Buytaert
committed
$categorized_count = db_select('aggregator_category_item')
->condition('iid', $feed->items, 'IN')
->countQuery()
->execute()
->fetchField();
Jennifer Hodgdon
committed
$this->assertEqual($feed->item_count, $categorized_count, 'Total items in feed equal to the total categorized feed items in database');
}
}
// Delete feed.
$this->deleteFeed($feed);
}
}
Dries Buytaert
committed
class ImportOPMLTestCase extends AggregatorTestCase {
Angie Byron
committed
public static function getInfo() {
Dries Buytaert
committed
return array(
'name' => 'Import feeds from OPML functionality',
'description' => 'Test OPML import.',
'group' => 'Aggregator',
Dries Buytaert
committed
);
}
/**
* Open OPML import form.
*/
function openImportForm() {
Dries Buytaert
committed
db_delete('aggregator_category')->execute();
Dries Buytaert
committed
Dries Buytaert
committed
$category = $this->randomName(10);
$cid = db_insert('aggregator_category')
Dries Buytaert
committed
->fields(array(
'title' => $category,
'description' => '',
))
->execute();
Dries Buytaert
committed
Angie Byron
committed
$this->drupalGet('admin/config/services/aggregator/add/opml');
Jennifer Hodgdon
committed
$this->assertText('A single OPML document may contain a collection of many feeds.', 'Found OPML help text.');
$this->assertField('files[upload]', 'Found file upload field.');
$this->assertField('remote', 'Found Remote URL field.');
$this->assertField('refresh', 'Found Refresh field.');
$this->assertFieldByName("category[$cid]", $cid, 'Found category field.');
Dries Buytaert
committed
}
/**
* Submit form filled with invalid fields.
*/
function validateImportFormFields() {
Dries Buytaert
committed
$before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
Dries Buytaert
committed
$edit = array();
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
Jennifer Hodgdon
committed
$this->assertRaw(t('You must <em>either</em> upload a file or enter a URL.'), 'Error if no fields are filled.');
Dries Buytaert
committed
$path = $this->getEmptyOpml();
$edit = array(
Dries Buytaert
committed
'files[upload]' => $path,
'remote' => file_create_url($path),
);
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
Jennifer Hodgdon
committed
$this->assertRaw(t('You must <em>either</em> upload a file or enter a URL.'), 'Error if both fields are filled.');
Dries Buytaert
committed
$edit = array('remote' => 'invalidUrl://empty');
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
Jennifer Hodgdon
committed
$this->assertText(t('This URL is not valid.'), 'Error if the URL is invalid.');
Dries Buytaert
committed
Dries Buytaert
committed
$after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
Jennifer Hodgdon
committed
$this->assertEqual($before, $after, 'No feeds were added during the three last form submissions.');
Dries Buytaert
committed
}
/**
* Submit form with invalid, empty and valid OPML files.
*/
function submitImportForm() {
Dries Buytaert
committed
$before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
Dries Buytaert
committed
$form['files[upload]'] = $this->getInvalidOpml();
Angie Byron
committed
$this->drupalPost('admin/config/services/aggregator/add/opml', $form, t('Import'));
Jennifer Hodgdon
committed
$this->assertText(t('No new feed has been added.'), 'Attempting to upload invalid XML.');
Dries Buytaert
committed
$edit = array('remote' => file_create_url($this->getEmptyOpml()));
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
Jennifer Hodgdon
committed
$this->assertText(t('No new feed has been added.'), 'Attempting to load empty OPML from remote URL.');
Dries Buytaert
committed
Dries Buytaert
committed
$after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
Jennifer Hodgdon
committed
$this->assertEqual($before, $after, 'No feeds were added during the two last form submissions.');
Dries Buytaert
committed
Dries Buytaert
committed
db_delete('aggregator_feed')->execute();
db_delete('aggregator_category')->execute();
db_delete('aggregator_category_feed')->execute();
Dries Buytaert
committed
Dries Buytaert
committed
$category = $this->randomName(10);
Dries Buytaert
committed
db_insert('aggregator_category')
->fields(array(
'cid' => 1,
'title' => $category,
'description' => '',
))
->execute();
Dries Buytaert
committed
$feeds[0] = $this->getFeedEditArray();
$feeds[1] = $this->getFeedEditArray();
$feeds[2] = $this->getFeedEditArray();
$edit = array(
Dries Buytaert
committed
'files[upload]' => $this->getValidOpml($feeds),
'refresh' => '900',
'category[1]' => $category,
);
$this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
Jennifer Hodgdon
committed
$this->assertRaw(t('A feed with the URL %url already exists.', array('%url' => $feeds[0]['url'])), 'Verifying that a duplicate URL was identified');
$this->assertRaw(t('A feed named %title already exists.', array('%title' => $feeds[1]['title'])), 'Verifying that a duplicate title was identified');
Dries Buytaert
committed
Dries Buytaert
committed
$after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
Jennifer Hodgdon
committed
$this->assertEqual($after, 2, 'Verifying that two distinct feeds were added.');
Dries Buytaert
committed
$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;
Dries Buytaert
committed
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;
Dries Buytaert
committed
}
Jennifer Hodgdon
committed
$this->assertEqual($title[$feeds[0]['url']], $feeds[0]['title'], 'First feed was added correctly.');
$this->assertEqual($url[$feeds[1]['title']], $feeds[1]['url'], 'Second feed was added correctly.');
$this->assertTrue($refresh, 'Refresh times are correct.');
$this->assertTrue($category, 'Categories are correct.');
Dries Buytaert
committed
}
function testOPMLImport() {
$this->openImportForm();
$this->validateImportFormFields();
$this->submitImportForm();
}
}
Angie Byron
committed
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
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 = variable_get('cron_key', 'drupal');
$this->createSampleNodes();
$feed = $this->createFeed();
$this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key)));
$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->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key)));
$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->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key)));
$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->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key)));
$this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
}
}
Dries Buytaert
committed
Dries Buytaert
committed
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
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;
Dries Buytaert
committed
// 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.');
Dries Buytaert
committed
// Position it.
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
Jennifer Hodgdon
committed
$this->assertText(t('The block settings have been updated.'), format_string('Block successfully moved to %region_name region.', array( '%region_name' => $region)));
Dries Buytaert
committed
// Confirm that the block is now being displayed on pages.
$this->drupalGet('node');
Jennifer Hodgdon
committed
$this->assertText(t($block['title']), 'Feed block is displayed on the page.');
Dries Buytaert
committed
// Find the expected read_more link.
$href = 'aggregator/sources/' . $feed->fid;
$links = $this->xpath('//a[@href = :href]', array(':href' => url($href)));
Jennifer Hodgdon
committed
$this->assert(isset($links[0]), format_string('Link to href %href found.', array('%href' => $href)));
Dries Buytaert
committed
// Visit that page.
$this->drupalGet($href);
$correct_titles = $this->xpath('//h1[normalize-space(text())=:title]', array(':title' => $feed->title));
Jennifer Hodgdon
committed
$this->assertFalse(empty($correct_titles), 'Aggregator feed page is available and has the correct title.');
Angie Byron
committed
// 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.
drupal_flush_all_caches();
// 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.');
Dries Buytaert
committed
}
Angie Byron
committed
/**
* 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.
variable_set('feed_default_items', 30);
// 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'));
Jennifer Hodgdon
committed
$this->assertTrue(!empty($elements), 'Individual source page contains a pager.');
Angie Byron
committed
// Reset the number of items in rss.xml to the default value.
variable_set('feed_default_items', 10);
}
Dries Buytaert
committed
}
Dries Buytaert
committed
/**
* Tests for feed parsing.
*/
class FeedParserTestCase extends AggregatorTestCase {
public static function getInfo() {
Dries Buytaert
committed
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);
Jennifer Hodgdon
committed
$this->assertResponse(200, format_string('Feed %name exists.', array('%name' => $feed->title)));
Dries Buytaert
committed
$this->assertText('First example feed item title');
$this->assertLinkByHref('http://example.com/example-turns-one');
$this->assertText('First example feed item description.');
Angie Byron
committed
// Several additional items that include elements over 255 characters.
$this->assertRaw("Second example feed item title.");
$this->assertText('Long link feed item title');
$this->assertText('Long link feed item description');
$this->assertLinkByHref('http://example.com/tomorrow/and/tomorrow/and/tomorrow/creeps/in/this/petty/pace/from/day/to/day/to/the/last/syllable/of/recorded/time/and/all/our/yesterdays/have/lighted/fools/the/way/to/dusty/death/out/out/brief/candle/life/is/but/a/walking/shadow/a/poor/player/that/struts/and/frets/his/hour/upon/the/stage/and/is/heard/no/more/it/is/a/tale/told/by/an/idiot/full/of/sound/and/fury/signifying/nothing');
$this->assertText('Long author feed item title');
$this->assertText('Long author feed item description');
$this->assertLinkByHref('http://example.com/long/author');
Dries Buytaert
committed
}
/**
* Test a feed that uses the Atom format.
*/
function testAtomSample() {
$feed = $this->createFeed($this->getAtomSample());
aggregator_refresh($feed);
$this->drupalGet('aggregator/sources/' . $feed->fid);
Jennifer Hodgdon
committed
$this->assertResponse(200, format_string('Feed %name exists.', array('%name' => $feed->title)));
Dries Buytaert
committed
$this->assertText('Atom-Powered Robots Run Amok');
$this->assertLinkByHref('http://example.org/2003/12/13/atom03');
$this->assertText('Some text.');
Dries Buytaert
committed
$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.');