mirror of
https://github.com/shlinkio/shlink.git
synced 2025-02-25 18:45:27 -06:00
Added test for orphan visits import
This commit is contained in:
parent
0aab1bdc4e
commit
739f5eb421
@ -28,15 +28,12 @@ use function sprintf;
|
|||||||
|
|
||||||
class ImportedLinksProcessor implements ImportedLinksProcessorInterface
|
class ImportedLinksProcessor implements ImportedLinksProcessorInterface
|
||||||
{
|
{
|
||||||
private ShortUrlRepositoryInterface $shortUrlRepo;
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly EntityManagerInterface $em,
|
private readonly EntityManagerInterface $em,
|
||||||
private readonly ShortUrlRelationResolverInterface $relationResolver,
|
private readonly ShortUrlRelationResolverInterface $relationResolver,
|
||||||
private readonly ShortCodeUniquenessHelperInterface $shortCodeHelper,
|
private readonly ShortCodeUniquenessHelperInterface $shortCodeHelper,
|
||||||
private readonly DoctrineBatchHelperInterface $batchHelper,
|
private readonly DoctrineBatchHelperInterface $batchHelper,
|
||||||
) {
|
) {
|
||||||
$this->shortUrlRepo = $this->em->getRepository(ShortUrl::class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function process(StyleInterface $io, ImportResult $result, ImportParams $params): void
|
public function process(StyleInterface $io, ImportResult $result, ImportParams $params): void
|
||||||
@ -95,7 +92,9 @@ class ImportedLinksProcessor implements ImportedLinksProcessorInterface
|
|||||||
bool $importShortCodes,
|
bool $importShortCodes,
|
||||||
callable $skipOnShortCodeConflict,
|
callable $skipOnShortCodeConflict,
|
||||||
): ShortUrlImporting {
|
): ShortUrlImporting {
|
||||||
$alreadyImportedShortUrl = $this->shortUrlRepo->findOneByImportedUrl($importedUrl);
|
/** @var ShortUrlRepositoryInterface $shortUrlRepo */
|
||||||
|
$shortUrlRepo = $this->em->getRepository(ShortUrl::class);
|
||||||
|
$alreadyImportedShortUrl = $shortUrlRepo->findOneByImportedUrl($importedUrl);
|
||||||
if ($alreadyImportedShortUrl !== null) {
|
if ($alreadyImportedShortUrl !== null) {
|
||||||
return ShortUrlImporting::fromExistingShortUrl($alreadyImportedShortUrl);
|
return ShortUrlImporting::fromExistingShortUrl($alreadyImportedShortUrl);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@ use Shlinkio\Shlink\Core\ShortUrl\Repository\ShortUrlRepositoryInterface;
|
|||||||
use Shlinkio\Shlink\Core\ShortUrl\Resolver\SimpleShortUrlRelationResolver;
|
use Shlinkio\Shlink\Core\ShortUrl\Resolver\SimpleShortUrlRelationResolver;
|
||||||
use Shlinkio\Shlink\Core\Util\DoctrineBatchHelperInterface;
|
use Shlinkio\Shlink\Core\Util\DoctrineBatchHelperInterface;
|
||||||
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
|
use Shlinkio\Shlink\Core\Visit\Entity\Visit;
|
||||||
|
use Shlinkio\Shlink\Core\Visit\Repository\VisitRepositoryInterface;
|
||||||
|
use Shlinkio\Shlink\Importer\Model\ImportedShlinkOrphanVisit;
|
||||||
use Shlinkio\Shlink\Importer\Model\ImportedShlinkUrl;
|
use Shlinkio\Shlink\Importer\Model\ImportedShlinkUrl;
|
||||||
use Shlinkio\Shlink\Importer\Model\ImportedShlinkVisit;
|
use Shlinkio\Shlink\Importer\Model\ImportedShlinkVisit;
|
||||||
use Shlinkio\Shlink\Importer\Model\ImportResult;
|
use Shlinkio\Shlink\Importer\Model\ImportResult;
|
||||||
@ -28,6 +30,7 @@ use Symfony\Component\Console\Style\StyleInterface;
|
|||||||
use function count;
|
use function count;
|
||||||
use function Functional\contains;
|
use function Functional\contains;
|
||||||
use function Functional\some;
|
use function Functional\some;
|
||||||
|
use function sprintf;
|
||||||
use function str_contains;
|
use function str_contains;
|
||||||
|
|
||||||
class ImportedLinksProcessorTest extends TestCase
|
class ImportedLinksProcessorTest extends TestCase
|
||||||
@ -42,7 +45,6 @@ class ImportedLinksProcessorTest extends TestCase
|
|||||||
{
|
{
|
||||||
$this->em = $this->createMock(EntityManagerInterface::class);
|
$this->em = $this->createMock(EntityManagerInterface::class);
|
||||||
$this->repo = $this->createMock(ShortUrlRepositoryInterface::class);
|
$this->repo = $this->createMock(ShortUrlRepositoryInterface::class);
|
||||||
$this->em->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
|
|
||||||
|
|
||||||
$this->shortCodeHelper = $this->createMock(ShortCodeUniquenessHelperInterface::class);
|
$this->shortCodeHelper = $this->createMock(ShortCodeUniquenessHelperInterface::class);
|
||||||
$batchHelper = $this->createMock(DoctrineBatchHelperInterface::class);
|
$batchHelper = $this->createMock(DoctrineBatchHelperInterface::class);
|
||||||
@ -68,6 +70,7 @@ class ImportedLinksProcessorTest extends TestCase
|
|||||||
];
|
];
|
||||||
$expectedCalls = count($urls);
|
$expectedCalls = count($urls);
|
||||||
|
|
||||||
|
$this->em->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
|
||||||
$this->repo->expects($this->exactly($expectedCalls))->method('findOneByImportedUrl')->willReturn(null);
|
$this->repo->expects($this->exactly($expectedCalls))->method('findOneByImportedUrl')->willReturn(null);
|
||||||
$this->shortCodeHelper->expects($this->exactly($expectedCalls))
|
$this->shortCodeHelper->expects($this->exactly($expectedCalls))
|
||||||
->method('ensureShortCodeUniqueness')
|
->method('ensureShortCodeUniqueness')
|
||||||
@ -89,6 +92,7 @@ class ImportedLinksProcessorTest extends TestCase
|
|||||||
new ImportedShlinkUrl(ImportSource::BITLY, 'baz', [], Chronos::now(), null, 'baz', null),
|
new ImportedShlinkUrl(ImportSource::BITLY, 'baz', [], Chronos::now(), null, 'baz', null),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
$this->em->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
|
||||||
$this->repo->expects($this->exactly(3))->method('findOneByImportedUrl')->willReturn(null);
|
$this->repo->expects($this->exactly(3))->method('findOneByImportedUrl')->willReturn(null);
|
||||||
$this->shortCodeHelper->expects($this->exactly(3))->method('ensureShortCodeUniqueness')->willReturn(true);
|
$this->shortCodeHelper->expects($this->exactly(3))->method('ensureShortCodeUniqueness')->willReturn(true);
|
||||||
$this->em->expects($this->exactly(3))->method('persist')->with(
|
$this->em->expects($this->exactly(3))->method('persist')->with(
|
||||||
@ -117,6 +121,7 @@ class ImportedLinksProcessorTest extends TestCase
|
|||||||
new ImportedShlinkUrl(ImportSource::BITLY, 'baz3', [], Chronos::now(), null, 'baz3', null),
|
new ImportedShlinkUrl(ImportSource::BITLY, 'baz3', [], Chronos::now(), null, 'baz3', null),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
$this->em->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
|
||||||
$this->repo->expects($this->exactly(count($urls)))->method('findOneByImportedUrl')->willReturnCallback(
|
$this->repo->expects($this->exactly(count($urls)))->method('findOneByImportedUrl')->willReturnCallback(
|
||||||
fn (ImportedShlinkUrl $url): ?ShortUrl
|
fn (ImportedShlinkUrl $url): ?ShortUrl
|
||||||
=> contains(['foo', 'baz2', 'baz3'], $url->longUrl) ? ShortUrl::fromImport($url, true) : null,
|
=> contains(['foo', 'baz2', 'baz3'], $url->longUrl) ? ShortUrl::fromImport($url, true) : null,
|
||||||
@ -142,6 +147,7 @@ class ImportedLinksProcessorTest extends TestCase
|
|||||||
new ImportedShlinkUrl(ImportSource::BITLY, 'baz3', [], Chronos::now(), null, 'baz3', 'bar'),
|
new ImportedShlinkUrl(ImportSource::BITLY, 'baz3', [], Chronos::now(), null, 'baz3', 'bar'),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
$this->em->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
|
||||||
$this->repo->expects($this->exactly(count($urls)))->method('findOneByImportedUrl')->willReturn(null);
|
$this->repo->expects($this->exactly(count($urls)))->method('findOneByImportedUrl')->willReturn(null);
|
||||||
$this->shortCodeHelper->expects($this->exactly(7))->method('ensureShortCodeUniqueness')->willReturnCallback(
|
$this->shortCodeHelper->expects($this->exactly(7))->method('ensureShortCodeUniqueness')->willReturnCallback(
|
||||||
fn ($_, bool $hasCustomSlug) => ! $hasCustomSlug,
|
fn ($_, bool $hasCustomSlug) => ! $hasCustomSlug,
|
||||||
@ -168,6 +174,7 @@ class ImportedLinksProcessorTest extends TestCase
|
|||||||
int $amountOfPersistedVisits,
|
int $amountOfPersistedVisits,
|
||||||
?ShortUrl $foundShortUrl,
|
?ShortUrl $foundShortUrl,
|
||||||
): void {
|
): void {
|
||||||
|
$this->em->method('getRepository')->with(ShortUrl::class)->willReturn($this->repo);
|
||||||
$this->repo->expects($this->once())->method('findOneByImportedUrl')->willReturn($foundShortUrl);
|
$this->repo->expects($this->once())->method('findOneByImportedUrl')->willReturn($foundShortUrl);
|
||||||
$this->shortCodeHelper->expects($this->exactly($foundShortUrl === null ? 1 : 0))
|
$this->shortCodeHelper->expects($this->exactly($foundShortUrl === null ? 1 : 0))
|
||||||
->method('ensureShortCodeUniqueness')
|
->method('ensureShortCodeUniqueness')
|
||||||
@ -220,9 +227,61 @@ class ImportedLinksProcessorTest extends TestCase
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildParams(): ImportParams
|
/**
|
||||||
|
* @param iterable<ImportedShlinkOrphanVisit> $visits
|
||||||
|
* @test
|
||||||
|
* @dataProvider provideOrphanVisits
|
||||||
|
*/
|
||||||
|
public function properAmountOfOrphanVisitsIsImported(
|
||||||
|
bool $importOrphanVisits,
|
||||||
|
iterable $visits,
|
||||||
|
int $expectedImportedVisits,
|
||||||
|
): void {
|
||||||
|
$this->io->expects($this->exactly($importOrphanVisits ? 2 : 1))->method('title');
|
||||||
|
$this->io->expects($importOrphanVisits ? $this->once() : $this->never())->method('text')->with(
|
||||||
|
sprintf('<info>Imported %s</info> orphan visits.', $expectedImportedVisits),
|
||||||
|
);
|
||||||
|
|
||||||
|
$visitRepo = $this->createMock(VisitRepositoryInterface::class);
|
||||||
|
$visitRepo->expects($importOrphanVisits ? $this->once() : $this->never())->method(
|
||||||
|
'findMostRecentOrphanVisit',
|
||||||
|
)->willReturn(null);
|
||||||
|
$this->em->expects($importOrphanVisits ? $this->once() : $this->never())->method('getRepository')->with(
|
||||||
|
Visit::class,
|
||||||
|
)->willReturn($visitRepo);
|
||||||
|
$this->em->expects($importOrphanVisits ? $this->exactly($expectedImportedVisits) : $this->never())->method(
|
||||||
|
'persist',
|
||||||
|
)->with($this->isInstanceOf(Visit::class));
|
||||||
|
|
||||||
|
$this->processor->process(
|
||||||
|
$this->io,
|
||||||
|
ImportResult::withShortUrlsAndOrphanVisits([], $visits),
|
||||||
|
$this->buildParams($importOrphanVisits),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideOrphanVisits(): iterable
|
||||||
{
|
{
|
||||||
return ImportSource::BITLY->toParamsWithCallableMap(['import_short_codes' => static fn () => true]);
|
yield 'import orphan disable without visits' => [false, [], 0];
|
||||||
|
yield 'import orphan enabled without visits' => [true, [], 0];
|
||||||
|
yield 'import orphan disabled with visits' => [false, [
|
||||||
|
new ImportedShlinkOrphanVisit('', '', Chronos::now(), '', '', null),
|
||||||
|
], 0];
|
||||||
|
yield 'import orphan enabled with visits' => [true, [
|
||||||
|
new ImportedShlinkOrphanVisit('', '', Chronos::now(), '', '', null),
|
||||||
|
new ImportedShlinkOrphanVisit('', '', Chronos::now(), '', '', null),
|
||||||
|
new ImportedShlinkOrphanVisit('', '', Chronos::now(), '', '', null),
|
||||||
|
new ImportedShlinkOrphanVisit('', '', Chronos::now(), '', '', null),
|
||||||
|
new ImportedShlinkOrphanVisit('', '', Chronos::now(), '', '', null),
|
||||||
|
], 5];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildParams(bool $importOrphanVisits = false): ImportParams
|
||||||
|
{
|
||||||
|
return ImportSource::BITLY->toParamsWithCallableMap([
|
||||||
|
ImportParams::IMPORT_SHORT_CODES_PARAM => static fn () => true,
|
||||||
|
ImportParams::IMPORT_ORPHAN_VISITS_PARAM => static fn () => $importOrphanVisits,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUpIoText(string $skippedText = 'Skipped', string $importedText = 'Imported'): stdClass
|
public function setUpIoText(string $skippedText = 'Skipped', string $importedText = 'Imported'): stdClass
|
||||||
|
Loading…
Reference in New Issue
Block a user