Merge pull request #1823 from acelaya-forks/feature/external-data-providers

Feature/external data providers
This commit is contained in:
Alejandro Celaya 2023-06-18 11:06:24 +02:00 committed by GitHub
commit edaf9e34f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 148 additions and 172 deletions

View file

@ -148,6 +148,10 @@
"@test:unit:ci",
"@infect:ci:unit"
],
"infect:test:db": [
"@test:db:sqlite:ci",
"@infect:ci:db"
],
"infect:test:api": [
"@test:api:ci",
"@infect:ci:api"

View file

@ -10,20 +10,18 @@ use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\CLI\Command\Api\DisableKeyCommand;
use Shlinkio\Shlink\Common\Exception\InvalidArgumentException;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
class DisableKeyCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & ApiKeyServiceInterface $apiKeyService;
protected function setUp(): void
{
$this->apiKeyService = $this->createMock(ApiKeyServiceInterface::class);
$this->commandTester = $this->testerForCommand(new DisableKeyCommand($this->apiKeyService));
$this->commandTester = CliTestUtils::testerForCommand(new DisableKeyCommand($this->apiKeyService));
}
#[Test]

View file

@ -12,14 +12,12 @@ use Shlinkio\Shlink\CLI\ApiKey\RoleResolverInterface;
use Shlinkio\Shlink\CLI\Command\Api\GenerateKeyCommand;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Tester\CommandTester;
class GenerateKeyCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & ApiKeyServiceInterface $apiKeyService;
@ -30,7 +28,7 @@ class GenerateKeyCommandTest extends TestCase
$roleResolver->method('determineRoles')->with($this->isInstanceOf(InputInterface::class))->willReturn([]);
$command = new GenerateKeyCommand($this->apiKeyService, $roleResolver);
$this->commandTester = $this->testerForCommand($command);
$this->commandTester = CliTestUtils::testerForCommand($command);
}
#[Test]

View file

@ -15,20 +15,18 @@ use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta;
use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
class ListKeysCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & ApiKeyServiceInterface $apiKeyService;
protected function setUp(): void
{
$this->apiKeyService = $this->createMock(ApiKeyServiceInterface::class);
$this->commandTester = $this->testerForCommand(new ListKeysCommand($this->apiKeyService));
$this->commandTester = CliTestUtils::testerForCommand(new ListKeysCommand($this->apiKeyService));
}
#[Test, DataProvider('provideKeysAndOutputs')]

View file

@ -18,7 +18,7 @@ use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\CLI\Command\Db\CreateDatabaseCommand;
use Shlinkio\Shlink\CLI\Util\ProcessRunnerInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Lock\LockFactory;
@ -27,8 +27,6 @@ use Symfony\Component\Process\PhpExecutableFinder;
class CreateDatabaseCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & ProcessRunnerInterface $processHelper;
private MockObject & Connection $regularConn;
@ -63,7 +61,7 @@ class CreateDatabaseCommandTest extends TestCase
$noDbNameConn->method('createSchemaManager')->withAnyParameters()->willReturn($this->schemaManager);
$command = new CreateDatabaseCommand($locker, $this->processHelper, $phpExecutableFinder, $em, $noDbNameConn);
$this->commandTester = $this->testerForCommand($command);
$this->commandTester = CliTestUtils::testerForCommand($command);
}
#[Test]

View file

@ -9,7 +9,7 @@ use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\CLI\Command\Db\MigrateDatabaseCommand;
use Shlinkio\Shlink\CLI\Util\ProcessRunnerInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Lock\LockFactory;
@ -18,8 +18,6 @@ use Symfony\Component\Process\PhpExecutableFinder;
class MigrateDatabaseCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & ProcessRunnerInterface $processHelper;
@ -36,7 +34,7 @@ class MigrateDatabaseCommandTest extends TestCase
$this->processHelper = $this->createMock(ProcessRunnerInterface::class);
$command = new MigrateDatabaseCommand($locker, $this->processHelper, $phpExecutableFinder);
$this->commandTester = $this->testerForCommand($command);
$this->commandTester = CliTestUtils::testerForCommand($command);
}
#[Test]

View file

@ -14,22 +14,20 @@ use Shlinkio\Shlink\Core\Domain\DomainServiceInterface;
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
use Shlinkio\Shlink\Core\Domain\Model\DomainItem;
use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
use function substr_count;
class DomainRedirectsCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & DomainServiceInterface $domainService;
protected function setUp(): void
{
$this->domainService = $this->createMock(DomainServiceInterface::class);
$this->commandTester = $this->testerForCommand(new DomainRedirectsCommand($this->domainService));
$this->commandTester = CliTestUtils::testerForCommand(new DomainRedirectsCommand($this->domainService));
}
#[Test, DataProvider('provideDomains')]

View file

@ -17,13 +17,11 @@ use Shlinkio\Shlink\Core\Visit\Entity\VisitLocation;
use Shlinkio\Shlink\Core\Visit\Model\Visitor;
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
use Shlinkio\Shlink\IpGeolocation\Model\Location;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
class GetDomainVisitsCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & VisitsStatsHelperInterface $visitsHelper;
private MockObject & ShortUrlStringifierInterface $stringifier;
@ -33,7 +31,7 @@ class GetDomainVisitsCommandTest extends TestCase
$this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class);
$this->stringifier = $this->createMock(ShortUrlStringifierInterface::class);
$this->commandTester = $this->testerForCommand(
$this->commandTester = CliTestUtils::testerForCommand(
new GetDomainVisitsCommand($this->visitsHelper, $this->stringifier),
);
}

View file

@ -15,20 +15,18 @@ use Shlinkio\Shlink\Core\Domain\DomainServiceInterface;
use Shlinkio\Shlink\Core\Domain\Entity\Domain;
use Shlinkio\Shlink\Core\Domain\Model\DomainItem;
use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
class ListDomainsCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & DomainServiceInterface $domainService;
protected function setUp(): void
{
$this->domainService = $this->createMock(DomainServiceInterface::class);
$this->commandTester = $this->testerForCommand(new ListDomainsCommand($this->domainService));
$this->commandTester = CliTestUtils::testerForCommand(new ListDomainsCommand($this->domainService));
}
#[Test, DataProvider('provideInputsAndOutputs')]

View file

@ -20,14 +20,12 @@ use Shlinkio\Shlink\Core\ShortUrl\Helper\ShortUrlStringifierInterface;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlCreation;
use Shlinkio\Shlink\Core\ShortUrl\Model\UrlShorteningResult;
use Shlinkio\Shlink\Core\ShortUrl\UrlShortenerInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Tester\CommandTester;
class CreateShortUrlCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & UrlShortenerInterface $urlShortener;
private MockObject & ShortUrlStringifierInterface $stringifier;
@ -45,7 +43,7 @@ class CreateShortUrlCommandTest extends TestCase
defaultShortCodesLength: 5,
),
);
$this->commandTester = $this->testerForCommand($command);
$this->commandTester = CliTestUtils::testerForCommand($command);
}
#[Test]

View file

@ -12,7 +12,7 @@ use Shlinkio\Shlink\CLI\Command\ShortUrl\DeleteShortUrlCommand;
use Shlinkio\Shlink\Core\Exception;
use Shlinkio\Shlink\Core\ShortUrl\DeleteShortUrlServiceInterface;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
use function sprintf;
@ -21,15 +21,13 @@ use const PHP_EOL;
class DeleteShortUrlCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & DeleteShortUrlServiceInterface $service;
protected function setUp(): void
{
$this->service = $this->createMock(DeleteShortUrlServiceInterface::class);
$this->commandTester = $this->testerForCommand(new DeleteShortUrlCommand($this->service));
$this->commandTester = CliTestUtils::testerForCommand(new DeleteShortUrlCommand($this->service));
}
#[Test]

View file

@ -13,20 +13,18 @@ use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
use Shlinkio\Shlink\Core\Model\BulkDeleteResult;
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlVisitsDeleterInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
class DeleteShortUrlVisitsCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & ShortUrlVisitsDeleterInterface $deleter;
protected function setUp(): void
{
$this->deleter = $this->createMock(ShortUrlVisitsDeleterInterface::class);
$this->commandTester = $this->testerForCommand(new DeleteShortUrlVisitsCommand($this->deleter));
$this->commandTester = CliTestUtils::testerForCommand(new DeleteShortUrlVisitsCommand($this->deleter));
}
#[Test, DataProvider('provideCancellingInputs')]

View file

@ -20,7 +20,7 @@ use Shlinkio\Shlink\Core\Visit\Model\Visitor;
use Shlinkio\Shlink\Core\Visit\Model\VisitsParams;
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
use Shlinkio\Shlink\IpGeolocation\Model\Location;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
use function Shlinkio\Shlink\Common\buildDateRange;
@ -28,8 +28,6 @@ use function sprintf;
class GetShortUrlVisitsCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & VisitsStatsHelperInterface $visitsHelper;
@ -37,7 +35,7 @@ class GetShortUrlVisitsCommandTest extends TestCase
{
$this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class);
$command = new GetShortUrlVisitsCommand($this->visitsHelper);
$this->commandTester = $this->testerForCommand($command);
$this->commandTester = CliTestUtils::testerForCommand($command);
}
#[Test]

View file

@ -21,7 +21,7 @@ use Shlinkio\Shlink\Core\ShortUrl\ShortUrlListServiceInterface;
use Shlinkio\Shlink\Core\ShortUrl\Transformer\ShortUrlDataTransformer;
use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
use function count;
@ -29,8 +29,6 @@ use function explode;
class ListShortUrlsCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & ShortUrlListServiceInterface $shortUrlService;
@ -40,7 +38,7 @@ class ListShortUrlsCommandTest extends TestCase
$command = new ListShortUrlsCommand($this->shortUrlService, new ShortUrlDataTransformer(
new ShortUrlStringifier([]),
));
$this->commandTester = $this->testerForCommand($command);
$this->commandTester = CliTestUtils::testerForCommand($command);
}
#[Test]

View file

@ -12,7 +12,7 @@ use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlIdentifier;
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlResolverInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
use function sprintf;
@ -21,15 +21,13 @@ use const PHP_EOL;
class ResolveUrlCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & ShortUrlResolverInterface $urlResolver;
protected function setUp(): void
{
$this->urlResolver = $this->createMock(ShortUrlResolverInterface::class);
$this->commandTester = $this->testerForCommand(new ResolveUrlCommand($this->urlResolver));
$this->commandTester = CliTestUtils::testerForCommand(new ResolveUrlCommand($this->urlResolver));
}
#[Test]

View file

@ -9,20 +9,18 @@ use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\CLI\Command\Tag\DeleteTagsCommand;
use Shlinkio\Shlink\Core\Tag\TagServiceInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
class DeleteTagsCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & TagServiceInterface $tagService;
protected function setUp(): void
{
$this->tagService = $this->createMock(TagServiceInterface::class);
$this->commandTester = $this->testerForCommand(new DeleteTagsCommand($this->tagService));
$this->commandTester = CliTestUtils::testerForCommand(new DeleteTagsCommand($this->tagService));
}
#[Test]

View file

@ -17,13 +17,11 @@ use Shlinkio\Shlink\Core\Visit\Entity\VisitLocation;
use Shlinkio\Shlink\Core\Visit\Model\Visitor;
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
use Shlinkio\Shlink\IpGeolocation\Model\Location;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
class GetTagVisitsCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & VisitsStatsHelperInterface $visitsHelper;
private MockObject & ShortUrlStringifierInterface $stringifier;
@ -33,7 +31,7 @@ class GetTagVisitsCommandTest extends TestCase
$this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class);
$this->stringifier = $this->createMock(ShortUrlStringifierInterface::class);
$this->commandTester = $this->testerForCommand(
$this->commandTester = CliTestUtils::testerForCommand(
new GetTagVisitsCommand($this->visitsHelper, $this->stringifier),
);
}

View file

@ -12,20 +12,18 @@ use Shlinkio\Shlink\CLI\Command\Tag\ListTagsCommand;
use Shlinkio\Shlink\Common\Paginator\Paginator;
use Shlinkio\Shlink\Core\Tag\Model\TagInfo;
use Shlinkio\Shlink\Core\Tag\TagServiceInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
class ListTagsCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & TagServiceInterface $tagService;
protected function setUp(): void
{
$this->tagService = $this->createMock(TagServiceInterface::class);
$this->commandTester = $this->testerForCommand(new ListTagsCommand($this->tagService));
$this->commandTester = CliTestUtils::testerForCommand(new ListTagsCommand($this->tagService));
}
#[Test]

View file

@ -12,20 +12,18 @@ use Shlinkio\Shlink\Core\Exception\TagNotFoundException;
use Shlinkio\Shlink\Core\Tag\Entity\Tag;
use Shlinkio\Shlink\Core\Tag\Model\TagRenaming;
use Shlinkio\Shlink\Core\Tag\TagServiceInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
class RenameTagCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & TagServiceInterface $tagService;
protected function setUp(): void
{
$this->tagService = $this->createMock(TagServiceInterface::class);
$this->commandTester = $this->testerForCommand(new RenameTagCommand($this->tagService));
$this->commandTester = CliTestUtils::testerForCommand(new RenameTagCommand($this->tagService));
}
#[Test]

View file

@ -11,20 +11,18 @@ use Shlinkio\Shlink\CLI\Command\Visit\DeleteOrphanVisitsCommand;
use Shlinkio\Shlink\CLI\Util\ExitCode;
use Shlinkio\Shlink\Core\Model\BulkDeleteResult;
use Shlinkio\Shlink\Core\Visit\VisitsDeleterInterface;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
class DeleteOrphanVisitsCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & VisitsDeleterInterface $deleter;
protected function setUp(): void
{
$this->deleter = $this->createMock(VisitsDeleterInterface::class);
$this->commandTester = $this->testerForCommand(new DeleteOrphanVisitsCommand($this->deleter));
$this->commandTester = CliTestUtils::testerForCommand(new DeleteOrphanVisitsCommand($this->deleter));
}
#[Test]

View file

@ -13,22 +13,20 @@ use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException;
use Shlinkio\Shlink\CLI\GeoLite\GeolocationDbUpdaterInterface;
use Shlinkio\Shlink\CLI\GeoLite\GeolocationResult;
use Shlinkio\Shlink\CLI\Util\ExitCode;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
use function sprintf;
class DownloadGeoLiteDbCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & GeolocationDbUpdaterInterface $dbUpdater;
protected function setUp(): void
{
$this->dbUpdater = $this->createMock(GeolocationDbUpdaterInterface::class);
$this->commandTester = $this->testerForCommand(new DownloadGeoLiteDbCommand($this->dbUpdater));
$this->commandTester = CliTestUtils::testerForCommand(new DownloadGeoLiteDbCommand($this->dbUpdater));
}
#[Test, DataProvider('provideFailureParams')]

View file

@ -17,13 +17,11 @@ use Shlinkio\Shlink\Core\Visit\Entity\VisitLocation;
use Shlinkio\Shlink\Core\Visit\Model\Visitor;
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
use Shlinkio\Shlink\IpGeolocation\Model\Location;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
class GetNonOrphanVisitsCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & VisitsStatsHelperInterface $visitsHelper;
private MockObject & ShortUrlStringifierInterface $stringifier;
@ -33,7 +31,7 @@ class GetNonOrphanVisitsCommandTest extends TestCase
$this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class);
$this->stringifier = $this->createMock(ShortUrlStringifierInterface::class);
$this->commandTester = $this->testerForCommand(
$this->commandTester = CliTestUtils::testerForCommand(
new GetNonOrphanVisitsCommand($this->visitsHelper, $this->stringifier),
);
}

View file

@ -15,20 +15,18 @@ use Shlinkio\Shlink\Core\Visit\Entity\VisitLocation;
use Shlinkio\Shlink\Core\Visit\Model\Visitor;
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelperInterface;
use Shlinkio\Shlink\IpGeolocation\Model\Location;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Tester\CommandTester;
class GetOrphanVisitsCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & VisitsStatsHelperInterface $visitsHelper;
protected function setUp(): void
{
$this->visitsHelper = $this->createMock(VisitsStatsHelperInterface::class);
$this->commandTester = $this->testerForCommand(new GetOrphanVisitsCommand($this->visitsHelper));
$this->commandTester = CliTestUtils::testerForCommand(new GetOrphanVisitsCommand($this->visitsHelper));
}
#[Test]

View file

@ -21,7 +21,7 @@ use Shlinkio\Shlink\Core\Visit\Geolocation\VisitToLocationHelperInterface;
use Shlinkio\Shlink\Core\Visit\Model\Visitor;
use Shlinkio\Shlink\IpGeolocation\Exception\WrongIpException;
use Shlinkio\Shlink\IpGeolocation\Model\Location;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Output\OutputInterface;
@ -34,8 +34,6 @@ use const PHP_EOL;
class LocateVisitsCommandTest extends TestCase
{
use CliTestUtilsTrait;
private CommandTester $commandTester;
private MockObject & VisitLocatorInterface $visitService;
private MockObject & VisitToLocationHelperInterface $visitToLocation;
@ -53,8 +51,8 @@ class LocateVisitsCommandTest extends TestCase
$command = new LocateVisitsCommand($this->visitService, $this->visitToLocation, $locker);
$this->downloadDbCommand = $this->createCommandMock(DownloadGeoLiteDbCommand::NAME);
$this->commandTester = $this->testerForCommand($command, $this->downloadDbCommand);
$this->downloadDbCommand = CliTestUtils::createCommandMock(DownloadGeoLiteDbCommand::NAME);
$this->commandTester = CliTestUtils::testerForCommand($command, $this->downloadDbCommand);
}
#[Test, DataProvider('provideArgs')]

View file

@ -9,12 +9,10 @@ use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Shlinkio\Shlink\CLI\Factory\ApplicationFactory;
use Shlinkio\Shlink\Core\Options\AppOptions;
use ShlinkioTest\Shlink\CLI\CliTestUtilsTrait;
use ShlinkioTest\Shlink\CLI\Util\CliTestUtils;
class ApplicationFactoryTest extends TestCase
{
use CliTestUtilsTrait;
private ApplicationFactory $factory;
protected function setUp(): void
@ -32,8 +30,8 @@ class ApplicationFactoryTest extends TestCase
'baz' => 'baz',
],
]);
$sm->setService('foo', $this->createCommandMock('foo'));
$sm->setService('bar', $this->createCommandMock('bar'));
$sm->setService('foo', CliTestUtils::createCommandMock('foo'));
$sm->setService('bar', CliTestUtils::createCommandMock('bar'));
$instance = ($this->factory)($sm);

View file

@ -2,20 +2,33 @@
declare(strict_types=1);
namespace ShlinkioTest\Shlink\CLI;
namespace ShlinkioTest\Shlink\CLI\Util;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\MockObject\Generator;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Tester\CommandTester;
trait CliTestUtilsTrait
class CliTestUtils
{
private function createCommandMock(string $name): MockObject & Command
public static function createCommandMock(string $name): MockObject & Command
{
$command = $this->createMock(Command::class);
static $generator = null;
if ($generator === null) {
$generator = new Generator();
}
$command = $generator->getMock(
Command::class,
callOriginalConstructor: false,
callOriginalClone: false,
cloneArguments: false,
allowMockingUnknownTypes: false,
);
$command->method('getName')->willReturn($name);
$command->method('isEnabled')->willReturn(true);
$command->method('getAliases')->willReturn([]);
@ -25,7 +38,7 @@ trait CliTestUtilsTrait
return $command;
}
private function testerForCommand(Command $mainCommand, Command ...$extraCommands): CommandTester
public static function testerForCommand(Command $mainCommand, Command ...$extraCommands): CommandTester
{
$app = new Application();
$app->add($mainCommand);

View file

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace ShlinkioTest\Shlink\Core\ShortUrl;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\DataProviderExternal;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@ -14,14 +14,12 @@ use Shlinkio\Shlink\Core\ShortUrl\Model\ShortUrlsParams;
use Shlinkio\Shlink\Core\ShortUrl\Repository\ShortUrlListRepositoryInterface;
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlListService;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
use ShlinkioTest\Shlink\Core\Util\ApiKeyHelpersTrait;
use ShlinkioTest\Shlink\Core\Util\ApiKeyDataProviders;
use function count;
class ShortUrlListServiceTest extends TestCase
{
use ApiKeyHelpersTrait;
private ShortUrlListService $service;
private MockObject & ShortUrlListRepositoryInterface $repo;
@ -31,7 +29,7 @@ class ShortUrlListServiceTest extends TestCase
$this->service = new ShortUrlListService($this->repo, new UrlShortenerOptions());
}
#[Test, DataProvider('provideAdminApiKeys')]
#[Test, DataProviderExternal(ApiKeyDataProviders::class, 'adminApiKeysProvider')]
public function listedUrlsAreReturnedFromEntityManager(?ApiKey $apiKey): void
{
$list = [

View file

@ -8,6 +8,7 @@ use Cake\Chronos\Chronos;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\DataProviderExternal;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@ -22,15 +23,13 @@ use Shlinkio\Shlink\Core\ShortUrl\ShortUrlResolver;
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
use Shlinkio\Shlink\Core\Visit\Model\Visitor;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
use ShlinkioTest\Shlink\Core\Util\ApiKeyHelpersTrait;
use ShlinkioTest\Shlink\Core\Util\ApiKeyDataProviders;
use function Functional\map;
use function range;
class ShortUrlResolverTest extends TestCase
{
use ApiKeyHelpersTrait;
private ShortUrlResolver $urlResolver;
private MockObject & EntityManagerInterface $em;
private MockObject & ShortUrlRepositoryInterface $repo;
@ -42,7 +41,7 @@ class ShortUrlResolverTest extends TestCase
$this->urlResolver = new ShortUrlResolver($this->em, new UrlShortenerOptions());
}
#[Test, DataProvider('provideAdminApiKeys')]
#[Test, DataProviderExternal(ApiKeyDataProviders::class, 'adminApiKeysProvider')]
public function shortCodeIsProperlyParsed(?ApiKey $apiKey): void
{
$shortUrl = ShortUrl::withLongUrl('https://expected_url');
@ -59,7 +58,7 @@ class ShortUrlResolverTest extends TestCase
self::assertSame($shortUrl, $result);
}
#[Test, DataProvider('provideAdminApiKeys')]
#[Test, DataProviderExternal(ApiKeyDataProviders::class, 'adminApiKeysProvider')]
public function exceptionIsThrownIfShortcodeIsNotFound(?ApiKey $apiKey): void
{
$shortCode = 'abc123';

View file

@ -21,15 +21,12 @@ use Shlinkio\Shlink\Core\ShortUrl\Resolver\SimpleShortUrlRelationResolver;
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlResolverInterface;
use Shlinkio\Shlink\Core\ShortUrl\ShortUrlService;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
use ShlinkioTest\Shlink\Core\Util\ApiKeyHelpersTrait;
use function array_fill_keys;
use function Shlinkio\Shlink\Core\enumValues;
class ShortUrlServiceTest extends TestCase
{
use ApiKeyHelpersTrait;
private ShortUrlService $service;
private MockObject & ShortUrlResolverInterface $urlResolver;
private MockObject & ShortUrlTitleResolutionHelperInterface $titleResolutionHelper;

View file

@ -6,6 +6,7 @@ namespace ShlinkioTest\Shlink\Core\Tag;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\DataProviderExternal;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@ -22,12 +23,10 @@ use Shlinkio\Shlink\Core\Tag\TagService;
use Shlinkio\Shlink\Rest\ApiKey\Model\ApiKeyMeta;
use Shlinkio\Shlink\Rest\ApiKey\Model\RoleDefinition;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
use ShlinkioTest\Shlink\Core\Util\ApiKeyHelpersTrait;
use ShlinkioTest\Shlink\Core\Util\ApiKeyDataProviders;
class TagServiceTest extends TestCase
{
use ApiKeyHelpersTrait;
private TagService $service;
private MockObject & EntityManagerInterface $em;
private MockObject & TagRepository $repo;
@ -101,7 +100,7 @@ class TagServiceTest extends TestCase
];
}
#[Test, DataProvider('provideAdminApiKeys')]
#[Test, DataProviderExternal(ApiKeyDataProviders::class, 'adminApiKeysProvider')]
public function deleteTagsDelegatesOnRepository(?ApiKey $apiKey): void
{
$this->repo->expects($this->once())->method('deleteByName')->with(['foo', 'bar'])->willReturn(4);
@ -122,7 +121,7 @@ class TagServiceTest extends TestCase
);
}
#[Test, DataProvider('provideAdminApiKeys')]
#[Test, DataProviderExternal(ApiKeyDataProviders::class, 'adminApiKeysProvider')]
public function renameInvalidTagThrowsException(?ApiKey $apiKey): void
{
$this->repo->expects($this->once())->method('findOneBy')->willReturn(null);
@ -152,7 +151,7 @@ class TagServiceTest extends TestCase
yield 'different names names' => ['foo', 'bar', 0];
}
#[Test, DataProvider('provideAdminApiKeys')]
#[Test, DataProviderExternal(ApiKeyDataProviders::class, 'adminApiKeysProvider')]
public function renameTagToAnExistingNameThrowsException(?ApiKey $apiKey): void
{
$this->repo->expects($this->once())->method('findOneBy')->willReturn(new Tag('foo'));

View file

@ -6,9 +6,9 @@ namespace ShlinkioTest\Shlink\Core\Util;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
trait ApiKeyHelpersTrait
class ApiKeyDataProviders
{
public static function provideAdminApiKeys(): iterable
public static function adminApiKeysProvider(): iterable
{
yield 'no API key' => [null];
yield 'admin API key' => [ApiKey::create()];

View file

@ -8,6 +8,7 @@ use Doctrine\ORM\EntityManagerInterface;
use Laminas\Stdlib\ArrayUtils;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\DataProviderExternal;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
@ -30,7 +31,7 @@ use Shlinkio\Shlink\Core\Visit\Persistence\VisitsListFiltering;
use Shlinkio\Shlink\Core\Visit\Repository\VisitRepository;
use Shlinkio\Shlink\Core\Visit\VisitsStatsHelper;
use Shlinkio\Shlink\Rest\Entity\ApiKey;
use ShlinkioTest\Shlink\Core\Util\ApiKeyHelpersTrait;
use ShlinkioTest\Shlink\Core\Util\ApiKeyDataProviders;
use function count;
use function Functional\map;
@ -38,8 +39,6 @@ use function range;
class VisitsStatsHelperTest extends TestCase
{
use ApiKeyHelpersTrait;
private VisitsStatsHelper $helper;
private MockObject & EntityManagerInterface $em;
@ -81,7 +80,7 @@ class VisitsStatsHelperTest extends TestCase
];
}
#[Test, DataProvider('provideAdminApiKeys')]
#[Test, DataProviderExternal(ApiKeyDataProviders::class, 'adminApiKeysProvider')]
public function infoReturnsVisitsForCertainShortCode(?ApiKey $apiKey): void
{
$shortCode = '123ABC';
@ -141,7 +140,7 @@ class VisitsStatsHelperTest extends TestCase
$this->helper->visitsForTag($tag, new VisitsParams(), $apiKey);
}
#[Test, DataProvider('provideAdminApiKeys')]
#[Test, DataProviderExternal(ApiKeyDataProviders::class, 'adminApiKeysProvider')]
public function visitsForTagAreReturnedAsExpected(?ApiKey $apiKey): void
{
$tag = 'foo';
@ -179,7 +178,7 @@ class VisitsStatsHelperTest extends TestCase
$this->helper->visitsForDomain($domain, new VisitsParams(), $apiKey);
}
#[Test, DataProvider('provideAdminApiKeys')]
#[Test, DataProviderExternal(ApiKeyDataProviders::class, 'adminApiKeysProvider')]
public function visitsForNonDefaultDomainAreReturnedAsExpected(?ApiKey $apiKey): void
{
$domain = 'foo.com';
@ -207,7 +206,7 @@ class VisitsStatsHelperTest extends TestCase
self::assertEquals($list, ArrayUtils::iteratorToArray($paginator->getCurrentPageResults()));
}
#[Test, DataProvider('provideAdminApiKeys')]
#[Test, DataProviderExternal(ApiKeyDataProviders::class, 'adminApiKeysProvider')]
public function visitsForDefaultDomainAreReturnedAsExpected(?ApiKey $apiKey): void
{
$repo = $this->createMock(DomainRepository::class);

View file

@ -5,24 +5,28 @@ declare(strict_types=1);
namespace ShlinkioApiTest\Shlink\Rest\Action;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\DataProviderExternal;
use PHPUnit\Framework\Attributes\Test;
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
use ShlinkioApiTest\Shlink\Rest\Utils\NotFoundUrlHelpersTrait;
use ShlinkioApiTest\Shlink\Rest\Utils\ApiTestDataProviders;
use ShlinkioApiTest\Shlink\Rest\Utils\UrlBuilder;
use function sprintf;
class DeleteShortUrlTest extends ApiTestCase
{
use NotFoundUrlHelpersTrait;
#[Test, DataProvider('provideInvalidUrls')]
#[Test, DataProviderExternal(ApiTestDataProviders::class, 'invalidUrlsProvider')]
public function notFoundErrorIsReturnWhenDeletingInvalidUrl(
string $shortCode,
?string $domain,
string $expectedDetail,
string $apiKey,
): void {
$resp = $this->callApiWithKey(self::METHOD_DELETE, $this->buildShortUrlPath($shortCode, $domain), [], $apiKey);
$resp = $this->callApiWithKey(
self::METHOD_DELETE,
UrlBuilder::buildShortUrlPath($shortCode, $domain),
apiKey: $apiKey,
);
$payload = $this->getJsonResponsePayload($resp);
self::assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());

View file

@ -9,16 +9,16 @@ use GuzzleHttp\Psr7\Query;
use GuzzleHttp\RequestOptions;
use Laminas\Diactoros\Uri;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\DataProviderExternal;
use PHPUnit\Framework\Attributes\Test;
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
use ShlinkioApiTest\Shlink\Rest\Utils\NotFoundUrlHelpersTrait;
use ShlinkioApiTest\Shlink\Rest\Utils\ApiTestDataProviders;
use ShlinkioApiTest\Shlink\Rest\Utils\UrlBuilder;
use function sprintf;
class EditShortUrlTest extends ApiTestCase
{
use NotFoundUrlHelpersTrait;
#[Test, DataProvider('provideMeta')]
public function metadataCanBeReset(array $meta): void
{
@ -99,14 +99,14 @@ class EditShortUrlTest extends ApiTestCase
yield 'invalid URL' => ['http://foo', self::STATUS_BAD_REQUEST, 'INVALID_URL'];
}
#[Test, DataProvider('provideInvalidUrls')]
#[Test, DataProviderExternal(ApiTestDataProviders::class, 'invalidUrlsProvider')]
public function tryingToEditInvalidUrlReturnsNotFoundError(
string $shortCode,
?string $domain,
string $expectedDetail,
string $apiKey,
): void {
$url = $this->buildShortUrlPath($shortCode, $domain);
$url = UrlBuilder::buildShortUrlPath($shortCode, $domain);
$resp = $this->callApiWithKey(self::METHOD_PATCH, $url, [RequestOptions::JSON => []], $apiKey);
$payload = $this->getJsonResponsePayload($resp);

View file

@ -7,16 +7,16 @@ namespace ShlinkioApiTest\Shlink\Rest\Action;
use Cake\Chronos\Chronos;
use GuzzleHttp\RequestOptions;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\DataProviderExternal;
use PHPUnit\Framework\Attributes\Test;
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
use ShlinkioApiTest\Shlink\Rest\Utils\NotFoundUrlHelpersTrait;
use ShlinkioApiTest\Shlink\Rest\Utils\ApiTestDataProviders;
use ShlinkioApiTest\Shlink\Rest\Utils\UrlBuilder;
use function sprintf;
class ResolveShortUrlTest extends ApiTestCase
{
use NotFoundUrlHelpersTrait;
#[Test, DataProvider('provideDisabledMeta')]
public function shortUrlIsProperlyResolvedEvenWhenNotEnabled(array $disabledMeta): void
{
@ -42,14 +42,18 @@ class ResolveShortUrlTest extends ApiTestCase
yield 'maxVisits reached' => [['maxVisits' => 1]];
}
#[Test, DataProvider('provideInvalidUrls')]
#[Test, DataProviderExternal(ApiTestDataProviders::class, 'invalidUrlsProvider')]
public function tryingToResolveInvalidUrlReturnsNotFoundError(
string $shortCode,
?string $domain,
string $expectedDetail,
string $apiKey,
): void {
$resp = $this->callApiWithKey(self::METHOD_GET, $this->buildShortUrlPath($shortCode, $domain), [], $apiKey);
$resp = $this->callApiWithKey(
self::METHOD_GET,
UrlBuilder::buildShortUrlPath($shortCode, $domain),
apiKey: $apiKey,
);
$payload = $this->getJsonResponsePayload($resp);
self::assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());

View file

@ -7,18 +7,18 @@ namespace ShlinkioApiTest\Shlink\Rest\Action;
use GuzzleHttp\Psr7\Query;
use Laminas\Diactoros\Uri;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\DataProviderExternal;
use PHPUnit\Framework\Attributes\Test;
use Shlinkio\Shlink\Common\Paginator\Paginator;
use Shlinkio\Shlink\TestUtils\ApiTest\ApiTestCase;
use ShlinkioApiTest\Shlink\Rest\Utils\NotFoundUrlHelpersTrait;
use ShlinkioApiTest\Shlink\Rest\Utils\ApiTestDataProviders;
use ShlinkioApiTest\Shlink\Rest\Utils\UrlBuilder;
use function sprintf;
class ShortUrlVisitsTest extends ApiTestCase
{
use NotFoundUrlHelpersTrait;
#[Test, DataProvider('provideInvalidUrls')]
#[Test, DataProviderExternal(ApiTestDataProviders::class, 'invalidUrlsProvider')]
public function tryingToGetVisitsForInvalidUrlReturnsNotFoundError(
string $shortCode,
?string $domain,
@ -27,9 +27,8 @@ class ShortUrlVisitsTest extends ApiTestCase
): void {
$resp = $this->callApiWithKey(
self::METHOD_GET,
$this->buildShortUrlPath($shortCode, $domain, '/visits'),
[],
$apiKey,
UrlBuilder::buildShortUrlPath($shortCode, $domain, '/visits'),
apiKey: $apiKey,
);
$payload = $this->getJsonResponsePayload($resp);

View file

@ -4,14 +4,9 @@ declare(strict_types=1);
namespace ShlinkioApiTest\Shlink\Rest\Utils;
use GuzzleHttp\Psr7\Query;
use Laminas\Diactoros\Uri;
use function sprintf;
trait NotFoundUrlHelpersTrait
class ApiTestDataProviders
{
public static function provideInvalidUrls(): iterable
public static function invalidUrlsProvider(): iterable
{
yield 'invalid shortcode' => ['invalid', null, 'No URL found with short code "invalid"', 'valid_api_key'];
yield 'invalid shortcode without domain' => [
@ -20,7 +15,7 @@ trait NotFoundUrlHelpersTrait
'No URL found with short code "abc123" for domain "example.com"',
'valid_api_key',
];
yield 'invalid shortcode + domain' => [
yield 'invalid shortcode and custom domain' => [
'custom-with-domain',
'example.com',
'No URL found with short code "custom-with-domain" for domain "example.com"',
@ -32,21 +27,11 @@ trait NotFoundUrlHelpersTrait
'No URL found with short code "ghi789"',
'author_api_key',
];
yield 'valid shortcode + domain with invalid API key' => [
yield 'valid shortcode and custom domain with invalid API key' => [
'custom-with-domain',
'some-domain.com',
'No URL found with short code "custom-with-domain" for domain "some-domain.com"',
'domain_api_key',
];
}
public function buildShortUrlPath(string $shortCode, ?string $domain, string $suffix = ''): string
{
$url = new Uri(sprintf('/short-urls/%s%s', $shortCode, $suffix));
if ($domain !== null) {
$url = $url->withQuery(Query::build(['domain' => $domain]));
}
return (string) $url;
}
}

View file

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace ShlinkioApiTest\Shlink\Rest\Utils;
use GuzzleHttp\Psr7\Query;
use Laminas\Diactoros\Uri;
use function sprintf;
class UrlBuilder
{
public static function buildShortUrlPath(string $shortCode, ?string $domain, string $suffix = ''): string
{
$url = new Uri(sprintf('/short-urls/%s%s', $shortCode, $suffix));
if ($domain !== null) {
$url = $url->withQuery(Query::build(['domain' => $domain]));
}
return $url->__toString();
}
}