Added orphan visits count to visits stats endpoint

This commit is contained in:
Alejandro Celaya 2021-02-08 22:44:58 +01:00
parent f7215fc2c5
commit 5278d7668c
8 changed files with 29 additions and 13 deletions

View file

@ -1,10 +1,14 @@
{ {
"type": "object", "type": "object",
"required": ["visitsCount"], "required": ["visitsCount", "orphanVisitsCount"],
"properties": { "properties": {
"visitsCount": { "visitsCount": {
"type": "number", "type": "number",
"description": "The total amount of visits received." "description": "The total amount of visits received on any short URL."
},
"orphanVisitsCount": {
"type": "number",
"description": "The total amount of visits that could not be matched to a short URL (visits to the base URL, an invalid short URL or any other kind of 404)."
} }
} }
} }

View file

@ -34,7 +34,8 @@
"examples": { "examples": {
"application/json": { "application/json": {
"visits": { "visits": {
"visitsCount": 1569874 "visitsCount": 1569874,
"orphanVisitsCount": 71345
} }
} }
} }

View file

@ -9,16 +9,19 @@ use JsonSerializable;
final class VisitsStats implements JsonSerializable final class VisitsStats implements JsonSerializable
{ {
private int $visitsCount; private int $visitsCount;
private int $orphanVisitsCount;
public function __construct(int $visitsCount) public function __construct(int $visitsCount, int $orphanVisitsCount)
{ {
$this->visitsCount = $visitsCount; $this->visitsCount = $visitsCount;
$this->orphanVisitsCount = $orphanVisitsCount;
} }
public function jsonSerialize(): array public function jsonSerialize(): array
{ {
return [ return [
'visitsCount' => $this->visitsCount, 'visitsCount' => $this->visitsCount,
'orphanVisitsCount' => $this->orphanVisitsCount,
]; ];
} }
} }

View file

@ -32,15 +32,11 @@ class VisitsStatsHelper implements VisitsStatsHelperInterface
} }
public function getVisitsStats(?ApiKey $apiKey = null): VisitsStats public function getVisitsStats(?ApiKey $apiKey = null): VisitsStats
{
return new VisitsStats($this->getVisitsCount($apiKey));
}
private function getVisitsCount(?ApiKey $apiKey): int
{ {
/** @var VisitRepository $visitsRepo */ /** @var VisitRepository $visitsRepo */
$visitsRepo = $this->em->getRepository(Visit::class); $visitsRepo = $this->em->getRepository(Visit::class);
return $visitsRepo->countVisits($apiKey);
return new VisitsStats($visitsRepo->countVisits($apiKey), $visitsRepo->countOrphanVisits());
} }
/** /**

View file

@ -51,13 +51,15 @@ class VisitsStatsHelperTest extends TestCase
public function returnsExpectedVisitsStats(int $expectedCount): void public function returnsExpectedVisitsStats(int $expectedCount): void
{ {
$repo = $this->prophesize(VisitRepository::class); $repo = $this->prophesize(VisitRepository::class);
$count = $repo->countVisits(null)->willReturn($expectedCount); $count = $repo->countVisits(null)->willReturn($expectedCount * 3);
$countOrphan = $repo->countOrphanVisits()->willReturn($expectedCount);
$getRepo = $this->em->getRepository(Visit::class)->willReturn($repo->reveal()); $getRepo = $this->em->getRepository(Visit::class)->willReturn($repo->reveal());
$stats = $this->helper->getVisitsStats(); $stats = $this->helper->getVisitsStats();
self::assertEquals(new VisitsStats($expectedCount), $stats); self::assertEquals(new VisitsStats($expectedCount * 3, $expectedCount), $stats);
$count->shouldHaveBeenCalledOnce(); $count->shouldHaveBeenCalledOnce();
$countOrphan->shouldHaveBeenCalledOnce();
$getRepo->shouldHaveBeenCalledOnce(); $getRepo->shouldHaveBeenCalledOnce();
} }

View file

@ -19,7 +19,9 @@ class GlobalVisitsTest extends ApiTestCase
self::assertArrayHasKey('visits', $payload); self::assertArrayHasKey('visits', $payload);
self::assertArrayHasKey('visitsCount', $payload['visits']); self::assertArrayHasKey('visitsCount', $payload['visits']);
self::assertArrayHasKey('orphanVisitsCount', $payload['visits']);
self::assertEquals($expectedVisits, $payload['visits']['visitsCount']); self::assertEquals($expectedVisits, $payload['visits']['visitsCount']);
self::assertEquals(3, $payload['visits']['orphanVisitsCount']);
} }
public function provideApiKeys(): iterable public function provideApiKeys(): iterable

View file

@ -47,6 +47,14 @@ class VisitsFixture extends AbstractFixture implements DependentFixtureInterface
Visit::forValidShortUrl($ghiShortUrl, new Visitor('shlink-tests-agent', 'https://app.shlink.io', '', '')), Visit::forValidShortUrl($ghiShortUrl, new Visitor('shlink-tests-agent', 'https://app.shlink.io', '', '')),
); );
$manager->persist(Visit::forBasePath(new Visitor('shlink-tests-agent', 'https://doma.in', '1.2.3.4', '')));
$manager->persist(
Visit::forRegularNotFound(new Visitor('shlink-tests-agent', 'https://doma.in/foo/bar', '1.2.3.4', '')),
);
$manager->persist(
Visit::forInvalidShortUrl(new Visitor('shlink-tests-agent', 'https://doma.in/foo', '1.2.3.4', '')),
);
$manager->flush(); $manager->flush();
} }
} }

View file

@ -31,7 +31,7 @@ class GlobalVisitsActionTest extends TestCase
public function statsAreReturnedFromHelper(): void public function statsAreReturnedFromHelper(): void
{ {
$apiKey = new ApiKey(); $apiKey = new ApiKey();
$stats = new VisitsStats(5); $stats = new VisitsStats(5, 3);
$getStats = $this->helper->getVisitsStats($apiKey)->willReturn($stats); $getStats = $this->helper->getVisitsStats($apiKey)->willReturn($stats);
/** @var JsonResponse $resp */ /** @var JsonResponse $resp */