aboutsummaryrefslogtreecommitdiffstats
path: root/tests/Core/Command/User
diff options
context:
space:
mode:
Diffstat (limited to 'tests/Core/Command/User')
-rw-r--r--tests/Core/Command/User/AddTest.php152
-rw-r--r--tests/Core/Command/User/AuthTokens/DeleteTest.php166
-rw-r--r--tests/Core/Command/User/DeleteTest.php31
-rw-r--r--tests/Core/Command/User/DisableTest.php26
-rw-r--r--tests/Core/Command/User/EnableTest.php26
-rw-r--r--tests/Core/Command/User/LastSeenTest.php31
-rw-r--r--tests/Core/Command/User/ProfileTest.php465
-rw-r--r--tests/Core/Command/User/SettingTest.php121
8 files changed, 863 insertions, 155 deletions
diff --git a/tests/Core/Command/User/AddTest.php b/tests/Core/Command/User/AddTest.php
new file mode 100644
index 00000000000..5a8bc3abea1
--- /dev/null
+++ b/tests/Core/Command/User/AddTest.php
@@ -0,0 +1,152 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+declare(strict_types=1);
+
+namespace Core\Command\User;
+
+use OC\Core\Command\User\Add;
+use OCA\Settings\Mailer\NewUserMailHelper;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\IAppConfig;
+use OCP\IGroupManager;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\Mail\IEMailTemplate;
+use OCP\mail\IMailer;
+use OCP\Security\ISecureRandom;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Test\TestCase;
+
+class AddTest extends TestCase {
+ /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
+ private $userManager;
+
+ /** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */
+ private $groupManager;
+
+ /** @var IMailer|\PHPUnit\Framework\MockObject\MockObject */
+ private $mailer;
+
+ /** @var IAppConfig|\PHPUnit\Framework\MockObject\MockObject */
+ private $appConfig;
+
+ /** @var NewUserMailHelper|\PHPUnit\Framework\MockObject\MockObject */
+ private $mailHelper;
+
+ /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */
+ private $eventDispatcher;
+
+ /** @var ISecureRandom|\PHPUnit\Framework\MockObject\MockObject */
+ private $secureRandom;
+
+ /** @var IUser|\PHPUnit\Framework\MockObject\MockObject */
+ private $user;
+
+ /** @var InputInterface|\PHPUnit\Framework\MockObject\MockObject */
+ private $consoleInput;
+
+ /** @var OutputInterface|\PHPUnit\Framework\MockObject\MockObject */
+ private $consoleOutput;
+
+ /** @var Add */
+ private $addCommand;
+
+ public function setUp(): void {
+ parent::setUp();
+
+ $this->userManager = static::createMock(IUserManager::class);
+ $this->groupManager = static::createStub(IGroupManager::class);
+ $this->mailer = static::createMock(IMailer::class);
+ $this->appConfig = static::createMock(IAppConfig::class);
+ $this->mailHelper = static::createMock(NewUserMailHelper::class);
+ $this->eventDispatcher = static::createStub(IEventDispatcher::class);
+ $this->secureRandom = static::createStub(ISecureRandom::class);
+
+ $this->user = static::createMock(IUser::class);
+
+ $this->consoleInput = static::createMock(InputInterface::class);
+ $this->consoleOutput = static::createMock(OutputInterface::class);
+
+ $this->addCommand = new Add(
+ $this->userManager,
+ $this->groupManager,
+ $this->mailer,
+ $this->appConfig,
+ $this->mailHelper,
+ $this->eventDispatcher,
+ $this->secureRandom
+ );
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('addEmailDataProvider')]
+ public function testAddEmail(
+ ?string $email,
+ bool $isEmailValid,
+ bool $shouldSendEmail,
+ ): void {
+ $this->user->expects($isEmailValid ? static::once() : static::never())
+ ->method('setSystemEMailAddress')
+ ->with(static::equalTo($email));
+
+ $this->userManager->method('createUser')
+ ->willReturn($this->user);
+
+ $this->appConfig->method('getValueString')
+ ->willReturn($shouldSendEmail ? 'yes' : 'no');
+
+ $this->mailer->method('validateMailAddress')
+ ->willReturn($isEmailValid);
+
+ $this->mailHelper->method('generateTemplate')
+ ->willReturn(static::createMock(IEMailTemplate::class));
+
+ $this->mailHelper->expects($isEmailValid && $shouldSendEmail ? static::once() : static::never())
+ ->method('sendMail');
+
+ $this->consoleInput->method('getOption')
+ ->willReturnMap([
+ ['generate-password', 'true'],
+ ['email', $email],
+ ['group', []],
+ ]);
+
+ $this->invokePrivate($this->addCommand, 'execute', [
+ $this->consoleInput,
+ $this->consoleOutput
+ ]);
+ }
+
+ /**
+ * @return array
+ */
+ public static function addEmailDataProvider(): array {
+ return [
+ 'Valid E-Mail' => [
+ 'info@example.com',
+ true,
+ true,
+ ],
+ 'Invalid E-Mail' => [
+ 'info@@example.com',
+ false,
+ false,
+ ],
+ 'No E-Mail' => [
+ '',
+ false,
+ false,
+ ],
+ 'Valid E-Mail, but no mail should be sent' => [
+ 'info@example.com',
+ true,
+ false,
+ ],
+ ];
+ }
+}
diff --git a/tests/Core/Command/User/AuthTokens/DeleteTest.php b/tests/Core/Command/User/AuthTokens/DeleteTest.php
new file mode 100644
index 00000000000..6692473c240
--- /dev/null
+++ b/tests/Core/Command/User/AuthTokens/DeleteTest.php
@@ -0,0 +1,166 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace Tests\Core\Command\User\AuthTokens;
+
+use OC\Authentication\Token\IProvider;
+use OC\Core\Command\User\AuthTokens\Delete;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Exception\RuntimeException;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Test\TestCase;
+
+class DeleteTest extends TestCase {
+ /** @var \PHPUnit\Framework\MockObject\MockObject */
+ protected $tokenProvider;
+ /** @var \PHPUnit\Framework\MockObject\MockObject */
+ protected $consoleInput;
+ /** @var \PHPUnit\Framework\MockObject\MockObject */
+ protected $consoleOutput;
+
+ /** @var \Symfony\Component\Console\Command\Command */
+ protected $command;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $tokenProvider = $this->tokenProvider = $this->getMockBuilder(IProvider::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock();
+ $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock();
+
+ /** @var \OC\Authentication\Token\IProvider $tokenProvider */
+ $this->command = new Delete($tokenProvider);
+ }
+
+ public function testDeleteTokenById(): void {
+ $this->consoleInput->expects($this->exactly(2))
+ ->method('getArgument')
+ ->willReturnMap([
+ ['uid', 'user'],
+ ['id', '42']
+ ]);
+
+ $this->consoleInput->expects($this->once())
+ ->method('getOption')
+ ->with('last-used-before')
+ ->willReturn(null);
+
+ $this->tokenProvider->expects($this->once())
+ ->method('invalidateTokenById')
+ ->with('user', 42);
+
+ $result = self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ $this->assertSame(Command::SUCCESS, $result);
+ }
+
+ public function testDeleteTokenByIdRequiresTokenId(): void {
+ $this->consoleInput->expects($this->exactly(2))
+ ->method('getArgument')
+ ->willReturnMap([
+ ['uid', 'user'],
+ ['id', null]
+ ]);
+
+ $this->consoleInput->expects($this->once())
+ ->method('getOption')
+ ->with('last-used-before')
+ ->willReturn(null);
+
+ $this->expectException(RuntimeException::class);
+
+ $this->tokenProvider->expects($this->never())->method('invalidateTokenById');
+
+ $result = self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ $this->assertSame(Command::FAILURE, $result);
+ }
+
+ public function testDeleteTokensLastUsedBefore(): void {
+ $this->consoleInput->expects($this->exactly(2))
+ ->method('getArgument')
+ ->willReturnMap([
+ ['uid', 'user'],
+ ['id', null]
+ ]);
+
+ $this->consoleInput->expects($this->once())
+ ->method('getOption')
+ ->with('last-used-before')
+ ->willReturn('946684800');
+
+ $this->tokenProvider->expects($this->once())
+ ->method('invalidateLastUsedBefore')
+ ->with('user', 946684800);
+
+ $result = self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ $this->assertSame(Command::SUCCESS, $result);
+ }
+
+ public function testLastUsedBeforeAcceptsIso8601Expanded(): void {
+ $this->consoleInput->expects($this->exactly(2))
+ ->method('getArgument')
+ ->willReturnMap([
+ ['uid', 'user'],
+ ['id', null]
+ ]);
+
+ $this->consoleInput->expects($this->once())
+ ->method('getOption')
+ ->with('last-used-before')
+ ->willReturn('2000-01-01T00:00:00Z');
+
+ $this->tokenProvider->expects($this->once())
+ ->method('invalidateLastUsedBefore')
+ ->with('user', 946684800);
+
+ $result = self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ $this->assertSame(Command::SUCCESS, $result);
+ }
+
+ public function testLastUsedBeforeAcceptsYmd(): void {
+ $this->consoleInput->expects($this->exactly(2))
+ ->method('getArgument')
+ ->willReturnMap([
+ ['uid', 'user'],
+ ['id', null]
+ ]);
+
+ $this->consoleInput->expects($this->once())
+ ->method('getOption')
+ ->with('last-used-before')
+ ->willReturn('2000-01-01');
+
+ $this->tokenProvider->expects($this->once())
+ ->method('invalidateLastUsedBefore')
+ ->with('user', 946684800);
+
+ $result = self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ $this->assertSame(Command::SUCCESS, $result);
+ }
+
+ public function testIdAndLastUsedBeforeAreMutuallyExclusive(): void {
+ $this->consoleInput->expects($this->exactly(2))
+ ->method('getArgument')
+ ->willReturnMap([
+ ['uid', 'user'],
+ ['id', '42']
+ ]);
+
+ $this->consoleInput->expects($this->once())
+ ->method('getOption')
+ ->with('last-used-before')
+ ->willReturn('946684800');
+
+ $this->expectException(RuntimeException::class);
+
+ $this->tokenProvider->expects($this->never())->method('invalidateLastUsedBefore');
+
+ $result = self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ $this->assertSame(Command::SUCCESS, $result);
+ }
+}
diff --git a/tests/Core/Command/User/DeleteTest.php b/tests/Core/Command/User/DeleteTest.php
index 6ac0ed0353c..4e06b0f91fc 100644
--- a/tests/Core/Command/User/DeleteTest.php
+++ b/tests/Core/Command/User/DeleteTest.php
@@ -1,22 +1,9 @@
<?php
+
/**
- * @author Joas Schilling <nickvergessen@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace Tests\Core\Command\User;
@@ -48,12 +35,12 @@ class DeleteTest extends TestCase {
$this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock();
$this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock();
- /** @var \OCP\IUserManager $userManager */
+ /** @var IUserManager $userManager */
$this->command = new Delete($userManager);
}
- public function validUserLastSeen() {
+ public static function validUserLastSeen(): array {
return [
[true, 'The specified user was deleted'],
[false, 'The specified user could not be deleted'],
@@ -61,12 +48,12 @@ class DeleteTest extends TestCase {
}
/**
- * @dataProvider validUserLastSeen
*
* @param bool $deleteSuccess
* @param string $expectedString
*/
- public function testValidUser($deleteSuccess, $expectedString) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('validUserLastSeen')]
+ public function testValidUser($deleteSuccess, $expectedString): void {
$user = $this->getMockBuilder(IUser::class)->getMock();
$user->expects($this->once())
->method('delete')
@@ -89,7 +76,7 @@ class DeleteTest extends TestCase {
self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
}
- public function testInvalidUser() {
+ public function testInvalidUser(): void {
$this->userManager->expects($this->once())
->method('get')
->with('user')
diff --git a/tests/Core/Command/User/DisableTest.php b/tests/Core/Command/User/DisableTest.php
index 0e1d1b72ac4..c1bc10dc6bf 100644
--- a/tests/Core/Command/User/DisableTest.php
+++ b/tests/Core/Command/User/DisableTest.php
@@ -1,24 +1,8 @@
<?php
+
/**
- * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Tests\Core\Command\User;
@@ -51,7 +35,7 @@ class DisableTest extends TestCase {
$this->command = new Disable($this->userManager);
}
- public function testValidUser() {
+ public function testValidUser(): void {
$user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('setEnabled')
@@ -74,7 +58,7 @@ class DisableTest extends TestCase {
self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
}
- public function testInvalidUser() {
+ public function testInvalidUser(): void {
$this->userManager->expects($this->once())
->method('get')
->with('user')
diff --git a/tests/Core/Command/User/EnableTest.php b/tests/Core/Command/User/EnableTest.php
index 6ff82aac673..b2820de14ef 100644
--- a/tests/Core/Command/User/EnableTest.php
+++ b/tests/Core/Command/User/EnableTest.php
@@ -1,24 +1,8 @@
<?php
+
/**
- * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace Tests\Core\Command\User;
@@ -51,7 +35,7 @@ class EnableTest extends TestCase {
$this->command = new Enable($this->userManager);
}
- public function testValidUser() {
+ public function testValidUser(): void {
$user = $this->createMock(IUser::class);
$user->expects($this->once())
->method('setEnabled')
@@ -74,7 +58,7 @@ class EnableTest extends TestCase {
self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
}
- public function testInvalidUser() {
+ public function testInvalidUser(): void {
$this->userManager->expects($this->once())
->method('get')
->with('user')
diff --git a/tests/Core/Command/User/LastSeenTest.php b/tests/Core/Command/User/LastSeenTest.php
index f861c2e5f77..64c710eacc5 100644
--- a/tests/Core/Command/User/LastSeenTest.php
+++ b/tests/Core/Command/User/LastSeenTest.php
@@ -1,22 +1,9 @@
<?php
+
/**
- * @author Joas Schilling <nickvergessen@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace Tests\Core\Command\User;
@@ -48,11 +35,11 @@ class LastSeenTest extends TestCase {
$this->consoleInput = $this->getMockBuilder(InputInterface::class)->getMock();
$this->consoleOutput = $this->getMockBuilder(OutputInterface::class)->getMock();
- /** @var \OCP\IUserManager $userManager */
+ /** @var IUserManager $userManager */
$this->command = new LastSeen($userManager);
}
- public function validUserLastSeen() {
+ public static function validUserLastSeen(): array {
return [
[0, 'never logged in'],
[time(), 'last login'],
@@ -60,12 +47,12 @@ class LastSeenTest extends TestCase {
}
/**
- * @dataProvider validUserLastSeen
*
* @param int $lastSeen
* @param string $expectedString
*/
- public function testValidUser($lastSeen, $expectedString) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('validUserLastSeen')]
+ public function testValidUser($lastSeen, $expectedString): void {
$user = $this->getMockBuilder(IUser::class)->getMock();
$user->expects($this->once())
->method('getLastLogin')
@@ -88,7 +75,7 @@ class LastSeenTest extends TestCase {
self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
}
- public function testInvalidUser() {
+ public function testInvalidUser(): void {
$this->userManager->expects($this->once())
->method('get')
->with('user')
diff --git a/tests/Core/Command/User/ProfileTest.php b/tests/Core/Command/User/ProfileTest.php
new file mode 100644
index 00000000000..ff5568bacfc
--- /dev/null
+++ b/tests/Core/Command/User/ProfileTest.php
@@ -0,0 +1,465 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace Core\Command\User;
+
+use OC\Core\Command\User\Profile;
+use OCP\Accounts\IAccount;
+use OCP\Accounts\IAccountManager;
+use OCP\Accounts\IAccountProperty;
+use OCP\IDBConnection;
+use OCP\IUser;
+use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Test\TestCase;
+
+class ProfileTest extends TestCase {
+
+ protected IAccountManager&MockObject $accountManager;
+ protected IUserManager&MockObject $userManager;
+ protected IDBConnection&MockObject $connection;
+ protected InputInterface&MockObject $consoleInput;
+ protected OutputInterface&MockObject $consoleOutput;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->accountManager = $this->createMock(IAccountManager::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->connection = $this->createMock(IDBConnection::class);
+ $this->consoleInput = $this->createMock(InputInterface::class);
+ $this->consoleOutput = $this->createMock(OutputInterface::class);
+ }
+
+ public function getCommand(array $methods = []): Profile|MockObject {
+ if (empty($methods)) {
+ return new Profile($this->userManager, $this->accountManager);
+ } else {
+ return $this->getMockBuilder(Profile::class)
+ ->setConstructorArgs([
+ $this->userManager,
+ $this->accountManager,
+ ])
+ ->onlyMethods($methods)
+ ->getMock();
+ }
+ }
+
+ public static function dataCheckInput(): array {
+ return [
+ 'Call with existing user should pass check' => [
+ [['uid', 'username']],
+ [],
+ [],
+ true,
+ null,
+ ],
+ 'Call with non-existing user should fail check' => [
+ [['uid', 'username']],
+ [],
+ [],
+ false,
+ 'The user "username" does not exist.',
+ ],
+
+ 'Call with uid, key and --default value should pass check' => [
+ [['uid', 'username'], ['key', 'configkey']],
+ [],
+ [['--default-value', false, true]],
+ true,
+ null,
+ ],
+ 'Call with uid and empty key with default-value option should fail check' => [
+ [['uid', 'username'], ['key', '']],
+ [],
+ [['--default-value', false, true]],
+ true,
+ 'The "default-value" option can only be used when specifying a key.',
+ ],
+
+ 'Call with uid, key, value should pass check' => [
+ [['uid', 'username'], ['key', 'configkey'], ['value', '']],
+ [],
+ [],
+ true,
+ null,
+ ],
+ 'Call with uid, empty key and empty value should fail check' => [
+ [['uid', 'username'], ['key', ''], ['value', '']],
+ [],
+ [],
+ true,
+ 'The value argument can only be used when specifying a key.',
+ ],
+ 'Call with uid, key, empty value and default-value option should fail check' => [
+ [['uid', 'username'], ['key', 'configkey'], ['value', '']],
+ [],
+ [['--default-value', false, true]],
+ true,
+ 'The value argument can not be used together with "default-value".',
+ ],
+ 'Call with uid, key, empty value and update-only option should pass check' => [
+ [['uid', 'username'], ['key', 'configkey'], ['value', '']],
+ [['update-only', true]],
+ [],
+ true,
+ null,
+ ],
+ 'Call with uid, key, null value and update-only option should fail check' => [
+ [['uid', 'username'], ['key', 'configkey'], ['value', null]],
+ [['update-only', true]],
+ [],
+ true,
+ 'The "update-only" option can only be used together with "value".',
+ ],
+
+ 'Call with uid, key and delete option should pass check' => [
+ [['uid', 'username'], ['key', 'configkey']],
+ [['delete', true]],
+ [],
+ true,
+ null,
+ ],
+ 'Call with uid, empty key and delete option should fail check' => [
+ [['uid', 'username'], ['key', '']],
+ [['delete', true]],
+ [],
+ true,
+ 'The "delete" option can only be used when specifying a key.',
+ ],
+ 'Call with uid, key, delete option and default-value should fail check' => [
+ [['uid', 'username'], ['key', 'configkey']],
+ [['delete', true]],
+ [['--default-value', false, true]],
+ true,
+ 'The "delete" option can not be used together with "default-value".',
+ ],
+ 'Call with uid, key, empty value and delete option should fail check' => [
+ [['uid', 'username'], ['key', 'configkey'], ['value', '']],
+ [['delete', true]],
+ [],
+ true,
+ 'The "delete" option can not be used together with "value".',
+ ],
+ 'Call with uid, key, delete and error-if-not-exists should pass check' => [
+ [['uid', 'username'], ['key', 'configkey']],
+ [['delete', true], ['error-if-not-exists', true]],
+ [],
+ true,
+ null,
+ ],
+ 'Call with uid, key and error-if-not-exists should fail check' => [
+ [['uid', 'username'], ['key', 'configkey']],
+ [['delete', false], ['error-if-not-exists', true]],
+ [],
+ true,
+ 'The "error-if-not-exists" option can only be used together with "delete".',
+ ],
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataCheckInput')]
+ public function testCheckInput(array $arguments, array $options, array $parameterOptions, bool $existingUser, ?string $expectedException): void {
+ $this->consoleInput->expects($this->any())
+ ->method('getArgument')
+ ->willReturnMap($arguments);
+ $this->consoleInput->expects($this->any())
+ ->method('getOption')
+ ->willReturnMap($options);
+ $this->consoleInput->expects($this->any())
+ ->method('hasParameterOption')
+ ->willReturnCallback(function (string|array $values, bool $onlyParams = false) use ($parameterOptions): bool {
+ $arguments = func_get_args();
+ foreach ($parameterOptions as $parameterOption) {
+ // check the arguments of the function, if they are the same, return the mocked value
+ if (array_diff($arguments, $parameterOption) === []) {
+ return end($parameterOption);
+ }
+ }
+
+ return false;
+ });
+
+ $returnedUser = null;
+ if ($existingUser) {
+ $mockUser = $this->createMock(IUser::class);
+ $mockUser->expects($this->once())->method('getUID')->willReturn('user');
+ $returnedUser = $mockUser;
+ }
+ $this->userManager->expects($this->once())
+ ->method('get')
+ ->willReturn($returnedUser);
+
+ $command = $this->getCommand();
+ try {
+ $this->invokePrivate($command, 'checkInput', [$this->consoleInput]);
+ $this->assertNull($expectedException);
+ } catch (\InvalidArgumentException $e) {
+ $this->assertEquals($expectedException, $e->getMessage());
+ }
+ }
+
+ public function testCheckInputExceptionCatch(): void {
+ $command = $this->getCommand(['checkInput']);
+ $command->expects($this->once())
+ ->method('checkInput')
+ ->willThrowException(new \InvalidArgumentException('test'));
+
+ $this->consoleOutput->expects($this->once())
+ ->method('writeln')
+ ->with('<error>test</error>');
+
+ $this->assertEquals(1, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
+ }
+
+ public static function dataExecuteDeleteProfileProperty(): array {
+ return [
+ 'Deleting existing property should succeed' => ['address', 'Berlin', false, null, Command::SUCCESS],
+ 'Deleting existing property with error-if-not-exists should succeed' => ['address', 'Berlin', true, null, Command::SUCCESS],
+ 'Deleting non-existing property should succeed' => ['address', '', false, null, Command::SUCCESS],
+ 'Deleting non-existing property with error-if-not-exists should fail' => ['address', '', true, '<error>The property does not exist for user "username".</error>', Command::FAILURE],
+ ];
+ }
+
+ /**
+ * Tests the deletion mechanism on profile settings.
+ */
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataExecuteDeleteProfileProperty')]
+ public function testExecuteDeleteProfileProperty(string $configKey, string $value, bool $errorIfNotExists, ?string $expectedLine, int $expectedReturn): void {
+ $uid = 'username';
+ $appName = 'profile';
+ $command = $this->getCommand([
+ 'writeArrayInOutputFormat',
+ 'checkInput',
+ ]);
+
+ $this->consoleInput->expects($this->any())
+ ->method('getArgument')
+ ->willReturnMap([
+ ['uid', $uid],
+ ['app', $appName],
+ ['key', $configKey],
+ ]);
+
+ $mocks = $this->setupProfilePropertiesMock([$configKey => $value]);
+
+ $command->expects($this->once())
+ ->method('checkInput')
+ ->willReturn($mocks['userMock']);
+
+ $this->consoleInput->expects($this->atLeastOnce())
+ ->method('hasParameterOption')
+ ->willReturnMap([
+ ['--delete', false, true],
+ ['--error-if-not-exists', false, $errorIfNotExists],
+ ]);
+
+ if ($expectedLine === null) {
+ $this->consoleOutput->expects($this->never())
+ ->method('writeln');
+ $mocks['profilePropertiesMocks'][0]->expects($this->once())
+ ->method('setValue')
+ ->with('');
+ $this->accountManager->expects($this->once())
+ ->method('updateAccount')
+ ->with($mocks['accountMock']);
+ } else {
+ $this->consoleOutput->expects($this->once())
+ ->method('writeln')
+ ->with($expectedLine);
+ $this->accountManager->expects($this->never())
+ ->method('updateAccount');
+ }
+
+ $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
+ }
+
+ public function testExecuteSetProfileProperty(): void {
+ $command = $this->getCommand([
+ 'writeArrayInOutputFormat',
+ 'checkInput',
+ ]);
+
+ $uid = 'username';
+ $propertyKey = 'address';
+ $propertyValue = 'Barcelona';
+
+ $this->consoleInput->expects($this->atLeast(3))
+ ->method('getArgument')
+ ->willReturnMap([
+ ['uid', $uid],
+ ['key', $propertyKey],
+ ['value', $propertyValue],
+ ]);
+
+ $mocks = $this->setupProfilePropertiesMock([$propertyKey => $propertyValue]);
+
+ $command->expects($this->once())
+ ->method('checkInput')
+ ->willReturn($mocks['userMock']);
+
+ $mocks['profilePropertiesMocks'][0]->expects($this->once())
+ ->method('setValue')
+ ->with($propertyValue);
+ $this->accountManager->expects($this->once())
+ ->method('updateAccount')
+ ->with($mocks['accountMock']);
+
+ $this->assertEquals(0, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
+ }
+
+ public static function dataExecuteGet(): array {
+ return [
+ 'Get property with set value should pass' => ['configkey', 'value', null, 'value', Command::SUCCESS],
+ 'Get property with empty value and default-value option should pass' => ['configkey', '', 'default-value', 'default-value', Command::SUCCESS],
+ 'Get property with empty value should fail' => ['configkey', '', null, '<error>The property does not exist for user "username".</error>', Command::FAILURE],
+ ];
+ }
+
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataExecuteGet')]
+ public function testExecuteGet(string $key, string $value, ?string $defaultValue, string $expectedLine, int $expectedReturn): void {
+ $command = $this->getCommand([
+ 'writeArrayInOutputFormat',
+ 'checkInput',
+ ]);
+
+ $uid = 'username';
+
+ $this->consoleInput->expects($this->any())
+ ->method('getArgument')
+ ->willReturnMap([
+ ['uid', $uid],
+ ['key', $key],
+ ]);
+
+ $mocks = $this->setupProfilePropertiesMock([$key => $value]);
+
+ $command->expects($this->once())
+ ->method('checkInput')
+ ->willReturn($mocks['userMock']);
+
+ if ($value === '') {
+ if ($defaultValue === null) {
+ $this->consoleInput->expects($this->atLeastOnce())
+ ->method('hasParameterOption')
+ ->willReturn(false);
+ } else {
+ $this->consoleInput->expects($this->atLeastOnce())
+ ->method('hasParameterOption')
+ ->willReturnCallback(fn (string|array $values): bool => $values === '--default-value');
+ $this->consoleInput->expects($this->once())
+ ->method('getOption')
+ ->with('default-value')
+ ->willReturn($defaultValue);
+ }
+ }
+
+ $this->consoleOutput->expects($this->once())
+ ->method('writeln')
+ ->with($expectedLine);
+
+ $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
+ }
+
+ public function testExecuteList(): void {
+ $uid = 'username';
+ $profileData = [
+ 'pronouns' => 'they/them',
+ 'address' => 'Berlin',
+ ];
+
+ $command = $this->getCommand([
+ 'writeArrayInOutputFormat',
+ 'checkInput',
+ ]);
+
+ $this->consoleInput->expects($this->any())
+ ->method('getArgument')
+ ->willReturnMap([
+ ['uid', $uid],
+ ['key', ''],
+ ]);
+
+ $mocks = $this->setupProfilePropertiesMock(['address' => $profileData['address'], 'pronouns' => $profileData['pronouns']]);
+
+ $command->expects($this->once())
+ ->method('checkInput')
+ ->willReturn($mocks['userMock']);
+
+ $command->expects($this->once())
+ ->method('writeArrayInOutputFormat')
+ ->with($this->consoleInput, $this->consoleOutput, $profileData);
+
+
+ $this->assertEquals(0, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
+ }
+
+ /**
+ * Helper to avoid boilerplate in tests in this file when mocking objects
+ * of IAccountProperty type.
+ *
+ * @param array<string, string> $properties the properties to be set up as key => value
+ * @return array{
+ * userMock: IUser&MockObject,
+ * accountMock: IAccount&MockObject,
+ * profilePropertiesMocks: IAccountProperty&MockObject[]
+ * }
+ */
+ private function setupProfilePropertiesMock(array $properties): array {
+ $userMock = $this->createMock(IUser::class);
+ $accountMock = $this->createMock(IAccount::class);
+ $this->accountManager->expects($this->atLeastOnce())
+ ->method('getAccount')
+ ->with($userMock)
+ ->willReturn($accountMock);
+
+ /** @var IAccountProperty&MockObject[] $propertiesMocks */
+ $propertiesMocks = [];
+ foreach ($properties as $key => $value) {
+ $propertiesMocks[] = $this->getAccountPropertyMock($key, $value);
+ }
+
+ if (count($properties) === 1) {
+ $accountMock->expects($this->atLeastOnce())
+ ->method('getProperty')
+ ->with(array_keys($properties)[0])
+ ->willReturn($propertiesMocks[array_key_first($propertiesMocks)]);
+ } else {
+ $accountMock->expects($this->atLeastOnce())
+ ->method('getAllProperties')
+ ->willReturnCallback(function () use ($propertiesMocks) {
+ foreach ($propertiesMocks as $property) {
+ yield $property;
+ }
+ });
+ }
+
+ return [
+ 'userMock' => $userMock,
+ 'accountMock' => $accountMock,
+ 'profilePropertiesMocks' => $propertiesMocks,
+ ];
+ }
+
+ private function getAccountPropertyMock(string $name, string $value): IAccountProperty&MockObject {
+ $propertyMock = $this->getMockBuilder(IAccountProperty::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $propertyMock->expects($this->any())
+ ->method('getName')
+ ->willReturn($name);
+ $propertyMock->expects($this->any())
+ ->method('getValue')
+ ->willReturn($value);
+
+ return $propertyMock;
+ }
+}
diff --git a/tests/Core/Command/User/SettingTest.php b/tests/Core/Command/User/SettingTest.php
index 964a707bf38..706e5b24742 100644
--- a/tests/Core/Command/User/SettingTest.php
+++ b/tests/Core/Command/User/SettingTest.php
@@ -1,83 +1,56 @@
<?php
+
/**
- * @author Joas Schilling <coding@schilljs.com>
- *
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace Tests\Core\Command\User;
+use InvalidArgumentException;
use OC\Core\Command\User\Setting;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Test\TestCase;
class SettingTest extends TestCase {
- /** @var \OCP\IUserManager|\PHPUnit\Framework\MockObject\MockObject */
- protected $userManager;
- /** @var \OCP\IConfig|\PHPUnit\Framework\MockObject\MockObject */
- protected $config;
- /** @var \OCP\IDBConnection|\PHPUnit\Framework\MockObject\MockObject */
- protected $connection;
- /** @var \Symfony\Component\Console\Input\InputInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $consoleInput;
- /** @var \Symfony\Component\Console\Output\OutputInterface|\PHPUnit\Framework\MockObject\MockObject */
- protected $consoleOutput;
+ protected IUserManager&MockObject $userManager;
+ protected IConfig&MockObject $config;
+ protected IDBConnection&MockObject $connection;
+ protected InputInterface&MockObject $consoleInput;
+ protected MockObject&OutputInterface $consoleOutput;
protected function setUp(): void {
parent::setUp();
- $this->userManager = $this->getMockBuilder(IUserManager::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->config = $this->getMockBuilder(IConfig::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->connection = $this->getMockBuilder(IDBConnection::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->consoleInput = $this->getMockBuilder(InputInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)
- ->disableOriginalConstructor()
- ->getMock();
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->config = $this->createMock(IConfig::class);
+ $this->connection = $this->createMock(IDBConnection::class);
+ $this->consoleInput = $this->createMock(InputInterface::class);
+ $this->consoleOutput = $this->createMock(OutputInterface::class);
}
public function getCommand(array $methods = []) {
if (empty($methods)) {
- return new Setting($this->userManager, $this->config, $this->connection);
+ return new Setting($this->userManager, $this->config);
} else {
- $mock = $this->getMockBuilder('OC\Core\Command\User\Setting')
+ $mock = $this->getMockBuilder(Setting::class)
->setConstructorArgs([
$this->userManager,
$this->config,
- $this->connection,
])
- ->setMethods($methods)
+ ->onlyMethods($methods)
->getMock();
return $mock;
}
}
- public function dataCheckInput() {
+ public static function dataCheckInput(): array {
return [
[
[['uid', 'username']],
@@ -191,7 +164,6 @@ class SettingTest extends TestCase {
}
/**
- * @dataProvider dataCheckInput
*
* @param array $arguments
* @param array $options
@@ -199,7 +171,8 @@ class SettingTest extends TestCase {
* @param mixed $user
* @param string $expectedException
*/
- public function testCheckInput($arguments, $options, $parameterOptions, $user, $expectedException) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataCheckInput')]
+ public function testCheckInput($arguments, $options, $parameterOptions, $user, $expectedException): void {
$this->consoleInput->expects($this->any())
->method('getArgument')
->willReturnMap($arguments);
@@ -208,7 +181,16 @@ class SettingTest extends TestCase {
->willReturnMap($options);
$this->consoleInput->expects($this->any())
->method('hasParameterOption')
- ->willReturnMap($parameterOptions);
+ ->willReturnCallback(function (string|array $config, bool $default = false) use ($parameterOptions): bool {
+ foreach ($parameterOptions as $parameterOption) {
+ if ($config === $parameterOption[0]
+ // Check the default value if the maps has 3 entries
+ && (!isset($parameterOption[2]) || $default === $parameterOption[1])) {
+ return end($parameterOption);
+ }
+ }
+ return false;
+ });
if ($user !== false) {
$this->userManager->expects($this->once())
@@ -223,16 +205,16 @@ class SettingTest extends TestCase {
try {
$this->invokePrivate($command, 'checkInput', [$this->consoleInput]);
$this->assertFalse($expectedException);
- } catch (\InvalidArgumentException $e) {
+ } catch (InvalidArgumentException $e) {
$this->assertEquals($expectedException, $e->getMessage());
}
}
- public function testCheckInputExceptionCatch() {
+ public function testCheckInputExceptionCatch(): void {
$command = $this->getCommand(['checkInput']);
$command->expects($this->once())
->method('checkInput')
- ->willThrowException(new \InvalidArgumentException('test'));
+ ->willThrowException(new InvalidArgumentException('test'));
$this->consoleOutput->expects($this->once())
->method('writeln')
@@ -241,7 +223,7 @@ class SettingTest extends TestCase {
$this->assertEquals(1, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
}
- public function dataExecuteDelete() {
+ public static function dataExecuteDelete(): array {
return [
['config', false, null, 0],
['config', true, null, 0],
@@ -251,14 +233,14 @@ class SettingTest extends TestCase {
}
/**
- * @dataProvider dataExecuteDelete
*
* @param string|null $value
* @param bool $errorIfNotExists
* @param string $expectedLine
* @param int $expectedReturn
*/
- public function testExecuteDelete($value, $errorIfNotExists, $expectedLine, $expectedReturn) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataExecuteDelete')]
+ public function testExecuteDelete($value, $errorIfNotExists, $expectedLine, $expectedReturn): void {
$command = $this->getCommand([
'writeArrayInOutputFormat',
'checkInput',
@@ -305,7 +287,7 @@ class SettingTest extends TestCase {
$this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
}
- public function dataExecuteSet() {
+ public static function dataExecuteSet(): array {
return [
['config', false, null, 0],
['config', true, null, 0],
@@ -315,14 +297,14 @@ class SettingTest extends TestCase {
}
/**
- * @dataProvider dataExecuteSet
*
* @param string|null $value
* @param bool $updateOnly
* @param string $expectedLine
* @param int $expectedReturn
*/
- public function testExecuteSet($value, $updateOnly, $expectedLine, $expectedReturn) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataExecuteSet')]
+ public function testExecuteSet($value, $updateOnly, $expectedLine, $expectedReturn): void {
$command = $this->getCommand([
'writeArrayInOutputFormat',
'checkInput',
@@ -373,7 +355,7 @@ class SettingTest extends TestCase {
$this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
}
- public function dataExecuteGet() {
+ public static function dataExecuteGet(): array {
return [
['config', null, 'config', 0],
[null, 'config', 'config', 0],
@@ -382,14 +364,14 @@ class SettingTest extends TestCase {
}
/**
- * @dataProvider dataExecuteGet
*
* @param string|null $value
* @param string|null $defaultValue
* @param string $expectedLine
* @param int $expectedReturn
*/
- public function testExecuteGet($value, $defaultValue, $expectedLine, $expectedReturn) {
+ #[\PHPUnit\Framework\Attributes\DataProvider('dataExecuteGet')]
+ public function testExecuteGet($value, $defaultValue, $expectedLine, $expectedReturn): void {
$command = $this->getCommand([
'writeArrayInOutputFormat',
'checkInput',
@@ -416,15 +398,16 @@ class SettingTest extends TestCase {
if ($defaultValue === null) {
$this->consoleInput->expects($this->atLeastOnce())
->method('hasParameterOption')
- ->willReturnMap([
- ['--default-value', false],
- ]);
+ ->willReturn(false);
} else {
$this->consoleInput->expects($this->atLeastOnce())
->method('hasParameterOption')
- ->willReturnMap([
- ['--default-value', false, true],
- ]);
+ ->willReturnCallback(function (string|array $config, bool $default = false): bool {
+ if ($config === '--default-value' && $default === false) {
+ return true;
+ }
+ return false;
+ });
$this->consoleInput->expects($this->once())
->method('getOption')
->with('default-value')
@@ -439,7 +422,7 @@ class SettingTest extends TestCase {
$this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
}
- public function testExecuteList() {
+ public function testExecuteList(): void {
$command = $this->getCommand([
'writeArrayInOutputFormat',
'checkInput',