• FM Gizmo

    Field Marketing Made Easier Than Ever
    Accelerate your business

    Features that put you ahead of your competitors
    Entirely Personalized

    Tailor-made solutions to optimise your growth
    Better Business Results

    Interactive Live Dashboards on any device
    Impress your customers

    Quick reporting for improved decision making

Contact Us

FM Gizmo

 

Field Marketing Made Easier Than Ever

 

 

 

 

What is FM Gizmo?

FMGizmo is an easy-to-use cloud-based system with a user-friendly mobile app for the field team. It helps you in managing Field Marketing Activities efficiently.

All data captured by your field team is uploaded to the FMGizmo Cloud instantly. No hassles of paperwork, emails or messaging! FM Gizmo provides interactive dashboards and customised reports that make you shine in front of your Clients. Now, you and your Clients can not only monitor the activity in real-time but also take corrective actions swiftly, this ensures your activity is always aligned with the campaign objective.

Switch to FM Gizmo today and streamline your activity management process. Spend more time expanding your business rather than be consumed by the administrative tasks.

FM Gizmo Mobile App

 


User friendly

Our easy-to-use mobile app ensures your field teams can effortlessly adapt to FM Gizmo  

Zero Paperwork

With cloud technology, every significant detail recorded in the mobile app is uploaded to our reliable and secured cloud eliminating the need for paperwork.

Geotagged

Information collected on the FM Gizmo App is Timestamped and Geotagged

Collect, Analyze, Deliver

Collect your information in Real-time, Evaluate field operations and Deliver better results

Mobile Verification

FM Gizmo offers verification of Mobile numbers collected during the activity. This ensures the authenticity of data and limits the need for data auditing

Realtime

Data is collected and sent to the cloud in real-time. This ensures close monitoring of the activities undertaken.

The FM Gizmo Cloud

 


Interactive Dashboards

Wow your clients by giving them Interactive Dashboards as per their needs!

Customizable Reports

FM Gizmo offers completely customizable reporting to meet your exact needs.

Realtime Data

FM Gizmo delivers data in real-time allowing you to give timely feedback to your team and take corrective decisions instantly.

Workflow Integration

Integrate your routine processes directly into FM Gizmo. FM Gizmo is equipped with workflows like Recce thru Implementation, Accept-Reject-Redo and many more.

Reliable

With a well-managed service platform, FM Gizmo is much more reliable and consistent than any in-house IT infrastructure.

Scalable

You can easily increase or decrease your cloud capacity according to your requirement. You only pay for what you need.

Salient Features

 

Realtime Data

Easy to Use

Geotagged

 

Customizable

Reliable

Scalable

How does it work?

A Simple 5 step process

Choose your activity

Retail Seeding, Rural Market Activations, Branding, Merchandizing, BTL, Haat etc.

Create your team

Create logins for your field team and their managers. Optionally you can also assign the route plan for your field team.

Customize the app to match your requirements

Choose what data is required to be collected and you are ready to start your activity.

Choose your dashboards

Choose from our predefined dashboards templates or tell us what you need and we will create one for you.

Get set go

You are ready to start your activity and make your field activity management easier than ever.

EXPAND YOUR HORIZONS

Switch to Working Wisely

 

About Us

Solutions that Work

Whether you are a start-up or an MNC, we believe in providing tailor-made solutions that will give you a decisive edge over your competition

Experience Matters

With our extensive expertise in market research  and related mobility solutions, we offer you a platform that delivers

 

Cost Effective

FM Gizmo is a cost-effective solution that also brings down your activity management overheads considerably

 

Strong Support

Our dedicated support team ensures your field team can reach out to us if they ever face any difficulties on the field

 

 

So why wait, order FM Gizmo now and switch to working wisely!

Contact Us

About FM Gizmo

FM Gizmo is a one-stop field marketing solution.

FM Gizmo's customizability can help you fulfil all your field activity needs.

Order FM Gizmo now and Switch to working wisely.

Get In Touch

912, Opal Square, Wagle Estate, Thane(W) - 400604, Maharashtra

sales@fmgizmo.com

Contact
AnonSec Shell
AnonSec Shell
Server IP : 158.69.222.254  /  Your IP : 216.73.216.235   [ Reverse IP ]
Web Server : nginx/1.12.2
System : Linux vps63628.vps.ovh.ca 3.10.0-957.27.2.el7.x86_64 #1 SMP Mon Jul 29 17:46:05 UTC 2019 x86_64
User : webadmin ( 1001)
PHP Version : 7.3.19
Disable Function : NONE
Domains : 5 Domains
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/www/html/yaymek/modules/aggregator/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     [ BACKUP SHELL ]     [ JUMPING ]     [ MASS DEFACE ]     [ SCAN ROOT ]     [ SYMLINK ]     

