Skip to content

Commit 21668f1

Browse files
committed
feat(delegation): add unit tests
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>
1 parent d11d808 commit 21668f1

5 files changed

Lines changed: 589 additions & 3 deletions

File tree

lib/Controller/DelegationController.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ public function getDelegatedUsers(int $accountId): JSONResponse {
6565
public function delegate(int $accountId, string $userId): JSONResponse {
6666

6767
$account = $this->accountService->findById($accountId);
68+
if ($this->currentUserId === null) {
69+
return new JSONResponse([], Http::STATUS_UNAUTHORIZED);
70+
}
71+
6872
if ($account->getUserId() !== $this->currentUserId) {
6973
return new JSONResponse([], Http::STATUS_UNAUTHORIZED);
7074
}
@@ -96,6 +100,11 @@ public function delegate(int $accountId, string $userId): JSONResponse {
96100
#[TrapError]
97101
public function unDelegate(int $accountId, string $userId): JSONResponse {
98102
$account = $this->accountService->findById($accountId);
103+
104+
if ($this->currentUserId === null) {
105+
return new JSONResponse([], Http::STATUS_UNAUTHORIZED);
106+
}
107+
99108
if ($account->getUserId() !== $this->currentUserId) {
100109
return new JSONResponse([], Http::STATUS_UNAUTHORIZED);
101110
}

lib/Controller/DraftsController.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public function create(
126126

127127
$this->service->saveMessage($account, $message, $to, $cc, $bcc, $attachments);
128128
$id = $message->getId();
129-
$this->delegationService->logDelegatedAction("$this->currentUserId created draft: $id on behalf of $effectiveUserId");
129+
$this->delegationService->logDelegatedAction("$this->userId created draft: $id on behalf of $effectiveUserId");
130130
return JsonResponse::success($message, Http::STATUS_CREATED);
131131
}
132132

@@ -214,7 +214,7 @@ public function destroy(int $id): JsonResponse {
214214
$this->accountService->find($effectiveUserId, $message->getAccountId());
215215

216216
$this->service->deleteMessage($effectiveUserId, $message);
217-
$this->delegationService->logDelegatedAction("$this->currentUserId deleted draft: $id on behalf of $effectiveUserId");
217+
$this->delegationService->logDelegatedAction("$this->userId deleted draft: $id on behalf of $effectiveUserId");
218218
return JsonResponse::success('Message deleted', Http::STATUS_ACCEPTED);
219219
}
220220

@@ -231,7 +231,7 @@ public function move(int $id): JsonResponse {
231231
$account = $this->accountService->find($effectiveUserId, $message->getAccountId());
232232

233233
$this->service->sendMessage($message, $account);
234-
$this->delegationService->logDelegatedAction("$this->currentUserId moved draft: $id to the IMAP server on behalf of $effectiveUserId");
234+
$this->delegationService->logDelegatedAction("$this->userId moved draft: $id to the IMAP server on behalf of $effectiveUserId");
235235
return JsonResponse::success(
236236
'Message moved to IMAP', Http::STATUS_ACCEPTED
237237
);

lib/Service/DelegationService.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ public function logDelegatedAction(string $logMessage) {
135135
private function notify(string $userId, string $currentUserId, Account $account, bool $delegated) {
136136
$notification = $this->notificationManager->createNotification();
137137
$displayName = $this->userManager->get($currentUserId)->getDisplayName();
138+
if ($displayName === null) {
139+
// To make PSALM happy
140+
// Shouldn't end here as both actions require user to be logged-in
141+
$displayName = $currentUserId;
142+
}
138143
$time = $this->time->getDateTime('now');
139144
$notification
140145
->setApp('mail')
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
namespace OCA\Mail\Tests\Unit\Controller;
11+
12+
use ChristophWurst\Nextcloud\Testing\TestCase;
13+
use OCA\Mail\Account;
14+
use OCA\Mail\Controller\DelegationController;
15+
use OCA\Mail\Db\Delegation;
16+
use OCA\Mail\Db\MailAccount;
17+
use OCA\Mail\Exception\DelegationExistsException;
18+
use OCA\Mail\Service\AccountService;
19+
use OCA\Mail\Service\DelegationService;
20+
use OCP\AppFramework\Http;
21+
use OCP\AppFramework\Http\JSONResponse;
22+
use OCP\IRequest;
23+
use OCP\IUserManager;
24+
use PHPUnit\Framework\MockObject\MockObject;
25+
26+
class DelegationControllerTest extends TestCase {
27+
private string $appName = 'mail';
28+
private string $currentUserId = 'owner';
29+
30+
private IRequest&MockObject $request;
31+
private DelegationService&MockObject $delegationService;
32+
private AccountService&MockObject $accountService;
33+
private IUserManager&MockObject $userManager;
34+
private DelegationController $controller;
35+
36+
private Account $ownAccount;
37+
private Account $otherAccount;
38+
39+
protected function setUp(): void {
40+
parent::setUp();
41+
42+
$this->request = $this->createMock(IRequest::class);
43+
$this->delegationService = $this->createMock(DelegationService::class);
44+
$this->accountService = $this->createMock(AccountService::class);
45+
$this->userManager = $this->createMock(IUserManager::class);
46+
47+
$this->controller = new DelegationController(
48+
$this->appName,
49+
$this->request,
50+
$this->delegationService,
51+
$this->accountService,
52+
$this->userManager,
53+
$this->currentUserId,
54+
);
55+
56+
$ownMailAccount = new MailAccount();
57+
$ownMailAccount->setId(1);
58+
$ownMailAccount->setUserId($this->currentUserId);
59+
$ownMailAccount->setEmail('owner@example.com');
60+
$this->ownAccount = new Account($ownMailAccount);
61+
62+
$otherMailAccount = new MailAccount();
63+
$otherMailAccount->setId(2);
64+
$otherMailAccount->setUserId('other');
65+
$otherMailAccount->setEmail('other@example.com');
66+
$this->otherAccount = new Account($otherMailAccount);
67+
}
68+
69+
public function testGetDelegatedUsersSuccess(): void {
70+
$delegation = new Delegation();
71+
$delegation->setId(10);
72+
$delegation->setAccountId(1);
73+
$delegation->setUserId('delegatee');
74+
75+
$this->accountService->expects($this->once())
76+
->method('findById')
77+
->with(1)
78+
->willReturn($this->ownAccount);
79+
80+
$this->delegationService->expects($this->once())
81+
->method('findDelegatedToUsersForAccount')
82+
->with(1)
83+
->willReturn([$delegation]);
84+
85+
$response = $this->controller->getDelegatedUsers(1);
86+
87+
$this->assertInstanceOf(JSONResponse::class, $response);
88+
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
89+
$this->assertEquals([$delegation], $response->getData());
90+
}
91+
92+
public function testGetDelegatedUsersUnauthorized(): void {
93+
$this->accountService->expects($this->once())
94+
->method('findById')
95+
->with(2)
96+
->willReturn($this->otherAccount);
97+
98+
$this->delegationService->expects($this->never())
99+
->method('findDelegatedToUsersForAccount');
100+
101+
$response = $this->controller->getDelegatedUsers(2);
102+
103+
$this->assertInstanceOf(JSONResponse::class, $response);
104+
$this->assertEquals(Http::STATUS_UNAUTHORIZED, $response->getStatus());
105+
}
106+
107+
public function testDelegateSuccess(): void {
108+
$delegation = new Delegation();
109+
$delegation->setId(10);
110+
$delegation->setAccountId(1);
111+
$delegation->setUserId('delegatee');
112+
113+
$this->accountService->expects($this->once())
114+
->method('findById')
115+
->with(1)
116+
->willReturn($this->ownAccount);
117+
118+
$this->userManager->expects($this->once())
119+
->method('userExists')
120+
->with('delegatee')
121+
->willReturn(true);
122+
123+
$this->delegationService->expects($this->once())
124+
->method('delegate')
125+
->with($this->ownAccount, 'delegatee', $this->currentUserId)
126+
->willReturn($delegation);
127+
128+
$response = $this->controller->delegate(1, 'delegatee');
129+
130+
$this->assertInstanceOf(JSONResponse::class, $response);
131+
$this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
132+
$this->assertEquals($delegation, $response->getData());
133+
}
134+
135+
public function testDelegateUnauthorized(): void {
136+
$this->accountService->expects($this->once())
137+
->method('findById')
138+
->with(2)
139+
->willReturn($this->otherAccount);
140+
141+
$this->delegationService->expects($this->never())
142+
->method('delegate');
143+
144+
$response = $this->controller->delegate(2, 'delegatee');
145+
146+
$this->assertInstanceOf(JSONResponse::class, $response);
147+
$this->assertEquals(Http::STATUS_UNAUTHORIZED, $response->getStatus());
148+
}
149+
150+
public function testDelegateToSelf(): void {
151+
$this->accountService->expects($this->once())
152+
->method('findById')
153+
->with(1)
154+
->willReturn($this->ownAccount);
155+
156+
$this->delegationService->expects($this->never())
157+
->method('delegate');
158+
159+
$response = $this->controller->delegate(1, $this->currentUserId);
160+
161+
$this->assertInstanceOf(JSONResponse::class, $response);
162+
$this->assertEquals(Http::STATUS_BAD_REQUEST, $response->getStatus());
163+
$this->assertEquals(['message' => 'Cannot delegate to yourself'], $response->getData());
164+
}
165+
166+
public function testDelegateUserNotFound(): void {
167+
$this->accountService->expects($this->once())
168+
->method('findById')
169+
->with(1)
170+
->willReturn($this->ownAccount);
171+
172+
$this->userManager->expects($this->once())
173+
->method('userExists')
174+
->with('nonexistent')
175+
->willReturn(false);
176+
177+
$this->delegationService->expects($this->never())
178+
->method('delegate');
179+
180+
$response = $this->controller->delegate(1, 'nonexistent');
181+
182+
$this->assertInstanceOf(JSONResponse::class, $response);
183+
$this->assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus());
184+
}
185+
186+
public function testDelegateAlreadyExists(): void {
187+
$this->accountService->expects($this->once())
188+
->method('findById')
189+
->with(1)
190+
->willReturn($this->ownAccount);
191+
192+
$this->userManager->expects($this->once())
193+
->method('userExists')
194+
->with('delegatee')
195+
->willReturn(true);
196+
197+
$this->delegationService->expects($this->once())
198+
->method('delegate')
199+
->with($this->ownAccount, 'delegatee', $this->currentUserId)
200+
->willThrowException(new DelegationExistsException('Delegation already exists'));
201+
202+
$response = $this->controller->delegate(1, 'delegatee');
203+
204+
$this->assertInstanceOf(JSONResponse::class, $response);
205+
$this->assertEquals(Http::STATUS_CONFLICT, $response->getStatus());
206+
$this->assertEquals(['message' => 'Delegation already exists'], $response->getData());
207+
}
208+
209+
public function testUnDelegateSuccess(): void {
210+
$this->accountService->expects($this->once())
211+
->method('findById')
212+
->with(1)
213+
->willReturn($this->ownAccount);
214+
215+
$this->delegationService->expects($this->once())
216+
->method('unDelegate')
217+
->with($this->ownAccount, 'delegatee', $this->currentUserId);
218+
219+
$response = $this->controller->unDelegate(1, 'delegatee');
220+
221+
$this->assertInstanceOf(JSONResponse::class, $response);
222+
$this->assertEquals(Http::STATUS_OK, $response->getStatus());
223+
}
224+
225+
public function testUnDelegateUnauthorized(): void {
226+
$this->accountService->expects($this->once())
227+
->method('findById')
228+
->with(2)
229+
->willReturn($this->otherAccount);
230+
231+
$this->delegationService->expects($this->never())
232+
->method('unDelegate');
233+
234+
$response = $this->controller->unDelegate(2, 'delegatee');
235+
236+
$this->assertInstanceOf(JSONResponse::class, $response);
237+
$this->assertEquals(Http::STATUS_UNAUTHORIZED, $response->getStatus());
238+
}
239+
}

0 commit comments

Comments
 (0)