nextcloud-shortcuts/tests/unit/Service/ShortcutServiceTest.php
Lukas Schaefer c5c1de0108
All checks were successful
PHPUnit SQLite / versions (pull_request) Successful in 4s
PHPUnit SQLite / changes (pull_request) Successful in 1s
Lint info.xml / info.xml lint (pull_request) Successful in 3s
PHP / versions (pull_request) Successful in 5s
Static analysis / versions (pull_request) Successful in 3s
REUSE Compliance Check / reuse-compliance-check (pull_request) Successful in 3s
Node / NPM (pull_request) Successful in 21s
PHP / PHP 8.5 (8.5) (pull_request) Successful in 54s
PHP / PHP 8.2 (8.2) (pull_request) Successful in 2m16s
PHPUnit SQLite / SQLite PHP 8.5 Nextcloud master (8.5, master) (pull_request) Successful in 2m27s
PHPUnit SQLite / phpunit-sqlite-summary (pull_request) Successful in 1s
Static analysis / static-psalm-analysis dev-stable34 (dev-stable34, 8.5) (pull_request) Successful in 1m48s
Static analysis / static-psalm-analysis dev-stable33 (dev-stable33, 8.5) (pull_request) Successful in 2m30s
Static analysis / static-psalm-analysis dev-master (dev-master, 8.5) (pull_request) Successful in 2m49s
Static analysis / static-psalm-analysis-summary (pull_request) Successful in 1s
Create initial version that supports shortcut files
Signed-off-by: Lukas Schaefer <lukas@lschaefer.xyz>
2026-08-01 12:28:04 -04:00

173 lines
7.1 KiB
PHP

<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Lukas Schaefer
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Shortcuts\Tests\Unit\Service;
use OCA\Shortcuts\Exception\ConflictException;
use OCA\Shortcuts\Exception\InvalidPathException;
use OCA\Shortcuts\Service\ShortcutService;
use OCP\Constants;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\IUser;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
final class ShortcutServiceTest extends TestCase {
private IRootFolder&MockObject $rootFolder;
private Folder&MockObject $userFolder;
private IUser&MockObject $user;
private ShortcutService $service;
protected function setUp(): void {
parent::setUp();
$this->rootFolder = $this->createMock(IRootFolder::class);
$this->userFolder = $this->createMock(Folder::class);
$this->user = $this->createMock(IUser::class);
$this->user->method('getUID')->willReturn('admin');
$this->rootFolder->method('getUserFolder')->with('admin')->willReturn($this->userFolder);
$this->service = new ShortcutService($this->rootFolder);
}
public function testCreateWritesBareFileId(): void {
$target = $this->createMock(File::class);
$target->method('getId')->willReturn(320);
$target->method('getName')->willReturn('main.tex');
$target->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
$target->method('getMimeType')->willReturn('application/x-tex');
$destination = $this->createMock(Folder::class);
$destination->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
$destination->method('nodeExists')->with('main.tex.nextcloudshortcut')->willReturn(false);
$created = $this->createMock(File::class);
$created->method('getId')->willReturn(999);
$created->method('getName')->willReturn('main.tex.nextcloudshortcut');
$created->method('getPath')->willReturn('/admin/files/test/main.tex.nextcloudshortcut');
$destination->expects($this->once())
->method('newFile')
->with('main.tex.nextcloudshortcut', '320')
->willReturn($created);
$this->userFolder->method('getFirstNodeById')->with(320)->willReturn($target);
$this->userFolder->method('get')->with('/test')->willReturn($destination);
$this->userFolder->method('getRelativePath')
->with('/admin/files/test/main.tex.nextcloudshortcut')
->willReturn('/test/main.tex.nextcloudshortcut');
$result = $this->service->create($this->user, 320, '/test');
$this->assertSame(999, $result['fileId']);
$this->assertSame(320, $result['targetFileId']);
$this->assertSame('file', $result['targetType']);
$this->assertSame('main.tex.nextcloudshortcut', $result['name']);
}
public function testCreateConflict(): void {
$target = $this->createMock(File::class);
$target->method('getId')->willReturn(1);
$target->method('getName')->willReturn('a.txt');
$target->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
$target->method('getMimeType')->willReturn('text/plain');
$this->userFolder->method('getFirstNodeById')->willReturn($target);
$this->userFolder->method('get')->with('/')->willReturn($this->userFolder);
$this->userFolder->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
$this->userFolder->method('nodeExists')->with('a.txt.nextcloudshortcut')->willReturn(true);
$this->expectException(ConflictException::class);
$this->service->create($this->user, 1, '/');
}
public function testResolveFile(): void {
$shortcut = $this->createMock(File::class);
$shortcut->method('getId')->willReturn(50);
$shortcut->method('getName')->willReturn('main.tex.nextcloudshortcut');
$shortcut->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
$shortcut->method('getMimeType')->willReturn('application/x-nextcloud-shortcut');
$shortcut->method('getContent')->willReturn("320\n");
$target = $this->createMock(File::class);
$target->method('getId')->willReturn(320);
$target->method('getName')->willReturn('main.tex');
$target->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
$target->method('getMimeType')->willReturn('application/x-tex');
$target->method('getPath')->willReturn('/admin/files/docs/main.tex');
$parent = $this->createMock(Folder::class);
$parent->method('getPath')->willReturn('/admin/files/docs');
$target->method('getParent')->willReturn($parent);
$this->userFolder->method('getFirstNodeById')->willReturnMap([
[50, $shortcut],
[320, $target],
]);
$this->userFolder->method('getRelativePath')->willReturnMap([
['/admin/files/docs/main.tex', '/docs/main.tex'],
['/admin/files/docs', '/docs'],
]);
$result = $this->service->resolve($this->user, 50);
$this->assertSame(320, $result['targetFileId']);
$this->assertSame('file', $result['targetType']);
$this->assertSame('/docs/main.tex', $result['path']);
$this->assertSame('/docs', $result['dirname']);
}
public function testResolveInvalidContents(): void {
$shortcut = $this->createMock(File::class);
$shortcut->method('getName')->willReturn('bad.nextcloudshortcut');
$shortcut->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
$shortcut->method('getMimeType')->willReturn('application/x-nextcloud-shortcut');
$shortcut->method('getContent')->willReturn('not-an-id');
$this->userFolder->method('getFirstNodeById')->willReturn($shortcut);
$this->expectException(InvalidPathException::class);
$this->service->resolve($this->user, 1);
}
public function testCreateCanonicalizesShortcutTarget(): void {
$innerShortcut = $this->createMock(File::class);
$innerShortcut->method('getId')->willReturn(10);
$innerShortcut->method('getName')->willReturn('a.nextcloudshortcut');
$innerShortcut->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
$innerShortcut->method('getMimeType')->willReturn('application/x-nextcloud-shortcut');
$innerShortcut->method('getContent')->willReturn('320');
$realTarget = $this->createMock(File::class);
$realTarget->method('getId')->willReturn(320);
$realTarget->method('getName')->willReturn('main.tex');
$realTarget->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
$realTarget->method('getMimeType')->willReturn('application/x-tex');
$created = $this->createMock(File::class);
$created->method('getId')->willReturn(11);
$created->method('getName')->willReturn('main.tex.nextcloudshortcut');
$created->method('getPath')->willReturn('/admin/files/main.tex.nextcloudshortcut');
$this->userFolder->method('getFirstNodeById')->willReturnMap([
[10, $innerShortcut],
[320, $realTarget],
]);
$this->userFolder->method('get')->with('/')->willReturn($this->userFolder);
$this->userFolder->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
$this->userFolder->method('nodeExists')->with('main.tex.nextcloudshortcut')->willReturn(false);
$this->userFolder->expects($this->once())
->method('newFile')
->with('main.tex.nextcloudshortcut', '320')
->willReturn($created);
$this->userFolder->method('getRelativePath')->willReturn('/main.tex.nextcloudshortcut');
$result = $this->service->create($this->user, 10, '/');
$this->assertSame(320, $result['targetFileId']);
$this->assertSame(11, $result['fileId']);
}
}