Current File : /var/www/html/yaymek/modules/aggregator/aggregator.test
<?php

/**
 * @file
 * Tests for aggregator.module.
 */

/**
 * Defines a base class for testing the 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);
  }

  /**
   * Creates an aggregator feed.
   *
   * This method simulates the form submission on path
   * admin/config/services/aggregator/add/feed.
   *
   * @param $feed_url
   *   (optional) If given, feed will be created with this URL, otherwise
   *   /rss.xml will be used. Defaults to NULL.
   *
   * @return $feed
   *   Full feed object if possible.
   *
   * @see getFeedEditArray()
   */
  function createFeed($feed_url = NULL) {
    $edit = $this->getFeedEditArray($feed_url);
    $this->drupalPost('admin/config/services/aggregator/add/feed', $edit, t('Save'));
    $this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title'])), format_string('The feed !name has been added.', array('!name' => $edit['title'])));

    $feed = db_query("SELECT *  FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $edit['title'], ':url' => $edit['url']))->fetch();
    $this->assertTrue(!empty($feed), 'The feed found in database.');
    return $feed;
  }

  /**
   * Deletes an aggregator feed.
   *
   * @param $feed
   *   Feed object representing the feed.
   */
  function deleteFeed($feed) {
    $this->drupalPost('admin/config/services/aggregator/edit/feed/' . $feed->fid, array(), t('Delete'));
    $this->assertRaw(t('The feed %title has been deleted.', array('%title' => $feed->title)), 'Feed deleted successfully.');
  }

  /**
   * Returns a randomly generated feed edit array.
   *
   * @param $feed_url
   *   (optional) If given, feed will be created with this URL, otherwise
   *   /rss.xml will be used. Defaults to NULL.
   * @return
   *   A feed array.
   */
  function getFeedEditArray($feed_url = NULL) {
    $feed_name = $this->randomName(10);
    if (!$feed_url) {
      $feed_url = url('rss.xml', array(
        'query' => array('feed' => $feed_name),
        'absolute' => TRUE,
      ));
    }
    $edit = array(
      'title' => $feed_name,
      'url' => $feed_url,
      'refresh' => '900',
    );
    return $edit;
  }

  /**
   * Returns the count of the randomly created feed array.
   *
   * @return
   *   Number of feed items on default feed created by createFeed().
   */
  function getDefaultFeedItemCount() {
    // Our tests are based off of rss.xml, so let's find out how many elements should be related.
    $feed_count = db_query_range('SELECT COUNT(*) FROM {node} n WHERE n.promote = 1 AND n.status = 1', 0, variable_get('feed_default_items', 10))->fetchField();
    return $feed_count > 10 ? 10 : $feed_count;
  }

  /**
   * Updates the feed items.
   *
   * This method simulates a click to
   * admin/config/services/aggregator/update/$fid.
   *
   * @param $feed
   *   Feed object representing the feed, passed by reference.
   * @param $expected_count
   *   Expected number of feed items.
   */
  function updateFeedItems(&$feed, $expected_count) {
    // First, let's ensure we can get to the rss xml.
    $this->drupalGet($feed->url);
    $this->assertResponse(200, format_string('!url is reachable.', array('!url' => $feed->url)));

    // Attempt to access the update link directly without an access token.
    $this->drupalGet('admin/config/services/aggregator/update/' . $feed->fid);
    $this->assertResponse(403);

    // Refresh the feed (simulated link click).
    $this->drupalGet('admin/config/services/aggregator');
    $this->clickLink('update items');

    // Ensure we have the right number of items.
    $result = db_query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid));
    $items = array();
    $feed->items = array();
    foreach ($result as $item) {
      $feed->items[] = $item->iid;
    }
    $feed->item_count = count($feed->items);
    $this->assertEqual($expected_count, $feed->item_count, format_string('Total items in feed equal to the total items in database (!val1 != !val2)', array('!val1' => $expected_count, '!val2' => $feed->item_count)));
  }

  /**
   * Confirms an item removal from a feed.
   *
   * @param $feed
   *   Feed object representing the feed.
   */
  function removeFeedItems($feed) {
    $this->drupalPost('admin/config/services/aggregator/remove/' . $feed->fid, array(), t('Remove items'));
    $this->assertRaw(t('The news items from %title have been removed.', array('%title' => $feed->title)), 'Feed items removed.');
  }

  /**
   * Adds and removes feed items and ensure that the count is zero.
   *
   * @param $feed
   *   Feed object representing the feed.
   * @param $expected_count
   *   Expected number of feed items.
   */
  function updateAndRemove($feed, $expected_count) {
    $this->updateFeedItems($feed, $expected_count);
    $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
    $this->assertTrue($count);
    $this->removeFeedItems($feed);
    $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
    $this->assertTrue($count == 0);
  }

  /**
   * Pulls feed categories from {aggregator_category_feed} table.
   *
   * @param $feed
   *   Feed object representing the feed.
   */
  function getFeedCategories($feed) {
    // add the categories to the feed so we can use them
    $result = db_query('SELECT cid FROM {aggregator_category_feed} WHERE fid = :fid', array(':fid' => $feed->fid));
    foreach ($result as $category) {
      $feed->categories[] = $category->cid;
    }
  }

  /**
   * Pulls categories from {aggregator_category} table.
   *
   * @return
   *   An associative array keyed by category ID and values are set to the
   *   category names.
   */
  function getCategories() {
    $categories = array();
    $result = db_query('SELECT * FROM {aggregator_category}');
    foreach ($result as $category) {
      $categories[$category->cid] = $category;
    }
    return $categories;
  }

  /**
   * Checks whether the feed name and URL are unique.
   *
   * @param $feed_name
   *   String containing the feed name to check.
   * @param $feed_url
   *   String containing the feed URL to check.
   *
   * @return
   *   TRUE if feed is unique.
   */
  function uniqueFeed($feed_name, $feed_url) {
    $result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed_name, ':url' => $feed_url))->fetchField();
    return (1 == $result);
  }

  /**
   * Creates a valid OPML file from an array of feeds.
   *
   * @param $feeds
   *   An array of feeds.
   *
   * @return
   *   Path to valid OPML file.
   */
  function getValidOpml($feeds) {
    // Properly escape URLs so that XML parsers don't choke on them.
    foreach ($feeds as &$feed) {
      $feed['url'] = htmlspecialchars($feed['url']);
    }
    /**
     * Does not have an XML declaration, must pass the parser.
     */
    $opml = <<<EOF
<opml version="1.0">
  <head></head>
  <body>
    <!-- First feed to be imported. -->
    <outline text="{$feeds[0]['title']}" xmlurl="{$feeds[0]['url']}" />

    <!-- Second feed. Test string delimitation and attribute order. -->
    <outline xmlurl='{$feeds[1]['url']}' text='{$feeds[1]['title']}'/>

    <!-- Test for duplicate URL and title. -->
    <outline xmlurl="{$feeds[0]['url']}" text="Duplicate URL"/>
    <outline xmlurl="http://duplicate.title" text="{$feeds[1]['title']}"/>

    <!-- Test that feeds are only added with required attributes. -->
    <outline text="{$feeds[2]['title']}" />
    <outline xmlurl="{$feeds[2]['url']}" />
  </body>
</opml>
EOF;

    $path = 'public://valid-opml.xml';
    return file_unmanaged_save_data($opml, $path);
  }

  /**
   * Creates 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);
  }

  /**
   * Creates a valid but empty OPML file.
   *
   * @return
   *   Path to empty OPML file.
   */
  function getEmptyOpml() {
    $opml = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<opml version="1.0">
  <head></head>
  <body>
    <outline text="Sample text" />
    <outline text="Sample text" url="Sample URL" />
  </body>
</opml>
EOF;

    $path = 'public://empty-opml.xml';
    return file_unmanaged_save_data($opml, $path);
  }

  function getRSS091Sample() {
    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_rss091.xml';
  }

  function getAtomSample() {
    // The content of this sample ATOM feed is based directly off of the
    // example provided in RFC 4287.
    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_atom.xml';
  }

  function getHtmlEntitiesSample() {
    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_title_entities.xml';
  }

  /**
   * Creates sample article nodes.
   *
   * @param $count
   *   (optional) The number of nodes to generate. Defaults to five.
   */
  function createSampleNodes($count = 5) {
    $langcode = LANGUAGE_NONE;
    // Post $count article nodes.
    for ($i = 0; $i < $count; $i++) {
      $edit = array();
      $edit['title'] = $this->randomName();
      $edit["body[$langcode][0][value]"] = $this->randomName();
      $this->drupalPost('node/add/article', $edit, t('Save'));
    }
  }
}

