mirror of
https://github.com/maelgangloff/domain-watchdog.git
synced 2025-12-17 17:55:42 +00:00
chore: merge test/add-phpunit
This commit is contained in:
commit
d3201e79af
@ -2,5 +2,3 @@
|
|||||||
KERNEL_CLASS='App\Kernel'
|
KERNEL_CLASS='App\Kernel'
|
||||||
APP_SECRET='$ecretf0rt3st'
|
APP_SECRET='$ecretf0rt3st'
|
||||||
SYMFONY_DEPRECATIONS_HELPER=999999
|
SYMFONY_DEPRECATIONS_HELPER=999999
|
||||||
PANTHER_APP_ENV=panther
|
|
||||||
PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots
|
|
||||||
|
|||||||
5
.github/workflows/symfony.yml
vendored
5
.github/workflows/symfony.yml
vendored
@ -42,7 +42,7 @@ jobs:
|
|||||||
${{ runner.os }}-node-
|
${{ runner.os }}-node-
|
||||||
|
|
||||||
- name: Install frontend dependencies
|
- name: Install frontend dependencies
|
||||||
run: yarn install
|
run: npm install --global yarn && yarn install
|
||||||
|
|
||||||
- name: Run PHP-CS-Fixer
|
- name: Run PHP-CS-Fixer
|
||||||
run: vendor/bin/php-cs-fixer fix --dry-run --diff
|
run: vendor/bin/php-cs-fixer fix --dry-run --diff
|
||||||
@ -50,5 +50,8 @@ jobs:
|
|||||||
- name: Run PHPStan
|
- name: Run PHPStan
|
||||||
run: vendor/bin/phpstan analyse
|
run: vendor/bin/phpstan analyse
|
||||||
|
|
||||||
|
- name: Run PHPUnit
|
||||||
|
run: vendor/bin/phpunit
|
||||||
|
|
||||||
- name: Run ESLint
|
- name: Run ESLint
|
||||||
run: yarn run eslint
|
run: yarn run eslint
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
###> phpunit/phpunit ###
|
###> phpunit/phpunit ###
|
||||||
/phpunit.xml
|
/phpunit.xml
|
||||||
.phpunit.result.cache
|
/.phpunit.cache/
|
||||||
###< phpunit/phpunit ###
|
###< phpunit/phpunit ###
|
||||||
|
|
||||||
###> symfony/phpunit-bridge ###
|
###> symfony/phpunit-bridge ###
|
||||||
|
|||||||
@ -147,7 +147,7 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"friendsofphp/php-cs-fixer": "^3.61",
|
"friendsofphp/php-cs-fixer": "^3.61",
|
||||||
"phpstan/phpstan": "^1.11",
|
"phpstan/phpstan": "^1.11",
|
||||||
"phpunit/phpunit": "^9.5",
|
"phpunit/phpunit": "^10",
|
||||||
"symfony/browser-kit": "7.1.*",
|
"symfony/browser-kit": "7.1.*",
|
||||||
"symfony/css-selector": "7.1.*",
|
"symfony/css-selector": "7.1.*",
|
||||||
"symfony/debug-bundle": "7.1.*",
|
"symfony/debug-bundle": "7.1.*",
|
||||||
|
|||||||
564
composer.lock
generated
564
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -5,16 +5,16 @@
|
|||||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||||
backupGlobals="false"
|
backupGlobals="false"
|
||||||
colors="true"
|
colors="true"
|
||||||
|
failOnNotice="true"
|
||||||
|
failOnWarning="true"
|
||||||
bootstrap="tests/bootstrap.php"
|
bootstrap="tests/bootstrap.php"
|
||||||
convertDeprecationsToExceptions="false"
|
cacheDirectory=".phpunit.cache"
|
||||||
>
|
>
|
||||||
<php>
|
<php>
|
||||||
<ini name="display_errors" value="1" />
|
<ini name="display_errors" value="1" />
|
||||||
<ini name="error_reporting" value="-1" />
|
<ini name="error_reporting" value="-1" />
|
||||||
<server name="APP_ENV" value="test" force="true" />
|
<server name="APP_ENV" value="test" force="true" />
|
||||||
<server name="SHELL_VERBOSITY" value="-1" />
|
<server name="SHELL_VERBOSITY" value="-1" />
|
||||||
<server name="SYMFONY_PHPUNIT_REMOVE" value="" />
|
|
||||||
<server name="SYMFONY_PHPUNIT_VERSION" value="9.5" />
|
|
||||||
</php>
|
</php>
|
||||||
|
|
||||||
<testsuites>
|
<testsuites>
|
||||||
@ -23,15 +23,11 @@
|
|||||||
</testsuite>
|
</testsuite>
|
||||||
</testsuites>
|
</testsuites>
|
||||||
|
|
||||||
<coverage processUncoveredFiles="true">
|
<source ignoreSuppressionOfDeprecations="true" restrictNotices="true" restrictWarnings="true">
|
||||||
<include>
|
<include>
|
||||||
<directory suffix=".php">src</directory>
|
<directory>src</directory>
|
||||||
</include>
|
</include>
|
||||||
</coverage>
|
</source>
|
||||||
|
|
||||||
<listeners>
|
|
||||||
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
|
|
||||||
</listeners>
|
|
||||||
|
|
||||||
<extensions>
|
<extensions>
|
||||||
</extensions>
|
</extensions>
|
||||||
@ -41,7 +41,7 @@ class RegisterDomainCommand extends Command
|
|||||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$io = new SymfonyStyle($input, $output);
|
$io = new SymfonyStyle($input, $output);
|
||||||
$ldhName = strtolower(idn_to_ascii($input->getArgument('domain')));
|
$ldhName = RDAPService::convertToIdn($input->getArgument('domain'));
|
||||||
$force = (bool) $input->getOption('force');
|
$force = (bool) $input->getOption('force');
|
||||||
$notif = (bool) $input->getOption('notif');
|
$notif = (bool) $input->getOption('notif');
|
||||||
$domain = $this->domainRepository->findOneBy(['ldhName' => $ldhName]);
|
$domain = $this->domainRepository->findOneBy(['ldhName' => $ldhName]);
|
||||||
|
|||||||
@ -41,7 +41,7 @@ class DomainRefreshController extends AbstractController
|
|||||||
*/
|
*/
|
||||||
public function __invoke(string $ldhName, Request $request): Domain
|
public function __invoke(string $ldhName, Request $request): Domain
|
||||||
{
|
{
|
||||||
$idnDomain = strtolower(idn_to_ascii($ldhName));
|
$idnDomain = RDAPService::convertToIdn($ldhName);
|
||||||
$userId = $this->getUser()->getUserIdentifier();
|
$userId = $this->getUser()->getUserIdentifier();
|
||||||
|
|
||||||
$this->logger->info('User {username} wants to update the domain name {idnDomain}.', [
|
$this->logger->info('User {username} wants to update the domain name {idnDomain}.', [
|
||||||
|
|||||||
@ -378,7 +378,7 @@ class Domain
|
|||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
private function isToBeWatchClosely(): bool
|
protected function isToBeWatchClosely(): bool
|
||||||
{
|
{
|
||||||
$status = $this->getStatus();
|
$status = $this->getStatus();
|
||||||
if ((!empty($status) && count(array_intersect($status, self::IMPORTANT_STATUS))) || $this->getDeleted()) {
|
if ((!empty($status) && count(array_intersect($status, self::IMPORTANT_STATUS))) || $this->getDeleted()) {
|
||||||
|
|||||||
@ -45,7 +45,7 @@ use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
|||||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||||
|
|
||||||
readonly class RDAPService
|
class RDAPService
|
||||||
{
|
{
|
||||||
/* @see https://www.iana.org/domains/root/db */
|
/* @see https://www.iana.org/domains/root/db */
|
||||||
public const ISO_TLD_EXCEPTION = ['ac', 'eu', 'uk', 'su', 'tp'];
|
public const ISO_TLD_EXCEPTION = ['ac', 'eu', 'uk', 'su', 'tp'];
|
||||||
@ -199,7 +199,7 @@ readonly class RDAPService
|
|||||||
throw new BadRequestException('Domain must contain at least one dot');
|
throw new BadRequestException('Domain must contain at least one dot');
|
||||||
}
|
}
|
||||||
|
|
||||||
$tld = strtolower(idn_to_ascii(substr($domain, $lastDotPosition + 1)));
|
$tld = self::convertToIdn(substr($domain, $lastDotPosition + 1));
|
||||||
$tldEntity = $this->tldRepository->findOneBy(['tld' => $tld]);
|
$tldEntity = $this->tldRepository->findOneBy(['tld' => $tld]);
|
||||||
|
|
||||||
if (null === $tldEntity) {
|
if (null === $tldEntity) {
|
||||||
|
|||||||
17
symfony.lock
17
symfony.lock
@ -13,6 +13,15 @@
|
|||||||
"src/ApiResource/.gitignore"
|
"src/ApiResource/.gitignore"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"doctrine/deprecations": {
|
||||||
|
"version": "1.1",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "main",
|
||||||
|
"version": "1.0",
|
||||||
|
"ref": "87424683adc81d7dc305eefec1fced883084aab9"
|
||||||
|
}
|
||||||
|
},
|
||||||
"doctrine/doctrine-bundle": {
|
"doctrine/doctrine-bundle": {
|
||||||
"version": "2.12",
|
"version": "2.12",
|
||||||
"recipe": {
|
"recipe": {
|
||||||
@ -113,16 +122,16 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"phpunit/phpunit": {
|
"phpunit/phpunit": {
|
||||||
"version": "9.6",
|
"version": "10.5",
|
||||||
"recipe": {
|
"recipe": {
|
||||||
"repo": "github.com/symfony/recipes",
|
"repo": "github.com/symfony/recipes",
|
||||||
"branch": "main",
|
"branch": "main",
|
||||||
"version": "9.6",
|
"version": "10.0",
|
||||||
"ref": "7364a21d87e658eb363c5020c072ecfdc12e2326"
|
"ref": "bb22cf8d8c554a623b427d5f3416b538f5525233"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
".env.test",
|
".env.test",
|
||||||
"phpunit.xml.dist",
|
"phpunit.dist.xml",
|
||||||
"tests/bootstrap.php"
|
"tests/bootstrap.php"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
245
tests/Entity/DomainTest.php
Normal file
245
tests/Entity/DomainTest.php
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Tests\Entity;
|
||||||
|
|
||||||
|
use App\Entity\Domain;
|
||||||
|
use App\Entity\DomainEvent;
|
||||||
|
use App\Entity\DomainStatus;
|
||||||
|
use PHPUnit\Framework\Attributes\DataProvider;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
final class DomainTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testIsRedemptionPeriod(): void
|
||||||
|
{
|
||||||
|
$this->assertTrue(
|
||||||
|
(new Domain())
|
||||||
|
->setStatus(['redemption period'])
|
||||||
|
->isRedemptionPeriod()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertFalse(
|
||||||
|
(new Domain())
|
||||||
|
->setStatus(['active'])
|
||||||
|
->isRedemptionPeriod()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsPendingDelete(): void
|
||||||
|
{
|
||||||
|
$this->assertTrue(
|
||||||
|
(new Domain())
|
||||||
|
->setStatus(['pending delete'])
|
||||||
|
->isPendingDelete()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertFalse(
|
||||||
|
(new Domain())
|
||||||
|
->setStatus(['active'])
|
||||||
|
->isPendingDelete()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertFalse(
|
||||||
|
(new Domain())
|
||||||
|
->setStatus(['redemption period', 'pending delete'])
|
||||||
|
->isPendingDelete()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function testGetExpiresInDays(): void
|
||||||
|
{
|
||||||
|
$this->assertNull(
|
||||||
|
(new Domain())
|
||||||
|
->setDeleted(true)
|
||||||
|
->getExpiresInDays(),
|
||||||
|
'No guess if the domain is flagged as deleted'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
90, // Expiration date (10 days) + Auto Renew Period (45 days) + Redemption Period (30 days) + Pending Delete (5 days)
|
||||||
|
(new Domain())
|
||||||
|
->addEvent(
|
||||||
|
(new DomainEvent())
|
||||||
|
->setDate((new \DateTimeImmutable())->add(new \DateInterval('P10D')))
|
||||||
|
->setAction('expiration')
|
||||||
|
->setDeleted(false)
|
||||||
|
)->getExpiresInDays(),
|
||||||
|
'Guess based on domain events date'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
5, // Pending Delete (5 days)
|
||||||
|
(new Domain())
|
||||||
|
->setStatus(['pending delete'])
|
||||||
|
->addDomainStatus(
|
||||||
|
(new DomainStatus())
|
||||||
|
->setAddStatus(['pending delete'])
|
||||||
|
->setDeleteStatus(['active'])
|
||||||
|
->setCreatedAt(new \DateTimeImmutable())
|
||||||
|
->setDate(new \DateTimeImmutable())
|
||||||
|
)->getExpiresInDays(),
|
||||||
|
'Guess based on domain EPP status'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
35, // Redemption Period (15 days) + Pending Delete (5 days)
|
||||||
|
(new Domain())
|
||||||
|
->setStatus(['redemption period'])
|
||||||
|
->addDomainStatus(
|
||||||
|
(new DomainStatus())
|
||||||
|
->setAddStatus(['redemption period'])
|
||||||
|
->setDeleteStatus(['active'])
|
||||||
|
->setCreatedAt(new \DateTimeImmutable())
|
||||||
|
->setDate(new \DateTimeImmutable())
|
||||||
|
)->getExpiresInDays(),
|
||||||
|
'Domain name entered in the redemption period'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
5, // Pending Delete (5 days)
|
||||||
|
(new Domain())
|
||||||
|
->setStatus(['pending delete'])
|
||||||
|
->addEvent(
|
||||||
|
(new DomainEvent())
|
||||||
|
->setDate((new \DateTimeImmutable())->sub(new \DateInterval('P10D')))
|
||||||
|
->setAction('expiration')
|
||||||
|
->setDeleted(false)
|
||||||
|
)
|
||||||
|
->addDomainStatus(
|
||||||
|
(new DomainStatus())
|
||||||
|
->setAddStatus(['pending delete'])
|
||||||
|
->setDeleteStatus(['active'])
|
||||||
|
->setCreatedAt(new \DateTimeImmutable())
|
||||||
|
->setDate(new \DateTimeImmutable())
|
||||||
|
)->getExpiresInDays(),
|
||||||
|
'Domain name entered in the pending delete period'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
1,
|
||||||
|
(new Domain())
|
||||||
|
->setStatus(['pending delete'])
|
||||||
|
->addEvent(
|
||||||
|
(new DomainEvent())
|
||||||
|
->setDate((new \DateTimeImmutable())->sub(new \DateInterval('P'.(45 + 30 + 4).'D')))
|
||||||
|
->setAction('expiration')
|
||||||
|
->setDeleted(false)
|
||||||
|
)
|
||||||
|
->addDomainStatus(
|
||||||
|
(new DomainStatus())
|
||||||
|
->setAddStatus(['pending delete'])
|
||||||
|
->setDeleteStatus(['active'])
|
||||||
|
->setCreatedAt(new \DateTimeImmutable())
|
||||||
|
->setDate(new \DateTimeImmutable())
|
||||||
|
)->getExpiresInDays(),
|
||||||
|
'Guess based on domain status in priority'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertNull(
|
||||||
|
(new Domain())->setStatus(['pending delete'])->getExpiresInDays(),
|
||||||
|
'Not enough data to guess'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
0,
|
||||||
|
(new Domain())
|
||||||
|
->setStatus(['pending delete'])
|
||||||
|
->addEvent(
|
||||||
|
(new DomainEvent())
|
||||||
|
->setDate(new \DateTimeImmutable())
|
||||||
|
->setAction('deletion')
|
||||||
|
->setDeleted(false)
|
||||||
|
)->getExpiresInDays(),
|
||||||
|
'deletion event on last day (AFNIC)'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSetLdhName(): void
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @see https://en.wikipedia.org/wiki/IDN_Test_TLDs
|
||||||
|
*/
|
||||||
|
$this->assertEquals('xn--zckzah',
|
||||||
|
(new Domain())->setLdhName('テスト')->getLdhName(),
|
||||||
|
'IDN TLD'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals('xn--r8jz45g.xn--zckzah',
|
||||||
|
(new Domain())->setLdhName('例え.テスト')->getLdhName(),
|
||||||
|
'IDN Domain Name'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals('test.xn--r8jz45g.xn--zckzah',
|
||||||
|
(new Domain())->setLdhName('test.例え.テスト')->getLdhName(),
|
||||||
|
'IDN FQDN'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isToBeUpdatedProvider(): array
|
||||||
|
{
|
||||||
|
$now = new \DateTimeImmutable();
|
||||||
|
|
||||||
|
return [
|
||||||
|
// 1. updatedAt >= 7 days -> true
|
||||||
|
[$now->modify('-8 days'), false, false, false, 10, false, [], true],
|
||||||
|
|
||||||
|
// 2. deleted = true && fromUser = true -> true
|
||||||
|
[$now->modify('-1 day'), true, true, false, 10, false, [], true],
|
||||||
|
|
||||||
|
// 3. deleted = true && fromUser = false -> false
|
||||||
|
[$now->modify('-1 day'), true, false, false, 10, false, [], false],
|
||||||
|
|
||||||
|
// 4. intensifyLastDay = true && expiresIn = 0 -> true
|
||||||
|
[$now->modify('-1 hour'), false, false, true, 0, false, [], true],
|
||||||
|
|
||||||
|
// 5. intensifyLastDay = true && expiresIn = 1 -> true
|
||||||
|
[$now->modify('-1 hour'), false, false, true, 1, false, [], true],
|
||||||
|
|
||||||
|
// 6. watchClosely = true && minutesDiff >= 12 -> true
|
||||||
|
[$now->modify('-15 minutes'), false, false, false, 5, true, [], true],
|
||||||
|
|
||||||
|
// 7. watchClosely = true && fromUser = true (minutesDiff < 12) -> true
|
||||||
|
[$now->modify('-1 minute'), false, true, false, 5, true, [], true],
|
||||||
|
|
||||||
|
// 8. status = "client hold" && updatedAt >= 1 jour -> true
|
||||||
|
[$now->modify('-2 days'), false, false, false, 10, false, ['client hold'], true],
|
||||||
|
|
||||||
|
// 9. no cases -> false
|
||||||
|
[$now->modify('-1 hour'), false, false, false, 10, false, [], false],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
#[DataProvider('isToBeUpdatedProvider')]
|
||||||
|
public function testIsToBeUpdated(
|
||||||
|
\DateTimeImmutable $updatedAt,
|
||||||
|
bool $deleted,
|
||||||
|
bool $fromUser,
|
||||||
|
bool $intensifyLastDay,
|
||||||
|
int $expiresIn,
|
||||||
|
bool $watchClosely,
|
||||||
|
array $status,
|
||||||
|
bool $expected,
|
||||||
|
): void {
|
||||||
|
$mock = $this->getMockBuilder(Domain::class)
|
||||||
|
->onlyMethods(['getUpdatedAt', 'getDeleted', 'getExpiresInDays', 'isToBeWatchClosely', 'getStatus'])
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
$mock->method('getUpdatedAt')->willReturn($updatedAt);
|
||||||
|
$mock->method('getDeleted')->willReturn($deleted);
|
||||||
|
$mock->method('getExpiresInDays')->willReturn($expiresIn);
|
||||||
|
$mock->method('isToBeWatchClosely')->willReturn($watchClosely);
|
||||||
|
$mock->method('getStatus')->willReturn($status);
|
||||||
|
|
||||||
|
$result = $mock->isToBeUpdated($fromUser, $intensifyLastDay);
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user