Rabbi_Gerzi/backend/tests/Unit/Controllers/ElementControllerTest.php

327 lines
11 KiB
PHP

<?php
namespace Tests\Unit\Controllers;
use App\Controllers\ElementController;
use App\Element\CreateElementDto;
use App\Element\Element;
use App\Element\UseCases\GetElement\GetElement;
use App\Element\UseCases\UpdateElement\UpdateDescription;
use App\Element\UseCases\UpdateElement\UpdateElement;
use App\Element\UseCases\UpdateElement\UpdateIconImage;
use App\Element\UseCases\UpdateElement\UpdateIconImageUrl;
use App\Element\UseCases\UpdateElement\UpdateLongPdf;
use App\Element\UseCases\UpdateElement\UpdateLongPdfPath;
use App\Element\UseCases\UpdateElement\UpdateRichText;
use App\Element\UseCases\UpdateElement\UpdateShortPdf;
use App\Element\UseCases\UpdateElement\UpdateShortPdfPath;
use App\Element\UseCases\UpdateElement\UpdateTitle;
use App\Element\UseCases\UpdateElement\UpdateYoutubeUrl;
use App\Set\Set as DomainSet;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Tests\Fakes\FakeElementRepository;
use Tests\Fakes\FakeFileUploader;
use Tests\TestCase;
class ElementControllerTest extends TestCase
{
private ElementController $controller;
private FakeElementRepository $elementRepo;
private FakeFileUploader $fileUploader;
protected function setUp(): void
{
$this->elementRepo = new FakeElementRepository();
$this->fileUploader = new FakeFileUploader();
$getElement = new GetElement($this->elementRepo);
$updateElement = new UpdateElement(
new UpdateTitle($this->elementRepo),
new UpdateDescription($this->elementRepo),
new UpdateIconImageUrl($this->elementRepo, $this->fileUploader),
new UpdateRichText($this->elementRepo),
new UpdateShortPdfPath($this->elementRepo, $this->fileUploader),
new UpdateLongPdfPath($this->elementRepo, $this->fileUploader),
new UpdateYoutubeUrl($this->elementRepo),
new UpdateIconImage(
$this->elementRepo,
$this->fileUploader,
),
new UpdateShortPdf(
$this->elementRepo,
$this->fileUploader,
),
new UpdateLongPdf(
$this->elementRepo,
$this->fileUploader,
),
$this->elementRepo,
);
$this->controller = new ElementController(
$getElement,
$updateElement,
$this->fileUploader,
);
}
public function testShowReturnsElementPayload(): void
{
$set = $this->createSet(1, 'Baderech');
$element = $this->createElement(
$set,
'Baderech HaAvodah',
'A structured path for growth',
'/assets/baderech-icon.png',
'<p>A structured path for growth</p>',
'/assets/pdfs/baderech.pdf',
'/assets/pdfs/baderech-long.pdf',
'https://www.youtube.com/watch?v=yHx-r4p6hHU&t=1s',
null,
);
$firstChildElement = $this->createElement(
$set,
'Avodah Foundations',
'Foundations for steady avodah',
null,
'<p>Foundations rich text</p>',
'/assets/pdfs/foundations.pdf',
null,
null,
$element,
);
$secondChildElement = $this->createElement(
$set,
'Daily Practice',
'Daily practices for growth',
null,
'<p>Daily practice rich text</p>',
null,
null,
null,
$element,
);
$response = $this->controller->show($element->getId());
$this->assertEquals(200, $response->getStatusCode());
$body = json_decode($response->getContent(), true);
$this->assertSame($element->getId(), $body['element']['id']);
$this->assertSame('Baderech HaAvodah', $body['element']['title']);
$this->assertSame(
'A structured path for growth',
$body['element']['description'],
);
$this->assertSame(
'<p>A structured path for growth</p>',
$body['element']['richText'],
);
$this->assertSame(
'/assets/baderech-icon.png',
$body['element']['iconImageUrl'],
);
$this->assertSame(
'/assets/pdfs/baderech.pdf',
$body['element']['shortPdfPath'],
);
$this->assertSame(
'/assets/pdfs/baderech-long.pdf',
$body['element']['longPdfPath'],
);
$this->assertSame(
'/assets/pdfs/baderech.pdf',
$body['element']['pdfPath'],
);
$this->assertSame(
'https://www.youtube.com/watch?v=yHx-r4p6hHU&t=1s',
$body['element']['youtubeUrl'],
);
$this->assertSame([
[
'id' => $firstChildElement->getId(),
'title' => 'Avodah Foundations',
'description' => 'Foundations for steady avodah',
],
[
'id' => $secondChildElement->getId(),
'title' => 'Daily Practice',
'description' => 'Daily practices for growth',
],
], $body['childElements']);
}
public function testShowReturns400WhenIdMissing(): void
{
$response = $this->controller->show(null);
$this->assertEquals(400, $response->getStatusCode());
$this->assertSame(
['error' => 'id is required'],
json_decode($response->getContent(), true),
);
}
public function testShowReturns404WhenElementDoesNotExist(): void
{
$response = $this->controller->show(999);
$this->assertEquals(404, $response->getStatusCode());
$this->assertSame(
['error' => 'Element not found'],
json_decode($response->getContent(), true),
);
}
public function testUpdateWithIconImageReturnsElementPayload(): void
{
$set = $this->createSet(1, 'Baderech');
$element = $this->createEmptyElement($set);
$fixturePath = __DIR__ . '/../../fixtures/icon.png';
$request = new Request([], [
'elementId' => (string) $element->getId(),
'fileType' => 'iconImage',
], [], [], [
'file' => new UploadedFile(
$fixturePath,
'icon.png',
'image/png',
null,
true,
),
], ['REQUEST_METHOD' => 'POST']);
$response = $this->controller->update($request);
$this->assertEquals(200, $response->getStatusCode());
$body = json_decode($response->getContent(), true);
$this->assertSame($element->getId(), $body['element']['id']);
$this->assertSame(
'https://test.local/storage/element-icons/fake-icon.png',
$body['element']['iconImageUrl'],
);
$this->assertSame(
'element-icons',
$this->fileUploader->uploads[0]['folder'],
);
}
public function testUpdateWithShortPdfReturnsElementPayload(): void
{
$set = $this->createSet(1, 'Baderech');
$element = $this->createEmptyElement($set);
$fixturePath = __DIR__ . '/../../fixtures/baderech.pdf';
$request = new Request([], [
'elementId' => (string) $element->getId(),
'fileType' => 'shortPdf',
], [], [], [
'file' => new UploadedFile(
$fixturePath,
'baderech.pdf',
'application/pdf',
null,
true,
),
], ['REQUEST_METHOD' => 'POST']);
$response = $this->controller->update($request);
$this->assertEquals(200, $response->getStatusCode());
$body = json_decode($response->getContent(), true);
$this->assertSame($element->getId(), $body['element']['id']);
$this->assertSame(
'https://test.local/storage/element-pdfs/short/fake-baderech.pdf',
$body['element']['shortPdfPath'],
);
$this->assertSame(
$body['element']['shortPdfPath'],
$body['element']['pdfPath'],
);
$this->assertSame(
'element-pdfs/short',
$this->fileUploader->uploads[0]['folder'],
);
}
public function testUpdateWithLongPdfReturnsElementPayload(): void
{
$set = $this->createSet(1, 'Baderech');
$element = $this->createEmptyElement($set);
$fixturePath = __DIR__ . '/../../fixtures/baderech.pdf';
$request = new Request([], [
'elementId' => (string) $element->getId(),
'fileType' => 'longPdf',
], [], [], [
'file' => new UploadedFile(
$fixturePath,
'baderech.pdf',
'application/pdf',
null,
true,
),
], ['REQUEST_METHOD' => 'POST']);
$response = $this->controller->update($request);
$this->assertEquals(200, $response->getStatusCode());
$body = json_decode($response->getContent(), true);
$this->assertSame($element->getId(), $body['element']['id']);
$this->assertSame(
'https://test.local/storage/element-pdfs/long/fake-baderech.pdf',
$body['element']['longPdfPath'],
);
$this->assertSame(
'element-pdfs/long',
$this->fileUploader->uploads[0]['folder'],
);
}
private function createSet(int $id, string $name): DomainSet
{
return new DomainSet(
id: $id,
name: $name,
description: "$name description",
iconImageUrl: '/assets/baderech-icon.png',
);
}
private function createEmptyElement(DomainSet $set): Element
{
return $this->createElement(
$set,
'Baderech HaAvodah',
'A structured path for growth',
null,
'<p>A structured path for growth</p>',
null,
null,
null,
null,
);
}
private function createElement(
DomainSet $set,
string $title,
string $description,
?string $iconImageUrl,
string $richText,
?string $shortPdfPath,
?string $longPdfPath,
?string $youtubeUrl,
?Element $parentElement,
): Element {
return $this->elementRepo->create(new CreateElementDto(
set: $set,
title: $title,
description: $description,
iconImageUrl: $iconImageUrl,
richText: $richText,
shortPdfPath: $shortPdfPath,
longPdfPath: $longPdfPath,
youtubeUrl: $youtubeUrl,
parentElement: $parentElement,
));
}
}