/**
 * Tests functionality of the configuration settings in the Aggregator module.
 */
class AggregatorConfigurationTestCase extends AggregatorTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Aggregator configuration',
      'description' => 'Test aggregator settings page.',
      'group' => 'Aggregator',
    );
  }

  /**
   * Tests the settings form to ensure the correct default values are used.
   */
  function testSettingsPage() {
    $edit = array(
      'aggregator_allowed_html_tags' => '<a>',
      'aggregator_summary_items' => 10,
      'aggregator_clear' => 3600,
      'aggregator_category_selector' => 'select',
      'aggregator_teaser_length' => 200,
    );
    $this->drupalPost('admin/config/services/aggregator/settings', $edit, t('Save configuration'));
    $this->assertText(t('The configuration options have been saved.'));

    foreach ($edit as $name => $value) {
      $this->assertFieldByName($name, $value, format_string('"@name" has correct default value.', array('@name' => $name)));
    }
  }
}

/**
 * Tests adding aggregator feeds.
 */
class AddFeedTestCase extends AggregatorTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Add feed functionality',
      'description' => 'Add feed test.',
      'group' => 'Aggregator'
    );
  }

  /**
   * Creates and ensures that a feed is unique, checks source, and deletes feed.
   */
  function testAddFeed() {
    $feed = $this->createFeed();

    // Check feed data.
    $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);
    $this->assertResponse(200, 'Feed source exists.');
    $this->assertText($feed->title, 'Page title');
    $this->drupalGet('aggregator/sources/' . $feed->fid . '/categorize');
    $this->assertResponse(200, 'Feed categorization page exists.');

    // Delete feed.
    $this->deleteFeed($feed);
  }

  /**
   * Tests feeds with very long URLs.
   */
  function testAddLongFeed() {
    // Create a feed with a URL of > 255 characters.
    $long_url = "https://www.google.com/search?ix=heb&sourceid=chrome&ie=UTF-8&q=angie+byron#sclient=psy-ab&hl=en&safe=off&source=hp&q=angie+byron&pbx=1&oq=angie+byron&aq=f&aqi=&aql=&gs_sm=3&gs_upl=0l0l0l10534l0l0l0l0l0l0l0l0ll0l0&bav=on.2,or.r_gc.r_pw.r_cp.,cf.osb&fp=a70b6b1f0abe28d8&biw=1629&bih=889&ix=heb";
    $feed = $this->createFeed($long_url);

    // Create a second feed of > 255 characters, where the only difference is
    // after the 255th character.
    $long_url_2 = "https://www.google.com/search?ix=heb&sourceid=chrome&ie=UTF-8&q=angie+byron#sclient=psy-ab&hl=en&safe=off&source=hp&q=angie+byron&pbx=1&oq=angie+byron&aq=f&aqi=&aql=&gs_sm=3&gs_upl=0l0l0l10534l0l0l0l0l0l0l0l0ll0l0&bav=on.2,or.r_gc.r_pw.r_cp.,cf.osb&fp=a70b6b1f0abe28d8&biw=1629&bih=889";
    $feed_2 = $this->createFeed($long_url_2);

    // Check feed data.
    $this->assertTrue($this->uniqueFeed($feed->title, $feed->url), 'The first long URL feed is unique.');
    $this->assertTrue($this->uniqueFeed($feed_2->title, $feed_2->url), 'The second long URL feed is unique.');

    // Check feed source.
    $this->drupalGet('aggregator/sources/' . $feed->fid);
    $this->assertResponse(200, 'Long URL feed source exists.');
    $this->assertText($feed->title, 'Page title');
    $this->drupalGet('aggregator/sources/' . $feed->fid . '/categorize');
    $this->assertResponse(200, 'Long URL feed categorization page exists.');

    // Delete feeds.
    $this->deleteFeed($feed);
    $this->deleteFeed($feed_2);
  }
}

