test media removal
This commit is contained in:
parent
d0810ba4b3
commit
4b432d9b99
4 changed files with 177 additions and 4 deletions
|
|
@ -12,6 +12,11 @@ class FakeFileUploader implements FileUploader
|
||||||
*/
|
*/
|
||||||
public array $uploads = [];
|
public array $uploads = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string[]
|
||||||
|
*/
|
||||||
|
public array $deletedPaths = [];
|
||||||
|
|
||||||
public function upload(FileToUpload $file, string $folder): string
|
public function upload(FileToUpload $file, string $folder): string
|
||||||
{
|
{
|
||||||
$this->uploads[] = ['file' => $file, 'folder' => $folder];
|
$this->uploads[] = ['file' => $file, 'folder' => $folder];
|
||||||
|
|
@ -23,4 +28,9 @@ class FakeFileUploader implements FileUploader
|
||||||
{
|
{
|
||||||
return 'https://test.local/storage/' . $path;
|
return 'https://test.local/storage/' . $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function delete(string $path): void
|
||||||
|
{
|
||||||
|
$this->deletedPaths[] = $path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -193,6 +193,60 @@ class ElementsEndpointTest extends TestCase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testAuthenticatedUpdateClearsUploadedMedia(): void
|
||||||
|
{
|
||||||
|
Storage::fake('public');
|
||||||
|
Storage::disk('public')->put(
|
||||||
|
'element-icons/original-icon.png',
|
||||||
|
'icon bytes',
|
||||||
|
);
|
||||||
|
Storage::disk('public')->put(
|
||||||
|
'element-pdfs/original.pdf',
|
||||||
|
'pdf bytes',
|
||||||
|
);
|
||||||
|
$setRepository = app(SetRepository::class);
|
||||||
|
$elementRepository = app(ElementRepository::class);
|
||||||
|
$set = $setRepository->create(new CreateSetDto(
|
||||||
|
name: 'Baderech HaAvodah',
|
||||||
|
description: 'A structured path for growth',
|
||||||
|
iconImageUrl: '/assets/baderech-haavodah-icon.png',
|
||||||
|
));
|
||||||
|
$element = $elementRepository->create(new CreateElementDto(
|
||||||
|
set: $set,
|
||||||
|
title: 'Baderech HaAvodah',
|
||||||
|
description: 'A structured path for growth',
|
||||||
|
iconImageUrl: 'element-icons/original-icon.png',
|
||||||
|
richText: '<p>A structured path for growth</p>',
|
||||||
|
pdfPath: 'element-pdfs/original.pdf',
|
||||||
|
youtubeUrl: null,
|
||||||
|
parentElement: null,
|
||||||
|
));
|
||||||
|
$this->createSession('valid-token');
|
||||||
|
|
||||||
|
$response = $this->withCredentials()
|
||||||
|
->withUnencryptedCookie('auth_token', 'valid-token')
|
||||||
|
->postJson('/api/element/update', [
|
||||||
|
'elementId' => $element->getId(),
|
||||||
|
'iconImageUrl' => '',
|
||||||
|
'pdfPath' => '',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response->assertOk();
|
||||||
|
$body = $response->json();
|
||||||
|
$this->assertNull($body['element']['iconImageUrl']);
|
||||||
|
$this->assertNull($body['element']['pdfPath']);
|
||||||
|
$updatedElement = $elementRepository->find($element->getId());
|
||||||
|
$this->assertNotNull($updatedElement);
|
||||||
|
$this->assertNull($updatedElement->getIconImageUrl());
|
||||||
|
$this->assertNull($updatedElement->getPdfPath());
|
||||||
|
Storage::disk('public')->assertMissing(
|
||||||
|
'element-icons/original-icon.png',
|
||||||
|
);
|
||||||
|
Storage::disk('public')->assertMissing(
|
||||||
|
'element-pdfs/original.pdf',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testIconImageUploadRequiresAuthentication(): void
|
public function testIconImageUploadRequiresAuthentication(): void
|
||||||
{
|
{
|
||||||
$setRepository = app(SetRepository::class);
|
$setRepository = app(SetRepository::class);
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,19 @@ use App\Element\UseCases\UpdateElement\UpdateYoutubeUrlRequest;
|
||||||
use App\Exceptions\BadRequestException;
|
use App\Exceptions\BadRequestException;
|
||||||
use App\Set\Set as DomainSet;
|
use App\Set\Set as DomainSet;
|
||||||
use Tests\Fakes\FakeElementRepository;
|
use Tests\Fakes\FakeElementRepository;
|
||||||
|
use Tests\Fakes\FakeFileUploader;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class UpdateElementFieldsTest extends TestCase
|
class UpdateElementFieldsTest extends TestCase
|
||||||
{
|
{
|
||||||
private FakeElementRepository $elementRepo;
|
private FakeElementRepository $elementRepo;
|
||||||
|
|
||||||
|
private FakeFileUploader $fileUploader;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->elementRepo = new FakeElementRepository();
|
$this->elementRepo = new FakeElementRepository();
|
||||||
|
$this->fileUploader = new FakeFileUploader();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUpdateTitleUpdatesOnlyTitle(): void
|
public function testUpdateTitleUpdatesOnlyTitle(): void
|
||||||
|
|
@ -88,7 +92,10 @@ class UpdateElementFieldsTest extends TestCase
|
||||||
public function testUpdateIconImageUrlClearsEmptyString(): void
|
public function testUpdateIconImageUrlClearsEmptyString(): void
|
||||||
{
|
{
|
||||||
$element = $this->createFilledElement();
|
$element = $this->createFilledElement();
|
||||||
$updateIconImageUrl = new UpdateIconImageUrl($this->elementRepo);
|
$updateIconImageUrl = new UpdateIconImageUrl(
|
||||||
|
$this->elementRepo,
|
||||||
|
$this->fileUploader,
|
||||||
|
);
|
||||||
|
|
||||||
$updatedElement = $updateIconImageUrl->execute(
|
$updatedElement = $updateIconImageUrl->execute(
|
||||||
new UpdateIconImageUrlRequest(
|
new UpdateIconImageUrlRequest(
|
||||||
|
|
@ -99,6 +106,32 @@ class UpdateElementFieldsTest extends TestCase
|
||||||
|
|
||||||
$this->assertNull($updatedElement->getIconImageUrl());
|
$this->assertNull($updatedElement->getIconImageUrl());
|
||||||
$this->assertSame($element->getTitle(), $updatedElement->getTitle());
|
$this->assertSame($element->getTitle(), $updatedElement->getTitle());
|
||||||
|
$this->assertSame([], $this->fileUploader->deletedPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUpdateIconImageUrlDeletesManagedFileWhenCleared(): void
|
||||||
|
{
|
||||||
|
$element = $this->createElementWithMedia(
|
||||||
|
'element-icons/original-icon.png',
|
||||||
|
'/assets/pdfs/original.pdf',
|
||||||
|
);
|
||||||
|
$updateIconImageUrl = new UpdateIconImageUrl(
|
||||||
|
$this->elementRepo,
|
||||||
|
$this->fileUploader,
|
||||||
|
);
|
||||||
|
|
||||||
|
$updatedElement = $updateIconImageUrl->execute(
|
||||||
|
new UpdateIconImageUrlRequest(
|
||||||
|
id: $element->getId(),
|
||||||
|
iconImageUrl: '',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertNull($updatedElement->getIconImageUrl());
|
||||||
|
$this->assertSame(
|
||||||
|
['element-icons/original-icon.png'],
|
||||||
|
$this->fileUploader->deletedPaths,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUpdateRichTextUpdatesOnlyRichText(): void
|
public function testUpdateRichTextUpdatesOnlyRichText(): void
|
||||||
|
|
@ -126,7 +159,10 @@ class UpdateElementFieldsTest extends TestCase
|
||||||
public function testUpdatePdfPathClearsEmptyString(): void
|
public function testUpdatePdfPathClearsEmptyString(): void
|
||||||
{
|
{
|
||||||
$element = $this->createFilledElement();
|
$element = $this->createFilledElement();
|
||||||
$updatePdfPath = new UpdatePdfPath($this->elementRepo);
|
$updatePdfPath = new UpdatePdfPath(
|
||||||
|
$this->elementRepo,
|
||||||
|
$this->fileUploader,
|
||||||
|
);
|
||||||
|
|
||||||
$updatedElement = $updatePdfPath->execute(
|
$updatedElement = $updatePdfPath->execute(
|
||||||
new UpdatePdfPathRequest(id: $element->getId(), pdfPath: '')
|
new UpdatePdfPathRequest(id: $element->getId(), pdfPath: '')
|
||||||
|
|
@ -134,6 +170,29 @@ class UpdateElementFieldsTest extends TestCase
|
||||||
|
|
||||||
$this->assertNull($updatedElement->getPdfPath());
|
$this->assertNull($updatedElement->getPdfPath());
|
||||||
$this->assertSame($element->getTitle(), $updatedElement->getTitle());
|
$this->assertSame($element->getTitle(), $updatedElement->getTitle());
|
||||||
|
$this->assertSame([], $this->fileUploader->deletedPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUpdatePdfPathDeletesManagedFileWhenCleared(): void
|
||||||
|
{
|
||||||
|
$element = $this->createElementWithMedia(
|
||||||
|
'/assets/original-icon.png',
|
||||||
|
'element-pdfs/original.pdf',
|
||||||
|
);
|
||||||
|
$updatePdfPath = new UpdatePdfPath(
|
||||||
|
$this->elementRepo,
|
||||||
|
$this->fileUploader,
|
||||||
|
);
|
||||||
|
|
||||||
|
$updatedElement = $updatePdfPath->execute(
|
||||||
|
new UpdatePdfPathRequest(id: $element->getId(), pdfPath: '')
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertNull($updatedElement->getPdfPath());
|
||||||
|
$this->assertSame(
|
||||||
|
['element-pdfs/original.pdf'],
|
||||||
|
$this->fileUploader->deletedPaths,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUpdateYoutubeUrlClearsEmptyString(): void
|
public function testUpdateYoutubeUrlClearsEmptyString(): void
|
||||||
|
|
@ -154,6 +213,16 @@ class UpdateElementFieldsTest extends TestCase
|
||||||
|
|
||||||
private function createFilledElement(): Element
|
private function createFilledElement(): Element
|
||||||
{
|
{
|
||||||
|
return $this->createElementWithMedia(
|
||||||
|
'/assets/original-icon.png',
|
||||||
|
'/assets/pdfs/original.pdf',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createElementWithMedia(
|
||||||
|
?string $iconImageUrl,
|
||||||
|
?string $pdfPath,
|
||||||
|
): Element {
|
||||||
$set = new DomainSet(
|
$set = new DomainSet(
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Baderech',
|
name: 'Baderech',
|
||||||
|
|
@ -165,9 +234,9 @@ class UpdateElementFieldsTest extends TestCase
|
||||||
set: $set,
|
set: $set,
|
||||||
title: 'Original title',
|
title: 'Original title',
|
||||||
description: 'Original description',
|
description: 'Original description',
|
||||||
iconImageUrl: '/assets/original-icon.png',
|
iconImageUrl: $iconImageUrl,
|
||||||
richText: '<p>Original rich text</p>',
|
richText: '<p>Original rich text</p>',
|
||||||
pdfPath: '/assets/pdfs/original.pdf',
|
pdfPath: $pdfPath,
|
||||||
youtubeUrl: 'https://www.youtube.com/watch?v=yHx-r4p6hHU',
|
youtubeUrl: 'https://www.youtube.com/watch?v=yHx-r4p6hHU',
|
||||||
parentElement: null,
|
parentElement: null,
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -151,4 +151,44 @@ describe('admin element editing', () => {
|
||||||
|
|
||||||
cy.resetDb()
|
cy.resetDb()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('removes uploaded icon and pdf files immediately through the UI', () => {
|
||||||
|
cy.resetDb()
|
||||||
|
loginAsAdmin()
|
||||||
|
cy.visit('/admin/element/1')
|
||||||
|
cy.intercept('POST', /\/api\/element\/update$/).as('updateElement')
|
||||||
|
|
||||||
|
cy.get('[data-cy="admin-element-icon-image-input"]').selectFile(
|
||||||
|
'public/assets/baderech-haavodah-icon.png',
|
||||||
|
{ force: true },
|
||||||
|
)
|
||||||
|
cy.wait('@updateElement')
|
||||||
|
cy.get('[data-cy="admin-element-pdf-input"]').selectFile(
|
||||||
|
'public/assets/pdfs/baderech.pdf',
|
||||||
|
{ force: true },
|
||||||
|
)
|
||||||
|
cy.wait('@updateElement')
|
||||||
|
|
||||||
|
cy.contains('button', 'Remove icon image').click()
|
||||||
|
cy.wait('@updateElement')
|
||||||
|
cy.get('[data-cy="admin-element-icon-image-status"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.and('contain.text', 'Icon image removed')
|
||||||
|
cy.get('[data-cy="admin-element-current-icon"]').should('not.exist')
|
||||||
|
cy.contains('No icon image').should('be.visible')
|
||||||
|
|
||||||
|
cy.contains('button', 'Remove PDF').click()
|
||||||
|
cy.wait('@updateElement')
|
||||||
|
cy.get('[data-cy="admin-element-pdf-status"]')
|
||||||
|
.should('be.visible')
|
||||||
|
.and('contain.text', 'PDF removed')
|
||||||
|
cy.get('[data-cy="admin-element-current-pdf"]').should('not.exist')
|
||||||
|
cy.contains('No PDF').should('be.visible')
|
||||||
|
|
||||||
|
cy.contains('header.site-header a', 'View Element').click()
|
||||||
|
cy.get('[data-cy="element-icon"]').should('not.exist')
|
||||||
|
cy.get('[data-cy="element-pdf-link"]').should('not.exist')
|
||||||
|
|
||||||
|
cy.resetDb()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue