aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/Core/Controller/PreviewControllerTest.php191
-rw-r--r--tests/data/app/expected-info.json4
-rw-r--r--tests/data/app/various-single-item.json50
-rw-r--r--tests/data/app/various-single-item.json.license2
-rw-r--r--tests/data/app/various-single-item.xml22
-rw-r--r--tests/karma.config.js6
-rw-r--r--tests/lib/App/InfoParserTest.php1
-rw-r--r--tests/lib/AppFramework/Db/EntityTest.php86
-rw-r--r--tests/lib/AppFramework/Db/QBMapperDBTest.php159
-rw-r--r--tests/lib/AppFramework/Db/QBMapperTest.php63
-rw-r--r--tests/lib/Authentication/LoginCredentials/StoreTest.php22
-rw-r--r--tests/lib/Comments/CommentTest.php6
-rw-r--r--tests/lib/Comments/ManagerTest.php7
-rw-r--r--tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php16
-rw-r--r--tests/lib/Files/Storage/LocalTest.php25
-rw-r--r--tests/lib/Files/Storage/StorageFactoryTest.php8
-rw-r--r--tests/lib/HelperStorageTest.php2
-rw-r--r--tests/lib/Share20/DefaultShareProviderTest.php36
-rw-r--r--tests/lib/Share20/ShareByMailProviderTest.php2
-rw-r--r--tests/lib/TemplateLayoutTest.php84
-rw-r--r--tests/lib/User/ManagerTest.php67
21 files changed, 769 insertions, 90 deletions
diff --git a/tests/Core/Controller/PreviewControllerTest.php b/tests/Core/Controller/PreviewControllerTest.php
index 4274f15e8ed..e7ecba27064 100644
--- a/tests/Core/Controller/PreviewControllerTest.php
+++ b/tests/Core/Controller/PreviewControllerTest.php
@@ -14,34 +14,35 @@ use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\Files\Storage\ISharedStorage;
use OCP\Files\Storage\IStorage;
use OCP\IPreview;
use OCP\IRequest;
use OCP\Preview\IMimeIconProvider;
+use OCP\Share\IAttributes;
+use OCP\Share\IShare;
+use PHPUnit\Framework\MockObject\MockObject;
class PreviewControllerTest extends \Test\TestCase {
- /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */
- private $rootFolder;
- /** @var string */
- private $userId;
+ private string $userId;
+ private PreviewController $controller;
- /** @var IPreview|\PHPUnit\Framework\MockObject\MockObject */
- private $previewManager;
-
- /** @var PreviewController|\PHPUnit\Framework\MockObject\MockObject */
- private $controller;
+ private IRootFolder&MockObject $rootFolder;
+ private IPreview&MockObject $previewManager;
+ private IRequest&MockObject $request;
protected function setUp(): void {
parent::setUp();
- $this->rootFolder = $this->createMock(IRootFolder::class);
$this->userId = 'user';
+ $this->rootFolder = $this->createMock(IRootFolder::class);
$this->previewManager = $this->createMock(IPreview::class);
+ $this->request = $this->createMock(IRequest::class);
$this->controller = new PreviewController(
'core',
- $this->createMock(IRequest::class),
+ $this->request,
$this->previewManager,
$this->rootFolder,
$this->userId,
@@ -124,7 +125,38 @@ class PreviewControllerTest extends \Test\TestCase {
$this->assertEquals($expected, $res);
}
- public function testForbiddenFile(): void {
+ public function testNoPreview() {
+ $userFolder = $this->createMock(Folder::class);
+ $this->rootFolder->method('getUserFolder')
+ ->with($this->equalTo($this->userId))
+ ->willReturn($userFolder);
+
+ $file = $this->createMock(File::class);
+ $userFolder->method('get')
+ ->with($this->equalTo('file'))
+ ->willReturn($file);
+
+ $storage = $this->createMock(IStorage::class);
+ $file->method('getStorage')
+ ->willReturn($storage);
+
+ $this->previewManager->method('isAvailable')
+ ->with($this->equalTo($file))
+ ->willReturn(true);
+
+ $file->method('isReadable')
+ ->willReturn(true);
+
+ $this->previewManager->method('getPreview')
+ ->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode'))
+ ->willThrowException(new NotFoundException());
+
+ $res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode');
+ $expected = new DataResponse([], Http::STATUS_NOT_FOUND);
+
+ $this->assertEquals($expected, $res);
+ }
+ public function testFileWithoutReadPermission() {
$userFolder = $this->createMock(Folder::class);
$this->rootFolder->method('getUserFolder')
->with($this->equalTo($this->userId))
@@ -148,36 +180,108 @@ class PreviewControllerTest extends \Test\TestCase {
$this->assertEquals($expected, $res);
}
- public function testNoPreview(): void {
+ public function testFileWithoutDownloadPermission() {
$userFolder = $this->createMock(Folder::class);
$this->rootFolder->method('getUserFolder')
->with($this->equalTo($this->userId))
->willReturn($userFolder);
$file = $this->createMock(File::class);
+ $file->method('getId')->willReturn(123);
$userFolder->method('get')
->with($this->equalTo('file'))
->willReturn($file);
- $storage = $this->createMock(IStorage::class);
+ $this->previewManager->method('isAvailable')
+ ->with($this->equalTo($file))
+ ->willReturn(true);
+
+ $shareAttributes = $this->createMock(IAttributes::class);
+ $shareAttributes->expects(self::atLeastOnce())
+ ->method('getAttribute')
+ ->with('permissions', 'download')
+ ->willReturn(false);
+
+ $share = $this->createMock(IShare::class);
+ $share->method('getAttributes')
+ ->willReturn($shareAttributes);
+
+ $storage = $this->createMock(ISharedStorage::class);
+ $storage->method('instanceOfStorage')
+ ->with(ISharedStorage::class)
+ ->willReturn(true);
+ $storage->method('getShare')
+ ->willReturn($share);
+
$file->method('getStorage')
->willReturn($storage);
+ $file->method('isReadable')
+ ->willReturn(true);
+
+ $this->request->method('getHeader')->willReturn('');
+
+ $res = $this->controller->getPreview('file', 10, 10, true, true);
+ $expected = new DataResponse([], Http::STATUS_FORBIDDEN);
+
+ $this->assertEquals($expected, $res);
+ }
+
+ public function testFileWithoutDownloadPermissionButHeader() {
+ $userFolder = $this->createMock(Folder::class);
+ $this->rootFolder->method('getUserFolder')
+ ->with($this->equalTo($this->userId))
+ ->willReturn($userFolder);
+
+ $file = $this->createMock(File::class);
+ $file->method('getId')->willReturn(123);
+ $userFolder->method('get')
+ ->with($this->equalTo('file'))
+ ->willReturn($file);
$this->previewManager->method('isAvailable')
->with($this->equalTo($file))
->willReturn(true);
+ $shareAttributes = $this->createMock(IAttributes::class);
+ $shareAttributes->method('getAttribute')
+ ->with('permissions', 'download')
+ ->willReturn(false);
+
+ $share = $this->createMock(IShare::class);
+ $share->method('getAttributes')
+ ->willReturn($shareAttributes);
+
+ $storage = $this->createMock(ISharedStorage::class);
+ $storage->method('instanceOfStorage')
+ ->with(ISharedStorage::class)
+ ->willReturn(true);
+ $storage->method('getShare')
+ ->willReturn($share);
+
+ $file->method('getStorage')
+ ->willReturn($storage);
$file->method('isReadable')
->willReturn(true);
+ $this->request
+ ->method('getHeader')
+ ->with('X-NC-Preview')
+ ->willReturn('true');
+
+ $preview = $this->createMock(ISimpleFile::class);
+ $preview->method('getName')->willReturn('my name');
+ $preview->method('getMTime')->willReturn(42);
$this->previewManager->method('getPreview')
->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode'))
- ->willThrowException(new NotFoundException());
+ ->willReturn($preview);
+ $preview->method('getMimeType')
+ ->willReturn('myMime');
$res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode');
- $expected = new DataResponse([], Http::STATUS_NOT_FOUND);
- $this->assertEquals($expected, $res);
+ $this->assertEquals('myMime', $res->getHeaders()['Content-Type']);
+ $this->assertEquals(Http::STATUS_OK, $res->getStatus());
+ $this->assertEquals($preview, $this->invokePrivate($res, 'file'));
}
public function testValidPreview(): void {
@@ -218,4 +322,57 @@ class PreviewControllerTest extends \Test\TestCase {
$this->assertEquals(Http::STATUS_OK, $res->getStatus());
$this->assertEquals($preview, $this->invokePrivate($res, 'file'));
}
+
+ public function testValidPreviewOfShare() {
+ $userFolder = $this->createMock(Folder::class);
+ $this->rootFolder->method('getUserFolder')
+ ->with($this->equalTo($this->userId))
+ ->willReturn($userFolder);
+
+ $file = $this->createMock(File::class);
+ $file->method('getId')->willReturn(123);
+ $userFolder->method('get')
+ ->with($this->equalTo('file'))
+ ->willReturn($file);
+
+ $this->previewManager->method('isAvailable')
+ ->with($this->equalTo($file))
+ ->willReturn(true);
+
+ // No attributes set -> download permitted
+ $share = $this->createMock(IShare::class);
+ $share->method('getAttributes')
+ ->willReturn(null);
+
+ $storage = $this->createMock(ISharedStorage::class);
+ $storage->method('instanceOfStorage')
+ ->with(ISharedStorage::class)
+ ->willReturn(true);
+ $storage->method('getShare')
+ ->willReturn($share);
+
+ $file->method('getStorage')
+ ->willReturn($storage);
+ $file->method('isReadable')
+ ->willReturn(true);
+
+ $this->request
+ ->method('getHeader')
+ ->willReturn('');
+
+ $preview = $this->createMock(ISimpleFile::class);
+ $preview->method('getName')->willReturn('my name');
+ $preview->method('getMTime')->willReturn(42);
+ $this->previewManager->method('getPreview')
+ ->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode'))
+ ->willReturn($preview);
+ $preview->method('getMimeType')
+ ->willReturn('myMime');
+
+ $res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode');
+
+ $this->assertEquals('myMime', $res->getHeaders()['Content-Type']);
+ $this->assertEquals(Http::STATUS_OK, $res->getStatus());
+ $this->assertEquals($preview, $this->invokePrivate($res, 'file'));
+ }
}
diff --git a/tests/data/app/expected-info.json b/tests/data/app/expected-info.json
index c3ea27af7d3..40ba6104104 100644
--- a/tests/data/app/expected-info.json
+++ b/tests/data/app/expected-info.json
@@ -6,7 +6,9 @@
"name": "Server-side Encryption",
"description": "\n\tThis application encrypts all files accessed by ownCloud at rest, wherever they are stored. As an example, with this application enabled, external cloud based Amazon S3 storage will be encrypted, protecting this data on storage outside of the control of the Admin. When this application is enabled for the first time, all files are encrypted as users log in and are prompted for their password. The recommended recovery key option enables recovery of files in case the key is lost. \n\tNote that this app encrypts all files that are touched by ownCloud, so external storage providers and applications such as SharePoint will see new files encrypted when they are accessed. Encryption is based on AES 128 or 256 bit keys. More information is available in the Encryption documentation \n\t",
"licence": "AGPL",
- "author": "Sam Tuke, Bjoern Schiessle, Florin Peter",
+ "author": [
+ "Sam Tuke, Bjoern Schiessle, Florin Peter"
+ ],
"requiremin": "4",
"shipped": "true",
"documentation": {
diff --git a/tests/data/app/various-single-item.json b/tests/data/app/various-single-item.json
new file mode 100644
index 00000000000..ae5e751ab49
--- /dev/null
+++ b/tests/data/app/various-single-item.json
@@ -0,0 +1,50 @@
+{
+ "id": "notifications",
+ "name": "Notifications",
+ "description": "A single screenshot should be an array",
+ "version": "1.0.0",
+ "licence": "agpl",
+ "author": [
+ "Joas Schilling"
+ ],
+ "dependencies": {
+ "nextcloud": {
+ "@attributes": {
+ "min-version": "16",
+ "max-version": "16"
+ }
+ },
+ "backend": []
+ },
+ "screenshot": [
+ "https://raw.githubusercontent.com/nextcloud/notifications/refs/heads/master/docs/screenshot.png"
+ ],
+ "category": [
+ "monitoring"
+ ],
+ "info": [],
+ "background-jobs": [],
+ "activity": {
+ "filters": [],
+ "settings": [],
+ "providers": []
+ },
+ "commands": [],
+ "remote": [],
+ "public": [],
+ "repair-steps": {
+ "install": [],
+ "pre-migration": [],
+ "post-migration": [],
+ "live-migration": [],
+ "uninstall": []
+ },
+ "settings": {
+ "admin": [],
+ "admin-section": [],
+ "personal": [],
+ "personal-section": []
+ },
+ "two-factor-providers": [],
+ "types": []
+}
diff --git a/tests/data/app/various-single-item.json.license b/tests/data/app/various-single-item.json.license
new file mode 100644
index 00000000000..84f7e70446e
--- /dev/null
+++ b/tests/data/app/various-single-item.json.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+SPDX-License-Identifier: AGPL-3.0-or-later
diff --git a/tests/data/app/various-single-item.xml b/tests/data/app/various-single-item.xml
new file mode 100644
index 00000000000..cb9595516e1
--- /dev/null
+++ b/tests/data/app/various-single-item.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<!--
+ - SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
+<info xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
+ <id>notifications</id>
+ <name>Notifications</name>
+ <description>A single screenshot should be an array</description>
+ <version>1.0.0</version>
+ <licence>agpl</licence>
+ <author>Joas Schilling</author>
+
+ <category>monitoring</category>
+
+ <screenshot>https://raw.githubusercontent.com/nextcloud/notifications/refs/heads/master/docs/screenshot.png</screenshot>
+
+ <dependencies>
+ <nextcloud min-version="16" max-version="16"/>
+ </dependencies>
+</info>
diff --git a/tests/karma.config.js b/tests/karma.config.js
index 2847b046b25..db8e6e9734d 100644
--- a/tests/karma.config.js
+++ b/tests/karma.config.js
@@ -41,14 +41,8 @@ module.exports = function(config) {
// up with the global namespace/classes/state
'dist/files_sharing-additionalScripts.js',
'dist/files_sharing-files_sharing_tab.js',
- 'dist/files_sharing-files_sharing.js',
'dist/files_sharing-main.js',
- 'apps/files_sharing/js/files_drop.js',
- 'apps/files_sharing/js/public.js',
- 'apps/files_sharing/js/sharedfilelist.js',
- 'apps/files_sharing/js/templates.js',
],
- testFiles: ['apps/files_sharing/tests/js/*.js']
},
'files_trashbin',
];
diff --git a/tests/lib/App/InfoParserTest.php b/tests/lib/App/InfoParserTest.php
index 66ff10266e2..1c429ccc405 100644
--- a/tests/lib/App/InfoParserTest.php
+++ b/tests/lib/App/InfoParserTest.php
@@ -53,6 +53,7 @@ class InfoParserTest extends TestCase {
[null, 'invalid-info.xml'],
['navigation-one-item.json', 'navigation-one-item.xml'],
['navigation-two-items.json', 'navigation-two-items.xml'],
+ ['various-single-item.json', 'various-single-item.xml'],
];
}
}
diff --git a/tests/lib/AppFramework/Db/EntityTest.php b/tests/lib/AppFramework/Db/EntityTest.php
index 8e6e6dcd645..3c844780b07 100644
--- a/tests/lib/AppFramework/Db/EntityTest.php
+++ b/tests/lib/AppFramework/Db/EntityTest.php
@@ -9,6 +9,7 @@
namespace Test\AppFramework\Db;
use OCP\AppFramework\Db\Entity;
+use OCP\DB\Types;
use PHPUnit\Framework\Constraint\IsType;
/**
@@ -29,21 +30,40 @@ use PHPUnit\Framework\Constraint\IsType;
* @method bool isAnotherBool()
* @method string getLongText()
* @method void setLongText(string $longText)
+ * @method \DateTime getTime()
+ * @method void setTime(\DateTime $time)
+ * @method \DateTimeImmutable getDatetime()
+ * @method void setDatetime(\DateTimeImmutable $datetime)
*/
class TestEntity extends Entity {
protected $name;
protected $email;
protected $testId;
+ protected $smallInt;
+ protected $bigInt;
protected $preName;
protected $trueOrFalse;
protected $anotherBool;
+ protected $text;
protected $longText;
+ protected $time;
+ protected $datetime;
public function __construct($name = null) {
- $this->addType('testId', 'integer');
+ $this->addType('testId', Types::INTEGER);
+ $this->addType('smallInt', Types::SMALLINT);
+ $this->addType('bigInt', Types::BIGINT);
+ $this->addType('anotherBool', Types::BOOLEAN);
+ $this->addType('text', Types::TEXT);
+ $this->addType('longText', Types::BLOB);
+ $this->addType('time', Types::TIME);
+ $this->addType('datetime', Types::DATETIME_IMMUTABLE);
+
+ // Legacy types
$this->addType('trueOrFalse', 'bool');
- $this->addType('anotherBool', 'boolean');
- $this->addType('longText', 'blob');
+ $this->addType('legacyInt', 'int');
+ $this->addType('doubleNowFloat', 'double');
+
$this->name = $name;
}
@@ -191,10 +211,28 @@ class EntityTest extends \Test\TestCase {
}
- public function testSetterCasts(): void {
+ public function dataSetterCasts(): array {
+ return [
+ ['Id', '3', 3],
+ ['smallInt', '3', 3],
+ ['bigInt', '' . PHP_INT_MAX, PHP_INT_MAX],
+ ['trueOrFalse', 0, false],
+ ['trueOrFalse', 1, true],
+ ['anotherBool', 0, false],
+ ['anotherBool', 1, true],
+ ['text', 33, '33'],
+ ['longText', PHP_INT_MAX, '' . PHP_INT_MAX],
+ ];
+ }
+
+
+ /**
+ * @dataProvider dataSetterCasts
+ */
+ public function testSetterCasts(string $field, mixed $in, mixed $out): void {
$entity = new TestEntity();
- $entity->setId('3');
- $this->assertSame(3, $entity->getId());
+ $entity->{'set' . $field}($in);
+ $this->assertSame($out, $entity->{'get' . $field}());
}
@@ -216,15 +254,39 @@ class EntityTest extends \Test\TestCase {
$this->assertSame($string, $entity->getLongText());
}
+ public function testSetterConvertsDatetime() {
+ $entity = new TestEntity();
+ $entity->setDatetime('2024-08-19 15:26:00');
+ $this->assertEquals(new \DateTimeImmutable('2024-08-19 15:26:00'), $entity->getDatetime());
+ }
+
+ public function testSetterDoesNotConvertNullOnDatetime() {
+ $entity = new TestEntity();
+ $entity->setDatetime(null);
+ $this->assertNull($entity->getDatetime());
+ }
+
+ public function testSetterConvertsTime() {
+ $entity = new TestEntity();
+ $entity->setTime('15:26:00');
+ $this->assertEquals(new \DateTime('15:26:00'), $entity->getTime());
+ }
public function testGetFieldTypes(): void {
$entity = new TestEntity();
$this->assertEquals([
- 'id' => 'integer',
- 'testId' => 'integer',
- 'trueOrFalse' => 'bool',
- 'anotherBool' => 'boolean',
- 'longText' => 'blob',
+ 'id' => Types::INTEGER,
+ 'testId' => Types::INTEGER,
+ 'smallInt' => Types::SMALLINT,
+ 'bigInt' => Types::BIGINT,
+ 'anotherBool' => Types::BOOLEAN,
+ 'text' => Types::TEXT,
+ 'longText' => Types::BLOB,
+ 'time' => Types::TIME,
+ 'datetime' => Types::DATETIME_IMMUTABLE,
+ 'trueOrFalse' => Types::BOOLEAN,
+ 'legacyInt' => Types::INTEGER,
+ 'doubleNowFloat' => Types::FLOAT,
], $entity->getFieldTypes());
}
@@ -232,7 +294,7 @@ class EntityTest extends \Test\TestCase {
public function testGetItInt(): void {
$entity = new TestEntity();
$entity->setId(3);
- $this->assertEquals('integer', gettype($entity->getId()));
+ $this->assertEquals(Types::INTEGER, gettype($entity->getId()));
}
diff --git a/tests/lib/AppFramework/Db/QBMapperDBTest.php b/tests/lib/AppFramework/Db/QBMapperDBTest.php
new file mode 100644
index 00000000000..72bc2d956d6
--- /dev/null
+++ b/tests/lib/AppFramework/Db/QBMapperDBTest.php
@@ -0,0 +1,159 @@
+<?php
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test\AppFramework\Db;
+
+use Doctrine\DBAL\Schema\SchemaException;
+use OCP\AppFramework\Db\Entity;
+use OCP\AppFramework\Db\QBMapper;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\DB\Types;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\Server;
+use Test\TestCase;
+
+/**
+ * @method void setTime(?\DateTime $time)
+ * @method ?\DateTime getTime()
+ * @method void setDatetime(?\DateTimeImmutable $datetime)
+ * @method ?\DateTimeImmutable getDatetime()
+ */
+class QBDBTestEntity extends Entity {
+ protected ?\DateTime $time = null;
+ protected ?\DateTimeImmutable $datetime = null;
+
+ public function __construct() {
+ $this->addType('time', Types::TIME);
+ $this->addType('datetime', Types::DATETIME_IMMUTABLE);
+ }
+}
+
+/**
+ * Class QBDBTestMapper
+ *
+ * @package Test\AppFramework\Db
+ */
+class QBDBTestMapper extends QBMapper {
+ public function __construct(IDBConnection $db) {
+ parent::__construct($db, 'testing', QBDBTestEntity::class);
+ }
+
+ public function getParameterTypeForPropertyForTest(Entity $entity, string $property) {
+ return parent::getParameterTypeForProperty($entity, $property);
+ }
+
+ public function getById(int $id): QBDBTestEntity {
+ $qb = $this->db->getQueryBuilder();
+ $query = $qb
+ ->select('*')
+ ->from($this->tableName)
+ ->where(
+ $qb->expr()->eq('id', $qb->createPositionalParameter($id, IQueryBuilder::PARAM_INT)),
+ );
+ return $this->findEntity($query);
+ }
+}
+
+/**
+ * Test real database handling (serialization)
+ * @group DB
+ */
+class QBMapperDBTest extends TestCase {
+ /** @var \Doctrine\DBAL\Connection|\OCP\IDBConnection */
+ protected $connection;
+ protected $schemaSetup = false;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->connection = \OCP\Server::get(IDBConnection::class);
+ $this->prepareTestingTable();
+ }
+
+ public function testInsertDateTime(): void {
+ $mapper = new QBDBTestMapper($this->connection);
+ $entity = new QBDBTestEntity();
+ $entity->setTime(new \DateTime('2003-01-01 12:34:00'));
+ $entity->setDatetime(new \DateTimeImmutable('2000-01-01 23:45:00'));
+
+ $result = $mapper->insert($entity);
+ $this->assertNotNull($result->getId());
+ }
+
+ public function testRetrieveDateTime(): void {
+ $time = new \DateTime('2000-01-01 01:01:00');
+ $datetime = new \DateTimeImmutable('2000-01-01 02:02:00');
+
+ $mapper = new QBDBTestMapper($this->connection);
+ $entity = new QBDBTestEntity();
+ $entity->setTime($time);
+ $entity->setDatetime($datetime);
+
+ $result = $mapper->insert($entity);
+ $this->assertNotNull($result->getId());
+
+ $dbEntity = $mapper->getById($result->getId());
+ $this->assertEquals($time->format('H:i:s'), $dbEntity->getTime()->format('H:i:s'));
+ $this->assertEquals($datetime->format('Y-m-d H:i:s'), $dbEntity->getDatetime()->format('Y-m-d H:i:s'));
+ // The date is not saved for "time"
+ $this->assertNotEquals($time->format('Y'), $dbEntity->getTime()->format('Y'));
+ }
+
+ public function testUpdateDateTime(): void {
+ $time = new \DateTime('2000-01-01 01:01:00');
+ $datetime = new \DateTimeImmutable('2000-01-01 02:02:00');
+
+ $mapper = new QBDBTestMapper($this->connection);
+ $entity = new QBDBTestEntity();
+ $entity->setTime('now');
+ $entity->setDatetime('now');
+
+ /** @var QBDBTestEntity */
+ $entity = $mapper->insert($entity);
+ $this->assertNotNull($entity->getId());
+
+ // Update the values
+ $entity->setTime($time);
+ $entity->setDatetime($datetime);
+ $mapper->update($entity);
+
+ $dbEntity = $mapper->getById($entity->getId());
+ $this->assertEquals($time->format('H:i:s'), $dbEntity->getTime()->format('H:i:s'));
+ $this->assertEquals($datetime->format('Y-m-d H:i:s'), $dbEntity->getDatetime()->format('Y-m-d H:i:s'));
+ }
+
+ protected function prepareTestingTable(): void {
+ if ($this->schemaSetup) {
+ $this->connection->getQueryBuilder()->delete('testing')->executeStatement();
+ }
+
+ $prefix = Server::get(IConfig::class)->getSystemValueString('dbtableprefix', 'oc_');
+ $schema = $this->connection->createSchema();
+ try {
+ $schema->getTable($prefix . 'testing');
+ $this->connection->getQueryBuilder()->delete('testing')->executeStatement();
+ } catch (SchemaException $e) {
+ $this->schemaSetup = true;
+ $table = $schema->createTable($prefix . 'testing');
+ $table->addColumn('id', Types::BIGINT, [
+ 'autoincrement' => true,
+ 'notnull' => true,
+ ]);
+
+ $table->addColumn('time', Types::TIME, [
+ 'notnull' => false,
+ ]);
+
+ $table->addColumn('datetime', Types::DATETIME_IMMUTABLE, [
+ 'notnull' => false,
+ ]);
+
+ $table->setPrimaryKey(['id']);
+ $this->connection->migrateToSchema($schema);
+ }
+ }
+}
diff --git a/tests/lib/AppFramework/Db/QBMapperTest.php b/tests/lib/AppFramework/Db/QBMapperTest.php
index f08beca05ca..3cf32e56f12 100644
--- a/tests/lib/AppFramework/Db/QBMapperTest.php
+++ b/tests/lib/AppFramework/Db/QBMapperTest.php
@@ -10,7 +10,9 @@ use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\QBMapper;
use OCP\DB\QueryBuilder\IExpressionBuilder;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\DB\Types;
use OCP\IDBConnection;
+use PHPUnit\Framework\MockObject\MockObject;
/**
* @method bool getBoolProp()
@@ -23,6 +25,8 @@ use OCP\IDBConnection;
* @method void setBooleanProp(bool $booleanProp)
* @method integer getIntegerProp()
* @method void setIntegerProp(integer $integerProp)
+ * @method ?\DateTimeImmutable getDatetimeProp()
+ * @method void setDatetimeProp(?\DateTimeImmutable $datetime)
*/
class QBTestEntity extends Entity {
protected $intProp;
@@ -31,14 +35,16 @@ class QBTestEntity extends Entity {
protected $integerProp;
protected $booleanProp;
protected $jsonProp;
+ protected $datetimeProp;
public function __construct() {
$this->addType('intProp', 'int');
$this->addType('boolProp', 'bool');
- $this->addType('stringProp', 'string');
- $this->addType('integerProp', 'integer');
- $this->addType('booleanProp', 'boolean');
- $this->addType('jsonProp', 'json');
+ $this->addType('stringProp', Types::STRING);
+ $this->addType('integerProp', Types::INTEGER);
+ $this->addType('booleanProp', Types::BOOLEAN);
+ $this->addType('jsonProp', Types::JSON);
+ $this->addType('datetimeProp', Types::DATETIME_IMMUTABLE);
}
}
@@ -63,25 +69,11 @@ class QBTestMapper extends QBMapper {
* @package Test\AppFramework\Db
*/
class QBMapperTest extends \Test\TestCase {
- /**
- * @var \PHPUnit\Framework\MockObject\MockObject|IDBConnection
- */
- protected $db;
-
- /**
- * @var \PHPUnit\Framework\MockObject\MockObject|IQueryBuilder
- */
- protected $qb;
- /**
- * @var \PHPUnit\Framework\MockObject\MockObject|IExpressionBuilder
- */
- protected $expr;
-
- /**
- * @var \Test\AppFramework\Db\QBTestMapper
- */
- protected $mapper;
+ protected IDBConnection&MockObject $db;
+ protected IQueryBuilder&MockObject $qb;
+ protected IExpressionBuilder&MockObject $expr;
+ protected QBTestMapper $mapper;
/**
* @throws \ReflectionException
@@ -109,36 +101,41 @@ class QBMapperTest extends \Test\TestCase {
public function testInsertEntityParameterTypeMapping(): void {
+ $datetime = new \DateTimeImmutable();
$entity = new QBTestEntity();
$entity->setIntProp(123);
$entity->setBoolProp(true);
$entity->setStringProp('string');
$entity->setIntegerProp(456);
$entity->setBooleanProp(false);
+ $entity->setDatetimeProp($datetime);
$intParam = $this->qb->createNamedParameter('int_prop', IQueryBuilder::PARAM_INT);
$boolParam = $this->qb->createNamedParameter('bool_prop', IQueryBuilder::PARAM_BOOL);
$stringParam = $this->qb->createNamedParameter('string_prop', IQueryBuilder::PARAM_STR);
$integerParam = $this->qb->createNamedParameter('integer_prop', IQueryBuilder::PARAM_INT);
$booleanParam = $this->qb->createNamedParameter('boolean_prop', IQueryBuilder::PARAM_BOOL);
+ $datetimeParam = $this->qb->createNamedParameter('datetime_prop', IQueryBuilder::PARAM_DATETIME_IMMUTABLE);
- $this->qb->expects($this->exactly(5))
+ $this->qb->expects($this->exactly(6))
->method('createNamedParameter')
->withConsecutive(
[$this->equalTo(123), $this->equalTo(IQueryBuilder::PARAM_INT)],
[$this->equalTo(true), $this->equalTo(IQueryBuilder::PARAM_BOOL)],
[$this->equalTo('string'), $this->equalTo(IQueryBuilder::PARAM_STR)],
[$this->equalTo(456), $this->equalTo(IQueryBuilder::PARAM_INT)],
- [$this->equalTo(false), $this->equalTo(IQueryBuilder::PARAM_BOOL)]
+ [$this->equalTo(false), $this->equalTo(IQueryBuilder::PARAM_BOOL)],
+ [$this->equalTo($datetime), $this->equalTo(IQueryBuilder::PARAM_DATETIME_IMMUTABLE)],
);
- $this->qb->expects($this->exactly(5))
+ $this->qb->expects($this->exactly(6))
->method('setValue')
->withConsecutive(
[$this->equalTo('int_prop'), $this->equalTo($intParam)],
[$this->equalTo('bool_prop'), $this->equalTo($boolParam)],
[$this->equalTo('string_prop'), $this->equalTo($stringParam)],
[$this->equalTo('integer_prop'), $this->equalTo($integerParam)],
- [$this->equalTo('boolean_prop'), $this->equalTo($booleanParam)]
+ [$this->equalTo('boolean_prop'), $this->equalTo($booleanParam)],
+ [$this->equalTo('datetime_prop'), $this->equalTo($datetimeParam)],
);
$this->mapper->insert($entity);
@@ -146,6 +143,7 @@ class QBMapperTest extends \Test\TestCase {
public function testUpdateEntityParameterTypeMapping(): void {
+ $datetime = new \DateTimeImmutable();
$entity = new QBTestEntity();
$entity->setId(789);
$entity->setIntProp(123);
@@ -154,6 +152,7 @@ class QBMapperTest extends \Test\TestCase {
$entity->setIntegerProp(456);
$entity->setBooleanProp(false);
$entity->setJsonProp(['hello' => 'world']);
+ $entity->setDatetimeProp($datetime);
$idParam = $this->qb->createNamedParameter('id', IQueryBuilder::PARAM_INT);
$intParam = $this->qb->createNamedParameter('int_prop', IQueryBuilder::PARAM_INT);
@@ -162,8 +161,9 @@ class QBMapperTest extends \Test\TestCase {
$integerParam = $this->qb->createNamedParameter('integer_prop', IQueryBuilder::PARAM_INT);
$booleanParam = $this->qb->createNamedParameter('boolean_prop', IQueryBuilder::PARAM_BOOL);
$jsonParam = $this->qb->createNamedParameter('json_prop', IQueryBuilder::PARAM_JSON);
+ $datetimeParam = $this->qb->createNamedParameter('datetime_prop', IQueryBuilder::PARAM_DATETIME_IMMUTABLE);
- $this->qb->expects($this->exactly(7))
+ $this->qb->expects($this->exactly(8))
->method('createNamedParameter')
->withConsecutive(
[$this->equalTo(123), $this->equalTo(IQueryBuilder::PARAM_INT)],
@@ -172,10 +172,11 @@ class QBMapperTest extends \Test\TestCase {
[$this->equalTo(456), $this->equalTo(IQueryBuilder::PARAM_INT)],
[$this->equalTo(false), $this->equalTo(IQueryBuilder::PARAM_BOOL)],
[$this->equalTo(['hello' => 'world']), $this->equalTo(IQueryBuilder::PARAM_JSON)],
+ [$this->equalTo($datetime), $this->equalTo(IQueryBuilder::PARAM_DATETIME_IMMUTABLE)],
[$this->equalTo(789), $this->equalTo(IQueryBuilder::PARAM_INT)],
);
- $this->qb->expects($this->exactly(6))
+ $this->qb->expects($this->exactly(7))
->method('set')
->withConsecutive(
[$this->equalTo('int_prop'), $this->equalTo($intParam)],
@@ -183,7 +184,8 @@ class QBMapperTest extends \Test\TestCase {
[$this->equalTo('string_prop'), $this->equalTo($stringParam)],
[$this->equalTo('integer_prop'), $this->equalTo($integerParam)],
[$this->equalTo('boolean_prop'), $this->equalTo($booleanParam)],
- [$this->equalTo('json_prop'), $this->equalTo($jsonParam)]
+ [$this->equalTo('json_prop'), $this->equalTo($jsonParam)],
+ [$this->equalTo('datetime_prop'), $this->equalTo($datetimeParam)],
);
$this->expr->expects($this->once())
@@ -216,6 +218,9 @@ class QBMapperTest extends \Test\TestCase {
$jsonType = $this->mapper->getParameterTypeForPropertyForTest($entity, 'jsonProp');
$this->assertEquals(IQueryBuilder::PARAM_JSON, $jsonType, 'JSON type property mapping incorrect');
+ $datetimeType = $this->mapper->getParameterTypeForPropertyForTest($entity, 'datetimeProp');
+ $this->assertEquals(IQueryBuilder::PARAM_DATETIME_IMMUTABLE, $datetimeType, 'DateTimeImmutable type property mapping incorrect');
+
$unknownType = $this->mapper->getParameterTypeForPropertyForTest($entity, 'someProp');
$this->assertEquals(IQueryBuilder::PARAM_STR, $unknownType, 'Unknown type property mapping incorrect');
}
diff --git a/tests/lib/Authentication/LoginCredentials/StoreTest.php b/tests/lib/Authentication/LoginCredentials/StoreTest.php
index 6f1e3a6d750..c58bb09faaa 100644
--- a/tests/lib/Authentication/LoginCredentials/StoreTest.php
+++ b/tests/lib/Authentication/LoginCredentials/StoreTest.php
@@ -15,6 +15,7 @@ use OC\Authentication\Token\IProvider;
use OC\Authentication\Token\IToken;
use OCP\Authentication\Exceptions\CredentialsUnavailableException;
use OCP\ISession;
+use OCP\Security\ICrypto;
use OCP\Session\Exceptions\SessionNotAvailableException;
use Psr\Log\LoggerInterface;
use Test\TestCase;
@@ -29,6 +30,8 @@ class StoreTest extends TestCase {
/** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
private $logger;
+ /** @var ICrypto|\PHPUnit\Framework\MockObject\MockObject */
+ private $crypto;
/** @var Store */
private $store;
@@ -39,20 +42,24 @@ class StoreTest extends TestCase {
$this->session = $this->createMock(ISession::class);
$this->tokenProvider = $this->createMock(IProvider::class);
$this->logger = $this->createMock(LoggerInterface::class);
+ $this->crypto = $this->createMock(ICrypto::class);
- $this->store = new Store($this->session, $this->logger, $this->tokenProvider);
+ $this->store = new Store($this->session, $this->logger, $this->crypto, $this->tokenProvider);
}
public function testAuthenticate(): void {
$params = [
'run' => true,
'uid' => 'user123',
- 'password' => 123456,
+ 'password' => '123456',
];
$this->session->expects($this->once())
->method('set')
->with($this->equalTo('login_credentials'), $this->equalTo(json_encode($params)));
+ $this->crypto->expects($this->once())
+ ->method('encrypt')
+ ->willReturn('123456');
$this->store->authenticate($params);
}
@@ -65,7 +72,7 @@ class StoreTest extends TestCase {
}
public function testGetLoginCredentialsNoTokenProvider(): void {
- $this->store = new Store($this->session, $this->logger, null);
+ $this->store = new Store($this->session, $this->logger, $this->crypto, null);
$this->expectException(CredentialsUnavailableException::class);
@@ -139,6 +146,9 @@ class StoreTest extends TestCase {
->method('exists')
->with($this->equalTo('login_credentials'))
->willReturn(true);
+ $this->crypto->expects($this->once())
+ ->method('decrypt')
+ ->willReturn($password);
$this->session->expects($this->exactly(2))
->method('get')
->willReturnMap([
@@ -176,6 +186,9 @@ class StoreTest extends TestCase {
->method('exists')
->with($this->equalTo('login_credentials'))
->willReturn(true);
+ $this->crypto->expects($this->once())
+ ->method('decrypt')
+ ->willReturn($password);
$this->session->expects($this->exactly(2))
->method('get')
->willReturnMap([
@@ -214,6 +227,9 @@ class StoreTest extends TestCase {
->method('exists')
->with($this->equalTo('login_credentials'))
->willReturn(true);
+ $this->crypto->expects($this->once())
+ ->method('decrypt')
+ ->willReturn($password);
$this->session->expects($this->once())
->method('get')
->with($this->equalTo('login_credentials'))
diff --git a/tests/lib/Comments/CommentTest.php b/tests/lib/Comments/CommentTest.php
index 742ce33071f..3cfc897b28e 100644
--- a/tests/lib/Comments/CommentTest.php
+++ b/tests/lib/Comments/CommentTest.php
@@ -196,6 +196,12 @@ class CommentTest extends TestCase {
['type' => 'federated_team', 'id' => 'Former Cirle'],
],
],
+ [
+ 'Emails are supported since 30.0.2 right? @"email/aa23d315de327cfc330f0401ea061005b2b0cdd45ec8346f12664dd1f34cb886"',
+ [
+ ['type' => 'email', 'id' => 'aa23d315de327cfc330f0401ea061005b2b0cdd45ec8346f12664dd1f34cb886'],
+ ],
+ ],
];
}
diff --git a/tests/lib/Comments/ManagerTest.php b/tests/lib/Comments/ManagerTest.php
index 9a36182d393..15961b029f5 100644
--- a/tests/lib/Comments/ManagerTest.php
+++ b/tests/lib/Comments/ManagerTest.php
@@ -14,6 +14,7 @@ use OCP\Comments\IComment;
use OCP\Comments\ICommentsEventHandler;
use OCP\Comments\ICommentsManager;
use OCP\Comments\NotFoundException;
+use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
@@ -70,11 +71,11 @@ class ManagerTest extends TestCase {
'actor_id' => $qb->createNamedParameter('alice'),
'message' => $qb->createNamedParameter('nice one'),
'verb' => $qb->createNamedParameter('comment'),
- 'creation_timestamp' => $qb->createNamedParameter($creationDT, 'datetime'),
- 'latest_child_timestamp' => $qb->createNamedParameter($latestChildDT, 'datetime'),
+ 'creation_timestamp' => $qb->createNamedParameter($creationDT, IQueryBuilder::PARAM_DATETIME_MUTABLE),
+ 'latest_child_timestamp' => $qb->createNamedParameter($latestChildDT, IQueryBuilder::PARAM_DATETIME_MUTABLE),
'object_type' => $qb->createNamedParameter('files'),
'object_id' => $qb->createNamedParameter($objectId),
- 'expire_date' => $qb->createNamedParameter($expireDate, 'datetime'),
+ 'expire_date' => $qb->createNamedParameter($expireDate, IQueryBuilder::PARAM_DATETIME_MUTABLE),
'reference_id' => $qb->createNamedParameter('referenceId'),
'meta_data' => $qb->createNamedParameter(json_encode(['last_edit_actor_id' => 'admin'])),
])
diff --git a/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php b/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php
index ed6e328881b..392fe9ff937 100644
--- a/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php
+++ b/tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php
@@ -7,9 +7,9 @@
namespace Test\DB\QueryBuilder;
use Doctrine\DBAL\Schema\SchemaException;
-use Doctrine\DBAL\Types\Types;
use OC\DB\QueryBuilder\Literal;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\DB\Types;
use OCP\IConfig;
use OCP\Server;
use Test\TestCase;
@@ -145,13 +145,13 @@ class ExpressionBuilderDBTest extends TestCase {
$dateTime = new \DateTime('2023-01-01');
$insert = $this->connection->getQueryBuilder();
$insert->insert('testing')
- ->values(['datetime' => $insert->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATE)])
+ ->values(['datetime' => $insert->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE)])
->executeStatement();
$query = $this->connection->getQueryBuilder();
$result = $query->select('*')
->from('testing')
- ->where($query->expr()->eq('datetime', $query->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATE)))
+ ->where($query->expr()->eq('datetime', $query->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE)))
->executeQuery();
$entries = $result->fetchAll();
$result->closeCursor();
@@ -163,13 +163,13 @@ class ExpressionBuilderDBTest extends TestCase {
$dateTimeCompare = new \DateTime('2022-01-02');
$insert = $this->connection->getQueryBuilder();
$insert->insert('testing')
- ->values(['datetime' => $insert->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATE)])
+ ->values(['datetime' => $insert->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE)])
->executeStatement();
$query = $this->connection->getQueryBuilder();
$result = $query->select('*')
->from('testing')
- ->where($query->expr()->lt('datetime', $query->createNamedParameter($dateTimeCompare, IQueryBuilder::PARAM_DATE)))
+ ->where($query->expr()->lt('datetime', $query->createNamedParameter($dateTimeCompare, IQueryBuilder::PARAM_DATETIME_MUTABLE)))
->executeQuery();
$entries = $result->fetchAll();
$result->closeCursor();
@@ -181,13 +181,13 @@ class ExpressionBuilderDBTest extends TestCase {
$dateTimeCompare = new \DateTime('2023-01-01');
$insert = $this->connection->getQueryBuilder();
$insert->insert('testing')
- ->values(['datetime' => $insert->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATE)])
+ ->values(['datetime' => $insert->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE)])
->executeStatement();
$query = $this->connection->getQueryBuilder();
$result = $query->select('*')
->from('testing')
- ->where($query->expr()->gt('datetime', $query->createNamedParameter($dateTimeCompare, IQueryBuilder::PARAM_DATE)))
+ ->where($query->expr()->gt('datetime', $query->createNamedParameter($dateTimeCompare, IQueryBuilder::PARAM_DATETIME_MUTABLE)))
->executeQuery();
$entries = $result->fetchAll();
$result->closeCursor();
@@ -223,7 +223,7 @@ class ExpressionBuilderDBTest extends TestCase {
'notnull' => true,
]);
- $table->addColumn('datetime', Types::DATETIME_MUTABLE, [
+ $table->addColumn('datetime', Types::DATETIME, [
'notnull' => false,
]);
diff --git a/tests/lib/Files/Storage/LocalTest.php b/tests/lib/Files/Storage/LocalTest.php
index 4a98970f233..65bc538ef17 100644
--- a/tests/lib/Files/Storage/LocalTest.php
+++ b/tests/lib/Files/Storage/LocalTest.php
@@ -7,6 +7,8 @@
namespace Test\Files\Storage;
+use OC\Files\Storage\Wrapper\Jail;
+
/**
* Class LocalTest
*
@@ -59,7 +61,7 @@ class LocalTest extends Storage {
public function testInvalidArgumentsNoArray(): void {
$this->expectException(\InvalidArgumentException::class);
- new \OC\Files\Storage\Local(null);
+ new \OC\Files\Storage\Local([]);
}
@@ -135,4 +137,25 @@ class LocalTest extends Storage {
// no exception thrown
$this->assertNotNull($this->instance);
}
+
+ public function testMoveNestedJail(): void {
+ $this->instance->mkdir('foo');
+ $this->instance->mkdir('foo/bar');
+ $this->instance->mkdir('target');
+ $this->instance->file_put_contents('foo/bar/file.txt', 'foo');
+ $jail1 = new Jail([
+ 'storage' => $this->instance,
+ 'root' => 'foo'
+ ]);
+ $jail2 = new Jail([
+ 'storage' => $jail1,
+ 'root' => 'bar'
+ ]);
+ $jail3 = new Jail([
+ 'storage' => $this->instance,
+ 'root' => 'target'
+ ]);
+ $jail3->moveFromStorage($jail2, 'file.txt', 'file.txt');
+ $this->assertTrue($this->instance->file_exists('target/file.txt'));
+ }
}
diff --git a/tests/lib/Files/Storage/StorageFactoryTest.php b/tests/lib/Files/Storage/StorageFactoryTest.php
index d1e8d927dc9..83e8a7bf6eb 100644
--- a/tests/lib/Files/Storage/StorageFactoryTest.php
+++ b/tests/lib/Files/Storage/StorageFactoryTest.php
@@ -16,10 +16,10 @@ use Test\TestCase;
class DummyWrapper extends Wrapper {
public $data;
- public function __construct($arguments) {
- parent::__construct($arguments);
- if (isset($arguments['data'])) {
- $this->data = $arguments['data'];
+ public function __construct(array $parameters) {
+ parent::__construct($parameters);
+ if (isset($parameters['data'])) {
+ $this->data = $parameters['data'];
}
}
}
diff --git a/tests/lib/HelperStorageTest.php b/tests/lib/HelperStorageTest.php
index 4d5002de3ab..455bd288351 100644
--- a/tests/lib/HelperStorageTest.php
+++ b/tests/lib/HelperStorageTest.php
@@ -72,7 +72,7 @@ class HelperStorageTest extends \Test\TestCase {
private function getStorageMock($freeSpace = 12) {
$this->storageMock = $this->getMockBuilder(Temporary::class)
->setMethods(['free_space'])
- ->setConstructorArgs([''])
+ ->setConstructorArgs([[]])
->getMock();
$this->storageMock->expects($this->once())
diff --git a/tests/lib/Share20/DefaultShareProviderTest.php b/tests/lib/Share20/DefaultShareProviderTest.php
index 5bed54cc18f..0351504e1a7 100644
--- a/tests/lib/Share20/DefaultShareProviderTest.php
+++ b/tests/lib/Share20/DefaultShareProviderTest.php
@@ -162,7 +162,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
$qb->setValue('token', $qb->expr()->literal($token));
}
if ($expiration) {
- $qb->setValue('expiration', $qb->createNamedParameter($expiration, IQueryBuilder::PARAM_DATE));
+ $qb->setValue('expiration', $qb->createNamedParameter($expiration, IQueryBuilder::PARAM_DATETIME_MUTABLE));
}
if ($parent) {
$qb->setValue('parent', $qb->expr()->literal($parent));
@@ -884,6 +884,7 @@ class DefaultShareProviderTest extends \Test\TestCase {
'file_target' => $qb->expr()->literal('myTarget'),
'permissions' => $qb->expr()->literal(13),
'token' => $qb->expr()->literal('secrettoken'),
+ 'label' => $qb->expr()->literal('the label'),
]);
$qb->execute();
$id = $qb->getLastInsertId();
@@ -899,10 +900,43 @@ class DefaultShareProviderTest extends \Test\TestCase {
$this->assertSame('sharedBy', $share->getSharedBy());
$this->assertSame('secrettoken', $share->getToken());
$this->assertSame('password', $share->getPassword());
+ $this->assertSame('the label', $share->getLabel());
$this->assertSame(true, $share->getSendPasswordByTalk());
$this->assertSame(null, $share->getSharedWith());
}
+ /**
+ * Assert that if no label is provided the label is correctly,
+ * as types on IShare, a string and not null
+ */
+ public function testGetShareByTokenNullLabel(): void {
+ $qb = $this->dbConn->getQueryBuilder();
+
+ $qb->insert('share')
+ ->values([
+ 'share_type' => $qb->expr()->literal(IShare::TYPE_LINK),
+ 'password' => $qb->expr()->literal('password'),
+ 'password_by_talk' => $qb->expr()->literal(true),
+ 'uid_owner' => $qb->expr()->literal('shareOwner'),
+ 'uid_initiator' => $qb->expr()->literal('sharedBy'),
+ 'item_type' => $qb->expr()->literal('file'),
+ 'file_source' => $qb->expr()->literal(42),
+ 'file_target' => $qb->expr()->literal('myTarget'),
+ 'permissions' => $qb->expr()->literal(13),
+ 'token' => $qb->expr()->literal('secrettoken'),
+ ]);
+ $qb->executeStatement();
+ $id = $qb->getLastInsertId();
+
+ $file = $this->createMock(File::class);
+
+ $this->rootFolder->method('getUserFolder')->with('shareOwner')->willReturnSelf();
+ $this->rootFolder->method('getFirstNodeById')->with(42)->willReturn($file);
+
+ $share = $this->provider->getShareByToken('secrettoken');
+ $this->assertEquals($id, $share->getId());
+ $this->assertSame('', $share->getLabel());
+ }
public function testGetShareByTokenNotFound(): void {
$this->expectException(\OCP\Share\Exceptions\ShareNotFound::class);
diff --git a/tests/lib/Share20/ShareByMailProviderTest.php b/tests/lib/Share20/ShareByMailProviderTest.php
index 01029e421e0..bc8e9e53df0 100644
--- a/tests/lib/Share20/ShareByMailProviderTest.php
+++ b/tests/lib/Share20/ShareByMailProviderTest.php
@@ -179,7 +179,7 @@ class ShareByMailProviderTest extends TestCase {
$qb->setValue('token', $qb->expr()->literal($token));
}
if ($expiration) {
- $qb->setValue('expiration', $qb->createNamedParameter($expiration, IQueryBuilder::PARAM_DATE));
+ $qb->setValue('expiration', $qb->createNamedParameter($expiration, IQueryBuilder::PARAM_DATETIME_MUTABLE));
}
if ($parent) {
$qb->setValue('parent', $qb->expr()->literal($parent));
diff --git a/tests/lib/TemplateLayoutTest.php b/tests/lib/TemplateLayoutTest.php
new file mode 100644
index 00000000000..405f1df7330
--- /dev/null
+++ b/tests/lib/TemplateLayoutTest.php
@@ -0,0 +1,84 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace Test;
+
+use OC\InitialStateService;
+use OC\TemplateLayout;
+use OCP\App\IAppManager;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IConfig;
+
+class TemplateLayoutTest extends \Test\TestCase {
+
+
+ /** @dataProvider dataVersionHash */
+ public function testVersionHash($path, $file, $installed, $debug, $expected): void {
+ $appManager = $this->createMock(IAppManager::class);
+ $appManager->expects(self::any())
+ ->method('getAppVersion')
+ ->willReturnCallback(fn ($appId) => match ($appId) {
+ 'shippedApp' => 'shipped_1',
+ 'otherApp' => 'other_2',
+ default => "$appId",
+ });
+ $appManager->expects(self::any())
+ ->method('isShipped')
+ ->willReturnCallback(fn (string $app) => $app === 'shippedApp');
+
+ $config = $this->createMock(IConfig::class);
+ $config->expects(self::atLeastOnce())
+ ->method('getSystemValueBool')
+ ->willReturnMap([
+ ['installed', false, $installed],
+ ['debug', false, $debug],
+ ]);
+ $config->expects(self::any())
+ ->method('getAppValue')
+ ->with('theming', 'cachebuster', '0')
+ ->willReturn('42');
+
+ $initialState = $this->createMock(InitialStateService::class);
+
+ $this->overwriteService(IConfig::class, $config);
+ $this->overwriteService(IAppManager::class, $appManager);
+ $this->overwriteService(InitialStateService::class, $initialState);
+
+ $layout = $this->getMockBuilder(TemplateLayout::class)
+ ->onlyMethods(['getAppNamefromPath'])
+ ->setConstructorArgs([TemplateResponse::RENDER_AS_ERROR])
+ ->getMock();
+
+ self::invokePrivate(TemplateLayout::class, 'versionHash', ['version_hash']);
+
+ $layout->expects(self::any())
+ ->method('getAppNamefromPath')
+ ->willReturnCallback(fn ($appName) => match($appName) {
+ 'apps/shipped' => 'shippedApp',
+ 'other/app.css' => 'otherApp',
+ default => false,
+ });
+
+ $hash = self::invokePrivate($layout, 'getVersionHashSuffix', [$path, $file]);
+ self::assertEquals($expected, $hash);
+ }
+
+ public static function dataVersionHash() {
+ return [
+ 'no hash if in debug mode' => ['apps/shipped', 'style.css', true, true, ''],
+ 'only version hash if not installed' => ['apps/shipped', 'style.css', false, false, '?v=version_hash'],
+ 'version hash with cache buster if app not found' => ['unknown/path', '', true, false, '?v=version_hash-42'],
+ 'version hash with cache buster if neither path nor file provided' => [false, false, true, false, '?v=version_hash-42'],
+ 'app version hash if external app' => ['', 'other/app.css', true, false, '?v=' . substr(md5('other_2'), 0, 8) . '-42'],
+ 'app version and version hash if shipped app' => ['apps/shipped', 'style.css', true, false, '?v=' . substr(md5('shipped_1-version_hash'), 0, 8) . '-42'],
+ 'prefer path over file' => ['apps/shipped', 'other/app.css', true, false, '?v=' . substr(md5('shipped_1-version_hash'), 0, 8) . '-42'],
+ ];
+ }
+
+}
diff --git a/tests/lib/User/ManagerTest.php b/tests/lib/User/ManagerTest.php
index 0adfa049e2c..53f57eee086 100644
--- a/tests/lib/User/ManagerTest.php
+++ b/tests/lib/User/ManagerTest.php
@@ -16,6 +16,7 @@ use OCP\ICache;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IUser;
+use OCP\IUserManager;
use Psr\Log\LoggerInterface;
use Test\TestCase;
@@ -579,7 +580,7 @@ class ManagerTest extends TestCase {
}
public function testCountUsersOnlyDisabled(): void {
- $manager = \OC::$server->getUserManager();
+ $manager = \OCP\Server::get(IUserManager::class);
// count other users in the db before adding our own
$countBefore = $manager->countDisabledUsers();
@@ -604,7 +605,7 @@ class ManagerTest extends TestCase {
}
public function testCountUsersOnlySeen(): void {
- $manager = \OC::$server->getUserManager();
+ $manager = \OCP\Server::get(IUserManager::class);
// count other users in the db before adding our own
$countBefore = $manager->countSeenUsers();
@@ -630,7 +631,7 @@ class ManagerTest extends TestCase {
}
public function testCallForSeenUsers(): void {
- $manager = \OC::$server->getUserManager();
+ $manager = \OCP\Server::get(IUserManager::class);
// count other users in the db before adding our own
$count = 0;
$function = function (IUser $user) use (&$count) {
@@ -663,6 +664,66 @@ class ManagerTest extends TestCase {
$user4->delete();
}
+ /**
+ * @runInSeparateProcess
+ * @preserveGlobalState disabled
+ */
+ public function testRecentlyActive(): void {
+ $config = \OCP\Server::get(IConfig::class);
+ $manager = \OCP\Server::get(IUserManager::class);
+
+ // Create some users
+ $now = (string)time();
+ $user1 = $manager->createUser('test_active_1', 'test_active_1');
+ $config->setUserValue('test_active_1', 'login', 'lastLogin', $now);
+ $user1->setDisplayName('test active 1');
+ $user1->setSystemEMailAddress('roger@active.com');
+
+ $user2 = $manager->createUser('TEST_ACTIVE_2_FRED', 'TEST_ACTIVE_2');
+ $config->setUserValue('TEST_ACTIVE_2_FRED', 'login', 'lastLogin', $now);
+ $user2->setDisplayName('TEST ACTIVE 2 UPPER');
+ $user2->setSystemEMailAddress('Fred@Active.Com');
+
+ $user3 = $manager->createUser('test_active_3', 'test_active_3');
+ $config->setUserValue('test_active_3', 'login', 'lastLogin', $now + 1);
+ $user3->setDisplayName('test active 3');
+
+ $user4 = $manager->createUser('test_active_4', 'test_active_4');
+ $config->setUserValue('test_active_4', 'login', 'lastLogin', $now);
+ $user4->setDisplayName('Test Active 4');
+
+ $user5 = $manager->createUser('test_inactive_1', 'test_inactive_1');
+ $user5->setDisplayName('Test Inactive 1');
+ $user2->setSystemEMailAddress('jeanne@Active.Com');
+
+ // Search recently active
+ // - No search, case-insensitive order
+ $users = $manager->getLastLoggedInUsers(4);
+ $this->assertEquals(['test_active_3', 'test_active_1', 'TEST_ACTIVE_2_FRED', 'test_active_4'], $users);
+ // - Search, case-insensitive order
+ $users = $manager->getLastLoggedInUsers(search: 'act');
+ $this->assertEquals(['test_active_3', 'test_active_1', 'TEST_ACTIVE_2_FRED', 'test_active_4'], $users);
+ // - No search with offset
+ $users = $manager->getLastLoggedInUsers(2, 2);
+ $this->assertEquals(['TEST_ACTIVE_2_FRED', 'test_active_4'], $users);
+ // - Case insensitive search (email)
+ $users = $manager->getLastLoggedInUsers(search: 'active.com');
+ $this->assertEquals(['test_active_1', 'TEST_ACTIVE_2_FRED'], $users);
+ // - Case insensitive search (display name)
+ $users = $manager->getLastLoggedInUsers(search: 'upper');
+ $this->assertEquals(['TEST_ACTIVE_2_FRED'], $users);
+ // - Case insensitive search (uid)
+ $users = $manager->getLastLoggedInUsers(search: 'fred');
+ $this->assertEquals(['TEST_ACTIVE_2_FRED'], $users);
+
+ // Delete users and config keys
+ $user1->delete();
+ $user2->delete();
+ $user3->delete();
+ $user4->delete();
+ $user5->delete();
+ }
+
public function testDeleteUser(): void {
$config = $this->getMockBuilder(AllConfig::class)
->disableOriginalConstructor()