From d0155e9d66665a7195194a988e16ff16623e28f0 Mon Sep 17 00:00:00 2001 From: Bernhard Posselt Date: Sun, 29 Nov 2015 17:03:52 +0100 Subject: first step at cleaning up integration tests --- db/newsmapper.php | 26 +++ phpunit.integration.xml | 2 +- tests/integration/IntegrationTest.php | 125 +++++++++++++ .../Tests/Integration/Fixtures/FolderFixture.php | 20 ++ .../Tests/Integration/Fixtures/ItemFixture.php | 20 ++ tests/integration/bootstrap.php | 204 --------------------- tests/integration/fixtures/FeedFixture.php | 50 +++++ tests/integration/fixtures/Fixture.php | 26 +++ 8 files changed, 268 insertions(+), 205 deletions(-) create mode 100644 tests/integration/IntegrationTest.php create mode 100644 tests/integration/OCA/News/Tests/Integration/Fixtures/FolderFixture.php create mode 100644 tests/integration/OCA/News/Tests/Integration/Fixtures/ItemFixture.php delete mode 100644 tests/integration/bootstrap.php create mode 100644 tests/integration/fixtures/FeedFixture.php create mode 100644 tests/integration/fixtures/Fixture.php diff --git a/db/newsmapper.php b/db/newsmapper.php index eea69df2a..a36956b16 100644 --- a/db/newsmapper.php +++ b/db/newsmapper.php @@ -29,5 +29,31 @@ abstract class NewsMapper extends Mapper { */ abstract public function find($id, $userId); + /** + * Performs a SELECT query with all arguments appened to the WHERE clause + * The SELECT will be performed on the current table and take the entity + * that is related for transforming the properties into column names + * @param array $search an assoc array from property to filter value + * @return array + */ + public function where(array $search) { + $entity = new $this->entityClass; + + // turn keys into sql query filter, e.g. feedId -> feed_id = :feedId + $filter = array_map(function ($property) use ($entity) { + $column = $entity->propertyToColumn($property); + return $column . ' = :' . $property; + }, array_keys($search)); + + $andStatement = implode(' AND ', $filter); + + $sql = 'SELECT * FROM `' . $this->getTableName() . '`'; + + if (count($search) > 0) { + $sql .= 'WHERE ' . $andStatement; + } + + return $this->findEntities($sql, $search); + } } \ No newline at end of file diff --git a/phpunit.integration.xml b/phpunit.integration.xml index efbdfe662..eba04489b 100644 --- a/phpunit.integration.xml +++ b/phpunit.integration.xml @@ -1,4 +1,4 @@ - + ./tests/integration diff --git a/tests/integration/IntegrationTest.php b/tests/integration/IntegrationTest.php new file mode 100644 index 000000000..1baa31359 --- /dev/null +++ b/tests/integration/IntegrationTest.php @@ -0,0 +1,125 @@ + + * @copyright Bernhard Posselt 2015 + */ + + +namespace OCA\News\Tests\Integration; + +use PHPUnit_Framework_TestCase; + +use OCP\IDb; +use OCP\IUserSession; +use OCP\IUserManager; + +use OCA\News\AppInfo\Application; +use OCA\News\Tests\Integration\Fixtures\Fixture; +use OCA\News\Tests\Integration\Fixtures\ItemFixture; +use OCA\News\Tests\Integration\Fixtures\FeedFixture; +use OCA\News\Tests\Integration\Fixtures\FolderFixture; +use OCA\News\Db\FeedMapper; +use OCA\News\Db\ItemMapper; +use OCA\News\Db\FolderMapper; + + +abstract class IntegrationTest extends PHPUnit_Framework_TestCase { + + protected $user = 'test'; + protected $userPassword = 'test'; + + /** @var ItemMapper */ + protected $itemMapper; + + /** @var FeedMapper */ + protected $feedMapper; + + /** @var FolderMapper */ + protected $folderMapper; + + protected function setUp() { + parent::setUp(); + $app = new Application(); + $this->container = $app->getContainer(); + $this->tearDownUser($this->user); + $this->setupUser($this->user, $this->userPassword); + + // set up database layers + $this->itemMapper = $this->container->query(ItemMapper::class); + $this->feedMapper = $this->container->query(FeedMapper::class); + $this->folderMapper = $this->container->query(FolderMapper::class); + } + + /** + * Saves a fixture in a database and returns the saved result + * @param Fixture $fixture + * @return \OCP\AppFramework\Db\Entity + */ + protected function loadFixture(Fixture $fixture) { + if ($fixture instanceof FeedFixture) { + return $this->feedMapper->insert($fixture); + } elseif ($fixture instanceof ItemFixture) { + return $this->itemMapper->insert($fixture); + } elseif ($fixture instanceof FolderFixture) { + return $this->folderMapper->insert($fixture); + } + + throw new \InvalidArgumentException('Invalid fixture class given'); + } + + /** + * Creates and logs in a new ownCloud user + * @param $user + * @param $password + */ + protected function setupUser($user, $password) { + $userManager = $this->container->query(IUserManager::class); + $userManager->createUser($user, $password); + + $session = $this->container->query(IUserSession::class); + $session->login($user, $password); + } + + /** + * Removes a user and his News app database entries from the database + * @param $user + */ + protected function tearDownUser($user) { + $userManager = $this->container->query(IUserManager::class); + + if ($userManager->userExists($user)) { + $userManager->get($user)->delete(); + } + + $this->clearNewsDatabase($user); + } + + /** + * Deletes all news entries of a given user + * @param string $user + */ + protected function clearUserNewsDatabase($user) { + $sql = [ + 'DELETE FROM *PREFIX*news_items WHERE feed_id IN ' . + '(SELECT id FROM *PREFIX*news_feeds WHERE user_id = ?)', + 'DELETE FROM *PREFIX*news_feeds WHERE user_id = ?', + 'DELETE FROM *PREFIX*news_folders WHERE user_id = ?' + ]; + + $db = $this->container->query(IDb::class); + foreach ($sql as $query) { + $db->prepareQuery($query)->execute([$user]); + } + } + + protected function tearDown() { + parent::tearDown(); + $this->tearDownUser($this->user); + } + +} \ No newline at end of file diff --git a/tests/integration/OCA/News/Tests/Integration/Fixtures/FolderFixture.php b/tests/integration/OCA/News/Tests/Integration/Fixtures/FolderFixture.php new file mode 100644 index 000000000..f934f00db --- /dev/null +++ b/tests/integration/OCA/News/Tests/Integration/Fixtures/FolderFixture.php @@ -0,0 +1,20 @@ + + * @copyright Bernhard Posselt 2015 + */ + + +namespace OCA\News\Tests\Integration\Fixtures; + + +use OCA\News\Db\Folder; + +class FolderFixture extends Folder { + use Fixture; +} \ No newline at end of file diff --git a/tests/integration/OCA/News/Tests/Integration/Fixtures/ItemFixture.php b/tests/integration/OCA/News/Tests/Integration/Fixtures/ItemFixture.php new file mode 100644 index 000000000..62806f208 --- /dev/null +++ b/tests/integration/OCA/News/Tests/Integration/Fixtures/ItemFixture.php @@ -0,0 +1,20 @@ + + * @copyright Bernhard Posselt 2015 + */ + + +namespace OCA\News\Tests\Integration\Fixtures; + + +use OCA\News\Db\Item; + +class ItemFixture extends Item { + use Fixture; +} \ No newline at end of file diff --git a/tests/integration/bootstrap.php b/tests/integration/bootstrap.php deleted file mode 100644 index 19a169a7e..000000000 --- a/tests/integration/bootstrap.php +++ /dev/null @@ -1,204 +0,0 @@ - - * @copyright Bernhard Posselt 2015 - */ - -namespace OCA\News\Tests\Integration; - -require_once __DIR__ . '/../bootstrap.php'; - -use PHPUnit_Framework_TestCase; -use OCP\IDb; -use OCP\IUserSession; -use OCP\IUserManager; - -use OCA\News\AppInfo\Application; -use OCA\News\Db\Folder; -use OCA\News\Db\Feed; -use OCA\News\Db\Item; -use OCA\News\Db\FeedMapper; -use OCA\News\Db\ItemMapper; -use OCA\News\Db\FolderMapper; - -class NewsIntegrationTest extends PHPUnit_Framework_TestCase { - - protected $userId = 'test'; - protected $userPassword = 'test'; - protected $container; - protected $folderMapper; - protected $feedMapper; - protected $itemMapper; - protected $folders = []; - protected $feeds = []; - protected $items = []; - - protected function setUp() { - $app = new Application(); - $this->container = $app->getContainer(); - $this->itemMapper = $this->container->query(ItemMapper::class); - $this->feedMapper = $this->container->query(FeedMapper::class); - $this->folderMapper = $this->container->query(FolderMapper::class); - - $this->cleanUp(); - - $this->loadFixtures( - $this->folderMapper, - $this->feedMapper, - $this->itemMapper - ); - } - - - protected function clearNewsDatabase($user='test') { - $sql = [ - 'DELETE FROM *PREFIX*news_items WHERE feed_id IN ' . - '(SELECT id FROM *PREFIX*news_feeds WHERE user_id = ?)', - 'DELETE FROM *PREFIX*news_feeds WHERE user_id = ?', - 'DELETE FROM *PREFIX*news_folders WHERE user_id = ?' - ]; - - $db = $this->container->query(IDb::class); - foreach ($sql as $query) { - $db->prepareQuery($query)->execute([$user]); - } - } - - - protected function loadFixtures($folderMapper, $feedMapper, $itemMapper) { - $folders = file_get_contents(__DIR__ . '/fixtures/folders.json'); - $feeds = file_get_contents(__DIR__ . '/fixtures/feeds.json'); - $items = file_get_contents(__DIR__ . '/fixtures/items.json'); - - $folders = json_decode($folders, true); - $feeds = json_decode($feeds, true); - $items = json_decode($items, true); - - // feeds in folders - foreach($folders as $folder) { - $newFolder = $this->createFolder($folder); - $this->folders[$folder['name']] = $newFolder; - - if (array_key_exists($folder['name'], $feeds)) { - foreach ($feeds[$folder['name']] as $feed) { - $feed['folderId'] = $newFolder->getId(); - $newFeed = $this->createFeed($feed); - $this->feeds[$feed['title']] = $newFeed; - - if (array_key_exists($feed['title'], $items)) { - foreach ($items[$feed['title']] as $item) { - $item['feedId'] = $newFeed->getId(); - $this->items[$item['title']] = - $this->createItem($item); - } - } - } - } - } - - // feeds in no folders - if (array_key_exists('no folder', $feeds)) { - foreach ($feeds['no folder'] as $feed) { - - $feed['folderId'] = 0; - $newFeed = $this->createFeed($feed); - $this->feeds[] = $newFeed; - - if (array_key_exists($feed['title'], $items)) { - foreach ($items[$feed['title']] as $item) { - $item['feedId'] = $newFeed->getId(); - $this->items[$item['title']] = - $this->createItem($item); - } - } - } - } - } - - private function createFolder($folder) { - $newFolder = new Folder(); - $newFolder->setName($folder['name']); - $newFolder->setUserId($this->userId); - $newFolder->setParentId(0); - $newFolder->setOpened($folder['opened']); - $newFolder->setDeletedAt($folder['deletedAt']); - return $this->folderMapper->insert($newFolder); - } - - private function createFeed($feed) { - $newFeed = new Feed(); - $newFeed->setUserId($this->userId); - $newFeed->setFolderId($feed['folderId']); - $newFeed->setTitle($feed['title']); - $newFeed->setUrl($feed['url']); - $newFeed->setLocation($feed['location']); - $newFeed->setFaviconLink($feed['faviconLink']); - $newFeed->setAdded($feed['added']); - $newFeed->setLink($feed['link']); - $newFeed->setPreventUpdate($feed['preventUpdate']); - $newFeed->setDeletedAt($feed['deletedAt']); - $newFeed->setArticlesPerUpdate($feed['articlesPerUpdate']); - $newFeed->setLastModified($feed['lastModified']); - $newFeed->setEtag($feed['etag']); - return $this->feedMapper->insert($newFeed); - } - - private function createItem($item) { - $newItem = new Item(); - $newItem->setFeedId($item['feedId']); - $newItem->setStatus($item['status']); - $newItem->setBody($item['body']); - $newItem->setTitle($item['title']); - $newItem->setAuthor($item['author']); - $newItem->setGuid($item['guid']); - $newItem->setGuidHash($item['guid']); - $newItem->setUrl($item['url']); - $newItem->setPubDate($item['pubDate']); - $newItem->setLastModified($item['lastModified']); - $newItem->setEnclosureMime($item['enclosureMime']); - $newItem->setEnclosureLink($item['enclosureLink']); - return $this->itemMapper->insert($newItem); - } - - protected function whenOlderThan($olderThan, $callback) { - $ocVersion = $this->ownCloudVersion; - if (version_compare(implode('.', $ocVersion), $olderThan, '<')) { - $callback(); - } - } - - - protected function setupUser($user, $password) { - $userManager = $this->container->query(IUserManager::class); - - if ($userManager->userExists($user)) { - $userManager->get($user)->delete(); - } - - $userManager->createUser($user, $password); - - $session = $this->container->query(IUserSession::class); - $session->login($user, $password); - } - - - private function cleanUp() { - $this->setupUser($this->userId, $this->userPassword); - $this->clearNewsDatabase($this->userId); - $this->folders = []; - $this->feeds = []; - $this->items = []; - } - - - protected function tearDown() { - $this->cleanUp(); - } - - -} diff --git a/tests/integration/fixtures/FeedFixture.php b/tests/integration/fixtures/FeedFixture.php new file mode 100644 index 000000000..286373c76 --- /dev/null +++ b/tests/integration/fixtures/FeedFixture.php @@ -0,0 +1,50 @@ + + * @copyright Bernhard Posselt 2015 + */ + + +namespace OCA\News\Tests\Integration\Fixtures; + + +use OCA\News\Db\Feed; + +class FeedFixture extends Feed { + + use Fixture; + + public function __construct(array $defaults=[]) { + parent::__construct(); + $defaults = array_combine([ + 'userId' => 'test', + 'urlHash' => 'urlHash', + 'url' => 'http://the.url.com', + 'title' => 'title', + 'faviconLink' => 'http://the.faviconLink.com', + 'added' => 9, + 'folderId' => 0, + 'unreadCount' => 0, + 'link' => 'http://thelink.com', + 'preventUpdate' => false, + 'deletedAt' => 0, + 'articlesPerUpdate' => 50, + 'lastModified' => 10, + 'etag' => '', + 'location' => 'http://thefeed.com', + 'ordering' => 0, + 'fullTextEnabled' => false, + 'pinned' => false, + 'updateMode' => 0, + 'updateErrorCount' => 0, + 'lastUpdateError' => 'lastUpdateError', + ], $defaults); + $this->fillDefaults($defaults); + } + +} \ No newline at end of file diff --git a/tests/integration/fixtures/Fixture.php b/tests/integration/fixtures/Fixture.php new file mode 100644 index 000000000..52015ebc2 --- /dev/null +++ b/tests/integration/fixtures/Fixture.php @@ -0,0 +1,26 @@ + + * @copyright Bernhard Posselt 2015 + */ + + +namespace OCA\News\Tests\Integration\Fixtures; + + +trait Fixture { + + public function fillDefaults(array $defaults=[]) { + foreach ($defaults as $key => $value) { + $method = 'set' . ucfirst($key); + $this->$method($value); + } + $this->resetUpdatedFields(); + } + +} \ No newline at end of file -- cgit v1.2.3