Compare commits

..

21 commits

Author SHA1 Message Date
Alexey Eschenko 07f89712d9 Merged in composer_update (pull request #27)
composer update.
2020-04-29 14:22:11 +00:00
Alexey Skobkin fd09f389f7
composer update. 2020-04-29 16:55:02 +03:00
Alexey Skobkin b6f7ac8ec5 Fixing UserRepositoryTest according to new test users. 2019-04-03 20:40:09 +03:00
Alexey Skobkin f598864d4d Crutch-fixing PostController::showAction() exception handling with 404 instead of 403 exception. 2019-04-03 20:34:16 +03:00
Alexey Skobkin 44c4158602 Fixing automatic replacing of AccessDeniedExceptions with InsufficientAuthenticationException in Symfony\Component\Security\Http\Firewall\ExceptionListener::handleAccessDeniedException(). 2019-04-03 20:16:34 +03:00
Alexey Skobkin aa751bbbc1 Fixing MainControllerTest::testAjaxUserAutoCompleteHasValidUserObjectsForUnnamedUser() in case of user's name in null instead of empty string. 2019-04-03 19:43:32 +03:00
Alexey Skobkin 9e5f59a2b2 Fixina small MainControllerTest problems. 2019-04-03 19:38:57 +03:00
Alexey Skobkin 7fcdcbf728 Fixing AJAX data deserialization in the MainControllerTest. 2019-04-03 19:34:01 +03:00
Alexey Skobkin 60dcc5e955 Fixing MainControllerTest dependencies. 2019-04-03 19:28:18 +03:00
Alexey Skobkin c3605b2db1 Fixing MainControllerTest::{testAjaxUserAutoCompleteHasOptions, testFindUsersLikeLogin}() and adding new tests for user without name. 2019-04-03 19:19:03 +03:00
Alexey Skobkin b455a6c8e7 Adding new tests in PostControllerTest to check for potential private post leakage. 2019-04-03 18:55:29 +03:00
Alexey Skobkin 5e8935ce66 Fixing PostController::showAction() exception on private author's post. 2019-04-03 18:52:36 +03:00
Alexey Skobkin d9c0673445 Fixing user and post data fixtures to fix PostControllerTest::testShortPostPageIsOk() according to previous privacy fix. New post for more advanced privacy test-cases added. Test must be written though. 2019-04-03 18:38:53 +03:00
Alexey Skobkin 0c004085fd Fixing privacy in PostController::showAction(). 2019-04-03 18:07:47 +03:00
Alexey Skobkin 184030ebd5 Disabling debug class loader in test environment to hide deprecation warnings. 2019-02-16 00:55:43 +03:00
Alexey Skobkin cbd24e85f9 Merge branch 'master' of bitbucket.org:skobkin/point-tools 2019-02-16 00:03:30 +03:00
Alexey Skobkin 5eb81e87be PHP removed from platrofm reqs. 2019-02-16 00:03:17 +03:00
Alexey Eschenko d4b5367c27 Merged in unit_testing (pull request #25)
Unit test added
2019-02-15 20:51:22 +00:00
Alexey Skobkin e5d5059c30 UserFactoryTest added 2019-02-15 23:42:31 +03:00
Alexey Eschenko 5d2ee61b49 Merged in fix_subscribers_update_local_users_list_fallback (pull request #24)
Fixes POINT-TOOLS-5 from Sentry.
2019-01-19 13:49:41 +00:00
Alexey Skobkin 3805ec366f Fixes POINT-TOOLS-5 from Sentry. 2019-01-19 16:43:34 +03:00
17 changed files with 1463 additions and 776 deletions

View file

@ -9,4 +9,4 @@ security:
security: false security: false
default: default:
anonymous: ~ anonymous: true

View file

@ -10,10 +10,6 @@ services:
resource: '../../src/Skobkin/Bundle/PointToolsBundle/*' resource: '../../src/Skobkin/Bundle/PointToolsBundle/*'
exclude: '../../src/Skobkin/Bundle/PointToolsBundle/{DataFixtures,DependencyInjection,DQL,DTO,Entity,Exception,Repository,Twig}' exclude: '../../src/Skobkin/Bundle/PointToolsBundle/{DataFixtures,DependencyInjection,DQL,DTO,Entity,Exception,Repository,Twig}'
Skobkin\Bundle\PointToolsBundle\DataFixtures\ORM\:
resource: '../../src/Skobkin/Bundle/PointToolsBundle/DataFixtures/ORM/*'
tags: ['doctrine.fixture.orm']
# HTTP clients # HTTP clients
# Default # Default
GuzzleHttp\ClientInterface: GuzzleHttp\ClientInterface:

View file

@ -13,6 +13,7 @@
}, },
"require": { "require": {
"php": ">=7.1.0", "php": ">=7.1.0",
"ext-json": "*",
"symfony/symfony": "^3.4", "symfony/symfony": "^3.4",
"doctrine/orm": "^2.5", "doctrine/orm": "^2.5",
"doctrine/annotations": "^1.3.0", "doctrine/annotations": "^1.3.0",
@ -38,7 +39,7 @@
"require-dev": { "require-dev": {
"symfony/phpunit-bridge": "^3.0", "symfony/phpunit-bridge": "^3.0",
"phpunit/phpunit": "^5.7", "phpunit/phpunit": "^5.7",
"doctrine/doctrine-fixtures-bundle": "^3" "doctrine/doctrine-fixtures-bundle": "^2.3"
}, },
"scripts": { "scripts": {
"symfony-scripts": [ "symfony-scripts": [
@ -57,10 +58,7 @@
] ]
}, },
"config": { "config": {
"bin-dir": "bin", "bin-dir": "bin"
"platform": {
"php": "7.1.23"
}
}, },
"extra": { "extra": {
"symfony-app-dir": "app", "symfony-app-dir": "app",

1828
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -19,6 +19,17 @@
</testsuite> </testsuite>
</testsuites> </testsuites>
<listeners>
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener">
<arguments>
<array>
<!-- set this option to 0 to disable the DebugClassLoader integration -->
<element key="debug-class-loader"><integer>0</integer></element>
</array>
</arguments>
</listener>
</listeners>
<filter> <filter>
<whitelist> <whitelist>
<directory>src</directory> <directory>src</directory>

View file

@ -228,7 +228,7 @@ class UpdateSubscriptionsCommand extends Command
); );
/** @var Subscription $subscription */ /** @var Subscription $subscription */
foreach ((array) $serviceUser->getSubscribers() as $subscription) { foreach ($serviceUser->getSubscribers() as $subscription) {
$usersForUpdate[] = $subscription->getSubscriber(); $usersForUpdate[] = $subscription->getSubscriber();
} }
} }

View file

@ -12,11 +12,19 @@ class PostController extends AbstractController
{ {
/** /**
* @ParamConverter("post", class="SkobkinPointToolsBundle:Blogs\Post") * @ParamConverter("post", class="SkobkinPointToolsBundle:Blogs\Post")
*
* @return Response
*/ */
public function showAction(Post $post, PostRepository $postRepository): Response public function showAction(Post $post, PostRepository $postRepository): Response
{ {
if ((!$post->getAuthor()->isPublic()) || $post->getAuthor()->isWhitelistOnly()) {
/**
* Throwing 404 instead of 403 because of
* @see \Symfony\Component\Security\Http\Firewall\ExceptionListener::handleAccessDeniedException()
* starts to replace 403 by 401 exceptions for anonymous users and tries to authenticate them.
*/
throw $this->createNotFoundException('Author\'s blog is private.');
//throw $this->createAccessDeniedException('Author\'s blog is private.');
}
return $this->render('SkobkinPointToolsBundle:Post:show.html.twig', [ return $this->render('SkobkinPointToolsBundle:Post:show.html.twig', [
'post' => $postRepository->getPostWithComments($post->getId()), 'post' => $postRepository->getPostWithComments($post->getId()),
]); ]);

View file

@ -2,13 +2,14 @@
namespace Skobkin\Bundle\PointToolsBundle\DataFixtures\ORM; namespace Skobkin\Bundle\PointToolsBundle\DataFixtures\ORM;
use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager; use Doctrine\Common\Persistence\ObjectManager;
use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\{Comment, Post}; use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Comment;
use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Post;
use Skobkin\Bundle\PointToolsBundle\Entity\User; use Skobkin\Bundle\PointToolsBundle\Entity\User;
class LoadCommentsData extends Fixture implements OrderedFixtureInterface class LoadCommentsData extends AbstractFixture implements OrderedFixtureInterface
{ {
public function load(ObjectManager $om) public function load(ObjectManager $om)
{ {

View file

@ -2,33 +2,64 @@
namespace Skobkin\Bundle\PointToolsBundle\DataFixtures\ORM; namespace Skobkin\Bundle\PointToolsBundle\DataFixtures\ORM;
use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\{AbstractFixture, OrderedFixtureInterface};
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager; use Doctrine\Common\Persistence\ObjectManager;
use Skobkin\Bundle\PointToolsBundle\Entity\Blogs\Post; use Skobkin\Bundle\PointToolsBundle\Entity\{Blogs\Post, User};
use Skobkin\Bundle\PointToolsBundle\Entity\User;
class LoadPostData extends Fixture implements OrderedFixtureInterface class LoadPostData extends AbstractFixture implements OrderedFixtureInterface
{ {
public const POST_ID_LONG = 'longpost';
public const POST_ID_SHORT = 'shortpost';
public const POST_ID_PR_USER = 'prusrpst';
public const POST_ID_WL_USER = 'wlusrpst';
public const POST_ID_PR_WL_USER = 'prwlusrpst';
public function load(ObjectManager $om) public function load(ObjectManager $om)
{ {
/** @var User $testUser */ /** @var User $mainUser */
$testUser = $this->getReference('test_user_99999'); $mainUser = $this->getReference('test_user_'.LoadUserData::USER_MAIN_ID);
/** @var User $privateUser */
$privateUser = $this->getReference('test_user_'.LoadUserData::USER_PRIV_ID);
/** @var User $wlUser */
$wlUser = $this->getReference('test_user_'.LoadUserData::USER_WLON_ID);
/** @var User $prWlUser */
$prWlUser = $this->getReference('test_user_'.LoadUserData::USER_PRWL_ID);
$longPost = (new Post('longpost', $testUser, new \DateTime(), Post::TYPE_POST)) $longPost = (new Post(self::POST_ID_LONG, $mainUser, new \DateTime(), Post::TYPE_POST))
->setText('Test post with many comments') ->setText('Test post with many comments')
->setPrivate(false) ->setPrivate(false)
->setDeleted(false) ->setDeleted(false)
; ;
$shortPost = (new Post('shortpost', $testUser, new \DateTime(), Post::TYPE_POST)) $shortPost = (new Post(self::POST_ID_SHORT, $mainUser, new \DateTime(), Post::TYPE_POST))
->setText('Test short post') ->setText('Test short post')
->setPrivate(false) ->setPrivate(false)
->setDeleted(false) ->setDeleted(false)
; ;
$privateUserPost = (new Post(self::POST_ID_PR_USER, $privateUser, new \DateTime(), Post::TYPE_POST))
->setText('Post from private user. Should not be visible in the public feed.')
->setPrivate(false)
->setDeleted(false)
;
$wlUserPost = (new Post(self::POST_ID_WL_USER, $wlUser, new \DateTime(), Post::TYPE_POST))
->setText('Post from whitelist-only user. Should only be visible for whitelisted users.')
->setPrivate(false)
->setDeleted(false)
;
$privateWlUserPost = (new Post(self::POST_ID_PR_WL_USER, $prWlUser, new \DateTime(), Post::TYPE_POST))
->setText('Post from private AND whitelist-only user. Should not be visible in the public feed.')
->setPrivate(false)
->setDeleted(false)
;
$om->persist($longPost); $om->persist($longPost);
$om->persist($shortPost); $om->persist($shortPost);
$om->persist($privateUserPost);
$om->persist($wlUserPost);
$om->persist($privateWlUserPost);
$om->flush(); $om->flush();
$this->addReference('test_post_longpost', $longPost); $this->addReference('test_post_longpost', $longPost);

View file

@ -2,7 +2,7 @@
namespace Skobkin\Bundle\PointToolsBundle\DataFixtures\ORM; namespace Skobkin\Bundle\PointToolsBundle\DataFixtures\ORM;
use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager; use Doctrine\Common\Persistence\ObjectManager;
use Skobkin\Bundle\PointToolsBundle\Entity\Subscription; use Skobkin\Bundle\PointToolsBundle\Entity\Subscription;
@ -12,7 +12,7 @@ use Skobkin\Bundle\PointToolsBundle\Entity\User;
/** /**
* Load user subscriptions * Load user subscriptions
*/ */
class LoadSubscribersData extends Fixture implements OrderedFixtureInterface class LoadSubscribersData extends AbstractFixture implements OrderedFixtureInterface
{ {
public function load(ObjectManager $om) public function load(ObjectManager $om)
{ {

View file

@ -2,32 +2,34 @@
namespace Skobkin\Bundle\PointToolsBundle\DataFixtures\ORM; namespace Skobkin\Bundle\PointToolsBundle\DataFixtures\ORM;
use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager; use Doctrine\Common\Persistence\ObjectManager;
use Skobkin\Bundle\PointToolsBundle\Entity\User; use Skobkin\Bundle\PointToolsBundle\Entity\User;
class LoadUserData extends Fixture implements OrderedFixtureInterface class LoadUserData extends AbstractFixture implements OrderedFixtureInterface
{ {
public const USER_MAIN_ID = 99999;
public const USER_SCND_ID = 99998;
public const USER_PRIV_ID = 99997;
public const USER_WLON_ID = 99996;
public const USER_PRWL_ID = 99995;
public const USER_UNNM_ID = 99994;
private $users = [ private $users = [
// 99999 ['id' => self::USER_MAIN_ID, 'login' => 'testuser', 'name' => 'Test User 1', 'private' => false, 'whitelist-only' => false],
['login' => 'testuser', 'name' => 'Test User 1'], ['id' => self::USER_SCND_ID, 'login' => 'testuser2', 'name' => 'Test User 2 for autocomplete test', 'private' => false, 'whitelist-only' => false],
// 99998 ['id' => self::USER_PRIV_ID, 'login' => 'private_user', 'name' => 'Test User 3', 'private' => true, 'whitelist-only' => false],
['login' => 'testuser2', 'name' => 'Test User 2'], ['id' => self::USER_WLON_ID, 'login' => 'whitelist_only_user', 'name' => 'Test User 4', 'private' => false, 'whitelist-only' => true],
// 99997 ['id' => self::USER_PRWL_ID, 'login' => 'private_whitelist_only_user', 'name' => 'Test User 4', 'private' => false, 'whitelist-only' => true],
['login' => 'testuser3', 'name' => 'Test User 3'], ['id' => self::USER_UNNM_ID, 'login' => 'unnamed_user', 'name' => null, 'private' => false, 'whitelist-only' => false],
// 99996
['login' => 'testuser4', 'name' => 'Test User 4'],
//99995
['login' => 'testuser5', 'name' => null],
]; ];
public function load(ObjectManager $om) public function load(ObjectManager $om)
{ {
$userId = 99999;
foreach ($this->users as $userData) { foreach ($this->users as $userData) {
$user = new User($userId--, new \DateTime(), $userData['login'], $userData['name']); $user = new User($userData['id'], new \DateTime(), $userData['login'], $userData['name']);
$user->updatePrivacy(!$userData['private'], $userData['whitelist-only']);
$om->persist($user); $om->persist($user);

View file

@ -4,14 +4,11 @@ namespace Skobkin\Bundle\PointToolsBundle\Service\Factory;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
class AbstractFactory abstract class AbstractFactory
{ {
/** /** @var LoggerInterface */
* @var LoggerInterface
*/
protected $logger; protected $logger;
public function __construct(LoggerInterface $logger) public function __construct(LoggerInterface $logger)
{ {
$this->logger = $logger; $this->logger = $logger;

View file

@ -10,9 +10,9 @@ use Skobkin\Bundle\PointToolsBundle\Exception\Factory\InvalidUserDataException;
class UserFactory extends AbstractFactory class UserFactory extends AbstractFactory
{ {
/** public const DATE_FORMAT = 'Y-m-d_H:i:s';
* @var UserRepository
*/ /** @var UserRepository */
private $userRepository; private $userRepository;
@ -55,6 +55,9 @@ class UserFactory extends AbstractFactory
return $user; return $user;
} }
/**
* @return User[]
*/
public function findOrCreateFromDTOArray(array $usersData): array public function findOrCreateFromDTOArray(array $usersData): array
{ {
// @todo LOG // @todo LOG

View file

@ -2,11 +2,12 @@
namespace Tests\Skobkin\PointToolsBundle\Controller; namespace Tests\Skobkin\PointToolsBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Client;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class MainControllerTest extends WebTestCase class MainControllerTest extends WebTestCase
{ {
public function testUserSearch() public function testUserSearch(): void
{ {
$client = static::createClient(); $client = static::createClient();
$crawler = $client->request('GET', '/'); $crawler = $client->request('GET', '/');
@ -19,7 +20,7 @@ class MainControllerTest extends WebTestCase
$this->assertTrue($client->getResponse()->isRedirect('/user/testuser'), 'Redirect to testuser\'s page didn\'t happen'); $this->assertTrue($client->getResponse()->isRedirect('/user/testuser'), 'Redirect to testuser\'s page didn\'t happen');
} }
public function testNonExistingUserSearch() public function testNonExistingUserSearch(): void
{ {
$client = static::createClient(); $client = static::createClient();
$crawler = $client->request('GET', '/'); $crawler = $client->request('GET', '/');
@ -49,7 +50,7 @@ class MainControllerTest extends WebTestCase
$this->assertEquals(' Login not found', $firstError->text(), 'Incorrect error text'); $this->assertEquals(' Login not found', $firstError->text(), 'Incorrect error text');
} }
public function testUserStats() public function testUserStats(): void
{ {
$client = static::createClient(); $client = static::createClient();
$crawler = $client->request('GET', '/'); $crawler = $client->request('GET', '/');
@ -75,14 +76,10 @@ class MainControllerTest extends WebTestCase
/** /**
* Tests AJAX user search autocomplete and returns JSON response string * Tests AJAX user search autocomplete and returns JSON response string
*
* @return string
*/ */
public function testAjaxUserAutoComplete() public function testAjaxUserAutoComplete(): string
{ {
$client = static::createClient(); $client = $this->createClientForAjaxUserSearchByLogin('testuser');
// We need to search all test user with 'testuser5' included which will test the code against null-string problem in User#getName()
$client->request('GET', '/ajax/users/search/testuser');
$this->assertTrue($client->getResponse()->headers->contains('Content-Type', 'application/json'), 'Response has "Content-Type" = "application/json"'); $this->assertTrue($client->getResponse()->headers->contains('Content-Type', 'application/json'), 'Response has "Content-Type" = "application/json"');
@ -91,26 +88,22 @@ class MainControllerTest extends WebTestCase
/** /**
* @depends testAjaxUserAutoComplete * @depends testAjaxUserAutoComplete
*
* @param $json
*/ */
public function testAjaxUserAutoCompleteHasOptions($json) public function testAjaxUserAutoCompleteHasOptions(string $json): array
{ {
$data = json_decode($json); $data = json_decode($json, true);
$this->assertNotNull($data, 'JSON data successfully decoded and not empty'); $this->assertNotNull($data, 'JSON data successfully decoded and not empty');
$this->assertTrue(is_array($data), 'JSON data is array'); $this->assertTrue(is_array($data), 'JSON data is array');
$this->assertCount(5, $data, 'Array has 5 elements'); $this->assertCount(2, $data, 'Array has 2 elements');
return $data; return $data;
} }
/** /**
* @depends testAjaxUserAutoCompleteHasOptions * @depends testAjaxUserAutoCompleteHasOptions
*
* @param array $users
*/ */
public function testAjaxUserAutoCompleteHasValidUserObjects(array $users) public function testAjaxUserAutoCompleteHasValidUserObjects(array $users): void
{ {
foreach ($users as $key => $user) { foreach ($users as $key => $user) {
$this->assertTrue(array_key_exists('login', $user), sprintf('%d row of result has \'login\' field', $key)); $this->assertTrue(array_key_exists('login', $user), sprintf('%d row of result has \'login\' field', $key));
@ -118,7 +111,43 @@ class MainControllerTest extends WebTestCase
} }
} }
public function testAjaxUserAutoCompleteForNonExistingUser() /**
* Tests AJAX user search autocomplete for unnamed user and returns JSON response string
*/
public function testAjaxUserAutoCompleteForUnnamedUser(): string
{
$client = $this->createClientForAjaxUserSearchByLogin('unnamed_user');
$this->assertTrue($client->getResponse()->headers->contains('Content-Type', 'application/json'), 'Response has "Content-Type" = "application/json"');
return $client->getResponse()->getContent();
}
/**
* @depends testAjaxUserAutoCompleteForUnnamedUser
*/
public function testAjaxUserAutoCompleteHasOptionsForUnnamedUser(string $json): array
{
$data = json_decode($json, true);
$this->assertNotNull($data, 'JSON data successfully decoded and not empty');
$this->assertInternalType('array', $data, 'JSON data is array');
$this->assertCount(1, $data, 'Array has 1 elements');
return reset($data);
}
/**
* @depends testAjaxUserAutoCompleteHasOptionsForUnnamedUser
*/
public function testAjaxUserAutoCompleteHasValidUserObjectsForUnnamedUser(array $user): void
{
$this->assertTrue(array_key_exists('login', $user), 'Result has \'login\' field');
$this->assertTrue(array_key_exists('name', $user), 'Result has \'name\' field');
$this->assertEquals(true, ('' === $user['name'] || null === $user['name']), 'User name is empty string or null');
}
public function testAjaxUserAutoCompleteIsEmptyForNonExistingUser(): void
{ {
$client = static::createClient(); $client = static::createClient();
$client->request('GET', '/ajax/users/search/aksdjhaskdjhqwhdgqkjwhdgkjah'); $client->request('GET', '/ajax/users/search/aksdjhaskdjhqwhdgqkjwhdgkjah');
@ -128,7 +157,15 @@ class MainControllerTest extends WebTestCase
$data = json_decode($client->getResponse()->getContent()); $data = json_decode($client->getResponse()->getContent());
$this->assertNotNull($data, 'JSON data successfully decoded and not empty'); $this->assertNotNull($data, 'JSON data successfully decoded and not empty');
$this->assertTrue(is_array($data), 'JSON data is array'); $this->assertInternalType('array', $data, 'JSON data is array');
$this->assertEquals(0, count($data), 'Array has no elements'); $this->assertCount(0, $data, 'Array has no elements');
}
private function createClientForAjaxUserSearchByLogin(string $login): Client
{
$client = static::createClient();
$client->request('GET', '/ajax/users/search/'.$login);
return $client;
} }
} }

View file

@ -2,15 +2,15 @@
namespace Tests\Skobkin\PointToolsBundle\Controller; namespace Tests\Skobkin\PointToolsBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Skobkin\Bundle\PointToolsBundle\DataFixtures\ORM\LoadPostData;
use Symfony\Bundle\FrameworkBundle\{Client, Test\WebTestCase};
use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\DomCrawler\Crawler;
class PostControllerTest extends WebTestCase class PostControllerTest extends WebTestCase
{ {
public function testNonExistingPostPage() public function testNonExistingPostPage()
{ {
$client = static::createClient(); $client = $this->createClientForPostId('nonexistingpost');
$client->request('GET', '/nonexistingpost');
$this->assertTrue($client->getResponse()->isNotFound(), '404 response code for non-existing post'); $this->assertTrue($client->getResponse()->isNotFound(), '404 response code for non-existing post');
} }
@ -20,12 +20,11 @@ class PostControllerTest extends WebTestCase
*/ */
public function testShortPostPageIsOk() public function testShortPostPageIsOk()
{ {
$client = static::createClient(); $client = $this->createClientForPostId(LoadPostData::POST_ID_SHORT);
$crawler = $client->request('GET', '/shortpost');
$this->assertTrue($client->getResponse()->isOk(), '200 response code for existing post'); $this->assertTrue($client->getResponse()->isOk(), '200 response code for existing post');
return $crawler; return $client->getCrawler();
} }
/** /**
@ -58,4 +57,33 @@ class PostControllerTest extends WebTestCase
$this->assertEquals(1, $p->count(), '.post-text has zero or more than one paragraphs'); $this->assertEquals(1, $p->count(), '.post-text has zero or more than one paragraphs');
$this->assertEquals('Test short post', $p->text(), '.post-text has no correct post text'); $this->assertEquals('Test short post', $p->text(), '.post-text has no correct post text');
} }
public function testPrivateUserPostForbidden()
{
$client = $this->createClientForPostId(LoadPostData::POST_ID_PR_USER);
$this->assertTrue($client->getResponse()->isNotFound(), '404 response code for private user\'s post');
}
public function testWhitelistOnlyUserPostForbidden()
{
$client = $this->createClientForPostId(LoadPostData::POST_ID_WL_USER);
$this->assertTrue($client->getResponse()->isNotFound(), '404 response code for whitelist-only user\'s post');
}
public function testPrivateWhitelistOnlyUserPostForbidden()
{
$client = $this->createClientForPostId(LoadPostData::POST_ID_PR_WL_USER);
$this->assertTrue($client->getResponse()->isNotFound(), '404 response code for private whitelist-only user\'s post');
}
private function createClientForPostId(string $id): Client
{
$client = static::createClient();
$client->request('GET', '/'.$id);
return $client;
}
} }

View file

@ -32,7 +32,7 @@ class UserRepositoryTest extends KernelTestCase
{ {
$users = $this->userRepo->findAll(); $users = $this->userRepo->findAll();
$this->assertCount(5, $users, 'Not exactly 5 users in the databas'); $this->assertCount(6, $users, 'Not exactly 6 users in the databas');
} }
public function testFindOneByLogin() public function testFindOneByLogin()
@ -58,14 +58,14 @@ class UserRepositoryTest extends KernelTestCase
// Searching LIKE %stus% (testuserX) // Searching LIKE %stus% (testuserX)
$users = $this->userRepo->findUsersLikeLogin('stus'); $users = $this->userRepo->findUsersLikeLogin('stus');
$this->assertCount(5, $users, 'Repository found not exactly 5 users'); $this->assertCount(2, $users, 'Repository found not exactly 5 users');
} }
public function testGetUsersCount() public function testGetUsersCount()
{ {
$count = $this->userRepo->getUsersCount(); $count = $this->userRepo->getUsersCount();
$this->assertEquals(5, $count, 'Counted not exactly 5 users'); $this->assertEquals(6, $count, 'Counted not exactly 5 users');
} }
public function testFindUserSubscribersById() public function testFindUserSubscribersById()

View file

@ -0,0 +1,141 @@
<?php
namespace Tests\Skobkin\PointToolsBundle\Service\Factory;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Skobkin\Bundle\PointToolsBundle\DTO\Api\User as UserDTO;
use Skobkin\Bundle\PointToolsBundle\Entity\User;
use Skobkin\Bundle\PointToolsBundle\Exception\Factory\InvalidUserDataException;
use Skobkin\Bundle\PointToolsBundle\Repository\UserRepository;
use Skobkin\Bundle\PointToolsBundle\Service\Factory\UserFactory;
class UserFactoryTest extends TestCase
{
private const LOCAL_USER_ID = 1;
private const LOCAL_USER_LOGIN = 'test-local';
private const LOCAL_USER_NAME = 'Test Local Name';
private const LOCAL_USER_CREATED = '1999-01-01_01:02:03';
private const REMOTE_USER_ID = 1;
private const REMOTE_USER_LOGIN = 'test-remote';
private const REMOTE_USER_NAME = 'Test Remote Name';
private const REMOTE_USER_CREATED = '2000-01-01_01:02:03';
public function testCreateFactory(): UserFactory
{
$testUser = new User(
self::LOCAL_USER_ID,
\DateTime::createFromFormat(UserFactory::DATE_FORMAT, self::LOCAL_USER_CREATED),
self::LOCAL_USER_LOGIN,
self::LOCAL_USER_NAME
);
$logger = $this->createMock(LoggerInterface::class);
$userRepository = $this->createMock(UserRepository::class);
$userRepository->expects($this->any())
->method('find')
->willReturnCallback(
function ($id) use ($testUser) {
if (1 === $id) {
return $testUser;
}
return null;
}
);
$userFactory = new UserFactory($logger, $userRepository);
$this->assertInstanceOf(UserFactory::class, $userFactory);
return $userFactory;
}
/**
* @dataProvider userDtoProvider
* @depends testCreateFactory
*/
public function testFindOrCreateFromDTO(UserDTO $userDto, UserFactory $userFactory)
{
$foundUser = $userFactory->findOrCreateFromDTO($userDto);
$this->assertInstanceOf(User::class, $foundUser);
$this->assertEquals(self::LOCAL_USER_ID, $foundUser->getId());
$this->assertEquals(self::REMOTE_USER_NAME, $foundUser->getName());
$this->assertEquals(self::REMOTE_USER_LOGIN, $foundUser->getLogin());
$testDate = \DateTime::createFromFormat(UserFactory::DATE_FORMAT, self::REMOTE_USER_CREATED);
$this->assertEquals($testDate, $foundUser->getCreatedAt());
}
/**
* @dataProvider userDtoArrayProvider
* @depends testCreateFactory
*/
public function testFindOrCreateFromDTOArray(array $userData, UserFactory $userFactory)
{
$foundUsers = $userFactory->findOrCreateFromDTOArray($userData);
$this->assertCount(2, $foundUsers);
$this->assertContainsOnlyInstancesOf(User::class, $foundUsers);
$testDate = \DateTime::createFromFormat(UserFactory::DATE_FORMAT, self::REMOTE_USER_CREATED);
$this->assertEquals(self::REMOTE_USER_ID, $foundUsers[0]->getId());
$this->assertEquals(self::REMOTE_USER_LOGIN, $foundUsers[0]->getLogin());
$this->assertEquals(self::REMOTE_USER_NAME, $foundUsers[0]->getName());
$this->assertEquals($testDate, $foundUsers[0]->getCreatedAt());
$this->assertEquals(self::REMOTE_USER_ID + 1, $foundUsers[1]->getId());
$this->assertEquals(self::REMOTE_USER_LOGIN, $foundUsers[1]->getLogin());
$this->assertEquals(self::REMOTE_USER_NAME, $foundUsers[1]->getName());
$this->assertEquals($testDate, $foundUsers[1]->getCreatedAt());
}
/**
* @dataProvider invalidUserDtoProvider
* @depends testCreateFactory
*/
public function testFindOrCreateFromDTOWithInvalidDTO(UserDTO $userDto, UserFactory $userFactory)
{
$this->expectException(InvalidUserDataException::class);
$foundUser = $userFactory->findOrCreateFromDTO($userDto);
}
public function userDtoProvider(): array
{
$userDto = new UserDTO();
$userDto->setId(self::REMOTE_USER_ID);
$userDto->setLogin(self::REMOTE_USER_LOGIN);
$userDto->setName(self::REMOTE_USER_NAME);
$userDto->setCreated(self::REMOTE_USER_CREATED);
return [[$userDto]];
}
public function userDtoArrayProvider(): array
{
$userDto1 = new UserDTO();
$userDto1->setId(self::REMOTE_USER_ID);
$userDto1->setLogin(self::REMOTE_USER_LOGIN);
$userDto1->setName(self::REMOTE_USER_NAME);
$userDto1->setCreated(self::REMOTE_USER_CREATED);
$userDto2 = new UserDTO();
$userDto2->setId(self::REMOTE_USER_ID + 1);
$userDto2->setLogin(self::REMOTE_USER_LOGIN);
$userDto2->setName(self::REMOTE_USER_NAME);
$userDto2->setCreated(self::REMOTE_USER_CREATED);
return [[[$userDto1, $userDto2]]];
}
public function invalidUserDtoProvider(): array
{
return [[new UserDTO()]];
}
}