Skip to content

Commit

Permalink
Add mod tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jskowronski39 committed Nov 1, 2023
1 parent e613da2 commit 0aa2c6d
Show file tree
Hide file tree
Showing 12 changed files with 1,048 additions and 11 deletions.
4 changes: 2 additions & 2 deletions .env.test
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# define your env variables for the test env here
KERNEL_CLASS='App\Kernel'
APP_SECRET='$ecretf0rt3st'
SYMFONY_DEPRECATIONS_HELPER=999999
SYMFONY_DEPRECATIONS_HELPER=weak
PANTHER_APP_ENV=panther
PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots

APP_SECURITY_OAUTH_DISCORD_SERVER_ID=

APP_SECURITY_API_ALLOWED_KEYS=test_key

APP_URL_TEAMSPEAK='teamspeak.example.com'
APP_URL_TEAMSPEAK='ts3server://ts.localhost.com?password=test'
4 changes: 2 additions & 2 deletions src/Form/Mod/Dto/ModFormDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
use Ramsey\Uuid\UuidInterface;
use Symfony\Component\Validator\Constraints as Assert;

#[UniqueSteamWorkshopMod(groups: [ModSourceEnum::STEAM_WORKSHOP->value])]
#[UniqueSteamWorkshopMod(groups: [ModSourceEnum::STEAM_WORKSHOP->value], errorPath: 'url')]
#[SteamWorkshopArma3ModUrl(groups: [ModSourceEnum::STEAM_WORKSHOP->value], errorPath: 'url', nameErrorPath: 'name')]
#[UniqueDirectoryMod(groups: [ModSourceEnum::DIRECTORY->value])]
#[UniqueDirectoryMod(groups: [ModSourceEnum::DIRECTORY->value], errorPath: 'directory')]
class ModFormDto extends AbstractFormDto
{
protected ?UuidInterface $id = null;
Expand Down
4 changes: 2 additions & 2 deletions src/Service/SteamApiClient/Helper/SteamHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

class SteamHelper
{
public const ITEM_URL_REGEX = '~^https://steamcommunity\.com/(?:sharedfiles|workshop)/filedetails/\?id=(\d+)$~';
public const APP_URL_REGEX = '~^https://store\.steampowered\.com/app/(\d+)~';
private const ITEM_URL_REGEX = '~^https://steamcommunity\.com/(?:sharedfiles|workshop)/filedetails/\?id=(\d+)$~';
private const APP_URL_REGEX = '~^https://store\.steampowered\.com/app/(\d+)~';

public static function profileIdToProfileUrl(int $profileId): string
{
Expand Down
6 changes: 5 additions & 1 deletion src/Validator/Mod/UniqueDirectoryModValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ public function validate(mixed $value, Constraint $constraint): void
}

$directory = $value->getDirectory();
if ('' === $directory || null === $directory) {
return;
}

$id = $value->getId();
if (!$directory || $this->isColumnValueUnique(DirectoryMod::class, ['directory' => $directory], $id)) {
if ($this->isColumnValueUnique(DirectoryMod::class, ['directory' => $directory], $id)) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Validator/WindowsDirectoryName.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class WindowsDirectoryName extends Regex
public $message = 'Invalid directory name.';

/** @var string */
public $pattern = '/^.{1,248}[^<>:"\/\|?*]$/ui';
public $pattern = '/^.[^\<\>\:\"\/\|\?\*]{1,248}$/ui';

public function __construct(
string $pattern = null,
Expand Down
49 changes: 46 additions & 3 deletions tests/_support/FunctionalTester.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace App\Tests;

use App\Entity\User\User;
use App\Test\Traits\TimeTrait;
use Codeception\Actor;
use Codeception\Lib\Friend;

Expand All @@ -25,8 +27,49 @@
class FunctionalTester extends Actor
{
use _generated\FunctionalTesterActions;
use TimeTrait;

/**
* Define custom actions here.
*/
public function amDiscordAuthenticatedAs(string $id, callable $preAuthCallback = null): User
{
/** @var User $user */
$user = $this->grabEntityFromRepository(User::class, ['id' => $id]);
if ($preAuthCallback) {
$preAuthCallback($user);

// Refresh user entity to avoid permission issues in subsequent requests
$this->haveInRepository($user);
}
$this->amLoggedInAs($user);

return $user;
}

public function seeResponseRedirectsTo(string $url): void
{
$this->seeResponseCodeIsRedirection();
$this->seeHttpHeader('Location', $url);
}

public function seeResponseRedirectsToDiscordAuth(): void
{
$this->seeResponseRedirectsTo('/security/connect/discord');
}

public function seeActionButton(string $tooltip, string $url = null): void
{
$selector = sprintf('a i[title="%s"]', $tooltip);
if ($url) {
$selector = sprintf('a[href="%s"] i[title="%s"]', $url, $tooltip);
}
$this->seeElement($selector);
}

public function dontSeeActionButton(string $tooltip, string $url = null): void
{
$selector = sprintf('a i[title="%s"]', $tooltip);
if ($url) {
$selector = sprintf('a[href="%s"] i[title="%s"]', $url, $tooltip);
}
$this->dontSeeElement($selector);
}
}
177 changes: 177 additions & 0 deletions tests/functional/Web/Mod/CreateDirectoryModCest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<?php

declare(strict_types=1);

namespace App\Tests\Functional\Web\Mod;

use App\DataFixtures\Mod\Directory\ArmaScriptProfilerModFixture;
use App\DataFixtures\User\RegularUserFixture;
use App\Entity\Mod\DirectoryMod;
use App\Entity\Mod\Enum\ModStatusEnum;
use App\Entity\User\User;
use App\Tests\FunctionalTester;
use Symfony\Component\HttpFoundation\Response;

class CreateDirectoryModCest
{
public function _before(FunctionalTester $I): void
{
$I->stopFollowingRedirects();
$I->freezeTime('2020-01-01T00:00:00+00:00');
}

public function createDirectoryModAsUnauthenticatedUser(FunctionalTester $I): void
{
$I->amOnPage('/mod/create');
$I->seeResponseRedirectsToDiscordAuth();
}

public function createDirectoryModAsUnauthorizedUser(FunctionalTester $I): void
{
$I->amDiscordAuthenticatedAs(RegularUserFixture::ID);

$I->amOnPage('/mod/create');
$I->seeResponseCodeIs(Response::HTTP_FORBIDDEN);
}

public function createDirectoryModAsAuthorizedUser(FunctionalTester $I): void
{
$user = $I->amDiscordAuthenticatedAs(RegularUserFixture::ID, function (User $user): void {
$user->getPermissions()->modCreate = true;
});

$I->amOnPage('/mod/create');

// Default form values
$I->seeOptionIsSelected('Mod source', 'Steam Workshop');
$I->seeInField('Mod directory', '');
$I->dontSee('Mod status'); // Not visible
$I->seeInField('Mod name', '');
$I->seeInField('Mod description', '');

// Fill form
$I->selectOption('Mod source', 'Directory');
$I->fillField('Mod directory', '@OCAP');
$I->fillField('Mod name', 'OCAP');
$I->fillField('Mod description', 'OCAP - AAR');
$I->click('Create mod');

$I->seeResponseRedirectsTo('/mod/list');

/** @var DirectoryMod $mod */
$mod = $I->grabEntityFromRepository(DirectoryMod::class, ['directory' => '@OCAP']);
$I->assertSame(null, $mod->getStatus());
$I->assertSame('OCAP', $mod->getName());
$I->assertSame('OCAP - AAR', $mod->getDescription());

$I->assertSame('2020-01-01T00:00:00+00:00', $mod->getCreatedAt()->format(DATE_ATOM));
// $I->assertSame($user, $mod->getCreatedBy()); // FIXME
$I->assertSame(null, $mod->getLastUpdatedAt());
$I->assertSame(null, $mod->getLastUpdatedBy());
}

public function createDirectoryModAsAuthorizedUserWithChangeModStatusPermission(FunctionalTester $I): void
{
$user = $I->amDiscordAuthenticatedAs(RegularUserFixture::ID, function (User $user): void {
$user->getPermissions()->modCreate = true;
$user->getPermissions()->modChangeStatus = true;
});

$I->amOnPage('/mod/create');

// Default form values
$I->seeOptionIsSelected('Mod source', 'Steam Workshop');
$I->seeInField('Mod directory', '');
$I->seeOptionIsSelected('Mod status', '');
$I->seeInField('Mod name', '');
$I->seeInField('Mod description', '');

// Fill form
$I->selectOption('Mod source', 'Directory');
$I->fillField('Mod directory', '@OCAP');
$I->selectOption('Mod status', 'Deprecated');
$I->fillField('Mod name', 'OCAP');
$I->fillField('Mod description', 'OCAP - AAR');
$I->click('Create mod');

$I->seeResponseRedirectsTo('/mod/list');

/** @var DirectoryMod $mod */
$mod = $I->grabEntityFromRepository(DirectoryMod::class, ['directory' => '@OCAP']);
$I->assertSame(ModStatusEnum::DEPRECATED, $mod->getStatus());
$I->assertSame('OCAP', $mod->getName());
$I->assertSame('OCAP - AAR', $mod->getDescription());

$I->assertSame('2020-01-01T00:00:00+00:00', $mod->getCreatedAt()->format(DATE_ATOM));
// $I->assertSame($user, $mod->getCreatedBy()); // FIXME
$I->assertSame(null, $mod->getLastUpdatedAt());
$I->assertSame(null, $mod->getLastUpdatedBy());
}

public function createDirectoryModAsAuthorizedUserWhenModAlreadyExists(FunctionalTester $I): void
{
$I->amDiscordAuthenticatedAs(RegularUserFixture::ID, function (User $user): void {
$user->getPermissions()->modCreate = true;
});

$I->amOnPage('/mod/create');

$I->selectOption('Mod source', 'Directory');
$I->fillField('Mod directory', ArmaScriptProfilerModFixture::DIRECTORY);
$I->fillField('Mod name', 'Arma Script Profiler');
$I->click('Create mod');

$I->canSeeFormErrorMessage('directory', 'Mod associated with directory "@Arma Script Profiler" already exist.');
}

public function createDirectoryModAsAuthorizedUserWithInvalidDirectoryName(FunctionalTester $I): void
{
$I->amDiscordAuthenticatedAs(RegularUserFixture::ID, function (User $user): void {
$user->getPermissions()->modCreate = true;
});

$I->amOnPage('/mod/create');

$I->selectOption('Mod source', 'Directory');
$I->fillField('Mod directory', '@OC/AP');
$I->fillField('Mod name', 'OCAP');
$I->click('Create mod');

$I->canSeeFormErrorMessage('directory', 'Invalid directory name.');
}

public function createDirectoryModAsAuthorizedUserWithoutRequiredData(FunctionalTester $I): void
{
$I->amDiscordAuthenticatedAs(RegularUserFixture::ID, function (User $user): void {
$user->getPermissions()->modCreate = true;
});

$I->amOnPage('/mod/create');

$I->selectOption('Mod source', 'Directory');
$I->fillField('Mod directory', '');
$I->fillField('Mod name', '');
$I->click('Create mod');

$I->canSeeFormErrorMessage('directory', 'This value should not be blank.');
$I->canSeeFormErrorMessage('name', 'This value should not be blank.');
}

public function createDirectoryModAsAuthorizedUserWithDataTooLong(FunctionalTester $I): void
{
$I->amDiscordAuthenticatedAs(RegularUserFixture::ID, function (User $user): void {
$user->getPermissions()->modCreate = true;
});

$I->amOnPage('/mod/create');

$I->selectOption('Mod source', 'Directory');
$I->fillField('Mod directory', '@OCAP');
$I->fillField('Mod name', str_repeat('a', 256));
$I->fillField('Mod description', str_repeat('a', 256));
$I->click('Create mod');

$I->canSeeFormErrorMessage('name', 'This value is too long. It should have 255 characters or less.');
$I->canSeeFormErrorMessage('description', 'This value is too long. It should have 255 characters or less.');
}
}
Loading

0 comments on commit 0aa2c6d

Please sign in to comment.