/**
 * Tests the categorize feed functionality in the Aggregator module.
 */
class CategorizeFeedTestCase extends AggregatorTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Categorize feed functionality',
      'description' => 'Categorize feed test.',
      'group' => 'Aggregator'
    );
  }

  /**
   * Creates a feed and makes sure you can add/delete categories to it.
   */
  function testCategorizeFeed() {

    // Create 2 categories.
    $category_1 = array('title' => $this->randomName(10), 'description' => '');
    $this->drupalPost('admin/config/services/aggregator/add/category', $category_1, t('Save'));
    $this->assertRaw(t('The category %title has been added.', array('%title' => $category_1['title'])), format_string('The category %title has been added.', array('%title' => $category_1['title'])));

    $category_2 = array('title' => $this->randomName(10), 'description' => '');
    $this->drupalPost('admin/config/services/aggregator/add/category', $category_2, t('Save'));
    $this->assertRaw(t('The category %title has been added.', array('%title' => $category_2['title'])), format_string('The category %title has been added.', array('%title' => $category_2['title'])));

    // Get categories from database.
    $categories = $this->getCategories();

    // Create a feed and assign 2 categories to it.
    $feed = $this->getFeedEditArray();
    $feed['block'] = 5;
    foreach ($categories as $cid => $category) {
      $feed['category'][$cid] = $cid;
    }

    // Use aggregator_save_feed() function to save the feed.
    aggregator_save_feed($feed);
    $db_feed = db_query("SELECT *  FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed['title'], ':url' => $feed['url']))->fetch();

    // Assert the feed has two categories.
    $this->getFeedCategories($db_feed);
    $this->assertEqual(count($db_feed->categories), 2, 'Feed has 2 categories');

    // Use aggregator_save_feed() to delete a category.
    $category = reset($categories);
    aggregator_save_category(array('cid' => $category->cid));

    // Assert that category is deleted.
    $db_category = db_query("SELECT COUNT(*) FROM {aggregator_category} WHERE cid = :cid", array(':cid' => $category->cid))->fetchField();
    $this->assertFalse($db_category, format_string('The category %title has been deleted.', array('%title' => $category->title)));

    // Assert that category has been removed from feed.
    $categorized_feeds = db_query("SELECT COUNT(*) FROM {aggregator_category_feed} WHERE cid = :cid", array(':cid' => $category->cid))->fetchField();
    $this->assertFalse($categorized_feeds, format_string('The category %title has been removed from feed %feed_title.', array('%title' => $category->title, '%feed_title' => $feed['title'])));

    // Assert that no broken links (associated with the deleted category)
    // appear on one of the other category pages.
    $this->createSampleNodes();
    $this->drupalGet('admin/config/services/aggregator');
    $this->clickLink('update items');
    $categories = $this->getCategories();
    $category = reset($categories);
    $this->drupalGet('aggregator/categories/' . $category->cid);
    global $base_path;
    $this->assertNoRaw('<a href="' . $base_path . 'aggregator/categories/"></a>,');
  }

}

