cms/drupal/modules/aggregator/aggregator.test
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * @file
       
     5  * Tests for aggregator.module.
       
     6  */
       
     7 
       
     8 /**
       
     9  * Defines a base class for testing the Aggregator module.
       
    10  */
       
    11 class AggregatorTestCase extends DrupalWebTestCase {
       
    12   function setUp() {
       
    13     parent::setUp('aggregator', 'aggregator_test');
       
    14     $web_user = $this->drupalCreateUser(array('administer news feeds', 'access news feeds', 'create article content'));
       
    15     $this->drupalLogin($web_user);
       
    16   }
       
    17 
       
    18   /**
       
    19    * Creates an aggregator feed.
       
    20    *
       
    21    * This method simulates the form submission on path
       
    22    * admin/config/services/aggregator/add/feed.
       
    23    *
       
    24    * @param $feed_url
       
    25    *   (optional) If given, feed will be created with this URL, otherwise
       
    26    *   /rss.xml will be used. Defaults to NULL.
       
    27    *
       
    28    * @return $feed
       
    29    *   Full feed object if possible.
       
    30    *
       
    31    * @see getFeedEditArray()
       
    32    */
       
    33   function createFeed($feed_url = NULL) {
       
    34     $edit = $this->getFeedEditArray($feed_url);
       
    35     $this->drupalPost('admin/config/services/aggregator/add/feed', $edit, t('Save'));
       
    36     $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'])));
       
    37 
       
    38     $feed = db_query("SELECT *  FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $edit['title'], ':url' => $edit['url']))->fetch();
       
    39     $this->assertTrue(!empty($feed), 'The feed found in database.');
       
    40     return $feed;
       
    41   }
       
    42 
       
    43   /**
       
    44    * Deletes an aggregator feed.
       
    45    *
       
    46    * @param $feed
       
    47    *   Feed object representing the feed.
       
    48    */
       
    49   function deleteFeed($feed) {
       
    50     $this->drupalPost('admin/config/services/aggregator/edit/feed/' . $feed->fid, array(), t('Delete'));
       
    51     $this->assertRaw(t('The feed %title has been deleted.', array('%title' => $feed->title)), 'Feed deleted successfully.');
       
    52   }
       
    53 
       
    54   /**
       
    55    * Returns a randomly generated feed edit array.
       
    56    *
       
    57    * @param $feed_url
       
    58    *   (optional) If given, feed will be created with this URL, otherwise
       
    59    *   /rss.xml will be used. Defaults to NULL.
       
    60    * @return
       
    61    *   A feed array.
       
    62    */
       
    63   function getFeedEditArray($feed_url = NULL) {
       
    64     $feed_name = $this->randomName(10);
       
    65     if (!$feed_url) {
       
    66       $feed_url = url('rss.xml', array(
       
    67         'query' => array('feed' => $feed_name),
       
    68         'absolute' => TRUE,
       
    69       ));
       
    70     }
       
    71     $edit = array(
       
    72       'title' => $feed_name,
       
    73       'url' => $feed_url,
       
    74       'refresh' => '900',
       
    75     );
       
    76     return $edit;
       
    77   }
       
    78 
       
    79   /**
       
    80    * Returns the count of the randomly created feed array.
       
    81    *
       
    82    * @return
       
    83    *   Number of feed items on default feed created by createFeed().
       
    84    */
       
    85   function getDefaultFeedItemCount() {
       
    86     // Our tests are based off of rss.xml, so let's find out how many elements should be related.
       
    87     $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();
       
    88     return $feed_count > 10 ? 10 : $feed_count;
       
    89   }
       
    90 
       
    91   /**
       
    92    * Updates the feed items.
       
    93    *
       
    94    * This method simulates a click to
       
    95    * admin/config/services/aggregator/update/$fid.
       
    96    *
       
    97    * @param $feed
       
    98    *   Feed object representing the feed, passed by reference.
       
    99    * @param $expected_count
       
   100    *   Expected number of feed items.
       
   101    */
       
   102   function updateFeedItems(&$feed, $expected_count) {
       
   103     // First, let's ensure we can get to the rss xml.
       
   104     $this->drupalGet($feed->url);
       
   105     $this->assertResponse(200, format_string('!url is reachable.', array('!url' => $feed->url)));
       
   106 
       
   107     // Attempt to access the update link directly without an access token.
       
   108     $this->drupalGet('admin/config/services/aggregator/update/' . $feed->fid);
       
   109     $this->assertResponse(403);
       
   110 
       
   111     // Refresh the feed (simulated link click).
       
   112     $this->drupalGet('admin/config/services/aggregator');
       
   113     $this->clickLink('update items');
       
   114 
       
   115     // Ensure we have the right number of items.
       
   116     $result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid));
       
   117     $items = array();
       
   118     $feed->items = array();
       
   119     foreach ($result as $item) {
       
   120       $feed->items[] = $item->iid;
       
   121     }
       
   122     $feed->item_count = count($feed->items);
       
   123     $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)));
       
   124   }
       
   125 
       
   126   /**
       
   127    * Confirms an item removal from a feed.
       
   128    *
       
   129    * @param $feed
       
   130    *   Feed object representing the feed.
       
   131    */
       
   132   function removeFeedItems($feed) {
       
   133     $this->drupalPost('admin/config/services/aggregator/remove/' . $feed->fid, array(), t('Remove items'));
       
   134     $this->assertRaw(t('The news items from %title have been removed.', array('%title' => $feed->title)), 'Feed items removed.');
       
   135   }
       
   136 
       
   137   /**
       
   138    * Adds and removes feed items and ensure that the count is zero.
       
   139    *
       
   140    * @param $feed
       
   141    *   Feed object representing the feed.
       
   142    * @param $expected_count
       
   143    *   Expected number of feed items.
       
   144    */
       
   145   function updateAndRemove($feed, $expected_count) {
       
   146     $this->updateFeedItems($feed, $expected_count);
       
   147     $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
       
   148     $this->assertTrue($count);
       
   149     $this->removeFeedItems($feed);
       
   150     $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
       
   151     $this->assertTrue($count == 0);
       
   152   }
       
   153 
       
   154   /**
       
   155    * Pulls feed categories from {aggregator_category_feed} table.
       
   156    *
       
   157    * @param $feed
       
   158    *   Feed object representing the feed.
       
   159    */
       
   160   function getFeedCategories($feed) {
       
   161     // add the categories to the feed so we can use them
       
   162     $result = db_query('SELECT cid FROM {aggregator_category_feed} WHERE fid = :fid', array(':fid' => $feed->fid));
       
   163     foreach ($result as $category) {
       
   164       $feed->categories[] = $category->cid;
       
   165     }
       
   166   }
       
   167 
       
   168   /**
       
   169    * Pulls categories from {aggregator_category} table.
       
   170    *
       
   171    * @return
       
   172    *   An associative array keyed by category ID and values are set to the
       
   173    *   category names.
       
   174    */
       
   175   function getCategories() {
       
   176     $categories = array();
       
   177     $result = db_query('SELECT * FROM {aggregator_category}');
       
   178     foreach ($result as $category) {
       
   179       $categories[$category->cid] = $category;
       
   180     }
       
   181     return $categories;
       
   182   }
       
   183 
       
   184   /**
       
   185    * Checks whether the feed name and URL are unique.
       
   186    *
       
   187    * @param $feed_name
       
   188    *   String containing the feed name to check.
       
   189    * @param $feed_url
       
   190    *   String containing the feed URL to check.
       
   191    *
       
   192    * @return
       
   193    *   TRUE if feed is unique.
       
   194    */
       
   195   function uniqueFeed($feed_name, $feed_url) {
       
   196     $result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed_name, ':url' => $feed_url))->fetchField();
       
   197     return (1 == $result);
       
   198   }
       
   199 
       
   200   /**
       
   201    * Creates a valid OPML file from an array of feeds.
       
   202    *
       
   203    * @param $feeds
       
   204    *   An array of feeds.
       
   205    *
       
   206    * @return
       
   207    *   Path to valid OPML file.
       
   208    */
       
   209   function getValidOpml($feeds) {
       
   210     // Properly escape URLs so that XML parsers don't choke on them.
       
   211     foreach ($feeds as &$feed) {
       
   212       $feed['url'] = htmlspecialchars($feed['url']);
       
   213     }
       
   214     /**
       
   215      * Does not have an XML declaration, must pass the parser.
       
   216      */
       
   217     $opml = <<<EOF
       
   218 <opml version="1.0">
       
   219   <head></head>
       
   220   <body>
       
   221     <!-- First feed to be imported. -->
       
   222     <outline text="{$feeds[0]['title']}" xmlurl="{$feeds[0]['url']}" />
       
   223 
       
   224     <!-- Second feed. Test string delimitation and attribute order. -->
       
   225     <outline xmlurl='{$feeds[1]['url']}' text='{$feeds[1]['title']}'/>
       
   226 
       
   227     <!-- Test for duplicate URL and title. -->
       
   228     <outline xmlurl="{$feeds[0]['url']}" text="Duplicate URL"/>
       
   229     <outline xmlurl="http://duplicate.title" text="{$feeds[1]['title']}"/>
       
   230 
       
   231     <!-- Test that feeds are only added with required attributes. -->
       
   232     <outline text="{$feeds[2]['title']}" />
       
   233     <outline xmlurl="{$feeds[2]['url']}" />
       
   234   </body>
       
   235 </opml>
       
   236 EOF;
       
   237 
       
   238     $path = 'public://valid-opml.xml';
       
   239     return file_unmanaged_save_data($opml, $path);
       
   240   }
       
   241 
       
   242   /**
       
   243    * Creates an invalid OPML file.
       
   244    *
       
   245    * @return
       
   246    *   Path to invalid OPML file.
       
   247    */
       
   248   function getInvalidOpml() {
       
   249     $opml = <<<EOF
       
   250 <opml>
       
   251   <invalid>
       
   252 </opml>
       
   253 EOF;
       
   254 
       
   255     $path = 'public://invalid-opml.xml';
       
   256     return file_unmanaged_save_data($opml, $path);
       
   257   }
       
   258 
       
   259   /**
       
   260    * Creates a valid but empty OPML file.
       
   261    *
       
   262    * @return
       
   263    *   Path to empty OPML file.
       
   264    */
       
   265   function getEmptyOpml() {
       
   266     $opml = <<<EOF
       
   267 <?xml version="1.0" encoding="utf-8"?>
       
   268 <opml version="1.0">
       
   269   <head></head>
       
   270   <body>
       
   271     <outline text="Sample text" />
       
   272     <outline text="Sample text" url="Sample URL" />
       
   273   </body>
       
   274 </opml>
       
   275 EOF;
       
   276 
       
   277     $path = 'public://empty-opml.xml';
       
   278     return file_unmanaged_save_data($opml, $path);
       
   279   }
       
   280 
       
   281   function getRSS091Sample() {
       
   282     return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_rss091.xml';
       
   283   }
       
   284 
       
   285   function getAtomSample() {
       
   286     // The content of this sample ATOM feed is based directly off of the
       
   287     // example provided in RFC 4287.
       
   288     return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_atom.xml';
       
   289   }
       
   290 
       
   291   function getHtmlEntitiesSample() {
       
   292     return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_title_entities.xml';
       
   293   }
       
   294 
       
   295   /**
       
   296    * Creates sample article nodes.
       
   297    *
       
   298    * @param $count
       
   299    *   (optional) The number of nodes to generate. Defaults to five.
       
   300    */
       
   301   function createSampleNodes($count = 5) {
       
   302     $langcode = LANGUAGE_NONE;
       
   303     // Post $count article nodes.
       
   304     for ($i = 0; $i < $count; $i++) {
       
   305       $edit = array();
       
   306       $edit['title'] = $this->randomName();
       
   307       $edit["body[$langcode][0][value]"] = $this->randomName();
       
   308       $this->drupalPost('node/add/article', $edit, t('Save'));
       
   309     }
       
   310   }
       
   311 }
       
   312 
       
   313 /**
       
   314  * Tests functionality of the configuration settings in the Aggregator module.
       
   315  */
       
   316 class AggregatorConfigurationTestCase extends AggregatorTestCase {
       
   317   public static function getInfo() {
       
   318     return array(
       
   319       'name' => 'Aggregator configuration',
       
   320       'description' => 'Test aggregator settings page.',
       
   321       'group' => 'Aggregator',
       
   322     );
       
   323   }
       
   324 
       
   325   /**
       
   326    * Tests the settings form to ensure the correct default values are used.
       
   327    */
       
   328   function testSettingsPage() {
       
   329     $edit = array(
       
   330       'aggregator_allowed_html_tags' => '<a>',
       
   331       'aggregator_summary_items' => 10,
       
   332       'aggregator_clear' => 3600,
       
   333       'aggregator_category_selector' => 'select',
       
   334       'aggregator_teaser_length' => 200,
       
   335     );
       
   336     $this->drupalPost('admin/config/services/aggregator/settings', $edit, t('Save configuration'));
       
   337     $this->assertText(t('The configuration options have been saved.'));
       
   338 
       
   339     foreach ($edit as $name => $value) {
       
   340       $this->assertFieldByName($name, $value, format_string('"@name" has correct default value.', array('@name' => $name)));
       
   341     }
       
   342   }
       
   343 }
       
   344 
       
   345 /**
       
   346  * Tests adding aggregator feeds.
       
   347  */
       
   348 class AddFeedTestCase extends AggregatorTestCase {
       
   349   public static function getInfo() {
       
   350     return array(
       
   351       'name' => 'Add feed functionality',
       
   352       'description' => 'Add feed test.',
       
   353       'group' => 'Aggregator'
       
   354     );
       
   355   }
       
   356 
       
   357   /**
       
   358    * Creates and ensures that a feed is unique, checks source, and deletes feed.
       
   359    */
       
   360   function testAddFeed() {
       
   361     $feed = $this->createFeed();
       
   362 
       
   363     // Check feed data.
       
   364     $this->assertEqual($this->getUrl(), url('admin/config/services/aggregator/add/feed', array('absolute' => TRUE)), 'Directed to correct url.');
       
   365     $this->assertTrue($this->uniqueFeed($feed->title, $feed->url), 'The feed is unique.');
       
   366 
       
   367     // Check feed source.
       
   368     $this->drupalGet('aggregator/sources/' . $feed->fid);
       
   369     $this->assertResponse(200, 'Feed source exists.');
       
   370     $this->assertText($feed->title, 'Page title');
       
   371     $this->drupalGet('aggregator/sources/' . $feed->fid . '/categorize');
       
   372     $this->assertResponse(200, 'Feed categorization page exists.');
       
   373 
       
   374     // Delete feed.
       
   375     $this->deleteFeed($feed);
       
   376   }
       
   377 
       
   378   /**
       
   379    * Tests feeds with very long URLs.
       
   380    */
       
   381   function testAddLongFeed() {
       
   382     // Create a feed with a URL of > 255 characters.
       
   383     $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";
       
   384     $feed = $this->createFeed($long_url);
       
   385 
       
   386     // Create a second feed of > 255 characters, where the only difference is
       
   387     // after the 255th character.
       
   388     $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";
       
   389     $feed_2 = $this->createFeed($long_url_2);
       
   390 
       
   391     // Check feed data.
       
   392     $this->assertTrue($this->uniqueFeed($feed->title, $feed->url), 'The first long URL feed is unique.');
       
   393     $this->assertTrue($this->uniqueFeed($feed_2->title, $feed_2->url), 'The second long URL feed is unique.');
       
   394 
       
   395     // Check feed source.
       
   396     $this->drupalGet('aggregator/sources/' . $feed->fid);
       
   397     $this->assertResponse(200, 'Long URL feed source exists.');
       
   398     $this->assertText($feed->title, 'Page title');
       
   399     $this->drupalGet('aggregator/sources/' . $feed->fid . '/categorize');
       
   400     $this->assertResponse(200, 'Long URL feed categorization page exists.');
       
   401 
       
   402     // Delete feeds.
       
   403     $this->deleteFeed($feed);
       
   404     $this->deleteFeed($feed_2);
       
   405   }
       
   406 }
       
   407 
       
   408 /**
       
   409  * Tests the categorize feed functionality in the Aggregator module.
       
   410  */
       
   411 class CategorizeFeedTestCase extends AggregatorTestCase {
       
   412   public static function getInfo() {
       
   413     return array(
       
   414       'name' => 'Categorize feed functionality',
       
   415       'description' => 'Categorize feed test.',
       
   416       'group' => 'Aggregator'
       
   417     );
       
   418   }
       
   419 
       
   420   /**
       
   421    * Creates a feed and makes sure you can add/delete categories to it.
       
   422    */
       
   423   function testCategorizeFeed() {
       
   424 
       
   425     // Create 2 categories.
       
   426     $category_1 = array('title' => $this->randomName(10), 'description' => '');
       
   427     $this->drupalPost('admin/config/services/aggregator/add/category', $category_1, t('Save'));
       
   428     $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'])));
       
   429 
       
   430     $category_2 = array('title' => $this->randomName(10), 'description' => '');
       
   431     $this->drupalPost('admin/config/services/aggregator/add/category', $category_2, t('Save'));
       
   432     $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'])));
       
   433 
       
   434     // Get categories from database.
       
   435     $categories = $this->getCategories();
       
   436 
       
   437     // Create a feed and assign 2 categories to it.
       
   438     $feed = $this->getFeedEditArray();
       
   439     $feed['block'] = 5;
       
   440     foreach ($categories as $cid => $category) {
       
   441       $feed['category'][$cid] = $cid;
       
   442     }
       
   443 
       
   444     // Use aggregator_save_feed() function to save the feed.
       
   445     aggregator_save_feed($feed);
       
   446     $db_feed = db_query("SELECT *  FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed['title'], ':url' => $feed['url']))->fetch();
       
   447 
       
   448     // Assert the feed has two categories.
       
   449     $this->getFeedCategories($db_feed);
       
   450     $this->assertEqual(count($db_feed->categories), 2, 'Feed has 2 categories');
       
   451 
       
   452     // Use aggregator_save_feed() to delete a category.
       
   453     $category = reset($categories);
       
   454     aggregator_save_category(array('cid' => $category->cid));
       
   455 
       
   456     // Assert that category is deleted.
       
   457     $db_category = db_query("SELECT COUNT(*) FROM {aggregator_category} WHERE cid = :cid", array(':cid' => $category->cid))->fetchField();
       
   458     $this->assertFalse($db_category, format_string('The category %title has been deleted.', array('%title' => $category->title)));
       
   459 
       
   460     // Assert that category has been removed from feed.
       
   461     $categorized_feeds = db_query("SELECT COUNT(*) FROM {aggregator_category_feed} WHERE cid = :cid", array(':cid' => $category->cid))->fetchField();
       
   462     $this->assertFalse($categorized_feeds, format_string('The category %title has been removed from feed %feed_title.', array('%title' => $category->title, '%feed_title' => $feed['title'])));
       
   463 
       
   464     // Assert that no broken links (associated with the deleted category)
       
   465     // appear on one of the other category pages.
       
   466     $this->createSampleNodes();
       
   467     $this->drupalGet('admin/config/services/aggregator');
       
   468     $this->clickLink('update items');
       
   469     $categories = $this->getCategories();
       
   470     $category = reset($categories);
       
   471     $this->drupalGet('aggregator/categories/' . $category->cid);
       
   472     global $base_path;
       
   473     $this->assertNoRaw('<a href="' . $base_path . 'aggregator/categories/"></a>,');
       
   474   }
       
   475 
       
   476 }
       
   477 
       
   478 /**
       
   479  * Tests functionality of updating the feed in the Aggregator module.
       
   480  */
       
   481 class UpdateFeedTestCase extends AggregatorTestCase {
       
   482   public static function getInfo() {
       
   483     return array(
       
   484       'name' => 'Update feed functionality',
       
   485       'description' => 'Update feed test.',
       
   486       'group' => 'Aggregator'
       
   487     );
       
   488   }
       
   489 
       
   490   /**
       
   491    * Creates a feed and attempts to update it.
       
   492    */
       
   493   function testUpdateFeed() {
       
   494     $remamining_fields = array('title', 'url', '');
       
   495     foreach ($remamining_fields as $same_field) {
       
   496       $feed = $this->createFeed();
       
   497 
       
   498       // Get new feed data array and modify newly created feed.
       
   499       $edit = $this->getFeedEditArray();
       
   500       $edit['refresh'] =  1800; // Change refresh value.
       
   501       if (isset($feed->{$same_field})) {
       
   502         $edit[$same_field] = $feed->{$same_field};
       
   503       }
       
   504       $this->drupalPost('admin/config/services/aggregator/edit/feed/' . $feed->fid, $edit, t('Save'));
       
   505       $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'])));
       
   506 
       
   507       // Check feed data.
       
   508       $this->assertEqual($this->getUrl(), url('admin/config/services/aggregator/', array('absolute' => TRUE)));
       
   509       $this->assertTrue($this->uniqueFeed($edit['title'], $edit['url']), 'The feed is unique.');
       
   510 
       
   511       // Check feed source.
       
   512       $this->drupalGet('aggregator/sources/' . $feed->fid);
       
   513       $this->assertResponse(200, 'Feed source exists.');
       
   514       $this->assertText($edit['title'], 'Page title');
       
   515 
       
   516       // Delete feed.
       
   517       $feed->title = $edit['title']; // Set correct title so deleteFeed() will work.
       
   518       $this->deleteFeed($feed);
       
   519     }
       
   520   }
       
   521 }
       
   522 
       
   523 /**
       
   524  * Tests functionality for removing feeds in the Aggregator module.
       
   525  */
       
   526 class RemoveFeedTestCase extends AggregatorTestCase {
       
   527   public static function getInfo() {
       
   528     return array(
       
   529       'name' => 'Remove feed functionality',
       
   530       'description' => 'Remove feed test.',
       
   531       'group' => 'Aggregator'
       
   532     );
       
   533   }
       
   534 
       
   535   /**
       
   536    * Removes a feed and ensures that all of its services are removed.
       
   537    */
       
   538   function testRemoveFeed() {
       
   539     $feed = $this->createFeed();
       
   540 
       
   541     // Delete feed.
       
   542     $this->deleteFeed($feed);
       
   543 
       
   544     // Check feed source.
       
   545     $this->drupalGet('aggregator/sources/' . $feed->fid);
       
   546     $this->assertResponse(404, 'Deleted feed source does not exists.');
       
   547 
       
   548     // Check database for feed.
       
   549     $result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed->title, ':url' => $feed->url))->fetchField();
       
   550     $this->assertFalse($result, 'Feed not found in database');
       
   551   }
       
   552 }
       
   553 
       
   554 /**
       
   555  * Tests functionality of updating a feed item in the Aggregator module.
       
   556  */
       
   557 class UpdateFeedItemTestCase extends AggregatorTestCase {
       
   558   public static function getInfo() {
       
   559     return array(
       
   560       'name' => 'Update feed item functionality',
       
   561       'description' => 'Update feed items from a feed.',
       
   562       'group' => 'Aggregator'
       
   563     );
       
   564   }
       
   565 
       
   566   /**
       
   567    * Tests running "update items" from 'admin/config/services/aggregator' page.
       
   568    */
       
   569   function testUpdateFeedItem() {
       
   570     $this->createSampleNodes();
       
   571 
       
   572     // Create a feed and test updating feed items if possible.
       
   573     $feed = $this->createFeed();
       
   574     if (!empty($feed)) {
       
   575       $this->updateFeedItems($feed, $this->getDefaultFeedItemCount());
       
   576       $this->removeFeedItems($feed);
       
   577     }
       
   578 
       
   579     // Delete feed.
       
   580     $this->deleteFeed($feed);
       
   581 
       
   582     // Test updating feed items without valid timestamp information.
       
   583     $edit = array(
       
   584       'title' => "Feed without publish timestamp",
       
   585       'url' => $this->getRSS091Sample(),
       
   586     );
       
   587 
       
   588     $this->drupalGet($edit['url']);
       
   589     $this->assertResponse(array(200), format_string('URL !url is accessible', array('!url' => $edit['url'])));
       
   590 
       
   591     $this->drupalPost('admin/config/services/aggregator/add/feed', $edit, t('Save'));
       
   592     $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'])));
       
   593 
       
   594     $feed = db_query("SELECT * FROM {aggregator_feed} WHERE url = :url", array(':url' => $edit['url']))->fetchObject();
       
   595 
       
   596     aggregator_refresh($feed);
       
   597     $before = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
       
   598 
       
   599     // Sleep for 3 second.
       
   600     sleep(3);
       
   601     db_update('aggregator_feed')
       
   602       ->condition('fid', $feed->fid)
       
   603       ->fields(array(
       
   604         'checked' => 0,
       
   605         'hash' => '',
       
   606         'etag' => '',
       
   607         'modified' => 0,
       
   608       ))
       
   609       ->execute();
       
   610     aggregator_refresh($feed);
       
   611 
       
   612     $after = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
       
   613     $this->assertTrue($before === $after, format_string('Publish timestamp of feed item was not updated (!before === !after)', array('!before' => $before, '!after' => $after)));
       
   614   }
       
   615 }
       
   616 
       
   617 class RemoveFeedItemTestCase extends AggregatorTestCase {
       
   618   public static function getInfo() {
       
   619     return array(
       
   620       'name' => 'Remove feed item functionality',
       
   621       'description' => 'Remove feed items from a feed.',
       
   622       'group' => 'Aggregator'
       
   623     );
       
   624   }
       
   625 
       
   626   /**
       
   627    * Tests running "remove items" from 'admin/config/services/aggregator' page.
       
   628    */
       
   629   function testRemoveFeedItem() {
       
   630     // Create a bunch of test feeds.
       
   631     $feed_urls = array();
       
   632     // No last-modified, no etag.
       
   633     $feed_urls[] = url('aggregator/test-feed', array('absolute' => TRUE));
       
   634     // Last-modified, but no etag.
       
   635     $feed_urls[] = url('aggregator/test-feed/1', array('absolute' => TRUE));
       
   636     // No Last-modified, but etag.
       
   637     $feed_urls[] = url('aggregator/test-feed/0/1', array('absolute' => TRUE));
       
   638     // Last-modified and etag.
       
   639     $feed_urls[] = url('aggregator/test-feed/1/1', array('absolute' => TRUE));
       
   640 
       
   641     foreach ($feed_urls as $feed_url) {
       
   642       $feed = $this->createFeed($feed_url);
       
   643       // Update and remove items two times in a row to make sure that removal
       
   644       // resets all 'modified' information (modified, etag, hash) and allows for
       
   645       // immediate update.
       
   646       $this->updateAndRemove($feed, 4);
       
   647       $this->updateAndRemove($feed, 4);
       
   648       $this->updateAndRemove($feed, 4);
       
   649       // Delete feed.
       
   650       $this->deleteFeed($feed);
       
   651     }
       
   652   }
       
   653 }
       
   654 
       
   655 /**
       
   656  * Tests categorization functionality in the Aggregator module.
       
   657  */
       
   658 class CategorizeFeedItemTestCase extends AggregatorTestCase {
       
   659   public static function getInfo() {
       
   660     return array(
       
   661       'name' => 'Categorize feed item functionality',
       
   662       'description' => 'Test feed item categorization.',
       
   663       'group' => 'Aggregator'
       
   664     );
       
   665   }
       
   666 
       
   667   /**
       
   668    * Checks that children of a feed inherit a defined category.
       
   669    *
       
   670    * If a feed has a category, make sure that the children inherit that
       
   671    * categorization.
       
   672    */
       
   673   function testCategorizeFeedItem() {
       
   674     $this->createSampleNodes();
       
   675 
       
   676     // Simulate form submission on "admin/config/services/aggregator/add/category".
       
   677     $edit = array('title' => $this->randomName(10), 'description' => '');
       
   678     $this->drupalPost('admin/config/services/aggregator/add/category', $edit, t('Save'));
       
   679     $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'])));
       
   680 
       
   681     $category = db_query("SELECT * FROM {aggregator_category} WHERE title = :title", array(':title' => $edit['title']))->fetch();
       
   682     $this->assertTrue(!empty($category), 'The category found in database.');
       
   683 
       
   684     $link_path = 'aggregator/categories/' . $category->cid;
       
   685     $menu_link = db_query("SELECT * FROM {menu_links} WHERE link_path = :link_path", array(':link_path' => $link_path))->fetch();
       
   686     $this->assertTrue(!empty($menu_link), 'The menu link associated with the category found in database.');
       
   687 
       
   688     $feed = $this->createFeed();
       
   689     db_insert('aggregator_category_feed')
       
   690       ->fields(array(
       
   691         'cid' => $category->cid,
       
   692         'fid' => $feed->fid,
       
   693       ))
       
   694       ->execute();
       
   695     $this->updateFeedItems($feed, $this->getDefaultFeedItemCount());
       
   696     $this->getFeedCategories($feed);
       
   697     $this->assertTrue(!empty($feed->categories), 'The category found in the feed.');
       
   698 
       
   699     // For each category of a feed, ensure feed items have that category, too.
       
   700     if (!empty($feed->categories) && !empty($feed->items)) {
       
   701       foreach ($feed->categories as $category) {
       
   702         $categorized_count = db_select('aggregator_category_item')
       
   703           ->condition('iid', $feed->items, 'IN')
       
   704           ->countQuery()
       
   705           ->execute()
       
   706           ->fetchField();
       
   707 
       
   708         $this->assertEqual($feed->item_count, $categorized_count, 'Total items in feed equal to the total categorized feed items in database');
       
   709       }
       
   710     }
       
   711 
       
   712     // Delete category from feed items when category is deleted.
       
   713     $cid = reset($feed->categories);
       
   714     $categories = $this->getCategories();
       
   715     $category_title = $categories[$cid]->title;
       
   716 
       
   717     // Delete category.
       
   718     aggregator_save_category(array('cid' => $cid));
       
   719 
       
   720     // Assert category has been removed from feed items.
       
   721     $categorized_count = db_query("SELECT COUNT(*) FROM {aggregator_category_item} WHERE cid = :cid", array(':cid' => $cid))->fetchField();
       
   722     $this->assertFalse($categorized_count, format_string('The category %title has been removed from feed items.', array('%title' => $category_title)));
       
   723     // Delete feed.
       
   724     $this->deleteFeed($feed);
       
   725   }
       
   726 
       
   727 }
       
   728 
       
   729 /**
       
   730  * Tests importing feeds from OPML functionality for the Aggregator module.
       
   731  */
       
   732 class ImportOPMLTestCase extends AggregatorTestCase {
       
   733   public static function getInfo() {
       
   734     return array(
       
   735       'name' => 'Import feeds from OPML functionality',
       
   736       'description' => 'Test OPML import.',
       
   737       'group' => 'Aggregator',
       
   738     );
       
   739   }
       
   740 
       
   741   /**
       
   742    * Opens OPML import form.
       
   743    */
       
   744   function openImportForm() {
       
   745     db_delete('aggregator_category')->execute();
       
   746 
       
   747     $category = $this->randomName(10);
       
   748     $cid = db_insert('aggregator_category')
       
   749       ->fields(array(
       
   750         'title' => $category,
       
   751         'description' => '',
       
   752       ))
       
   753       ->execute();
       
   754 
       
   755     $this->drupalGet('admin/config/services/aggregator/add/opml');
       
   756     $this->assertText('A single OPML document may contain a collection of many feeds.', 'Found OPML help text.');
       
   757     $this->assertField('files[upload]', 'Found file upload field.');
       
   758     $this->assertField('remote', 'Found Remote URL field.');
       
   759     $this->assertField('refresh', 'Found Refresh field.');
       
   760     $this->assertFieldByName("category[$cid]", $cid, 'Found category field.');
       
   761   }
       
   762 
       
   763   /**
       
   764    * Submits form filled with invalid fields.
       
   765    */
       
   766   function validateImportFormFields() {
       
   767     $before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
       
   768 
       
   769     $edit = array();
       
   770     $this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
       
   771     $this->assertRaw(t('You must <em>either</em> upload a file or enter a URL.'), 'Error if no fields are filled.');
       
   772 
       
   773     $path = $this->getEmptyOpml();
       
   774     $edit = array(
       
   775       'files[upload]' => $path,
       
   776       'remote' => file_create_url($path),
       
   777     );
       
   778     $this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
       
   779     $this->assertRaw(t('You must <em>either</em> upload a file or enter a URL.'), 'Error if both fields are filled.');
       
   780 
       
   781     $edit = array('remote' => 'invalidUrl://empty');
       
   782     $this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
       
   783     $this->assertText(t('This URL is not valid.'), 'Error if the URL is invalid.');
       
   784 
       
   785     $after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
       
   786     $this->assertEqual($before, $after, 'No feeds were added during the three last form submissions.');
       
   787   }
       
   788 
       
   789   /**
       
   790    * Submits form with invalid, empty, and valid OPML files.
       
   791    */
       
   792   function submitImportForm() {
       
   793     $before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
       
   794 
       
   795     $form['files[upload]'] = $this->getInvalidOpml();
       
   796     $this->drupalPost('admin/config/services/aggregator/add/opml', $form, t('Import'));
       
   797     $this->assertText(t('No new feed has been added.'), 'Attempting to upload invalid XML.');
       
   798 
       
   799     $edit = array('remote' => file_create_url($this->getEmptyOpml()));
       
   800     $this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
       
   801     $this->assertText(t('No new feed has been added.'), 'Attempting to load empty OPML from remote URL.');
       
   802 
       
   803     $after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
       
   804     $this->assertEqual($before, $after, 'No feeds were added during the two last form submissions.');
       
   805 
       
   806     db_delete('aggregator_feed')->execute();
       
   807     db_delete('aggregator_category')->execute();
       
   808     db_delete('aggregator_category_feed')->execute();
       
   809 
       
   810     $category = $this->randomName(10);
       
   811     db_insert('aggregator_category')
       
   812       ->fields(array(
       
   813         'cid' => 1,
       
   814         'title' => $category,
       
   815         'description' => '',
       
   816       ))
       
   817       ->execute();
       
   818 
       
   819     $feeds[0] = $this->getFeedEditArray();
       
   820     $feeds[1] = $this->getFeedEditArray();
       
   821     $feeds[2] = $this->getFeedEditArray();
       
   822     $edit = array(
       
   823       'files[upload]' => $this->getValidOpml($feeds),
       
   824       'refresh'       => '900',
       
   825       'category[1]'   => $category,
       
   826     );
       
   827     $this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
       
   828     $this->assertRaw(t('A feed with the URL %url already exists.', array('%url' => $feeds[0]['url'])), 'Verifying that a duplicate URL was identified');
       
   829     $this->assertRaw(t('A feed named %title already exists.', array('%title' => $feeds[1]['title'])), 'Verifying that a duplicate title was identified');
       
   830 
       
   831     $after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
       
   832     $this->assertEqual($after, 2, 'Verifying that two distinct feeds were added.');
       
   833 
       
   834     $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");
       
   835     $refresh = $category = TRUE;
       
   836     foreach ($feeds_from_db as $feed) {
       
   837       $title[$feed->url] = $feed->title;
       
   838       $url[$feed->title] = $feed->url;
       
   839       $category = $category && $feed->cid == 1;
       
   840       $refresh = $refresh && $feed->refresh == 900;
       
   841     }
       
   842 
       
   843     $this->assertEqual($title[$feeds[0]['url']], $feeds[0]['title'], 'First feed was added correctly.');
       
   844     $this->assertEqual($url[$feeds[1]['title']], $feeds[1]['url'], 'Second feed was added correctly.');
       
   845     $this->assertTrue($refresh, 'Refresh times are correct.');
       
   846     $this->assertTrue($category, 'Categories are correct.');
       
   847   }
       
   848 
       
   849   /**
       
   850    * Tests the import of an OPML file.
       
   851    */
       
   852   function testOPMLImport() {
       
   853     $this->openImportForm();
       
   854     $this->validateImportFormFields();
       
   855     $this->submitImportForm();
       
   856   }
       
   857 }
       
   858 
       
   859 /**
       
   860  * Tests functionality of the cron process in the Aggregator module.
       
   861  */
       
   862 class AggregatorCronTestCase extends AggregatorTestCase {
       
   863   public static function getInfo() {
       
   864     return array(
       
   865       'name' => 'Update on cron functionality',
       
   866       'description' => 'Update feeds on cron.',
       
   867       'group' => 'Aggregator'
       
   868     );
       
   869   }
       
   870 
       
   871   /**
       
   872    * Adds feeds and updates them via cron process.
       
   873    */
       
   874   public function testCron() {
       
   875     // Create feed and test basic updating on cron.
       
   876     global $base_url;
       
   877     $key = variable_get('cron_key', 'drupal');
       
   878     $this->createSampleNodes();
       
   879     $feed = $this->createFeed();
       
   880     $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key)));
       
   881     $this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
       
   882     $this->removeFeedItems($feed);
       
   883     $this->assertEqual(0, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
       
   884     $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key)));
       
   885     $this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
       
   886 
       
   887     // Test feed locking when queued for update.
       
   888     $this->removeFeedItems($feed);
       
   889     db_update('aggregator_feed')
       
   890       ->condition('fid', $feed->fid)
       
   891       ->fields(array(
       
   892         'queued' => REQUEST_TIME,
       
   893       ))
       
   894       ->execute();
       
   895     $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key)));
       
   896     $this->assertEqual(0, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
       
   897     db_update('aggregator_feed')
       
   898       ->condition('fid', $feed->fid)
       
   899       ->fields(array(
       
   900         'queued' => 0,
       
   901       ))
       
   902       ->execute();
       
   903     $this->drupalGet($base_url . '/cron.php', array('external' => TRUE, 'query' => array('cron_key' => $key)));
       
   904     $this->assertEqual(5, db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(), 'Expected number of items in database.');
       
   905   }
       
   906 }
       
   907 
       
   908 /**
       
   909  * Tests rendering functionality in the Aggregator module.
       
   910  */
       
   911 class AggregatorRenderingTestCase extends AggregatorTestCase {
       
   912   public static function getInfo() {
       
   913     return array(
       
   914       'name' => 'Checks display of aggregator items',
       
   915       'description' => 'Checks display of aggregator items on the page.',
       
   916       'group' => 'Aggregator'
       
   917     );
       
   918   }
       
   919 
       
   920   /**
       
   921    * Adds a feed block to the page and checks its links.
       
   922    *
       
   923    * @todo Test the category block as well.
       
   924    */
       
   925   public function testBlockLinks() {
       
   926     // Create feed.
       
   927     $this->createSampleNodes();
       
   928     $feed = $this->createFeed();
       
   929     $this->updateFeedItems($feed, $this->getDefaultFeedItemCount());
       
   930 
       
   931     // Place block on page (@see block.test:moveBlockToRegion())
       
   932     // Need admin user to be able to access block admin.
       
   933     $this->admin_user = $this->drupalCreateUser(array(
       
   934       'administer blocks',
       
   935       'access administration pages',
       
   936       'administer news feeds',
       
   937       'access news feeds',
       
   938     ));
       
   939     $this->drupalLogin($this->admin_user);
       
   940 
       
   941     // Prepare to use the block admin form.
       
   942     $block = array(
       
   943       'module' => 'aggregator',
       
   944       'delta' => 'feed-' . $feed->fid,
       
   945       'title' => $feed->title,
       
   946     );
       
   947     $region = 'footer';
       
   948     $edit = array();
       
   949     $edit['blocks[' . $block['module'] . '_' . $block['delta'] . '][region]'] = $region;
       
   950     // Check the feed block is available in the block list form.
       
   951     $this->drupalGet('admin/structure/block');
       
   952     $this->assertFieldByName('blocks[' . $block['module'] . '_' . $block['delta'] . '][region]', '', 'Aggregator feed block is available for positioning.');
       
   953     // Position it.
       
   954     $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
       
   955     $this->assertText(t('The block settings have been updated.'), format_string('Block successfully moved to %region_name region.', array( '%region_name' => $region)));
       
   956     // Confirm that the block is now being displayed on pages.
       
   957     $this->drupalGet('node');
       
   958     $this->assertText(t($block['title']), 'Feed block is displayed on the page.');
       
   959 
       
   960     // Find the expected read_more link.
       
   961     $href = 'aggregator/sources/' . $feed->fid;
       
   962     $links = $this->xpath('//a[@href = :href]', array(':href' => url($href)));
       
   963     $this->assert(isset($links[0]), format_string('Link to href %href found.', array('%href' => $href)));
       
   964 
       
   965     // Visit that page.
       
   966     $this->drupalGet($href);
       
   967     $correct_titles = $this->xpath('//h1[normalize-space(text())=:title]', array(':title' => $feed->title));
       
   968     $this->assertFalse(empty($correct_titles), 'Aggregator feed page is available and has the correct title.');
       
   969 
       
   970     // Set the number of news items to 0 to test that the block does not show
       
   971     // up.
       
   972     $feed->block = 0;
       
   973     aggregator_save_feed((array) $feed);
       
   974     // It is necessary to flush the cache after saving the number of items.
       
   975     drupal_flush_all_caches();
       
   976     // Check that the block is no longer displayed.
       
   977     $this->drupalGet('node');
       
   978     $this->assertNoText(t($block['title']), 'Feed block is not displayed on the page when number of items is set to 0.');
       
   979   }
       
   980 
       
   981   /**
       
   982    * Creates a feed and checks that feed's page.
       
   983    */
       
   984   public function testFeedPage() {
       
   985     // Increase the number of items published in the rss.xml feed so we have
       
   986     // enough articles to test paging.
       
   987     variable_set('feed_default_items', 30);
       
   988 
       
   989     // Create a feed with 30 items.
       
   990     $this->createSampleNodes(30);
       
   991     $feed = $this->createFeed();
       
   992     $this->updateFeedItems($feed, 30);
       
   993 
       
   994     // Check for the presence of a pager.
       
   995     $this->drupalGet('aggregator/sources/' . $feed->fid);
       
   996     $elements = $this->xpath("//ul[@class=:class]", array(':class' => 'pager'));
       
   997     $this->assertTrue(!empty($elements), 'Individual source page contains a pager.');
       
   998 
       
   999     // Reset the number of items in rss.xml to the default value.
       
  1000     variable_set('feed_default_items', 10);
       
  1001   }
       
  1002 }
       
  1003 
       
  1004 /**
       
  1005  * Tests feed parsing in the Aggregator module.
       
  1006  */
       
  1007 class FeedParserTestCase extends AggregatorTestCase {
       
  1008   public static function getInfo() {
       
  1009     return array(
       
  1010       'name' => 'Feed parser functionality',
       
  1011       'description' => 'Test the built-in feed parser with valid feed samples.',
       
  1012       'group' => 'Aggregator',
       
  1013     );
       
  1014   }
       
  1015 
       
  1016   function setUp() {
       
  1017     parent::setUp();
       
  1018     // Do not remove old aggregator items during these tests, since our sample
       
  1019     // feeds have hardcoded dates in them (which may be expired when this test
       
  1020     // is run).
       
  1021     variable_set('aggregator_clear', AGGREGATOR_CLEAR_NEVER);
       
  1022   }
       
  1023 
       
  1024   /**
       
  1025    * Tests a feed that uses the RSS 0.91 format.
       
  1026    */
       
  1027   function testRSS091Sample() {
       
  1028     $feed = $this->createFeed($this->getRSS091Sample());
       
  1029     aggregator_refresh($feed);
       
  1030     $this->drupalGet('aggregator/sources/' . $feed->fid);
       
  1031     $this->assertResponse(200, format_string('Feed %name exists.', array('%name' => $feed->title)));
       
  1032     $this->assertText('First example feed item title');
       
  1033     $this->assertLinkByHref('http://example.com/example-turns-one');
       
  1034     $this->assertText('First example feed item description.');
       
  1035 
       
  1036     // Several additional items that include elements over 255 characters.
       
  1037     $this->assertRaw("Second example feed item title.");
       
  1038     $this->assertText('Long link feed item title');
       
  1039     $this->assertText('Long link feed item description');
       
  1040     $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');
       
  1041     $this->assertText('Long author feed item title');
       
  1042     $this->assertText('Long author feed item description');
       
  1043     $this->assertLinkByHref('http://example.com/long/author');
       
  1044   }
       
  1045 
       
  1046   /**
       
  1047    * Tests a feed that uses the Atom format.
       
  1048    */
       
  1049   function testAtomSample() {
       
  1050     $feed = $this->createFeed($this->getAtomSample());
       
  1051     aggregator_refresh($feed);
       
  1052     $this->drupalGet('aggregator/sources/' . $feed->fid);
       
  1053     $this->assertResponse(200, format_string('Feed %name exists.', array('%name' => $feed->title)));
       
  1054     $this->assertText('Atom-Powered Robots Run Amok');
       
  1055     $this->assertLinkByHref('http://example.org/2003/12/13/atom03');
       
  1056     $this->assertText('Some text.');
       
  1057     $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.');
       
  1058   }
       
  1059 
       
  1060   /**
       
  1061    * Tests a feed that uses HTML entities in item titles.
       
  1062    */
       
  1063   function testHtmlEntitiesSample() {
       
  1064     $feed = $this->createFeed($this->getHtmlEntitiesSample());
       
  1065     aggregator_refresh($feed);
       
  1066     $this->drupalGet('aggregator/sources/' . $feed->fid);
       
  1067     $this->assertResponse(200, format_string('Feed %name exists.', array('%name' => $feed->title)));
       
  1068     $this->assertRaw("Quote&quot; Amp&amp;");
       
  1069   }
       
  1070 }