* @copyright 2008-2010 Phergie Development Team (http://phergie.org) * @license http://phergie.org/license New BSD License * @link http://pear.phergie.org/package/Phergie_Tests */ /** * Unit test suite for Pherge_Plugin_Karma. * * @category Phergie * @package Phergie_Tests * @author Phergie Development Team * @license http://phergie.org/license New BSD License * @link http://pear.phergie.org/package/Phergie_Tests */ class Phergie_Plugin_KarmaTest extends Phergie_Plugin_TestCase { /** * Skips tests if the SQLite PDO driver is not available. * * @return void */ public function setUp() { if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) { $this->markTestSkipped('PDO or pdo_sqlite extension is required'); } parent::setUp(); } /** * Configures the plugin to use a temporary copy of the database. * * @return PDO Connection to the temporary database */ private function createMockDatabase() { $dbPath = $this->getPluginsPath('Karma/karma.db'); $db = $this->getMockDatabase($dbPath); $this->plugin->setDb($db); return $db; } /** * Tests the requirement of the Command plugin. * * @return void */ public function testRequiresCommandPlugin() { $this->assertRequiresPlugin('Command'); $this->plugin->onLoad(); } /** * Initiates a karma event with a specified term. * * @param string $term Karma term * * @return Phergie_Event_Request Initiated mock event */ private function initiateKarmaEvent($term) { $args = array( 'receiver' => $this->source, 'text' => 'karma ' . $term ); $event = $this->getMockEvent('privmsg', $args); $this->plugin->setEvent($event); return $event; } /** * Checks for an expected karma response. * * @param Phergie_Event_Request $event Event containing the karma * request * @param string $term Karma term * @param string $response Portion of the response * message following the term * from the original event * * @return void */ private function checkForKarmaResponse($event, $term, $response) { $text = $event->getNick() . ': ' . $response; $this->assertEmitsEvent('privmsg', array($event->getSource(), $text)); $this->plugin->onCommandKarma($term); } /** * Tests that a default database is used when none is specified. * * @return void */ public function testGetDb() { $db = $this->plugin->getDb(); $this->assertType('PDO', $db); } /** * Tests specifying a custom database for the plugin to use. * * @return void */ public function testSetDb() { $db = $this->createMockDatabase(); $this->assertSame($db, $this->plugin->getDb()); } /** * Tests that issuing the karma command with an unknown term returns a * neutral rating. * * @return void */ public function testKarmaCommandOnUnknownTerm() { $term = 'foo'; $this->createMockDatabase(); $event = $this->initiateKarmaEvent($term); $this->checkForKarmaResponse($event, $term, $term . ' has neutral karma.'); } /** * Tests that issuing the karma command with the term "me" returns the * the karma rating for the initiating user. * * @return void */ public function testKarmaCommandOnUser() { $term = 'me'; $this->createMockDatabase(); $event = $this->initiateKarmaEvent($term); $this->checkForKarmaResponse($event, $term, 'You have neutral karma.'); } /** * Tests that issuing the karma command with a term that has a fixed * karma rating results in that rating being returned. * * @return void */ public function testKarmaCommandWithFixedKarmaTerm() { $term = 'phergie'; $this->createMockDatabase(); $event = $this->initiateKarmaEvent($term); $this->checkForKarmaResponse($event, $term, 'phergie has karma of awesome.'); } /** * Supporting method that tests the result of a karma term rating change. * * @param string $term Karma term for which the rating is being * changed * @param string $operation ++ or -- * @param int $karma Expected karma rating after the change is * applied */ private function checkForKarmaRatingChange($term, $operation, $karma) { $args = array( 'receiver' => $this->source, 'text' => $term . $operation ); $event = $this->getMockEvent('privmsg', $args); $this->plugin->setEvent($event); $this->plugin->onPrivmsg(); $event = $this->initiateKarmaEvent($term); $this->checkForKarmaResponse($event, $term, $term . ' has karma of ' . $karma . '.'); } /** * Tests incrementing the karma rating of a new term. * * @return void */ public function testIncrementingKarmaRating() { $this->createMockDatabase(); $this->checkForKarmaRatingChange('foo', '++', 1); } /** * Tests decrementing the karma rating of a new term. * * @return void */ public function testDecrementingKarmaRating() { $this->createMockDatabase(); $this->checkForKarmaRatingChange('foo', '--', -1); } /** * Tests modifying the karma rating of an existing term. * * @return void */ public function testChangingExistingKarmaRating() { $term = 'foo'; $this->createMockDatabase(); $this->checkForKarmaRatingChange($term, '++', 1); $this->checkForKarmaRatingChange($term, '++', 2); } /** * Tests resetting the karma rating of an existing term to 0. * * @return void */ public function testResettingExistingKarmaRating() { $term = 'foo'; $this->createMockDatabase(); $this->checkForKarmaRatingChange($term, '++', 1); $this->plugin->onCommandReincarnate($term); $event = $this->initiateKarmaEvent($term); $this->checkForKarmaResponse($event, $term, $term . ' has neutral karma.'); } /** * Data provider for testKarmaComparisons(). * * @return array Enumerated array of enumerated arrays each containing a * set of parameter values for a single call to * testKarmaComparisons() */ public function dataProviderTestKarmaComparisons() { $term1 = 'foo'; $term2 = 'bar'; $positive = 'True that.'; $negative = 'No sir, not at all.'; return array( array($term1, $term2, 1, 0, '>', $positive), array($term1, $term2, 0, 1, '>', $negative), array($term1, $term2, 1, 1, '>', $negative), array($term1, $term2, 1, 0, '<', $negative), array($term1, $term2, 0, 1, '<', $positive), array($term1, $term2, 1, 1, '<', $negative), array($term1, 'phergie', 1, 0, '>', $positive), array('phergie', $term2, 0, 1, '<', $positive), array($term1, 'everything', 0, 0, '>', $positive), array('everything', $term2, 0, 0, '>', $positive), ); } /** * Tests comparing the karma ratings of two terms. * * @param string $term1 First term * @param string $term2 Second term * @param int $karma1 Karma rating of the first time, 0 or 1 * @param int $karma2 Karma rating of the second term, 0 or 1 * @param string $operator Comparison operator, > or < * @param string $response Response to check for * * @return void * @dataProvider dataProviderTestKarmaComparisons */ public function testKarmaComparisons($term1, $term2, $karma1, $karma2, $operator, $response ) { $db = $this->createMockDatabase(); // Reduce answer tables to expected response $stmt = $db->prepare('DELETE FROM positive_answers WHERE answer != ?'); $stmt->execute(array($response)); $stmt = $db->prepare('DELETE FROM negative_answers WHERE answer != ?'); $stmt->execute(array($response)); if ($karma1) { $this->checkForKarmaRatingChange($term1, '++', 1); } if ($karma2) { $this->checkForKarmaRatingChange($term2, '++', 1); } $args = array( 'receiver' => $this->source, 'text' => $term1 . ' ' . $operator . ' ' . $term2 ); $event = $this->getMockEvent('privmsg', $args); $this->plugin->setEvent($event); // Test lack of a response for terms with fixed karma ratings if ($term1 == 'phergie' || $term2 == 'phergie') { $callback = 'assertDoesNotEmitEvent'; } else { $callback = 'assertEmitsEvent'; } $this->$callback('privmsg', array($event->getSource(), $response)); $this->plugin->onPrivmsg(); // Test for karma changes when one term is "everything" if ($term1 == 'everything' || $term2 == 'everything') { if ($term1 == 'everything') { $term = $term2; $karma = ($operator == '>') ? -1 : 1; } else { $term = $term1; $karma = ($operator == '>') ? 1 : -1; } $event = $this->initiateKarmaEvent($term); $this->checkForKarmaResponse($event, $term, $term . ' has karma of ' . $karma . '.'); } } }