/**
 * Tests functionality of updating the feed in the Aggregator module.
 */
class UpdateFeedTestCase extends AggregatorTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Update feed functionality',
      'description' => 'Update feed test.',
      'group' => 'Aggregator'
    );
  }

  /**
   * Creates a feed and attempts to update it.
   */
  function testUpdateFeed() {
    $remamining_fields = array('title', 'url', '');
    foreach ($remamining_fields as $same_field) {
      $feed = $this->createFeed();

      // Get new feed data array and modify newly created feed.
      $edit = $this->getFeedEditArray();
      $edit['refresh'] =  1800; // Change refresh value.
      if (isset($feed->{$same_field})) {
        $edit[$same_field] = $feed->{$same_field};
      }
      $this->drupalPost('admin/config/services/aggregator/edit/feed/' . $feed->fid, $edit, t('Save'));
      $this->assertRaw(t('The feed %name has been updated.', array('%name' => $edit['title'])), format_string('The feed %name has been updated.', array('%name' => $edit['title'])));

      // Check feed data.
      $this->assertEqual($this->getUrl(), url('admin/config/services/aggregator/', array('absolute' => TRUE)));
      $this->assertTrue($this->uniqueFeed($edit['title'], $edit['url']), 'The feed is unique.');

      // Check feed source.
      $this->drupalGet('aggregator/sources/' . $feed->fid);
      $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);
    }
  }
}

/**
 * Tests functionality for removing feeds in the Aggregator module.
 */
class RemoveFeedTestCase extends AggregatorTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Remove feed functionality',
      'description' => 'Remove feed test.',
      'group' => 'Aggregator'
    );
  }

  /**
   * Removes a feed and ensures that all of its services are removed.
   */
  function testRemoveFeed() {
    $feed = $this->createFeed();

    // Delete feed.
    $this->deleteFeed($feed);

    // Check feed source.
    $this->drupalGet('aggregator/sources/' . $feed->fid);
    $this->assertResponse(404, 'Deleted feed source does not exists.');

    // Check database for feed.
    $result = db_query("SELECT COUNT(*) FROM {aggregator_feed} WHERE title = :title AND url = :url", array(':title' => $feed->title, ':url' => $feed->url))->fetchField();
    $this->assertFalse($result, 'Feed not found in database');
  }
}

/**
 * Tests functionality of updating a feed item in the Aggregator module.
 */
class UpdateFeedItemTestCase extends AggregatorTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Update feed item functionality',
      'description' => 'Update feed items from a feed.',
      'group' => 'Aggregator'
    );
  }

  /**
   * Tests running "update items" from 'admin/config/services/aggregator' page.
   */
  function testUpdateFeedItem() {
    $this->createSampleNodes();

    // Create a feed and test updating feed items if possible.
    $feed = $this->createFeed();
    if (!empty($feed)) {
      $this->updateFeedItems($feed, $this->getDefaultFeedItemCount());
      $this->removeFeedItems($feed);
    }

    // Delete feed.
    $this->deleteFeed($feed);

    // Test updating feed items without valid timestamp information.
    $edit = array(
      'title' => "Feed without publish timestamp",
      'url' => $this->getRSS091Sample(),
    );

    $this->drupalGet($edit['url']);
    $this->assertResponse(array(200), format_string('URL !url is accessible', array('!url' => $edit['url'])));

    $this->drupalPost('admin/config/services/aggregator/add/feed', $edit, t('Save'));
    $this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title'])), 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();

    aggregator_refresh($feed);
    $before = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();

    // Sleep for 3 second.
    sleep(3);
    db_update('aggregator_feed')
      ->condition('fid', $feed->fid)
      ->fields(array(
        'checked' => 0,
        'hash' => '',
        'etag' => '',
        'modified' => 0,
      ))
      ->execute();
    aggregator_refresh($feed);

    $after = db_query('SELECT timestamp FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField();
    $this->assertTrue($before === $after, format_string('Publish timestamp of feed item was not updated (!before === !after)', array('!before' => $before, '!after' => $after)));
  }
}

