opsdash-app/opsdash/tests/php/Service/OverviewEventsCollectorTest.php
2026-02-11 10:33:30 +07:00

224 lines
7.3 KiB
PHP

<?php
declare(strict_types=1);
namespace OCA\Opsdash\Tests\Service;
use DateTimeImmutable;
use OCA\Opsdash\Service\CalendarParsingService;
use OCA\Opsdash\Service\OverviewEventsCollector;
use OCP\Calendar\IManager;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
class OverviewEventsCollectorTest extends TestCase {
public function testCollectSkipsUnselectedCalendars(): void {
$manager = new class() implements IManager {
public array $responses = [];
public function newQuery(string $principal): object {
return new class() {
public string $calendar = '';
public function addSearchCalendar(string $calendar): void { $this->calendar = $calendar; }
public function setTimerangeStart($from): void {}
public function setTimerangeEnd($to): void {}
};
}
public function searchForPrincipal(object $q): array {
return $this->responses[$q->calendar] ?? [];
}
};
$manager->responses = [
'cal-a' => [['id' => 1]],
'cal-b' => [['id' => 2]],
];
$calendarService = new class() extends CalendarParsingService {
public function parseRows(array $raw, string $calendarName, ?string $calendarId = null): array {
return array_map(
fn ($row) => ['calendar' => $calendarName, 'calendar_id' => $calendarId, 'hours' => 1, 'allday' => false],
$raw,
);
}
};
$logger = $this->createMock(LoggerInterface::class);
$collector = new OverviewEventsCollector($manager, $calendarService, $logger);
$calA = new class() {
public function getUri(): string { return 'cal-a'; }
public function getDisplayName(): string { return 'A'; }
};
$calB = new class() {
public function getUri(): string { return 'cal-b'; }
public function getDisplayName(): string { return 'B'; }
};
$res = $collector->collect(
principal: 'principals/users/admin',
cals: [$calA, $calB],
includeAll: false,
selectedIds: ['cal-a'],
from: new DateTimeImmutable('2025-01-01T00:00:00Z'),
to: new DateTimeImmutable('2025-01-08T00:00:00Z'),
maxPerCal: 50,
maxTotal: 50,
debug: true,
);
$this->assertCount(1, $res['events']);
$this->assertSame('cal-a', $res['events'][0]['calendar_id']);
$this->assertFalse($res['truncated']);
$this->assertCount(1, $res['queryDbg']);
$this->assertSame('cal-a', $res['queryDbg'][0]['calendar_id']);
}
public function testCollectAppliesCapsAndReportsTruncation(): void {
$manager = new class() implements IManager {
public array $responses = [];
public function newQuery(string $principal): object {
return new class() {
public string $calendar = '';
public function addSearchCalendar(string $calendar): void { $this->calendar = $calendar; }
public function setTimerangeStart($from): void {}
public function setTimerangeEnd($to): void {}
};
}
public function searchForPrincipal(object $q): array {
return $this->responses[$q->calendar] ?? [];
}
};
$manager->responses = [
'cal-a' => array_fill(0, 10, ['id' => 1]),
'cal-b' => array_fill(0, 10, ['id' => 2]),
];
$calendarService = new class() extends CalendarParsingService {
public function parseRows(array $raw, string $calendarName, ?string $calendarId = null): array {
return array_map(
fn ($row) => ['calendar' => $calendarName, 'calendar_id' => $calendarId, 'hours' => 1, 'allday' => false],
$raw,
);
}
};
$logger = $this->createMock(LoggerInterface::class);
$collector = new OverviewEventsCollector($manager, $calendarService, $logger);
$calA = new class() {
public function getUri(): string { return 'cal-a'; }
public function getDisplayName(): string { return 'A'; }
};
$calB = new class() {
public function getUri(): string { return 'cal-b'; }
public function getDisplayName(): string { return 'B'; }
};
$res = $collector->collect(
principal: 'principals/users/admin',
cals: [$calA, $calB],
includeAll: true,
selectedIds: [],
from: new DateTimeImmutable('2025-01-01T00:00:00Z'),
to: new DateTimeImmutable('2025-01-08T00:00:00Z'),
maxPerCal: 3,
maxTotal: 5,
debug: false,
);
$this->assertTrue($res['truncated']);
$this->assertCount(5, $res['events']);
$this->assertSame('cal-a', $res['events'][0]['calendar_id']);
$this->assertSame('cal-b', $res['events'][4]['calendar_id']);
}
public function testCollectCachesIdenticalRequestsWithinInstance(): void {
$manager = new class() implements IManager {
public int $calls = 0;
public array $responses = [];
public function newQuery(string $principal): object {
return new class() {
public string $calendar = '';
public function addSearchCalendar(string $calendar): void { $this->calendar = $calendar; }
public function setTimerangeStart($from): void {}
public function setTimerangeEnd($to): void {}
};
}
public function searchForPrincipal(object $q): array {
$this->calls++;
return $this->responses[$q->calendar] ?? [];
}
};
$manager->responses = [
'cal-a' => [['id' => 1], ['id' => 2]],
'cal-b' => [['id' => 3]],
];
$calendarService = new class() extends CalendarParsingService {
public function parseRows(array $raw, string $calendarName, ?string $calendarId = null): array {
return array_map(
fn ($row) => ['calendar' => $calendarName, 'calendar_id' => $calendarId, 'hours' => 1, 'allday' => false],
$raw,
);
}
};
$logger = $this->createMock(LoggerInterface::class);
$collector = new OverviewEventsCollector($manager, $calendarService, $logger);
$calA = new class() {
public function getUri(): string { return 'cal-a'; }
public function getDisplayName(): string { return 'A'; }
};
$calB = new class() {
public function getUri(): string { return 'cal-b'; }
public function getDisplayName(): string { return 'B'; }
};
$from = new DateTimeImmutable('2025-01-01T00:00:00Z');
$to = new DateTimeImmutable('2025-01-08T00:00:00Z');
$first = $collector->collect(
principal: 'principals/users/admin',
cals: [$calA, $calB],
includeAll: true,
selectedIds: [],
from: $from,
to: $to,
maxPerCal: 50,
maxTotal: 50,
debug: false,
);
$second = $collector->collect(
principal: 'principals/users/admin',
cals: [$calA, $calB],
includeAll: true,
selectedIds: [],
from: $from,
to: $to,
maxPerCal: 50,
maxTotal: 50,
debug: false,
);
$this->assertCount(3, $first['events']);
$this->assertCount(3, $second['events']);
$this->assertSame(2, $manager->calls, 'Second identical collect should be served from cache.');
// Debug mode keeps a separate cache entry.
$collector->collect(
principal: 'principals/users/admin',
cals: [$calA, $calB],
includeAll: true,
selectedIds: [],
from: $from,
to: $to,
maxPerCal: 50,
maxTotal: 50,
debug: true,
);
$this->assertSame(4, $manager->calls);
}
}