Tests, translations Entries, Posts
This commit is contained in:
parent
00eba82768
commit
f7f1572190
|
@ -6,7 +6,7 @@ PANTHER_APP_ENV=panther
|
|||
DATABASE_URL="postgresql://symfony:ChangeMe@127.0.0.1:5432/app_test?serverVersion=13&charset=utf8"
|
||||
MAILER_DSN=null://default
|
||||
KBIN_JS_ENABLED=false
|
||||
KBIN_DEFAULT_LANG=pl
|
||||
KBIN_DEFAULT_LANG=en
|
||||
KBIN_DOMAIN=kbin.test
|
||||
ELASTICSEARCH_ENABLED=false
|
||||
KBIN_API_ITEMS_PER_PAGE=2
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,9 +1,10 @@
|
|||
.kbin-page-login,
|
||||
.kbin-page-register,
|
||||
.kbin-page-reset-password {
|
||||
.kbin-page-reset-password,
|
||||
.kbin-page-reset-password-email-sent {
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
max-width: 35rem;
|
||||
max-width: 30rem;
|
||||
|
||||
p {
|
||||
margin-bottom: .5rem;
|
||||
|
@ -47,3 +48,10 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.kbin-page-reset-password-email-sent {
|
||||
p:last-of-type {
|
||||
margin-top: 2rem;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
}
|
||||
|
||||
button {
|
||||
height: 100%;
|
||||
padding-bottom: .5rem;
|
||||
padding-top: .5rem;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
}
|
||||
|
||||
button {
|
||||
height: 100%;
|
||||
padding-bottom: .5rem;
|
||||
padding-top: .5rem;
|
||||
}
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
front:
|
||||
controller: App\Controller\Entry\FrontController::front
|
||||
controller: App\Controller\Entry\EntryFrontController::front
|
||||
defaults: { sortBy: ~, time: '∞', type: ~ }
|
||||
path: /{sortBy}/{time}/{type}
|
||||
methods: [GET]
|
||||
requirements: { sortBy: "%front_sort_options%" }
|
||||
|
||||
front_subscribed:
|
||||
controller: App\Controller\Entry\FrontController::subscribed
|
||||
controller: App\Controller\Entry\EntryFrontController::subscribed
|
||||
defaults: { sortBy: ~, time: '∞', type: ~ }
|
||||
path: /sub/{sortBy}/{time}/{type}
|
||||
methods: [GET]
|
||||
requirements: { sortBy: "%front_sort_options%" }
|
||||
|
||||
front_moderated:
|
||||
controller: App\Controller\Entry\FrontController::moderated
|
||||
controller: App\Controller\Entry\EntryFrontController::moderated
|
||||
defaults: { sortBy: ~, time: '∞', type: ~ }
|
||||
path: /mod/{sortBy}/{time}/{type}
|
||||
methods: [GET]
|
||||
requirements: { sortBy: "%front_sort_options%" }
|
||||
|
||||
front_favourite:
|
||||
controller: App\Controller\Entry\FrontController::favourite
|
||||
controller: App\Controller\Entry\EntryFrontController::favourite
|
||||
defaults: { sortBy: ~, time: '∞', type: ~ }
|
||||
path: /fav/{sortBy}/{time}/{type}
|
||||
methods: [GET]
|
||||
requirements: { sortBy: "%front_sort_options%" }
|
||||
|
||||
front_magazine:
|
||||
controller: App\Controller\Entry\FrontController::magazine
|
||||
controller: App\Controller\Entry\EntryFrontController::magazine
|
||||
defaults: { sortBy: ~, time: '∞', type: ~ }
|
||||
path: /m/{name}/{sortBy}/{time}/{type}
|
||||
methods: [GET]
|
||||
|
|
|
@ -3,7 +3,7 @@ post_comment_create:
|
|||
defaults: { slug: -, parent_comment_id: null }
|
||||
path:
|
||||
en: /m/{magazine_name}/p/{post_id}/{slug}/reply/{parent_comment_id}
|
||||
pl: /m/{magazine_name}/p/{post_id}/{slug}/odpowiedź/{parent_comment_id}
|
||||
pl: /m/{magazine_name}/w/{post_id}/{slug}/odpowiedź/{parent_comment_id}
|
||||
methods: [ GET, POST ]
|
||||
|
||||
post_comment_edit:
|
||||
|
@ -11,7 +11,7 @@ post_comment_edit:
|
|||
defaults: { slug: -, }
|
||||
path:
|
||||
en: /m/{magazine_name}/p/{post_id}/{slug}/reply/{comment_id}/edit
|
||||
pl: /m/{magazine_name}/p/{post_id}/{slug}/odpowiedź/{comment_id}/edytuj
|
||||
pl: /m/{magazine_name}/w/{post_id}/{slug}/odpowiedź/{comment_id}/edytuj
|
||||
methods: [ GET, POST ]
|
||||
|
||||
post_comment_delete:
|
||||
|
@ -43,7 +43,7 @@ post_comment_voters:
|
|||
defaults: { slug: -, }
|
||||
path:
|
||||
en: /m/{magazine_name}/p/{post_id}/{slug}/reply/{comment_id}/votes
|
||||
pl: /m/{magazine_name}/p/{post_id}/{slug}/odpowiedź/{comment_id}/głosy
|
||||
pl: /m/{magazine_name}/w/{post_id}/{slug}/odpowiedź/{comment_id}/głosy
|
||||
methods: [ GET ]
|
||||
|
||||
post_comment_favourites:
|
||||
|
@ -51,7 +51,7 @@ post_comment_favourites:
|
|||
defaults: { slug: -, }
|
||||
path:
|
||||
en: /m/{magazine_name}/p/{post_id}/{slug}/reply/{comment_id}/favourites
|
||||
pl: /m/{magazine_name}/p/{post_id}/{slug}/odpowiedź/{comment_id}/ulubione
|
||||
pl: /m/{magazine_name}/w/{post_id}/{slug}/odpowiedź/{comment_id}/ulubione
|
||||
methods: [ GET ]
|
||||
|
||||
post_comment_vote:
|
||||
|
@ -122,7 +122,7 @@ post_voters:
|
|||
defaults: { slug: -, sortBy: ~ }
|
||||
path:
|
||||
en: /m/{magazine_name}/p/{post_id}/{slug}/votes
|
||||
pl: /m/{magazine_name}/p/{post_id}/{slug}/głosy
|
||||
pl: /m/{magazine_name}/w/{post_id}/{slug}/głosy
|
||||
methods: [ GET ]
|
||||
|
||||
post_favourites:
|
||||
|
@ -130,7 +130,7 @@ post_favourites:
|
|||
defaults: { slug: -, sortBy: ~ }
|
||||
path:
|
||||
en: /m/{magazine_name}/p/{post_id}/{slug}/favourites
|
||||
pl: /m/{magazine_name}/p/{post_id}/{slug}/ulubione
|
||||
pl: /m/{magazine_name}/w/{post_id}/{slug}/ulubione
|
||||
methods: [ GET ]
|
||||
|
||||
post_single:
|
||||
|
@ -138,7 +138,7 @@ post_single:
|
|||
defaults: { slug: -, sortBy: ~ }
|
||||
path:
|
||||
en: /m/{magazine_name}/p/{post_id}/{slug}/{sortBy}
|
||||
pl: /m/{magazine_name}/p/{post_id}/{slug}/{sortBy}
|
||||
pl: /m/{magazine_name}/w/{post_id}/{slug}/{sortBy}
|
||||
methods: [ GET ]
|
||||
|
||||
post_create:
|
||||
|
@ -151,7 +151,7 @@ post_edit:
|
|||
defaults: { slug: -, }
|
||||
path:
|
||||
en: /m/{magazine_name}/p/{post_id}/{slug}/edit
|
||||
pl: /m/{magazine_name}/p/{post_id}/{slug}/edytuj
|
||||
pl: /m/{magazine_name}/w/{post_id}/{slug}/edytuj
|
||||
methods: [ GET, POST ]
|
||||
|
||||
post_delete:
|
||||
|
|
|
@ -15,7 +15,7 @@ use Symfony\Component\HttpFoundation\JsonResponse;
|
|||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class FrontController extends AbstractController
|
||||
class EntryFrontController extends AbstractController
|
||||
{
|
||||
public function __construct(private readonly EntryRepository $repository)
|
||||
{
|
||||
|
@ -78,7 +78,7 @@ class FrontController extends AbstractController
|
|||
}
|
||||
|
||||
return $this->render(
|
||||
'front/front.html.twig',
|
||||
'entry/front.html.twig',
|
||||
[
|
||||
'entries' => $listing,
|
||||
]
|
||||
|
@ -111,7 +111,7 @@ class FrontController extends AbstractController
|
|||
}
|
||||
|
||||
return $this->render(
|
||||
'front/front.html.twig',
|
||||
'entry/front.html.twig',
|
||||
[
|
||||
'entries' => $listing,
|
||||
]
|
||||
|
@ -144,7 +144,7 @@ class FrontController extends AbstractController
|
|||
}
|
||||
|
||||
return $this->render(
|
||||
'front/front.html.twig',
|
||||
'entry/front.html.twig',
|
||||
[
|
||||
'entries' => $listing,
|
||||
]
|
|
@ -20,7 +20,7 @@ class EntryVotersController extends AbstractController
|
|||
public function __invoke(string $type, Magazine $magazine, Entry $entry, Request $request): Response
|
||||
{
|
||||
$votes = $entry->votes->filter(
|
||||
fn($e) => $e->choice === ($type === 'up' ? VoteInterface::VOTE_UP : VoteInterface::VOTE_DOWN)
|
||||
fn ($e) => $e->choice === ('up' === $type ? VoteInterface::VOTE_UP : VoteInterface::VOTE_DOWN)
|
||||
);
|
||||
|
||||
if ($request->isXmlHttpRequest()) {
|
||||
|
|
|
@ -19,6 +19,7 @@ use App\Repository\PostCommentRepository;
|
|||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Doctrine\ORM\Mapping\Cache;
|
||||
use Doctrine\ORM\Mapping\Column;
|
||||
use Doctrine\ORM\Mapping\Entity;
|
||||
use Doctrine\ORM\Mapping\GeneratedValue;
|
||||
|
|
|
@ -18,11 +18,11 @@ class UserChecker implements UserCheckerInterface
|
|||
}
|
||||
|
||||
if (!$user->isVerified) {
|
||||
throw new CustomUserMessageAccountStatusException('Twoje konto nie jest aktywne.');
|
||||
throw new CustomUserMessageAccountStatusException('Your account is not active.');
|
||||
}
|
||||
|
||||
if ($user->isBanned) {
|
||||
throw new CustomUserMessageAccountStatusException('Twoje konto jest zbanowane.');
|
||||
throw new CustomUserMessageAccountStatusException('Your account has been banned.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,5 +8,7 @@ use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
|
|||
#[AsTwigComponent('entry_comment')]
|
||||
final class EntryCommentComponent
|
||||
{
|
||||
public EntryComment $comment;
|
||||
public EntryComment $comment;
|
||||
public bool $showMagazine = true;
|
||||
public bool $showEntry = true;
|
||||
}
|
||||
|
|
12
src/Twig/Components/EntryInlineComponent.php
Normal file
12
src/Twig/Components/EntryInlineComponent.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace App\Twig\Components;
|
||||
|
||||
use App\Entity\Entry;
|
||||
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
|
||||
|
||||
#[AsTwigComponent('entry_inline')]
|
||||
final class EntryInlineComponent
|
||||
{
|
||||
public Entry $entry;
|
||||
}
|
|
@ -11,11 +11,14 @@ final class PostComponent
|
|||
{
|
||||
public Post $post;
|
||||
public bool $isSingle = false;
|
||||
public bool $showMagazine = true;
|
||||
|
||||
#[PostMount]
|
||||
public function postMount(array $attr): array
|
||||
{
|
||||
if ($this->isSingle) {
|
||||
$this->showMagazine = false;
|
||||
|
||||
if (isset($attr['class'])) {
|
||||
$attr['class'] = trim('kbin-post--single '.$attr['class']);
|
||||
} else {
|
||||
|
|
|
@ -10,9 +10,9 @@ use Symfony\UX\TwigComponent\Attribute\PostMount;
|
|||
#[AsTwigComponent('related_posts')]
|
||||
final class RelatedPostsComponent
|
||||
{
|
||||
const TYPE_TAG = 'tag';
|
||||
const TYPE_MAGAZINE = 'magazine';
|
||||
const TYPE_RANDOM = 'random';
|
||||
public const TYPE_TAG = 'tag';
|
||||
public const TYPE_MAGAZINE = 'magazine';
|
||||
public const TYPE_RANDOM = 'random';
|
||||
|
||||
public int $limit = 4;
|
||||
public ?string $tag = null;
|
||||
|
@ -56,5 +56,4 @@ final class RelatedPostsComponent
|
|||
|
||||
return $posts;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,9 @@ final class ContextExtension extends AbstractExtension
|
|||
return [
|
||||
new TwigFunction('is_route_name', [ContextExtensionRuntime::class, 'isRouteName']),
|
||||
new TwigFunction('is_route_name_contains', [ContextExtensionRuntime::class, 'isRouteNameContains']),
|
||||
new TwigFunction('is_route_name_end_with', [ContextExtensionRuntime::class, 'isRouteNameEndWith']),
|
||||
new TwigFunction('route_has_param', [ContextExtensionRuntime::class, 'routeHasParam']),
|
||||
new TwigFunction('get_active_sort_option', [ContextExtensionRuntime::class, 'getActiveSortOption']),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,7 @@ use Twig\Extension\AbstractExtension;
|
|||
use Twig\TwigFilter;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
final class
|
||||
FormattingExtension extends AbstractExtension
|
||||
final class FormattingExtension extends AbstractExtension
|
||||
{
|
||||
public function getFilters(): array
|
||||
{
|
||||
|
|
|
@ -4,7 +4,6 @@ namespace App\Twig\Extension;
|
|||
|
||||
use App\Twig\Runtime\NavbarExtensionRuntime;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
class NavbarExtension extends AbstractExtension
|
||||
|
|
|
@ -4,7 +4,6 @@ namespace App\Twig\Extension;
|
|||
|
||||
use App\Twig\Runtime\OptionsExtensionRuntime;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
class OptionsExtension extends AbstractExtension
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace App\Twig\Extension;
|
||||
|
||||
use App\Twig\Runtime\MagazineExtensionRuntime;
|
||||
use App\Twig\Runtime\UserExtensionRuntime;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
|
|
|
@ -18,6 +18,11 @@ class ContextExtensionRuntime implements RuntimeExtensionInterface
|
|||
return str_contains($this->getCurrentRouteName(), $needle);
|
||||
}
|
||||
|
||||
public function isRouteNameEndWith(string $needle): bool
|
||||
{
|
||||
return str_ends_with($this->getCurrentRouteName(), $needle);
|
||||
}
|
||||
|
||||
public function isRouteName(string $needle): bool
|
||||
{
|
||||
return $this->getCurrentRouteName() === $needle;
|
||||
|
@ -32,4 +37,9 @@ class ContextExtensionRuntime implements RuntimeExtensionInterface
|
|||
{
|
||||
return $this->requestStack->getCurrentRequest()->get('_route') ?? 'front';
|
||||
}
|
||||
|
||||
public function getActiveSortOption(): string
|
||||
{
|
||||
return $this->requestStack->getCurrentRequest()->get('sortBy') ?? 'hot';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@ class LinkExtensionRuntime implements RuntimeExtensionInterface
|
|||
{
|
||||
if ($this->settingsManager->get('KBIN_DOMAIN') === parse_url($url, PHP_URL_HOST)) {
|
||||
return 'follow';
|
||||
};
|
||||
}
|
||||
|
||||
return 'nofollow noopener noreferrer';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,41 +17,57 @@ class NavbarExtensionRuntime implements RuntimeExtensionInterface
|
|||
public function navbarThreadsUrl(): string
|
||||
{
|
||||
if ($magazine = $this->requestStack->getCurrentRequest()->get('magazine')) {
|
||||
return $this->entriesMagazine($magazine->name);
|
||||
return $this->urlGenerator->generate('front_magazine', ['name' => $magazine->name]);
|
||||
}
|
||||
|
||||
return $this->front();
|
||||
if ($domain = $this->requestStack->getCurrentRequest()->get('domain')) {
|
||||
return $this->urlGenerator->generate('domain_front', ['name' => $domain->name]);
|
||||
}
|
||||
|
||||
if ($tag = $this->requestStack->getCurrentRequest()->get('tag')) {
|
||||
return $this->urlGenerator->generate('tag_overall', ['name' => $tag]);
|
||||
}
|
||||
|
||||
if (str_ends_with($this->getCurrentRouteName(), '_subscribed')) {
|
||||
return $this->urlGenerator->generate('front_subscribed');
|
||||
}
|
||||
|
||||
if (str_ends_with($this->getCurrentRouteName(), '_favourite')) {
|
||||
return $this->urlGenerator->generate('front_favourite');
|
||||
}
|
||||
|
||||
if (str_ends_with($this->getCurrentRouteName(), '_moderated')) {
|
||||
return $this->urlGenerator->generate('front_moderated');
|
||||
}
|
||||
|
||||
return $this->urlGenerator->generate('front');
|
||||
}
|
||||
|
||||
public function navbarPostsUrl(): string
|
||||
{
|
||||
if ($magazine = $this->requestStack->getCurrentRequest()->get('magazine')) {
|
||||
return $this->postsMagazine($magazine->name);
|
||||
return $this->urlGenerator->generate('magazine_posts', ['name' => $magazine->name]);
|
||||
}
|
||||
|
||||
return $this->posts();
|
||||
}
|
||||
if ($tag = $this->requestStack->getCurrentRequest()->get('tag')) {
|
||||
return $this->urlGenerator->generate('tag_posts_front', ['name' => $tag]);
|
||||
}
|
||||
|
||||
private function front(): string
|
||||
{
|
||||
return $this->urlGenerator->generate('front');
|
||||
}
|
||||
if (str_ends_with($this->getCurrentRouteName(), '_subscribed')) {
|
||||
return $this->urlGenerator->generate('posts_subscribed');
|
||||
}
|
||||
|
||||
private function entriesMagazine(string $name): string
|
||||
{
|
||||
return $this->urlGenerator->generate('front_magazine', ['name' => $name]);
|
||||
}
|
||||
if (str_ends_with($this->getCurrentRouteName(), '_favourite')) {
|
||||
return $this->urlGenerator->generate('posts_favourite');
|
||||
}
|
||||
|
||||
if (str_ends_with($this->getCurrentRouteName(), '_moderated')) {
|
||||
return $this->urlGenerator->generate('posts_moderated');
|
||||
}
|
||||
|
||||
private function posts(): string
|
||||
{
|
||||
return $this->urlGenerator->generate('posts_front');
|
||||
}
|
||||
|
||||
private function postsMagazine(string $name): string
|
||||
{
|
||||
return $this->urlGenerator->generate('magazine_posts', ['name' => $name]);
|
||||
}
|
||||
|
||||
private function getCurrentRouteName(): string
|
||||
{
|
||||
return $this->requestStack->getCurrentRequest()->get('_route') ?? 'front';
|
||||
|
|
|
@ -38,7 +38,7 @@ class OptionsExtensionRuntime implements RuntimeExtensionInterface
|
|||
return true;
|
||||
}
|
||||
|
||||
if (null === $params[$name] && $value == EntryRepository::SORT_DEFAULT) {
|
||||
if (null === $params[$name] && EntryRepository::SORT_DEFAULT == $value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class UrlExtensionRuntime implements RuntimeExtensionInterface
|
|||
return $this->urlGenerator->generate('entry_single', [
|
||||
'magazine_name' => $entry->magazine->name,
|
||||
'entry_id' => $entry->getId(),
|
||||
'slug' => $entry->slug === '' ? 'icon' : $entry->slug,
|
||||
'slug' => '' === $entry->slug ? 'icon' : $entry->slug,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ class UrlExtensionRuntime implements RuntimeExtensionInterface
|
|||
return $this->urlGenerator->generate('entry_favourites', [
|
||||
'magazine_name' => $entry->magazine->name,
|
||||
'entry_id' => $entry->getId(),
|
||||
'slug' => $entry->slug === '' ? 'icon' : $entry->slug,
|
||||
'slug' => '' === $entry->slug ? 'icon' : $entry->slug,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ class UrlExtensionRuntime implements RuntimeExtensionInterface
|
|||
return $this->urlGenerator->generate('entry_voters', [
|
||||
'magazine_name' => $entry->magazine->name,
|
||||
'entry_id' => $entry->getId(),
|
||||
'slug' => $entry->slug === '' ? 'icon' : $entry->slug,
|
||||
'slug' => '' === $entry->slug ? 'icon' : $entry->slug,
|
||||
'type' => $type,
|
||||
]);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ class UrlExtensionRuntime implements RuntimeExtensionInterface
|
|||
return $this->urlGenerator->generate('post_single', [
|
||||
'magazine_name' => $post->magazine->name,
|
||||
'post_id' => $post->getId(),
|
||||
'slug' => $post->slug === '' ? 'icon' : $post->slug,
|
||||
'slug' => '' === $post->slug ? 'icon' : $post->slug,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ class UrlExtensionRuntime implements RuntimeExtensionInterface
|
|||
return $this->urlGenerator->generate('post_favourites', [
|
||||
'magazine_name' => $post->magazine->name,
|
||||
'post_id' => $post->getId(),
|
||||
'slug' => $post->slug === '' ? 'icon' : $post->slug,
|
||||
'slug' => '' === $post->slug ? 'icon' : $post->slug,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ class UrlExtensionRuntime implements RuntimeExtensionInterface
|
|||
return $this->urlGenerator->generate('post_voters', [
|
||||
'magazine_name' => $post->magazine->name,
|
||||
'post_id' => $post->getId(),
|
||||
'slug' => $post->slug === '' ? 'icon' : $post->slug,
|
||||
'slug' => '' === $post->slug ? 'icon' : $post->slug,
|
||||
'type' => $type,
|
||||
]);
|
||||
}
|
||||
|
|
12
templates/_email/confirmation_email.html.twig
Normal file
12
templates/_email/confirmation_email.html.twig
Normal file
|
@ -0,0 +1,12 @@
|
|||
<h1>{{ 'email_confirm_header'|trans }}</h1>
|
||||
|
||||
<p>
|
||||
{{ 'email_confirm_content'|trans }} <br><br>
|
||||
<a href="{{ signedUrl|raw }}">{{ 'email_verify'|trans }}</a>.
|
||||
{{ 'email_confirm_expire'|trans }}
|
||||
{# Link wygaśnie za {{ expiresAtMessageKey|trans(expiresAtMessageData, 'VerifyEmailBundle') }}. #}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Cheers!
|
||||
</p>
|
8
templates/_email/contact.html.twig
Normal file
8
templates/_email/contact.html.twig
Normal file
|
@ -0,0 +1,8 @@
|
|||
<h1>{{ 'contact'|trans }}</h1>
|
||||
|
||||
<ul>
|
||||
<li>{{ name }}</li>
|
||||
<li>{{ senderEmail }}</li>
|
||||
</ul>
|
||||
|
||||
<p>{{ message }}</p>
|
6
templates/_email/delete_account_request.html.twig
Normal file
6
templates/_email/delete_account_request.html.twig
Normal file
|
@ -0,0 +1,6 @@
|
|||
<h1>User delete account</h1>
|
||||
|
||||
<ul>
|
||||
<li>{{ username }}</li>
|
||||
<li>{{ mail }}</li>
|
||||
</ul>
|
|
@ -2,6 +2,8 @@
|
|||
<header>
|
||||
{{ component('user_inline', {user: this.comment.user}) }},
|
||||
{{ component('date', {date: this.comment.createdAt}) }}
|
||||
{% if this.showMagazine %}{{ 'to'|trans }} {{ component('magazine_inline', {magazine: this.comment.magazine}) }}{% endif %}
|
||||
{% if this.showEntry %}{{ 'in'|trans }} {{ component('entry_inline', {entry: this.comment.entry}) }}{% endif %}
|
||||
</header>
|
||||
{% if this.comment.user.avatar %}
|
||||
{{ component('user_avatar', {user: this.comment.user, width: 40, height: 40}) }}
|
||||
|
|
1
templates/components/entry_inline.html.twig
Normal file
1
templates/components/entry_inline.html.twig
Normal file
|
@ -0,0 +1 @@
|
|||
<a href="{{ path('entry_single', {magazine_name: this.entry.magazine.name, entry_id: this.entry.id, slug: this.entry.slug }) }}">{{ this.entry.title }}</a>
|
|
@ -2,7 +2,7 @@
|
|||
<header>
|
||||
{{ component('user_inline', {user: this.post.user}) }},
|
||||
<a href="{{ post_url(this.post) }}"
|
||||
class="kbin-link-muted">{{ component('date', {date: this.post.createdAt}) }}</a>
|
||||
class="kbin-link-muted">{{ component('date', {date: this.post.createdAt}) }}</a> {% if this.showMagazine %}{{ 'to'|trans }} {{ component('magazine_inline', {magazine: this.post.magazine}) }}{% endif %}
|
||||
</header>
|
||||
{% if this.post.user.avatar %}
|
||||
{{ component('user_avatar', {user: this.post.user, width: 40, height: 40}) }}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<aside class="kbin-comments kbin-entry-comments">
|
||||
{% for comment in comments %}
|
||||
{{ component('entry_comment', {comment: comment}) }}
|
||||
{{ component('entry_comment', {comment: comment, showMagazine: magazine is not defined or not magazine, showEntry: entry is not defined or not entry}) }}
|
||||
{% endfor %}
|
||||
</aside>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<aside class="kbin-options" id="kbin-comments-options">
|
||||
<div class="kbin-options__title"><h2>{{ 'comments'|trans }} (0)</h2></div>
|
||||
<div class="kbin-options__title"><h2>{{ 'comments'|trans }} ({{ entry.commentCount }})</h2></div>
|
||||
<menu class="kbin-options__sort">
|
||||
<li>
|
||||
<a href="{{ options_url('sortBy', 'top'|trans|lower) }}"
|
|
@ -6,9 +6,8 @@
|
|||
<div id="kbin-content">
|
||||
{{ component('entry', {entry: entry, isSingle: true, showShortSentence: false, showBody:false}) }}
|
||||
|
||||
{% include 'entry/comment/_options_sort.html.twig' %}
|
||||
{% include 'entry/comment/_options.html.twig' %}
|
||||
{{ component('entry_comment', {comment: parent}) }}
|
||||
{% include 'entry/comment/_add_comment.html.twig' %}
|
||||
{% include 'entry/_options_activity.html.twig' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
27
templates/entry/comment/front.html.twig
Normal file
27
templates/entry/comment/front.html.twig
Normal file
|
@ -0,0 +1,27 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{%- block title -%}
|
||||
title
|
||||
{%- endblock -%}
|
||||
|
||||
{% block mainClass %}kbin-page-entry-front{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% if magazine is defined and magazine %}
|
||||
<h1 hidden>{{ magazine.title }}</h1>
|
||||
<h2>{{ get_active_sort_option()|trans }}</h2>
|
||||
{% else %}
|
||||
<h1 hidden>{{ get_active_sort_option()|trans }}</h1>
|
||||
{% endif %}
|
||||
{% include 'entry/_options.html.twig' %}
|
||||
{% if magazine is defined and magazine %}
|
||||
{% if magazine.apId %}
|
||||
<div class="kbin-alert kbin-alert__info">
|
||||
<p>{{ 'federated_magazine_info'|trans }} <a
|
||||
href="{{ magazine.apProfileId }}">{{ 'go_to_original_instance'|trans }}</a></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% include 'entry/comment/_list.html.twig' %}
|
||||
{% endblock %}
|
||||
|
|
@ -8,7 +8,12 @@
|
|||
|
||||
{% block body %}
|
||||
<header>
|
||||
<h1 hidden>{{ 'hot'|trans }}</h1>
|
||||
{% if magazine is defined and magazine %}
|
||||
<h1 hidden>{{ magazine.title }}</h1>
|
||||
<h2 hidden>{{ get_active_sort_option()|trans }}</h2>
|
||||
{% else %}
|
||||
<h1 hidden>{{ get_active_sort_option()|trans }}</h1>
|
||||
{% endif %}
|
||||
</header>
|
||||
{% include 'entry/_options.html.twig' %}
|
||||
{% if magazine is defined and magazine %}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<div id="kbin-content">
|
||||
{{ component('entry', {entry: entry, isSingle: true, showShortSentence: false, showBody:true}) }}
|
||||
|
||||
{% include 'entry/comment/_options_sort.html.twig' %}
|
||||
{% include 'entry/comment/_options.html.twig' %}
|
||||
{% if comments|length %}
|
||||
{% include 'entry/comment/_list.html.twig' %}
|
||||
{% else %}
|
||||
|
|
|
@ -12,6 +12,26 @@
|
|||
<div class="kbin-magazine">
|
||||
<span>/m/</span><a href="{{ path('front_magazine', {name: magazine.name}) }}">{{ magazine.name }}</a>
|
||||
</div>
|
||||
{% elseif domain is defined and domain %}
|
||||
<div class="kbin-magazine">
|
||||
<span>/d/</span><a href="{{ path('domain_front', {name: domain.name}) }}">{{ domain.name }}</a>
|
||||
</div>
|
||||
{% elseif tag is defined and tag %}
|
||||
<div class="kbin-magazine">
|
||||
<span>#</span><a href="{{ path('tag_front', {name: tag}) }}">{{ tag }}</a>
|
||||
</div>
|
||||
{% elseif is_route_name_end_with('_subscribed') %}
|
||||
<div class="kbin-magazine">
|
||||
<span>/</span><a href="{{ path('front_subscribed') }}">sub</a>
|
||||
</div>
|
||||
{% elseif is_route_name_end_with('_favourite') %}
|
||||
<div class="kbin-magazine">
|
||||
<span>/</span><a href="{{ path('front_favourite') }}">fav</a>
|
||||
</div>
|
||||
{% elseif is_route_name_end_with('_moderated') %}
|
||||
<div class="kbin-magazine">
|
||||
<span>/</span><a href="{{ path('front_moderated') }}">mod</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
<nav>
|
||||
<menu>
|
||||
|
@ -27,16 +47,16 @@
|
|||
{{ 'microblog'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
{# <li>#}
|
||||
{# <a href="#">#}
|
||||
{# {{ 'events'|trans }}#}
|
||||
{# </a>#}
|
||||
{# </li>#}
|
||||
<li>
|
||||
<a href="#">
|
||||
{{ 'people'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
{{ 'events'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">
|
||||
{{ 'magazines'|trans }}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div id="kbin-content">
|
||||
{% for post in posts %}
|
||||
{{ component('post', {post: post}) }}
|
||||
{{ component('post', {post: post, showMagazine: magazine is not defined or not magazine}) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<aside class="kbin-options" id="kbin-options">
|
||||
<div class="kbin-options__title"><h2>{{ 'comments'|trans }} ({{ post.commentCount }})</h2></div>
|
||||
<menu class="kbin-options__layout">
|
||||
<li><a href="#" title="{{ 'change_view'|trans }}" aria-label="{{ 'change_view'|trans }}"><i class="kbin-icon__layout"></i></a></li>
|
||||
</menu>
|
|
@ -7,9 +7,12 @@
|
|||
{% block mainClass %}kbin-page-post-front{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<header>
|
||||
<h1 hidden>{{ 'hot'|trans }}</h1>
|
||||
</header>
|
||||
{% if magazine is defined and magazine %}
|
||||
<h1 hidden>{{ magazine.title }}</h1>
|
||||
<h2 hidden>{{ get_active_sort_option()|trans }}</h2>
|
||||
{% else %}
|
||||
<h1 hidden>{{ get_active_sort_option()|trans }}</h1>
|
||||
{% endif %}
|
||||
{% include 'post/_add_post.html.twig' %}
|
||||
{% include 'post/_options.html.twig' %}
|
||||
{% if magazine is defined and magazine %}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<div id="kbin-content">
|
||||
{{ component('post', {post: post, isSingle: true}) }}
|
||||
|
||||
{% include 'post/comment/_options_sort.html.twig' %}
|
||||
{% include 'post/comment/_options.html.twig' %}
|
||||
{% if comments|length %}
|
||||
{% include 'post/comment/_list.html.twig' %}
|
||||
{% else %}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block mainClass %}kbin-page-reset-password{% endblock %}
|
||||
{% block mainClass %}kbin-page-reset-password-email-sent{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div id="kbin-content" class="kbin-section kbin-section--top">
|
||||
<h1>{{ 'check_email'|trans }}</h1>
|
||||
<p>{{ 'reset_check_email_desc'|trans }} {{ resetToken.expirationMessageKey|trans(resetToken.expirationMessageData, 'ResetPasswordBundle') }}.</p>
|
||||
<p>{{ 'reset_check_email_desc2'|trans }} <a href="{{ path('app_forgot_password_request') }}">{{ 'try_again'|trans }}</a>.</p>
|
||||
<div class="container">
|
||||
<h1>{{ 'check_email'|trans }}</h1>
|
||||
<p>{{ 'reset_check_email_desc'|trans({'%expire%': resetToken.expirationMessageKey|trans(resetToken.expirationMessageData, 'ResetPasswordBundle')}) }}</p>
|
||||
<p>{{ 'reset_check_email_desc2'|trans }}</p>
|
||||
<p><a class="kbin-btn kbin-btn__secondry" href="{{ path('app_forgot_password_request') }}">{{ 'try_again'|trans }}</a></p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -11,16 +11,16 @@
|
|||
{% endfor %}
|
||||
<h1>{{ 'register'|trans }}</h1>
|
||||
{{ form_row(form.username, {
|
||||
label: 'username'
|
||||
label: 'username',
|
||||
}) }}
|
||||
{{ form_row(form.email, {
|
||||
label: 'email'
|
||||
|
||||
}) }}
|
||||
{{ form_row(form.plainPassword, {
|
||||
label: 'password'
|
||||
}) }}
|
||||
{{ form_row(form.agreeTerms, {
|
||||
translation_domain: false,
|
||||
label: 'agree_terms'|trans({
|
||||
'%terms_link_start%' : '<a href="'~path('page_terms')~'">', '%terms_link_end%' : '</a>',
|
||||
'%policy_link_start%' : '<a href="'~path('page_privacy_policy')~'">', '%policy_link_end%' : '</a>',
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests;
|
||||
|
||||
|
@ -16,8 +18,8 @@ abstract class ApiTestCase extends BaseApiTestCase
|
|||
public function __construct($name = null, array $data = [], $dataName = '')
|
||||
{
|
||||
parent::__construct($name, $data, $dataName);
|
||||
$this->users = new ArrayCollection();
|
||||
$this->users = new ArrayCollection();
|
||||
$this->magazines = new ArrayCollection();
|
||||
$this->entries = new ArrayCollection();
|
||||
$this->entries = new ArrayCollection();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ use App\Service\MagazineManager;
|
|||
use App\Service\PostCommentManager;
|
||||
use App\Service\PostManager;
|
||||
use App\Service\VoteManager;
|
||||
use DateTime;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
trait FactoryTrait
|
||||
|
@ -64,13 +63,13 @@ trait FactoryTrait
|
|||
yield [
|
||||
'username' => 'adminUser',
|
||||
'password' => 'adminUser123',
|
||||
'email' => 'adminUser@example.com',
|
||||
'email' => 'adminUser@example.com',
|
||||
];
|
||||
|
||||
yield [
|
||||
'username' => 'JohnDoe',
|
||||
'password' => 'JohnDoe123',
|
||||
'email' => 'JohnDoe@example.com',
|
||||
'email' => 'JohnDoe@example.com',
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -80,15 +79,15 @@ trait FactoryTrait
|
|||
|
||||
$user = new User($email ?: $username.'@example.com', $username, $password ?: 'secret');
|
||||
|
||||
$user->isVerified = $active;
|
||||
$user->notifyOnNewEntry = true;
|
||||
$user->notifyOnNewEntryReply = true;
|
||||
$user->isVerified = $active;
|
||||
$user->notifyOnNewEntry = true;
|
||||
$user->notifyOnNewEntryReply = true;
|
||||
$user->notifyOnNewEntryCommentReply = true;
|
||||
$user->notifyOnNewPost = true;
|
||||
$user->notifyOnNewPostReply = true;
|
||||
$user->notifyOnNewPostCommentReply = true;
|
||||
$user->showProfileFollowings = true;
|
||||
$user->showProfileSubscriptions = true;
|
||||
$user->notifyOnNewPost = true;
|
||||
$user->notifyOnNewPostReply = true;
|
||||
$user->notifyOnNewPostCommentReply = true;
|
||||
$user->showProfileFollowings = true;
|
||||
$user->showProfileSubscriptions = true;
|
||||
|
||||
$manager->persist($user);
|
||||
$manager->flush();
|
||||
|
@ -101,15 +100,15 @@ trait FactoryTrait
|
|||
private function provideMagazines(): iterable
|
||||
{
|
||||
yield [
|
||||
'name' => 'acme',
|
||||
'name' => 'acme',
|
||||
'title' => 'Magazyn polityczny',
|
||||
'user' => $this->getUserByUsername('JohnDoe'),
|
||||
'user' => $this->getUserByUsername('JohnDoe'),
|
||||
];
|
||||
|
||||
yield [
|
||||
'name' => 'kbin',
|
||||
'name' => 'kbin',
|
||||
'title' => 'kbin devlog',
|
||||
'user' => $this->getUserByUsername('adminUser'),
|
||||
'user' => $this->getUserByUsername('adminUser'),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -125,7 +124,7 @@ trait FactoryTrait
|
|||
|
||||
if ($isAdmin) {
|
||||
$user->roles = ['ROLE_ADMIN'];
|
||||
$manager = static::getContainer()->get(EntityManagerInterface::class);
|
||||
$manager = static::getContainer()->get(EntityManagerInterface::class);
|
||||
|
||||
$manager->persist($user);
|
||||
$manager->flush();
|
||||
|
@ -141,9 +140,9 @@ trait FactoryTrait
|
|||
*/
|
||||
$manager = static::getContainer()->get(MagazineManager::class);
|
||||
|
||||
$dto = new MagazineDto();
|
||||
$dto->name = $name;
|
||||
$dto->title = $title ?? 'Przykładowy magazyn';
|
||||
$dto = new MagazineDto();
|
||||
$dto->name = $name;
|
||||
$dto->title = $title ?? 'Magazine title';
|
||||
|
||||
$magazine = $manager->create($dto, $user ?? $this->getUserByUsername('JohnDoe'));
|
||||
|
||||
|
@ -154,27 +153,27 @@ trait FactoryTrait
|
|||
|
||||
protected function loadNotificationsFixture()
|
||||
{
|
||||
$owner = $this->getUserByUsername('owner');
|
||||
$owner = $this->getUserByUsername('owner');
|
||||
$magazine = $this->getMagazineByName('acme', $owner);
|
||||
|
||||
$actor = $this->getUserByUsername('actor');
|
||||
$actor = $this->getUserByUsername('actor');
|
||||
$regular = $this->getUserByUsername('JohnDoe');
|
||||
|
||||
$entry = $this->getEntryByTitle('test', null, 'test', $magazine, $actor);
|
||||
$entry = $this->getEntryByTitle('test', null, 'test', $magazine, $actor);
|
||||
$comment = $this->createEntryComment('test', $entry, $regular);
|
||||
(static::getContainer()->get(EntryCommentManager::class))->delete($owner, $comment);
|
||||
(static::getContainer()->get(EntryManager::class))->delete($owner, $entry);
|
||||
static::getContainer()->get(EntryCommentManager::class)->delete($owner, $comment);
|
||||
static::getContainer()->get(EntryManager::class)->delete($owner, $entry);
|
||||
|
||||
$post = $this->createPost('test', $magazine, $actor);
|
||||
$post = $this->createPost('test', $magazine, $actor);
|
||||
$comment = $this->createPostComment('test', $post, $regular);
|
||||
(static::getContainer()->get(PostCommentManager::class))->delete($owner, $comment);
|
||||
(static::getContainer()->get(PostManager::class))->delete($owner, $post);
|
||||
static::getContainer()->get(PostCommentManager::class)->delete($owner, $comment);
|
||||
static::getContainer()->get(PostManager::class)->delete($owner, $post);
|
||||
|
||||
(static::getContainer()->get(MagazineManager::class))->ban(
|
||||
static::getContainer()->get(MagazineManager::class)->ban(
|
||||
$magazine,
|
||||
$actor,
|
||||
$owner,
|
||||
(new MagazineBanDto())->create('test', new DateTime('+1 day'))
|
||||
(new MagazineBanDto())->create('test', new \DateTime('+1 day'))
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -204,26 +203,31 @@ trait FactoryTrait
|
|||
|
||||
if (!$entry) {
|
||||
$magazine = $magazine ?? $this->getMagazineByName('acme');
|
||||
$user = $user ?? $this->getUserByUsername('JohnDoe');
|
||||
$entry = $this->createEntry($title, $magazine, $user, $url, $body);
|
||||
$user = $user ?? $this->getUserByUsername('JohnDoe');
|
||||
$entry = $this->createEntry($title, $magazine, $user, $url, $body);
|
||||
}
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
protected function createEntry(string $title, Magazine $magazine, User $user, ?string $url = null, ?string $body = 'testowa treść'): Entry
|
||||
{
|
||||
protected function createEntry(
|
||||
string $title,
|
||||
Magazine $magazine,
|
||||
User $user,
|
||||
?string $url = null,
|
||||
?string $body = 'Test entry content'
|
||||
): Entry {
|
||||
/**
|
||||
* @var $manager EntryManager
|
||||
*/
|
||||
$manager = static::getContainer()->get(EntryManager::class);
|
||||
|
||||
$dto = new EntryDto();
|
||||
$dto = new EntryDto();
|
||||
$dto->magazine = $magazine;
|
||||
$dto->title = $title;
|
||||
$dto->user = $user;
|
||||
$dto->url = $url;
|
||||
$dto->body = $body;
|
||||
$dto->title = $title;
|
||||
$dto->user = $user;
|
||||
$dto->url = $url;
|
||||
$dto->body = $body;
|
||||
|
||||
$entry = $manager->create($dto, $user);
|
||||
|
||||
|
@ -240,11 +244,16 @@ trait FactoryTrait
|
|||
$manager = static::getContainer()->get(EntryCommentManager::class);
|
||||
|
||||
if ($parent) {
|
||||
$dto = (new EntryCommentDto())->createWithParent($entry ?? $this->getEntryByTitle('Przykladowa treść'), $parent, null, $body);
|
||||
$dto = (new EntryCommentDto())->createWithParent(
|
||||
$entry ?? $this->getEntryByTitle('Przykladowa treść'),
|
||||
$parent,
|
||||
null,
|
||||
$body
|
||||
);
|
||||
} else {
|
||||
$dto = new EntryCommentDto();
|
||||
$dto = new EntryCommentDto();
|
||||
$dto->entry = $entry ?? $this->getEntryByTitle('Przykladowa treść');
|
||||
$dto->body = $body;
|
||||
$dto->body = $body;
|
||||
}
|
||||
|
||||
return $manager->create($dto, $user ?? $this->getUserByUsername('JohnDoe'));
|
||||
|
@ -257,9 +266,9 @@ trait FactoryTrait
|
|||
*/
|
||||
$manager = static::getContainer()->get(PostManager::class);
|
||||
|
||||
$dto = new PostDto();
|
||||
$dto = new PostDto();
|
||||
$dto->magazine = $magazine ?: $this->getMagazineByName('acme');
|
||||
$dto->body = $body;
|
||||
$dto->body = $body;
|
||||
|
||||
return $manager->create($dto, $user ?? $this->getUserByUsername('JohnDoe'));
|
||||
}
|
||||
|
@ -271,7 +280,7 @@ trait FactoryTrait
|
|||
*/
|
||||
$manager = static::getContainer()->get(PostCommentManager::class);
|
||||
|
||||
$dto = new PostCommentDto();
|
||||
$dto = new PostCommentDto();
|
||||
$dto->post = $post ?? $this->createPost('testowy post');
|
||||
$dto->body = $body;
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\ApiDataProvider;
|
||||
|
||||
|
||||
use App\Tests\ApiTestCase;
|
||||
use App\Tests\FactoryTrait;
|
||||
use DateTimeInterface;
|
||||
|
||||
class EntryCollectionDataProviderTest extends ApiTestCase
|
||||
{
|
||||
|
@ -33,59 +33,58 @@ class EntryCollectionDataProviderTest extends ApiTestCase
|
|||
// $this->assertMatchesResourceCollectionJsonSchema(EntryDto::class); // todo image
|
||||
|
||||
$this->assertJsonContains([
|
||||
'@context' => '/api/contexts/entry',
|
||||
'@id' => '/api/entries',
|
||||
'@type' => 'hydra:Collection',
|
||||
'hydra:member' => [
|
||||
'@context' => '/api/contexts/entry',
|
||||
'@id' => '/api/entries',
|
||||
'@type' => 'hydra:Collection',
|
||||
'hydra:member' => [
|
||||
[
|
||||
'@id' => '/api/entries/'.$entry->getId(),
|
||||
'@type' => 'entry',
|
||||
'magazine' => [
|
||||
'@id' => '/api/magazines/acme',
|
||||
'@id' => '/api/entries/'.$entry->getId(),
|
||||
'@type' => 'entry',
|
||||
'magazine' => [
|
||||
'@id' => '/api/magazines/acme',
|
||||
'@type' => 'magazine',
|
||||
'name' => 'acme',
|
||||
'name' => 'acme',
|
||||
],
|
||||
'user' => [
|
||||
'@id' => '/api/users/JohnDoe',
|
||||
'@type' => 'user',
|
||||
'user' => [
|
||||
'@id' => '/api/users/JohnDoe',
|
||||
'@type' => 'user',
|
||||
'username' => 'JohnDoe',
|
||||
],
|
||||
'image' => [
|
||||
'@id' => '/api/images/'.$entry->image->getId(),
|
||||
'@type' => 'image',
|
||||
'filePath' => $entry->image->filePath,
|
||||
'width' => 1280,
|
||||
'height' => 1280
|
||||
'image' => [
|
||||
'@id' => '/api/images/'.$entry->image->getId(),
|
||||
'@type' => 'image',
|
||||
'filePath' => $entry->image->filePath,
|
||||
'width' => 1280,
|
||||
'height' => 1280,
|
||||
],
|
||||
'domain' => [
|
||||
'@id' => '/api/domains/'.$entry->domain->getId(),
|
||||
'domain' => [
|
||||
'@id' => '/api/domains/'.$entry->domain->getId(),
|
||||
'@type' => 'domain',
|
||||
'name' => 'karab.in',
|
||||
'name' => 'karab.in',
|
||||
],
|
||||
'title' => 'test1',
|
||||
'url' => 'https://karab.in/',
|
||||
'comments' => 1,
|
||||
'uv' => 1,
|
||||
'dv' => 1,
|
||||
'isAdult' => false,
|
||||
'views' => 0,
|
||||
'score' => 0,
|
||||
'title' => 'test1',
|
||||
'url' => 'https://karab.in/',
|
||||
'comments' => 1,
|
||||
'uv' => 1,
|
||||
'dv' => 1,
|
||||
'isAdult' => false,
|
||||
'views' => 0,
|
||||
'score' => 0,
|
||||
'visibility' => 'visible',
|
||||
'createdAt' => $entry->createdAt->format(DateTimeInterface::RFC3339),
|
||||
'lastActive' => $entry->lastActive->format(DateTimeInterface::RFC3339),
|
||||
'id' => $entry->getId(),
|
||||
'type' => 'link',
|
||||
'createdAt' => $entry->createdAt->format(\DateTimeInterface::RFC3339),
|
||||
'lastActive' => $entry->lastActive->format(\DateTimeInterface::RFC3339),
|
||||
'id' => $entry->getId(),
|
||||
'type' => 'link',
|
||||
],
|
||||
],
|
||||
'hydra:totalItems' => 3,
|
||||
'hydra:view' => [
|
||||
'@id' => '/api/entries?page=1',
|
||||
'@type' => 'hydra:PartialCollectionView',
|
||||
'hydra:view' => [
|
||||
'@id' => '/api/entries?page=1',
|
||||
'@type' => 'hydra:PartialCollectionView',
|
||||
'hydra:first' => '/api/entries?page=1',
|
||||
'hydra:last' => '/api/entries?page=2',
|
||||
'hydra:next' => '/api/entries?page=2',
|
||||
'hydra:last' => '/api/entries?page=2',
|
||||
'hydra:next' => '/api/entries?page=2',
|
||||
],
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\ApiDataProvider;
|
||||
|
||||
|
||||
use App\Tests\ApiTestCase;
|
||||
use App\Tests\FactoryTrait;
|
||||
use DateTimeInterface;
|
||||
|
||||
class EntryItemDataProviderTest extends ApiTestCase
|
||||
{
|
||||
|
@ -32,54 +32,52 @@ class EntryItemDataProviderTest extends ApiTestCase
|
|||
|
||||
$response = $client->request('GET', '/api/entries/'.$entry->getId());
|
||||
|
||||
|
||||
$this->assertCount(21, $response->toArray());
|
||||
|
||||
// $this->assertMatchesResourceItemJsonSchema(EntryDto::class); // @todo image
|
||||
|
||||
$this->assertJsonEquals([
|
||||
'@context' => '/api/contexts/entry',
|
||||
'@id' => '/api/entries/'.$entry->getId(),
|
||||
'@type' => 'entry',
|
||||
'magazine' => [
|
||||
'@id' => '/api/magazines/acme',
|
||||
'@context' => '/api/contexts/entry',
|
||||
'@id' => '/api/entries/'.$entry->getId(),
|
||||
'@type' => 'entry',
|
||||
'magazine' => [
|
||||
'@id' => '/api/magazines/acme',
|
||||
'@type' => 'magazine',
|
||||
'name' => 'acme',
|
||||
'name' => 'acme',
|
||||
],
|
||||
'user' => [
|
||||
'@id' => '/api/users/JohnDoe',
|
||||
'@type' => 'user',
|
||||
'user' => [
|
||||
'@id' => '/api/users/JohnDoe',
|
||||
'@type' => 'user',
|
||||
'username' => 'JohnDoe',
|
||||
'avatar' => null,
|
||||
'avatar' => null,
|
||||
],
|
||||
'image' => [
|
||||
'@id' => '/api/images/'.$entry->image->getId(),
|
||||
'@type' => 'image',
|
||||
'filePath' => $entry->image->filePath,
|
||||
'width' => 1280,
|
||||
'height' => 1280
|
||||
'image' => [
|
||||
'@id' => '/api/images/'.$entry->image->getId(),
|
||||
'@type' => 'image',
|
||||
'filePath' => $entry->image->filePath,
|
||||
'width' => 1280,
|
||||
'height' => 1280,
|
||||
],
|
||||
'domain' => [
|
||||
'@id' => '/api/domains/'.$entry->domain->getId(),
|
||||
'@type' => 'domain',
|
||||
'name' => 'karab.in',
|
||||
'domain' => [
|
||||
'@id' => '/api/domains/'.$entry->domain->getId(),
|
||||
'@type' => 'domain',
|
||||
'name' => 'karab.in',
|
||||
'entryCount' => 3,
|
||||
],
|
||||
'title' => 'test1',
|
||||
'url' => 'https://karab.in/',
|
||||
'body' => null,
|
||||
'comments' => 1,
|
||||
'uv' => 1,
|
||||
'dv' => 1,
|
||||
'isAdult' => false,
|
||||
'views' => 0,
|
||||
'score' => 0,
|
||||
'title' => 'test1',
|
||||
'url' => 'https://karab.in/',
|
||||
'body' => null,
|
||||
'comments' => 1,
|
||||
'uv' => 1,
|
||||
'dv' => 1,
|
||||
'isAdult' => false,
|
||||
'views' => 0,
|
||||
'score' => 0,
|
||||
'visibility' => 'visible',
|
||||
'createdAt' => $entry->createdAt->format(DateTimeInterface::RFC3339),
|
||||
'lastActive' => $entry->lastActive->format(DateTimeInterface::RFC3339),
|
||||
'id' => $entry->getId(),
|
||||
'type' => 'link',
|
||||
'createdAt' => $entry->createdAt->format(\DateTimeInterface::RFC3339),
|
||||
'lastActive' => $entry->lastActive->format(\DateTimeInterface::RFC3339),
|
||||
'id' => $entry->getId(),
|
||||
'type' => 'link',
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\ApiDataProvider;
|
||||
|
||||
|
||||
use App\DTO\MagazineDto;
|
||||
use App\Tests\ApiTestCase;
|
||||
use App\Tests\FactoryTrait;
|
||||
|
@ -29,40 +30,39 @@ class MagazineCollectionDataProviderTest extends ApiTestCase
|
|||
$this->assertMatchesResourceCollectionJsonSchema(MagazineDto::class);
|
||||
|
||||
$this->assertJsonContains([
|
||||
'@context' => '/api/contexts/magazine',
|
||||
'@id' => '/api/magazines',
|
||||
'@type' => 'hydra:Collection',
|
||||
'hydra:member' => [
|
||||
'@context' => '/api/contexts/magazine',
|
||||
'@id' => '/api/magazines',
|
||||
'@type' => 'hydra:Collection',
|
||||
'hydra:member' => [
|
||||
[
|
||||
'@id' => '/api/magazines/acme',
|
||||
'@type' => 'magazine',
|
||||
'user' => [
|
||||
'@id' => '/api/users/JohnDoe',
|
||||
'@type' => 'user',
|
||||
'@id' => '/api/magazines/acme',
|
||||
'@type' => 'magazine',
|
||||
'user' => [
|
||||
'@id' => '/api/users/JohnDoe',
|
||||
'@type' => 'user',
|
||||
'username' => 'JohnDoe',
|
||||
],
|
||||
'cover' => null,
|
||||
'name' => 'acme',
|
||||
'title' => 'Przykładowy magazyn',
|
||||
'description' => null,
|
||||
'rules' => null,
|
||||
'cover' => null,
|
||||
'name' => 'acme',
|
||||
'title' => 'Magazine title',
|
||||
'description' => null,
|
||||
'rules' => null,
|
||||
'subscriptionsCount' => 1,
|
||||
'entryCount' => 1,
|
||||
'entryCommentCount' => 1,
|
||||
'postCount' => 1,
|
||||
'postCommentCount' => 1,
|
||||
'isAdult' => false,
|
||||
'entryCount' => 1,
|
||||
'entryCommentCount' => 1,
|
||||
'postCount' => 1,
|
||||
'postCommentCount' => 1,
|
||||
'isAdult' => false,
|
||||
],
|
||||
],
|
||||
'hydra:totalItems' => 3,
|
||||
'hydra:view' => [
|
||||
'@id' => '/api/magazines?page=1',
|
||||
'@type' => 'hydra:PartialCollectionView',
|
||||
'hydra:view' => [
|
||||
'@id' => '/api/magazines?page=1',
|
||||
'@type' => 'hydra:PartialCollectionView',
|
||||
'hydra:first' => '/api/magazines?page=1',
|
||||
'hydra:last' => '/api/magazines?page=2',
|
||||
'hydra:next' => '/api/magazines?page=2',
|
||||
'hydra:last' => '/api/magazines?page=2',
|
||||
'hydra:next' => '/api/magazines?page=2',
|
||||
],
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\ApiDataProvider;
|
||||
|
||||
|
||||
use App\DTO\MagazineDto;
|
||||
use App\Tests\ApiTestCase;
|
||||
use App\Tests\FactoryTrait;
|
||||
|
@ -25,27 +26,26 @@ class MagazineItemDataProviderTest extends ApiTestCase
|
|||
$this->assertMatchesResourceItemJsonSchema(MagazineDto::class);
|
||||
|
||||
$this->assertJsonEquals([
|
||||
'@context' => '/api/contexts/magazine',
|
||||
'@id' => '/api/magazines/acme',
|
||||
'@type' => 'magazine',
|
||||
'user' => [
|
||||
'@id' => '/api/users/JohnDoe',
|
||||
'@type' => 'user',
|
||||
'@context' => '/api/contexts/magazine',
|
||||
'@id' => '/api/magazines/acme',
|
||||
'@type' => 'magazine',
|
||||
'user' => [
|
||||
'@id' => '/api/users/JohnDoe',
|
||||
'@type' => 'user',
|
||||
'username' => 'JohnDoe',
|
||||
'avatar' => null,
|
||||
'avatar' => null,
|
||||
],
|
||||
'cover' => null,
|
||||
'name' => 'acme',
|
||||
'title' => 'Przykładowy magazyn',
|
||||
'description' => null,
|
||||
'rules' => null,
|
||||
'cover' => null,
|
||||
'name' => 'acme',
|
||||
'title' => 'Magazine title',
|
||||
'description' => null,
|
||||
'rules' => null,
|
||||
'subscriptionsCount' => 1,
|
||||
'entryCount' => 1,
|
||||
'entryCommentCount' => 1,
|
||||
'postCount' => 1,
|
||||
'postCommentCount' => 1,
|
||||
'isAdult' => false,
|
||||
'entryCount' => 1,
|
||||
'entryCommentCount' => 1,
|
||||
'postCount' => 1,
|
||||
'postCommentCount' => 1,
|
||||
'isAdult' => false,
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\ApiDataProvider;
|
||||
|
||||
use App\Tests\ApiTestCase;
|
||||
use App\Tests\FactoryTrait;
|
||||
use DateTimeInterface;
|
||||
|
||||
class PostCollectionDataProviderTest extends ApiTestCase
|
||||
{
|
||||
|
@ -33,56 +34,56 @@ class PostCollectionDataProviderTest extends ApiTestCase
|
|||
// $this->assertMatchesResourceCollectionJsonSchema(PostDto::class); // todo image
|
||||
|
||||
$this->assertJsonContains([
|
||||
'@context' => '/api/contexts/post',
|
||||
'@id' => '/api/posts',
|
||||
'@type' => 'hydra:Collection',
|
||||
'hydra:member' => [
|
||||
'@context' => '/api/contexts/post',
|
||||
'@id' => '/api/posts',
|
||||
'@type' => 'hydra:Collection',
|
||||
'hydra:member' => [
|
||||
[
|
||||
'@id' => '/api/posts/'.$post->getId(),
|
||||
'@type' => 'post',
|
||||
'magazine' => [
|
||||
'@id' => '/api/magazines/acme',
|
||||
'@id' => '/api/posts/'.$post->getId(),
|
||||
'@type' => 'post',
|
||||
'magazine' => [
|
||||
'@id' => '/api/magazines/acme',
|
||||
'@type' => 'magazine',
|
||||
'name' => 'acme',
|
||||
'name' => 'acme',
|
||||
],
|
||||
'user' => [
|
||||
'@id' => '/api/users/JohnDoe',
|
||||
'@type' => 'user',
|
||||
'user' => [
|
||||
'@id' => '/api/users/JohnDoe',
|
||||
'@type' => 'user',
|
||||
'username' => 'JohnDoe',
|
||||
],
|
||||
'image' => null, // @todo
|
||||
'comments' => 1,
|
||||
'uv' => 2,
|
||||
'isAdult' => false,
|
||||
'score' => 2,
|
||||
'visibility' => 'visible',
|
||||
'createdAt' => $post->createdAt->format(DateTimeInterface::RFC3339),
|
||||
'lastActive' => $post->lastActive->format(DateTimeInterface::RFC3339),
|
||||
'id' => $post->getId(),
|
||||
'image' => null, // @todo
|
||||
'comments' => 1,
|
||||
'uv' => 2,
|
||||
'isAdult' => false,
|
||||
'score' => 2,
|
||||
'visibility' => 'visible',
|
||||
'createdAt' => $post->createdAt->format(\DateTimeInterface::RFC3339),
|
||||
'lastActive' => $post->lastActive->format(\DateTimeInterface::RFC3339),
|
||||
'id' => $post->getId(),
|
||||
'bestComments' => [
|
||||
[
|
||||
'@id' => '/api/post_comments/'.$comment->getId(),
|
||||
'@type' => 'post_comment',
|
||||
'user' => [
|
||||
'@id' => '/api/users/JohnDoe',
|
||||
'@type' => 'user',
|
||||
'@id' => '/api/post_comments/'.$comment->getId(),
|
||||
'@type' => 'post_comment',
|
||||
'user' => [
|
||||
'@id' => '/api/users/JohnDoe',
|
||||
'@type' => 'user',
|
||||
'username' => 'JohnDoe',
|
||||
'avatar' => null,
|
||||
'avatar' => null,
|
||||
],
|
||||
'uv' => 2,
|
||||
'createdAt' => $comment->createdAt->format(DateTimeInterface::RFC3339),
|
||||
'lastActive' => $comment->lastActive->format(DateTimeInterface::RFC3339),
|
||||
'uv' => 2,
|
||||
'createdAt' => $comment->createdAt->format(\DateTimeInterface::RFC3339),
|
||||
'lastActive' => $comment->lastActive->format(\DateTimeInterface::RFC3339),
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'hydra:totalItems' => 3,
|
||||
'hydra:view' => [
|
||||
'@id' => '/api/posts?page=1',
|
||||
'@type' => 'hydra:PartialCollectionView',
|
||||
'hydra:view' => [
|
||||
'@id' => '/api/posts?page=1',
|
||||
'@type' => 'hydra:PartialCollectionView',
|
||||
'hydra:first' => '/api/posts?page=1',
|
||||
'hydra:last' => '/api/posts?page=2',
|
||||
'hydra:next' => '/api/posts?page=2',
|
||||
'hydra:last' => '/api/posts?page=2',
|
||||
'hydra:next' => '/api/posts?page=2',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\Command;
|
||||
|
||||
|
@ -16,7 +18,7 @@ class AdminCommandTest extends KernelTestCase
|
|||
|
||||
public function testCreateUser(): void
|
||||
{
|
||||
$dto = (new UserDto())->create('actor', 'contact@example.com');
|
||||
$dto = (new UserDto())->create('actor', 'contact@example.com');
|
||||
$dto->plainPassword = 'secret';
|
||||
|
||||
static::getContainer()->get('App\Service\UserManager')
|
||||
|
@ -35,7 +37,7 @@ class AdminCommandTest extends KernelTestCase
|
|||
{
|
||||
$application = new Application(self::bootKernel());
|
||||
|
||||
$this->command = $application->find('kbin:user:admin');
|
||||
$this->command = $application->find('kbin:user:admin');
|
||||
$this->repository = static::getContainer()->get(UserRepository::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\Command;
|
||||
|
||||
|
@ -20,7 +22,7 @@ class UserCommandTest extends KernelTestCase
|
|||
$tester->execute(
|
||||
[
|
||||
'username' => 'actor',
|
||||
'email' => 'contact@example.com',
|
||||
'email' => 'contact@example.com',
|
||||
'password' => 'secret',
|
||||
]
|
||||
);
|
||||
|
|
161
tests/Functional/Controller/Entry/EntryFrontControllerTest.php
Normal file
161
tests/Functional/Controller/Entry/EntryFrontControllerTest.php
Normal file
|
@ -0,0 +1,161 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\Controller\Entry;
|
||||
|
||||
use App\Tests\WebTestCase;
|
||||
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
|
||||
|
||||
class EntryFrontControllerTest extends WebTestCase
|
||||
{
|
||||
public function testFrontPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$client->request('GET', '/');
|
||||
$this->assertSelectorTextContains('h1', 'Hot');
|
||||
|
||||
$crawler = $client->request('GET', '/newest');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'JohnDoe');
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-active', 'Threads');
|
||||
|
||||
$this->assertcount(2, $crawler->filter('.kbin-entry'));
|
||||
|
||||
foreach ($this->getSortOptions() as $sortOption) {
|
||||
$crawler = $client->click($crawler->filter('.kbin-options__sort')->selectLink($sortOption)->link());
|
||||
$this->assertSelectorTextContains('.kbin-options__sort', $sortOption);
|
||||
$this->assertSelectorTextContains('h1', ucfirst($sortOption));
|
||||
}
|
||||
}
|
||||
|
||||
public function testMagazinePage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$client->request('GET', '/m/acme');
|
||||
$this->assertSelectorTextContains('h2', 'Hot');
|
||||
|
||||
$crawler = $client->request('GET', '/m/acme/newest');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'JohnDoe');
|
||||
$this->assertSelectorTextNotContains('.kbin-entry__meta', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/m/acme');
|
||||
$this->assertSelectorTextContains('#kbin-sidebar .kbin-magazine', 'acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-active', 'Threads');
|
||||
|
||||
$this->assertcount(1, $crawler->filter('.kbin-entry'));
|
||||
|
||||
foreach ($this->getSortOptions() as $sortOption) {
|
||||
$crawler = $client->click($crawler->filter('.kbin-options__sort')->selectLink($sortOption)->link());
|
||||
$this->assertSelectorTextContains('.kbin-options__sort', $sortOption);
|
||||
$this->assertSelectorTextContains('h1', 'Magazine title');
|
||||
$this->assertSelectorTextContains('h2', ucfirst($sortOption));
|
||||
}
|
||||
}
|
||||
|
||||
public function testSubPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$client->request('GET', '/sub');
|
||||
$this->assertSelectorTextContains('h1', 'Hot');
|
||||
|
||||
$crawler = $client->request('GET', '/sub/newest');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'JohnDoe');
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/sub');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-active', 'Threads');
|
||||
|
||||
$this->assertcount(1, $crawler->filter('.kbin-entry'));
|
||||
|
||||
foreach ($this->getSortOptions() as $sortOption) {
|
||||
$crawler = $client->click($crawler->filter('.kbin-options__sort')->selectLink($sortOption)->link());
|
||||
$this->assertSelectorTextContains('.kbin-options__sort', $sortOption);
|
||||
$this->assertSelectorTextContains('h1', ucfirst($sortOption));
|
||||
}
|
||||
}
|
||||
|
||||
public function testModPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$client->request('GET', '/mod');
|
||||
$this->assertSelectorTextContains('h1', 'Hot');
|
||||
|
||||
$crawler = $client->request('GET', '/mod/newest');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'JohnDoe');
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/mod');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-active', 'Threads');
|
||||
|
||||
$this->assertcount(1, $crawler->filter('.kbin-entry'));
|
||||
|
||||
foreach ($this->getSortOptions() as $sortOption) {
|
||||
$crawler = $client->click($crawler->filter('.kbin-options__sort')->selectLink($sortOption)->link());
|
||||
$this->assertSelectorTextContains('.kbin-options__sort', $sortOption);
|
||||
$this->assertSelectorTextContains('h1', ucfirst($sortOption));
|
||||
}
|
||||
}
|
||||
|
||||
public function testFavPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$client->request('GET', '/fav');
|
||||
$this->assertSelectorTextContains('h1', 'Hot');
|
||||
|
||||
$crawler = $client->request('GET', '/fav/newest');
|
||||
|
||||
// @todo
|
||||
// $this->assertSelectorTextContains('.kbin-entry__meta', 'JaneDoe');
|
||||
// $this->assertSelectorTextContains('.kbin-entry__meta', 'to kbin');
|
||||
//
|
||||
// $this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/fav');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-active', 'Threads');
|
||||
|
||||
$this->assertcount(0, $crawler->filter('.kbin-entry'));
|
||||
|
||||
foreach ($this->getSortOptions() as $sortOption) {
|
||||
$crawler = $client->click($crawler->filter('.kbin-options__sort')->selectLink($sortOption)->link());
|
||||
$this->assertSelectorTextContains('.kbin-options__sort', $sortOption);
|
||||
$this->assertSelectorTextContains('h1', ucfirst($sortOption));
|
||||
}
|
||||
}
|
||||
|
||||
private function prepareEntries(): KernelBrowser
|
||||
{
|
||||
$client = $this->createClient();
|
||||
|
||||
$client->loginUser($this->getUserByUsername('JohnDoe'));
|
||||
|
||||
$this->getEntryByTitle(
|
||||
'test entry 1',
|
||||
'https://kbin.pub',
|
||||
null,
|
||||
$this->getMagazineByName('kbin', $this->getUserByUsername('JaneDoe')),
|
||||
$this->getUserByUsername('JaneDoe')
|
||||
);
|
||||
|
||||
$this->getEntryByTitle('test entry 2');
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
private function getSortOptions(): array
|
||||
{
|
||||
return ['top', 'hot', 'newest', 'active', 'commented'];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\Controller\Entry;
|
||||
|
||||
use App\Entity\Contracts\VoteInterface;
|
||||
use App\Service\FavouriteManager;
|
||||
use App\Service\VoteManager;
|
||||
use App\Tests\WebTestCase;
|
||||
|
||||
class EntrySingleControllerTest extends WebTestCase
|
||||
{
|
||||
public function testUserCanGoToEntryFromFrontpage(): void
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->loginUser($this->getUserByUsername('JohnDoe'));
|
||||
$this->getEntryByTitle('test entry 1');
|
||||
|
||||
$crawler = $client->request('GET', '/');
|
||||
$client->click($crawler->selectLink('test entry 1')->link());
|
||||
|
||||
$this->assertSelectorTextContains('article h1', 'test entry 1');
|
||||
$this->assertSelectorTextContains('#kbin-main', 'No comments');
|
||||
$this->assertSelectorTextContains('#kbin-sidebar .kbin-entry-info', 'Thread');
|
||||
$this->assertSelectorTextContains('#kbin-sidebar .kbin-magazine', 'Magazine');
|
||||
$this->assertSelectorTextContains('#kbin-sidebar .kbin-user-list', 'Moderators');
|
||||
$this->assertSelectorTextContains('#kbin-sidebar .kbin-posts', 'Related posts');
|
||||
}
|
||||
|
||||
public function testUserCanSeeArticle(): void
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->loginUser($this->getUserByUsername('JohnDoe'));
|
||||
$entry = $this->getEntryByTitle('test entry 1', null, 'Test entry content');
|
||||
|
||||
$client->request('GET', "/m/acme/t/{$entry->getId()}/test-entry-1");
|
||||
|
||||
$this->assertSelectorTextContains('article h1', 'test entry 1');
|
||||
$this->assertSelectorNotExists('article h1 a');
|
||||
$this->assertSelectorTextContains('article', 'Test entry content');
|
||||
}
|
||||
|
||||
public function testUserCanSeeLink(): void
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->loginUser($this->getUserByUsername('JohnDoe'));
|
||||
$entry = $this->getEntryByTitle('test entry 1', 'https://kbin.pub');
|
||||
|
||||
$client->request('GET', "/m/acme/t/{$entry->getId()}/test-entry-1");
|
||||
$this->assertSelectorExists('article h1 a[href="https://kbin.pub"]', 'test entry 1');
|
||||
}
|
||||
|
||||
public function testPostActivityCounter(): void
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->loginUser($this->getUserByUsername('JohnDoe'));
|
||||
$entry = $this->getEntryByTitle('test entry 1');
|
||||
|
||||
$manager = static::getContainer()->get(VoteManager::class);
|
||||
$manager->vote($entry, $this->getUserByUsername('JohnDoe'), VoteInterface::VOTE_UP);
|
||||
$manager->vote($entry, $this->getUserByUsername('JaneDoe'), VoteInterface::VOTE_DOWN);
|
||||
|
||||
$manager = static::getContainer()->get(FavouriteManager::class);
|
||||
$manager->toggle($entry, $this->getUserByUsername('JohnDoe'));
|
||||
$manager->toggle($entry, $this->getUserByUsername('JaneDoe'));
|
||||
|
||||
$client->request('GET', "/m/acme/t/{$entry->getId()}/test-entry-1");
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-options', 'Activity (3)');
|
||||
}
|
||||
|
||||
public function testUserCanSeePhoto(): void
|
||||
{
|
||||
// @todo
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\Controller\Entry;
|
||||
|
||||
use App\Tests\WebTestCase;
|
||||
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
|
||||
|
||||
class FrontControllerTest extends WebTestCase
|
||||
{
|
||||
public function testFrontPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$crawler = $client->request('GET', '/');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'JohnDoe');
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'to acme');
|
||||
|
||||
$this->assertcount(2, $crawler->filter('.kbin-entry'));
|
||||
}
|
||||
|
||||
public function testMagazinePage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$this->getEntryByTitle('testowa treść');
|
||||
|
||||
$crawler = $client->request('GET', '/m/acme');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'JohnDoe');
|
||||
$this->assertSelectorTextNotContains('.kbin-entry__meta', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/m/acme');
|
||||
$this->assertSelectorTextContains('#kbin-sidebar .kbin-magazine', 'acme');
|
||||
|
||||
$this->assertcount(1, $crawler->filter('.kbin-entry'));
|
||||
}
|
||||
|
||||
public function testSubPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$crawler = $client->request('GET', '/sub');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'JohnDoe');
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/sub');
|
||||
|
||||
$this->assertcount(1, $crawler->filter('.kbin-entry'));
|
||||
}
|
||||
|
||||
public function testModPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$crawler = $client->request('GET', '/mod');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'JohnDoe');
|
||||
$this->assertSelectorTextContains('.kbin-entry__meta', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/mod');
|
||||
|
||||
$this->assertcount(1, $crawler->filter('.kbin-entry'));
|
||||
}
|
||||
|
||||
public function testFavPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$crawler = $client->request('GET', '/fav');
|
||||
|
||||
// $this->assertSelectorTextContains('.kbin-entry__meta', 'JaneDoe');
|
||||
// $this->assertSelectorTextContains('.kbin-entry__meta', 'to kbin');
|
||||
//
|
||||
// $this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/fav');
|
||||
|
||||
$this->assertcount(0, $crawler->filter('.kbin-entry'));
|
||||
}
|
||||
|
||||
private function prepareEntries(): KernelBrowser
|
||||
{
|
||||
$client = $this->createClient();
|
||||
|
||||
$this->getEntryByTitle(
|
||||
'entry test 1',
|
||||
'https://kbin.pub',
|
||||
null,
|
||||
$this->getMagazineByName('kbin', $this->getUserByUsername('JaneDoe')),
|
||||
$this->getUserByUsername('JaneDoe')
|
||||
);
|
||||
|
||||
$client->loginUser($this->getUserByUsername('JohnDoe'));
|
||||
$this->getEntryByTitle('entry test 2');
|
||||
|
||||
return $client;
|
||||
}
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\Controller\Post;
|
||||
|
||||
use App\Tests\WebTestCase;
|
||||
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
|
||||
|
||||
class FrontControllerTest extends WebTestCase
|
||||
{
|
||||
public function testFrontPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$crawler = $client->request('GET', '/microblog');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'JohnDoe');
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'to acme');
|
||||
|
||||
$this->assertcount(2, $crawler->filter('.kbin-entry'));
|
||||
}
|
||||
|
||||
public function testMagazinePage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$crawler = $client->request('GET', '/m/acme/microblog');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'JohnDoe');
|
||||
$this->assertSelectorTextNotContains('.kbin-post header', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/m/acme');
|
||||
$this->assertSelectorTextContains('#kbin-sidebar .kbin-magazine', 'acme');
|
||||
|
||||
$this->assertcount(1, $crawler->filter('.kbin-post'));
|
||||
}
|
||||
|
||||
public function testSubPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$crawler = $client->request('GET', '/sub');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'JohnDoe');
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/sub');
|
||||
|
||||
$this->assertcount(1, $crawler->filter('.kbin-post'));
|
||||
}
|
||||
|
||||
public function testModPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$crawler = $client->request('GET', '/mod');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'JohnDoe');
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/mod');
|
||||
|
||||
$this->assertcount(1, $crawler->filter('.kbin-post'));
|
||||
}
|
||||
|
||||
public function testFavPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$crawler = $client->request('GET', '/fav');
|
||||
|
||||
// $this->assertSelectorTextContains('.kbin-entry__meta', 'JaneDoe');
|
||||
// $this->assertSelectorTextContains('.kbin-entry__meta', 'to kbin');
|
||||
//
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/fav');
|
||||
|
||||
$this->assertcount(0, $crawler->filter('.kbin-post'));
|
||||
}
|
||||
|
||||
private function prepareEntries(): KernelBrowser
|
||||
{
|
||||
$client = $this->createClient();
|
||||
|
||||
$this->createPost(
|
||||
'post test 1',
|
||||
$this->getMagazineByName('kbin', $this->getUserByUsername('JaneDoe')),
|
||||
$this->getUserByUsername('JaneDoe')
|
||||
);
|
||||
|
||||
$client->loginUser($this->getUserByUsername('JohnDoe'));
|
||||
$this->createPost('post test 2');
|
||||
|
||||
return $client;
|
||||
}
|
||||
}
|
158
tests/Functional/Controller/Post/PostFrontControllerTest.php
Normal file
158
tests/Functional/Controller/Post/PostFrontControllerTest.php
Normal file
|
@ -0,0 +1,158 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\Controller\Post;
|
||||
|
||||
use App\Tests\WebTestCase;
|
||||
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
|
||||
|
||||
class PostFrontControllerTest extends WebTestCase
|
||||
{
|
||||
public function testFrontPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$client->request('GET', '/microblog');
|
||||
$this->assertSelectorTextContains('h1', 'Hot');
|
||||
|
||||
$crawler = $client->request('GET', '/microblog/newest');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'JohnDoe');
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-active', 'Microblog');
|
||||
|
||||
$this->assertcount(2, $crawler->filter('.kbin-post'));
|
||||
|
||||
foreach ($this->getSortOptions() as $sortOption) {
|
||||
$crawler = $client->click($crawler->filter('.kbin-options__sort')->selectLink($sortOption)->link());
|
||||
$this->assertSelectorTextContains('.kbin-options__sort', $sortOption);
|
||||
$this->assertSelectorTextContains('h1', ucfirst($sortOption));
|
||||
}
|
||||
}
|
||||
|
||||
public function testMagazinePage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$client->request('GET', '/m/acme/microblog');
|
||||
$this->assertSelectorTextContains('h2', 'Hot');
|
||||
|
||||
$crawler = $client->request('GET', '/m/acme/microblog/newest');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'JohnDoe');
|
||||
$this->assertSelectorTextNotContains('.kbin-post header', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/m/acme');
|
||||
$this->assertSelectorTextContains('#kbin-sidebar .kbin-magazine', 'acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-active', 'Microblog');
|
||||
|
||||
$this->assertcount(1, $crawler->filter('.kbin-post'));
|
||||
|
||||
foreach ($this->getSortOptions() as $sortOption) {
|
||||
$crawler = $client->click($crawler->filter('.kbin-options__sort')->selectLink($sortOption)->link());
|
||||
$this->assertSelectorTextContains('.kbin-options__sort', $sortOption);
|
||||
$this->assertSelectorTextContains('h1', 'Magazine title');
|
||||
$this->assertSelectorTextContains('h2', ucfirst($sortOption));
|
||||
}
|
||||
}
|
||||
|
||||
public function testSubPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$client->request('GET', '/sub/microblog');
|
||||
$this->assertSelectorTextContains('h1', 'Hot');
|
||||
|
||||
$crawler = $client->request('GET', '/sub/microblog/newest');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'JohnDoe');
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/sub');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-active', 'Microblog');
|
||||
|
||||
$this->assertcount(1, $crawler->filter('.kbin-post'));
|
||||
|
||||
foreach ($this->getSortOptions() as $sortOption) {
|
||||
$crawler = $client->click($crawler->filter('.kbin-options__sort')->selectLink($sortOption)->link());
|
||||
$this->assertSelectorTextContains('.kbin-options__sort', $sortOption);
|
||||
$this->assertSelectorTextContains('h1', ucfirst($sortOption));
|
||||
}
|
||||
}
|
||||
|
||||
public function testModPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$client->request('GET', '/mod/microblog');
|
||||
$this->assertSelectorTextContains('h1', 'Hot');
|
||||
|
||||
$crawler = $client->request('GET', '/mod/microblog/newest');
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'JohnDoe');
|
||||
$this->assertSelectorTextContains('.kbin-post header', 'to acme');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/mod');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-active', 'Microblog');
|
||||
|
||||
$this->assertcount(1, $crawler->filter('.kbin-post'));
|
||||
|
||||
foreach ($this->getSortOptions() as $sortOption) {
|
||||
$crawler = $client->click($crawler->filter('.kbin-options__sort')->selectLink($sortOption)->link());
|
||||
$this->assertSelectorTextContains('.kbin-options__sort', $sortOption);
|
||||
$this->assertSelectorTextContains('h1', ucfirst($sortOption));
|
||||
}
|
||||
}
|
||||
|
||||
public function testFavPage(): void
|
||||
{
|
||||
$client = $this->prepareEntries();
|
||||
|
||||
$client->request('GET', '/fav/microblog');
|
||||
$this->assertSelectorTextContains('h1', 'Hot');
|
||||
|
||||
$crawler = $client->request('GET', '/fav/microblog/newest');
|
||||
|
||||
// @todo
|
||||
// $this->assertSelectorTextContains('.kbin-entry__meta', 'JaneDoe');
|
||||
// $this->assertSelectorTextContains('.kbin-entry__meta', 'to kbin');
|
||||
//
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-magazine', '/fav');
|
||||
|
||||
$this->assertSelectorTextContains('#kbin-header .kbin-active', 'Microblog');
|
||||
|
||||
$this->assertcount(0, $crawler->filter('.kbin-post'));
|
||||
|
||||
foreach ($this->getSortOptions() as $sortOption) {
|
||||
$crawler = $client->click($crawler->filter('.kbin-options__sort')->selectLink($sortOption)->link());
|
||||
$this->assertSelectorTextContains('.kbin-options__sort', $sortOption);
|
||||
$this->assertSelectorTextContains('h1', ucfirst($sortOption));
|
||||
}
|
||||
}
|
||||
|
||||
private function prepareEntries(): KernelBrowser
|
||||
{
|
||||
$client = $this->createClient();
|
||||
|
||||
$this->createPost(
|
||||
'test post 1',
|
||||
$this->getMagazineByName('kbin', $this->getUserByUsername('JaneDoe')),
|
||||
$this->getUserByUsername('JaneDoe')
|
||||
);
|
||||
|
||||
$client->loginUser($this->getUserByUsername('JohnDoe'));
|
||||
$this->createPost('test post 2');
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
private function getSortOptions(): array
|
||||
{
|
||||
return ['top', 'hot', 'newest', 'active', 'commented'];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\Controller\Post;
|
||||
|
||||
use App\Entity\Contracts\VoteInterface;
|
||||
use App\Service\FavouriteManager;
|
||||
use App\Service\VoteManager;
|
||||
use App\Tests\WebTestCase;
|
||||
|
||||
class PostSingleControllerTest extends WebTestCase
|
||||
{
|
||||
public function testUserCanGoToPostFromFrontpage(): void
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->loginUser($this->getUserByUsername('JohnDoe'));
|
||||
$this->createPost('test post 1');
|
||||
|
||||
$crawler = $client->request('GET', '/microblog');
|
||||
$client->click($crawler->selectLink('now')->link());
|
||||
|
||||
$this->assertSelectorTextContains('blockquote', 'test post 1');
|
||||
$this->assertSelectorTextContains('#kbin-main', 'No comments');
|
||||
$this->assertSelectorTextContains('#kbin-sidebar .kbin-magazine', 'Magazine');
|
||||
$this->assertSelectorTextContains('#kbin-sidebar .kbin-user-list', 'Moderators');
|
||||
}
|
||||
|
||||
public function testUserCanSeePost(): void
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->loginUser($this->getUserByUsername('JohnDoe'));
|
||||
$post = $this->createPost('test post 1');
|
||||
|
||||
$client->request('GET', "/m/acme/p/{$post->getId()}/test-post-1");
|
||||
|
||||
$this->assertSelectorTextContains('blockquote', 'test post 1');
|
||||
}
|
||||
|
||||
public function testPostActivityCounter(): void
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$client->loginUser($this->getUserByUsername('JohnDoe'));
|
||||
$post = $this->createPost('test post 1');
|
||||
|
||||
$manager = static::getContainer()->get(VoteManager::class);
|
||||
$manager->vote($post, $this->getUserByUsername('JohnDoe'), VoteInterface::VOTE_UP);
|
||||
$manager->vote($post, $this->getUserByUsername('JaneDoe'), VoteInterface::VOTE_DOWN);
|
||||
|
||||
$manager = static::getContainer()->get(FavouriteManager::class);
|
||||
$manager->toggle($post, $this->getUserByUsername('JohnDoe'));
|
||||
$manager->toggle($post, $this->getUserByUsername('JaneDoe'));
|
||||
|
||||
$client->request('GET', "/m/acme/p/{$post->getId()}/test-post-1");
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-options', 'Activity (3)');
|
||||
}
|
||||
}
|
32
tests/Functional/Controller/Security/LoginControllerTest.php
Normal file
32
tests/Functional/Controller/Security/LoginControllerTest.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\Controller\Security;
|
||||
|
||||
use App\Tests\WebTestCase;
|
||||
|
||||
class LoginControllerTest extends WebTestCase
|
||||
{
|
||||
public function testUserCanLogin(): void
|
||||
{
|
||||
$client = $this->createClient();
|
||||
$user = $this->getUserByUsername('JohnDoe');
|
||||
|
||||
$crawler = $client->request('GET', '/');
|
||||
$crawler = $client->click($crawler->filter('header')->selectLink('Log in')->link());
|
||||
|
||||
$client->submit(
|
||||
$crawler->selectButton('Log in')->form(
|
||||
[
|
||||
'email' => 'JohnDoe',
|
||||
'password' => 'secret',
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
// $this->assertSelectorTextNotContains('header', 'Log in'); // @todo
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Functional\Controller\Security;
|
||||
|
||||
use App\Tests\WebTestCase;
|
||||
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
|
||||
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
|
||||
|
||||
class RegisterControllerTest extends WebTestCase
|
||||
{
|
||||
public function testUserCanVerifyAccount(): void
|
||||
{
|
||||
$client = $this->createClient();
|
||||
|
||||
$this->registerUserAccount($client);
|
||||
|
||||
$this->assertEmailCount(1);
|
||||
|
||||
/** @var TemplatedEmail $email */
|
||||
$email = $this->getMailerMessage();
|
||||
|
||||
$this->assertEmailHeaderSame($email, 'To', 'johndoe@kbin.pub');
|
||||
|
||||
$verifyLink = $email->getContext()['signedUrl'];
|
||||
|
||||
$crawler = $client->request('GET', $verifyLink);
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
$client->submit(
|
||||
$crawler->selectButton('Log in')->form(
|
||||
[
|
||||
'email' => 'JohnDoe',
|
||||
'password' => 'secret',
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
$client->followRedirect();
|
||||
|
||||
$this->assertSelectorTextNotContains('#kbin-header', 'Log in');
|
||||
}
|
||||
|
||||
private function registerUserAccount(KernelBrowser $client): void
|
||||
{
|
||||
$crawler = $client->request('GET', '/register');
|
||||
|
||||
$client->submit(
|
||||
$crawler->filter('form[name=user_register]')->selectButton('Register')->form(
|
||||
[
|
||||
'user_register[username]' => 'JohnDoe',
|
||||
'user_register[email]' => 'johndoe@kbin.pub',
|
||||
'user_register[plainPassword][first]' => 'secret',
|
||||
'user_register[plainPassword][second]' => 'secret',
|
||||
'user_register[agreeTerms]' => true,
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testUserCannotLoginWithoutConfirmation()
|
||||
{
|
||||
$client = $this->createClient();
|
||||
|
||||
$this->registerUserAccount($client);
|
||||
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
$crawler = $client->click($crawler->filter('#kbin-header')->selectLink('Log in')->link());
|
||||
|
||||
$client->submit(
|
||||
$crawler->selectButton('Log in')->form(
|
||||
[
|
||||
'email' => 'JohnDoe',
|
||||
'password' => 'wrong_password',
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
$client->followRedirect();
|
||||
|
||||
$this->assertSelectorTextContains('.kbin-alert__danger', 'Your account is not active.');
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Service;
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Service;
|
||||
|
||||
use App\Service\MentionManager;
|
||||
use App\Service\TagManager;
|
||||
use App\Tests\WebTestCase;
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Utils;
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests;
|
||||
|
||||
|
@ -16,8 +18,8 @@ abstract class WebTestCase extends BaseWebTestCase
|
|||
public function __construct($name = null, array $data = [], $dataName = '')
|
||||
{
|
||||
parent::__construct($name, $data, $dataName);
|
||||
$this->users = new ArrayCollection();
|
||||
$this->users = new ArrayCollection();
|
||||
$this->magazines = new ArrayCollection();
|
||||
$this->entries = new ArrayCollection();
|
||||
$this->entries = new ArrayCollection();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<?php declare(strict_types=1);
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Symfony\Component\Dotenv\Dotenv;
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ register: Register
|
|||
reset_password: Reset password
|
||||
show_more: Show more
|
||||
to: to
|
||||
in: in
|
||||
username: Username
|
||||
email: Email
|
||||
repeat_password: Repeat password
|
||||
|
@ -88,8 +89,15 @@ change_theme: Change theme
|
|||
useful: Useful
|
||||
help: Help
|
||||
check_email: Check your email
|
||||
reset_check_email_desc: 'If an account matching your email exists, then an email was just sent that contains a link that you can use to reset your password. This link will expire in'
|
||||
reset_check_email_desc2: "If you don't receive an email please check your spam folder or try again."
|
||||
reset_check_email_desc: If an account matching your email exists, then an email was just sent that contains a link that you can use to reset your password. This link will expire in %expire%.
|
||||
reset_check_email_desc2: If you don't receive an email please check your spam folder.
|
||||
try_again: Try again
|
||||
up_vote: Up vote
|
||||
down_vote: Down vote
|
||||
down_vote: Down vote
|
||||
email_confirm_header: Hello! Confirm your email address.
|
||||
email_confirm_content: 'If you want to activate your account click on the link below:'
|
||||
email_verify: Confirm email address
|
||||
email_confirm_expire: The link will expire in 1 hour.
|
||||
email_confirm_title: Confirm your email address.
|
||||
Your account is not active: Your account is not active.
|
||||
Your account has been banned: Your account has been banned.
|
2
translations/security.en.yaml
Normal file
2
translations/security.en.yaml
Normal file
|
@ -0,0 +1,2 @@
|
|||
Your account is not active.: Your account is not active.
|
||||
Your account has been banned.: Your account has been banned.
|
Loading…
Reference in a new issue