class RemoveFeedItemTestCase extends AggregatorTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Remove feed item functionality',
      'description' => 'Remove feed items from a feed.',
      'group' => 'Aggregator'
    );
  }

  /**
   * Tests running "remove items" from 'admin/config/services/aggregator' page.
   */
  function testRemoveFeedItem() {
    // Create a bunch of test feeds.
    $feed_urls = array();
    // No last-modified, no etag.
    $feed_urls[] = url('aggregator/test-feed', array('absolute' => TRUE));
    // Last-modified, but no etag.
    $feed_urls[] = url('aggregator/test-feed/1', array('absolute' => TRUE));
    // No Last-modified, but etag.
    $feed_urls[] = url('aggregator/test-feed/0/1', array('absolute' => TRUE));
    // Last-modified and etag.
    $feed_urls[] = url('aggregator/test-feed/1/1', array('absolute' => TRUE));

    foreach ($feed_urls as $feed_url) {
      $feed = $this->createFeed($feed_url);
      // Update and remove items two times in a row to make sure that removal
      // resets all 'modified' information (modified, etag, hash) and allows for
      // immediate update.
      $this->updateAndRemove($feed, 4);
      $this->updateAndRemove($feed, 4);
      $this->updateAndRemove($feed, 4);
      // Delete feed.
      $this->deleteFeed($feed);
    }
  }
}

/**
 * Tests categorization functionality in the Aggregator module.
 */
class CategorizeFeedItemTestCase extends AggregatorTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Categorize feed item functionality',
      'description' => 'Test feed item categorization.',
      'group' => 'Aggregator'
    );
  }

  /**
   * Checks that children of a feed inherit a defined category.
   *
   * If a feed has a category, make sure that the children inherit that
   * categorization.
   */
  function testCategorizeFeedItem() {
    $this->createSampleNodes();

    // Simulate form submission on "admin/config/services/aggregator/add/category".
    $edit = array('title' => $this->randomName(10), 'description' => '');
    $this->drupalPost('admin/config/services/aggregator/add/category', $edit, t('Save'));
    $this->assertRaw(t('The category %title has been added.', array('%title' => $edit['title'])), format_string('The category %title has been added.', array('%title' => $edit['title'])));

    $category = db_query("SELECT * FROM {aggregator_category} WHERE title = :title", array(':title' => $edit['title']))->fetch();
    $this->assertTrue(!empty($category), 'The category found in database.');

    $link_path = 'aggregator/categories/' . $category->cid;
    $menu_link = db_query("SELECT * FROM {menu_links} WHERE link_path = :link_path", array(':link_path' => $link_path))->fetch();
    $this->assertTrue(!empty($menu_link), 'The menu link associated with the category found in database.');

    $feed = $this->createFeed();
    db_insert('aggregator_category_feed')
      ->fields(array(
        'cid' => $category->cid,
        'fid' => $feed->fid,
      ))
      ->execute();
    $this->updateFeedItems($feed, $this->getDefaultFeedItemCount());
    $this->getFeedCategories($feed);
    $this->assertTrue(!empty($feed->categories), 'The category found in the feed.');

    // For each category of a feed, ensure feed items have that category, too.
    if (!empty($feed->categories) && !empty($feed->items)) {
      foreach ($feed->categories as $category) {
        $categorized_count = db_select('aggregator_category_item')
          ->condition('iid', $feed->items, 'IN')
          ->countQuery()
          ->execute()
          ->fetchField();

        $this->assertEqual($feed->item_count, $categorized_count, 'Total items in feed equal to the total categorized feed items in database');
      }
    }

    // Delete category from feed items when category is deleted.
    $cid = reset($feed->categories);
    $categories = $this->getCategories();
    $category_title = $categories[$cid]->title;

    // Delete category.
    aggregator_save_category(array('cid' => $cid));

    // Assert category has been removed from feed items.
    $categorized_count = db_query("SELECT COUNT(*) FROM {aggregator_category_item} WHERE cid = :cid", array(':cid' => $cid))->fetchField();
    $this->assertFalse($categorized_count, format_string('The category %title has been removed from feed items.', array('%title' => $category_title)));
    // Delete feed.
    $this->deleteFeed($feed);
  }

}

