53b3fd945a
Database Portability Tests / Integration (mysql) (push) Has been skipped
Database Portability Tests / Integration (postgres) (push) Has been skipped
Database Portability Tests / Integration (sqlite) (push) Has been skipped
Database Portability Tests / Verify no MySQL-specific SQL (push) Successful in 5s
Database Portability Tests / Unit Tests (PlatformHelper) (push) Failing after 43s
Inventory: - General material, stock items, and sales CRUD - Category management with CategoryPicker component - Inventory reports service - Database migrations and mappers Frontend: - Inventory view with tabs (Allgemeinmaterial, Verkaufsmaterial, Verkäufe) - Forms for general material, stock items, and sales - Search bar fix: flexbox wrapper with inline icon replaces broken NcTextField icon slot Tests: - All 1,491 tests pass (zero errors, warnings, deprecations) - BundleImportServiceTest: fixed ZipArchive empty-file deprecation - BundleImportService: null-coalescing for targetFields - PHPUnit test infra: make test target via container CLAUDE.md: - Added Testing section as PR gating criterion
109 lines
4.2 KiB
PHP
109 lines
4.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace OCA\Mitgliederverwaltung\Tests\Db;
|
|
|
|
use OCA\Mitgliederverwaltung\Db\StockItem;
|
|
use OCA\Mitgliederverwaltung\Db\StockItemMapper;
|
|
use OCP\AppFramework\Db\DoesNotExistException;
|
|
use OCP\DB\QueryBuilder\IExpressionBuilder;
|
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
|
use OCP\DB\IResult;
|
|
use OCP\IDBConnection;
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class StockItemMapperTest extends TestCase {
|
|
|
|
private IDBConnection&MockObject $db;
|
|
private IQueryBuilder&MockObject $qb;
|
|
private IExpressionBuilder&MockObject $expr;
|
|
private IResult&MockObject $result;
|
|
|
|
protected function setUp(): void {
|
|
parent::setUp();
|
|
|
|
$this->db = $this->createMock(IDBConnection::class);
|
|
$this->qb = $this->createMock(IQueryBuilder::class);
|
|
$this->expr = $this->createMock(IExpressionBuilder::class);
|
|
$this->result = $this->createMock(IResult::class);
|
|
|
|
$this->qb->method('expr')->willReturn($this->expr);
|
|
$this->qb->method('select')->willReturnSelf();
|
|
$this->qb->method('from')->willReturnSelf();
|
|
$this->qb->method('where')->willReturnSelf();
|
|
$this->qb->method('orderBy')->willReturnSelf();
|
|
$this->qb->method('createNamedParameter')->willReturn(':param');
|
|
$this->qb->method('createFunction')->willReturnCallback(fn($call) => $call);
|
|
$this->qb->method('getSQL')->willReturn('SELECT * FROM test');
|
|
|
|
$this->expr->method('eq')->willReturn('col = :param');
|
|
$this->expr->method('isNull')->willReturn('col IS NULL');
|
|
|
|
$this->db->method('getQueryBuilder')->willReturn($this->qb);
|
|
}
|
|
|
|
private function configureResultRows(array $rows): void {
|
|
$fetchCalls = array_merge($rows, [false]);
|
|
$this->result->method('fetch')
|
|
->willReturnOnConsecutiveCalls(...$fetchCalls);
|
|
$this->result->method('closeCursor')->willReturn(true);
|
|
$this->qb->method('executeQuery')->willReturn($this->result);
|
|
}
|
|
|
|
private function configureResultSingleRow(array $row): void {
|
|
$this->result->method('fetch')
|
|
->willReturnOnConsecutiveCalls($row, false);
|
|
$this->result->method('closeCursor')->willReturn(true);
|
|
$this->qb->method('executeQuery')->willReturn($this->result);
|
|
}
|
|
|
|
private function configureResultEmpty(): void {
|
|
$this->result->method('fetch')->willReturn(false);
|
|
$this->result->method('closeCursor')->willReturn(true);
|
|
$this->qb->method('executeQuery')->willReturn($this->result);
|
|
}
|
|
|
|
private function stockRow(int $id = 1, string $name = 'Pfadfinderhemd', ?string $urls = '[{"url":"https://shop.example.com","provider":"shop"}]'): array {
|
|
return [
|
|
'id' => $id,
|
|
'name' => $name,
|
|
'provider_urls_json' => $urls,
|
|
'created_at' => '2026-04-21 00:00:00',
|
|
'updated_at' => '2026-04-21 00:00:00',
|
|
];
|
|
}
|
|
|
|
public function testCreateAndFind(): void {
|
|
$this->configureResultSingleRow($this->stockRow(42, 'Pfadfinderhemd'));
|
|
$mapper = new StockItemMapper($this->db);
|
|
$item = $mapper->findById(42);
|
|
$this->assertSame(42, $item->getId());
|
|
$this->assertSame('Pfadfinderhemd', $item->getName());
|
|
}
|
|
|
|
public function testFindAll(): void {
|
|
$this->configureResultRows([
|
|
$this->stockRow(1, 'Pfadfinderhemd'),
|
|
$this->stockRow(2, 'Pfadfindershirt'),
|
|
]);
|
|
$mapper = new StockItemMapper($this->db);
|
|
$items = $mapper->findAll();
|
|
$this->assertCount(2, $items);
|
|
$this->assertSame('Pfadfinderhemd', $items[0]->getName());
|
|
}
|
|
|
|
public function testProviderUrlsJsonSerialization(): void {
|
|
$this->configureResultSingleRow($this->stockRow(1, 'Hemd', '[{"url":"https://shop.example.com","provider":"shop"},{"url":"https://bestell.example.com","provider":"bestell"}]'));
|
|
$mapper = new StockItemMapper($this->db);
|
|
$item = $mapper->findById(1);
|
|
$json = $item->getProviderUrlsJson();
|
|
$this->assertNotNull($json);
|
|
$decoded = json_decode($json, true);
|
|
$this->assertCount(2, $decoded);
|
|
$this->assertSame('https://shop.example.com', $decoded[0]['url']);
|
|
$this->assertSame('shop', $decoded[0]['provider']);
|
|
}
|
|
}
|