/**
 * Tests importing feeds from OPML functionality for the Aggregator module.
 */
class ImportOPMLTestCase extends AggregatorTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Import feeds from OPML functionality',
      'description' => 'Test OPML import.',
      'group' => 'Aggregator',
    );
  }

  /**
   * Opens OPML import form.
   */
  function openImportForm() {
    db_delete('aggregator_category')->execute();

    $category = $this->randomName(10);
    $cid = db_insert('aggregator_category')
      ->fields(array(
        'title' => $category,
        'description' => '',
      ))
      ->execute();

    $this->drupalGet('admin/config/services/aggregator/add/opml');
    $this->assertText('A single OPML document may contain a collection of many feeds.', '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.');
  }

  /**
   * Submits form filled with invalid fields.
   */
  function validateImportFormFields() {
    $before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();

    $edit = array();
    $this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
    $this->assertRaw(t('You must <em>either</em> upload a file or enter a URL.'), 'Error if no fields are filled.');

    $path = $this->getEmptyOpml();
    $edit = array(
      'files[upload]' => $path,
      'remote' => file_create_url($path),
    );
    $this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
    $this->assertRaw(t('You must <em>either</em> upload a file or enter a URL.'), 'Error if both fields are filled.');

    $edit = array('remote' => 'invalidUrl://empty');
    $this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
    $this->assertText(t('This URL is not valid.'), 'Error if the URL is invalid.');

    $after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
    $this->assertEqual($before, $after, 'No feeds were added during the three last form submissions.');
  }

  /**
   * Submits form with invalid, empty, and valid OPML files.
   */
  function submitImportForm() {
    $before = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();

    $form['files[upload]'] = $this->getInvalidOpml();
    $this->drupalPost('admin/config/services/aggregator/add/opml', $form, t('Import'));
    $this->assertText(t('No new feed has been added.'), 'Attempting to upload invalid XML.');

    $edit = array('remote' => file_create_url($this->getEmptyOpml()));
    $this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
    $this->assertText(t('No new feed has been added.'), 'Attempting to load empty OPML from remote URL.');

    $after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
    $this->assertEqual($before, $after, 'No feeds were added during the two last form submissions.');

    db_delete('aggregator_feed')->execute();
    db_delete('aggregator_category')->execute();
    db_delete('aggregator_category_feed')->execute();

    $category = $this->randomName(10);
    db_insert('aggregator_category')
      ->fields(array(
        'cid' => 1,
        'title' => $category,
        'description' => '',
      ))
      ->execute();

    $feeds[0] = $this->getFeedEditArray();
    $feeds[1] = $this->getFeedEditArray();
    $feeds[2] = $this->getFeedEditArray();
    $edit = array(
      'files[upload]' => $this->getValidOpml($feeds),
      'refresh'       => '900',
      'category[1]'   => $category,
    );
    $this->drupalPost('admin/config/services/aggregator/add/opml', $edit, t('Import'));
    $this->assertRaw(t('A feed with the URL %url already exists.', array('%url' => $feeds[0]['url'])), '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');

    $after = db_query('SELECT COUNT(*) FROM {aggregator_feed}')->fetchField();
    $this->assertEqual($after, 2, 'Verifying that two distinct feeds were added.');

    $feeds_from_db = db_query("SELECT f.title, f.url, f.refresh, cf.cid FROM {aggregator_feed} f LEFT JOIN {aggregator_category_feed} cf ON f.fid = cf.fid");
    $refresh = $category = TRUE;
    foreach ($feeds_from_db as $feed) {
      $title[$feed->url] = $feed->title;
      $url[$feed->title] = $feed->url;
      $category = $category && $feed->cid == 1;
      $refresh = $refresh && $feed->refresh == 900;
    }

    $this->assertEqual($title[$feeds[0]['url']], $feeds[0]['title'], '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.');
  }

  /**
   * Tests the import of an OPML file.
   */
  function testOPMLImport() {
    $this->openImportForm();
    $this->validateImportFormFields();
    $this->submitImportForm();
  }
}

/**
 * Tests functionality of the cron process in the Aggregator module.
 */
class AggregatorCronTestCase extends AggregatorTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Update on cron functionality',
      'description' => 'Update feeds on cron.',
      'group' => 'Aggregator'
    );
  }

  /**
   * Adds feeds and updates them via cron process.
   */
  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.');
  }
}

/**
 * Tests rendering functionality in the Aggregator module.
 */
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'
    );
  }

  /**
   * Adds a feed block to the page and checks its links.
   *
   * @todo Test the category block as well.
   */
  public function testBlockLinks() {
    // Create feed.
    $this->createSampleNodes();
    $feed = $this->createFeed();
    $this->updateFeedItems($feed, $this->getDefaultFeedItemCount());

    // Place block on page (@see block.test:moveBlockToRegion())
    // Need admin user to be able to access block admin.
    $this->admin_user = $this->drupalCreateUser(array(
      'administer blocks',
      'access administration pages',
      'administer news feeds',
      'access news feeds',
    ));
    $this->drupalLogin($this->admin_user);

    // Prepare to use the block admin form.
    $block = array(
      'module' => 'aggregator',
      'delta' => 'feed-' . $feed->fid,
      'title' => $feed->title,
    );
    $region = 'footer';
    $edit = array();
    $edit['blocks[' . $block['module'] . '_' . $block['delta'] . '][region]'] = $region;
    // Check the feed block is available in the block list form.
    $this->drupalGet('admin/structure/block');
    $this->assertFieldByName('blocks[' . $block['module'] . '_' . $block['delta'] . '][region]', '', 'Aggregator feed block is available for positioning.');
    // Position it.
    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
    $this->assertText(t('The block settings have been updated.'), format_string('Block successfully moved to %region_name region.', array( '%region_name' => $region)));
    // Confirm that the block is now being displayed on pages.
    $this->drupalGet('node');
    $this->assertText(t($block['title']), 'Feed block is displayed on the page.');

    // Find the expected read_more link.
    $href = 'aggregator/sources/' . $feed->fid;
    $links = $this->xpath('//a[@href = :href]', array(':href' => url($href)));
    $this->assert(isset($links[0]), format_string('Link to href %href found.', array('%href' => $href)));

    // Visit that page.
    $this->drupalGet($href);
    $correct_titles = $this->xpath('//h1[normalize-space(text())=:title]', array(':title' => $feed->title));
    $this->assertFalse(empty($correct_titles), 'Aggregator feed page is available and has the correct title.');

    // Set the number of news items to 0 to test that the block does not show
    // up.
    $feed->block = 0;
    aggregator_save_feed((array) $feed);
    // It is necessary 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.');
  }

  /**
   * Creates a feed and checks 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'));
    $this->assertTrue(!empty($elements), 'Individual source page contains a pager.');

    // Reset the number of items in rss.xml to the default value.
    variable_set('feed_default_items', 10);
  }
}

/**
 * Tests feed parsing in the Aggregator module.
 */
class FeedParserTestCase extends AggregatorTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Feed parser functionality',
      'description' => 'Test the built-in feed parser with valid feed samples.',
      'group' => 'Aggregator',
    );
  }

  function setUp() {
    parent::setUp();
    // Do not remove old aggregator items during these tests, since our sample
    // feeds have hardcoded dates in them (which may be expired when this test
    // is run).
    variable_set('aggregator_clear', AGGREGATOR_CLEAR_NEVER);
  }

  /**
   * Tests a feed that uses the RSS 0.91 format.
   */
  function testRSS091Sample() {
    $feed = $this->createFeed($this->getRSS091Sample());
    aggregator_refresh($feed);
    $this->drupalGet('aggregator/sources/' . $feed->fid);
    $this->assertResponse(200, format_string('Feed %name exists.', array('%name' => $feed->title)));
    $this->assertText('First example feed item title');
    $this->assertLinkByHref('http://example.com/example-turns-one');
    $this->assertText('First example feed item description.');

    // 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');
  }

  /**
   * Tests a feed that uses the Atom format.
   */
  function testAtomSample() {
    $feed = $this->createFeed($this->getAtomSample());
    aggregator_refresh($feed);
    $this->drupalGet('aggregator/sources/' . $feed->fid);
    $this->assertResponse(200, format_string('Feed %name exists.', array('%name' => $feed->title)));
    $this->assertText('Atom-Powered Robots Run Amok');
    $this->assertLinkByHref('http://example.org/2003/12/13/atom03');
    $this->assertText('Some text.');
    $this->assertEqual('urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a', db_query('SELECT guid FROM {aggregator_item} WHERE link = :link', array(':link' => 'http://example.org/2003/12/13/atom03'))->fetchField(), 'Atom entry id element is parsed correctly.');
  }

  /**
   * Tests a feed that uses HTML entities in item titles.
   */
  function testHtmlEntitiesSample() {
    $feed = $this->createFeed($this->getHtmlEntitiesSample());
    aggregator_refresh($feed);
    $this->drupalGet('aggregator/sources/' . $feed->fid);
    $this->assertResponse(200, format_string('Feed %name exists.', array('%name' => $feed->title)));
    $this->assertRaw("Quote&quot; Amp&amp;");
  }
}

Anon7 - 2022
AnonSec Team