diff options
Diffstat (limited to 'apps/files/tests')
22 files changed, 680 insertions, 7191 deletions
diff --git a/apps/files/tests/Activity/Filter/GenericTest.php b/apps/files/tests/Activity/Filter/GenericTest.php index f7c7cafaec4..40e2f9848b5 100644 --- a/apps/files/tests/Activity/Filter/GenericTest.php +++ b/apps/files/tests/Activity/Filter/GenericTest.php @@ -1,31 +1,16 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> - * - * @author Joas Schilling <coding@schilljs.com> - * @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 OCA\Files\Tests\Activity\Filter; use OCA\Files\Activity\Filter\Favorites; use OCA\Files\Activity\Filter\FileChanges; use OCP\Activity\IFilter; +use OCP\Server; use Test\TestCase; /** @@ -35,83 +20,62 @@ use Test\TestCase; * @group DB */ class GenericTest extends TestCase { - public function dataFilters() { + public static function dataFilters(): array { return [ [Favorites::class], [FileChanges::class], ]; } - /** - * @dataProvider dataFilters - * @param string $filterClass - */ - public function testImplementsInterface($filterClass) { - $filter = \OC::$server->query($filterClass); + #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')] + public function testImplementsInterface(string $filterClass): void { + $filter = Server::get($filterClass); $this->assertInstanceOf(IFilter::class, $filter); } - /** - * @dataProvider dataFilters - * @param string $filterClass - */ - public function testGetIdentifier($filterClass) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')] + public function testGetIdentifier(string $filterClass): void { /** @var IFilter $filter */ - $filter = \OC::$server->query($filterClass); + $filter = Server::get($filterClass); $this->assertIsString($filter->getIdentifier()); } - /** - * @dataProvider dataFilters - * @param string $filterClass - */ - public function testGetName($filterClass) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')] + public function testGetName(string $filterClass): void { /** @var IFilter $filter */ - $filter = \OC::$server->query($filterClass); + $filter = Server::get($filterClass); $this->assertIsString($filter->getName()); } - /** - * @dataProvider dataFilters - * @param string $filterClass - */ - public function testGetPriority($filterClass) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')] + public function testGetPriority(string $filterClass): void { /** @var IFilter $filter */ - $filter = \OC::$server->query($filterClass); + $filter = Server::get($filterClass); $priority = $filter->getPriority(); $this->assertIsInt($filter->getPriority()); $this->assertGreaterThanOrEqual(0, $priority); $this->assertLessThanOrEqual(100, $priority); } - /** - * @dataProvider dataFilters - * @param string $filterClass - */ - public function testGetIcon($filterClass) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')] + public function testGetIcon(string $filterClass): void { /** @var IFilter $filter */ - $filter = \OC::$server->query($filterClass); + $filter = Server::get($filterClass); $this->assertIsString($filter->getIcon()); $this->assertStringStartsWith('http', $filter->getIcon()); } - /** - * @dataProvider dataFilters - * @param string $filterClass - */ - public function testFilterTypes($filterClass) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')] + public function testFilterTypes(string $filterClass): void { /** @var IFilter $filter */ - $filter = \OC::$server->query($filterClass); + $filter = Server::get($filterClass); $this->assertIsArray($filter->filterTypes([])); } - /** - * @dataProvider dataFilters - * @param string $filterClass - */ - public function testAllowedApps($filterClass) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataFilters')] + public function testAllowedApps(string $filterClass): void { /** @var IFilter $filter */ - $filter = \OC::$server->query($filterClass); + $filter = Server::get($filterClass); $this->assertIsArray($filter->allowedApps()); } } diff --git a/apps/files/tests/Activity/ProviderTest.php b/apps/files/tests/Activity/ProviderTest.php index 3598c982ddd..b6ba095ecfe 100644 --- a/apps/files/tests/Activity/ProviderTest.php +++ b/apps/files/tests/Activity/ProviderTest.php @@ -1,29 +1,14 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com> - * - * @author Joas Schilling <coding@schilljs.com> - * @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: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCA\Files\Tests\Activity; use OCA\Files\Activity\Provider; +use OCP\Activity\Exceptions\UnknownActivityException; use OCP\Activity\IEvent; use OCP\Activity\IEventMerger; use OCP\Activity\IManager; @@ -43,23 +28,14 @@ use Test\TestCase; * @package OCA\Files\Tests\Activity */ class ProviderTest extends TestCase { - - /** @var IFactory|MockObject */ - protected $l10nFactory; - /** @var IURLGenerator|MockObject */ - protected $url; - /** @var IManager|MockObject */ - protected $activityManager; - /** @var IUserManager|MockObject */ - protected $userManager; - /** @var IRootFolder|MockObject */ - protected $rootFolder; - /** @var ICloudIdManager|MockObject */ - protected $cloudIdManager; - /** @var IContactsManager|MockObject */ - protected $contactsManager; - /** @var IEventMerger|MockObject */ - protected $eventMerger; + protected IFactory&MockObject $l10nFactory; + protected IURLGenerator&MockObject $url; + protected IManager&MockObject $activityManager; + protected IUserManager&MockObject $userManager; + protected IRootFolder&MockObject $rootFolder; + protected ICloudIdManager&MockObject $cloudIdManager; + protected IContactsManager&MockObject $contactsManager; + protected IEventMerger&MockObject $eventMerger; protected function setUp(): void { parent::setUp(); @@ -91,7 +67,7 @@ class ProviderTest extends TestCase { $this->contactsManager, $this->eventMerger, ]) - ->setMethods($methods) + ->onlyMethods($methods) ->getMock(); } return new Provider( @@ -106,23 +82,16 @@ class ProviderTest extends TestCase { ); } - public function dataGetFile() { + public static function dataGetFile(): array { return [ [[42 => '/FortyTwo.txt'], null, '42', 'FortyTwo.txt', 'FortyTwo.txt'], [['23' => '/Twenty/Three.txt'], null, '23', 'Three.txt', 'Twenty/Three.txt'], - ['/Foo/Bar.txt', 128, 128, 'Bar.txt', 'Foo/Bar.txt'], // Legacy from ownCloud 8.2 and before + ['/Foo/Bar.txt', 128, '128', 'Bar.txt', 'Foo/Bar.txt'], // Legacy from ownCloud 8.2 and before ]; } - /** - * @dataProvider dataGetFile - * @param mixed $parameter - * @param mixed $eventId - * @param int $id - * @param string $name - * @param string $path - */ - public function testGetFile($parameter, $eventId, $id, $name, $path) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetFile')] + public function testGetFile(array|string $parameter, ?int $eventId, string $id, string $name, string $path): void { $provider = $this->getProvider(); if ($eventId !== null) { @@ -149,14 +118,14 @@ class ProviderTest extends TestCase { } - public function testGetFileThrows() { - $this->expectException(\InvalidArgumentException::class); + public function testGetFileThrows(): void { + $this->expectException(UnknownActivityException::class); $provider = $this->getProvider(); self::invokePrivate($provider, 'getFile', ['/Foo/Bar.txt', null]); } - public function dataGetUser() { + public static function dataGetUser(): array { return [ ['test', 'Test user', null, ['type' => 'user', 'id' => 'test', 'name' => 'Test user']], ['test@http://localhost', null, ['user' => 'test', 'displayId' => 'test@localhost', 'remote' => 'localhost', 'name' => null], ['type' => 'user', 'id' => 'test', 'name' => 'test@localhost', 'server' => 'localhost']], @@ -165,13 +134,7 @@ class ProviderTest extends TestCase { ]; } - /** - * @dataProvider dataGetUser - * @param string $uid - * @param string|null $userDisplayName - * @param array|null $cloudIdData - * @param array $expected - */ + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetUser')] public function testGetUser(string $uid, ?string $userDisplayName, ?array $cloudIdData, array $expected): void { $provider = $this->getProvider(); diff --git a/apps/files/tests/Activity/Setting/GenericTest.php b/apps/files/tests/Activity/Setting/GenericTest.php index b0d42aa27ac..df6b1e0f6d4 100644 --- a/apps/files/tests/Activity/Setting/GenericTest.php +++ b/apps/files/tests/Activity/Setting/GenericTest.php @@ -1,36 +1,20 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> - * - * @author Joas Schilling <coding@schilljs.com> - * @author Robin Appelman <robin@icewind.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 OCA\Files\Tests\Activity\Setting; use OCA\Files\Activity\Settings\FavoriteAction; use OCA\Files\Activity\Settings\FileChanged; use OCP\Activity\ISetting; +use OCP\Server; use Test\TestCase; class GenericTest extends TestCase { - public function dataSettings() { + public static function dataSettings(): array { return [ [FavoriteAction::class], [FileChanged::class], @@ -38,85 +22,61 @@ class GenericTest extends TestCase { ]; } - /** - * @dataProvider dataSettings - * @param string $settingClass - */ - public function testImplementsInterface($settingClass) { - $setting = \OC::$server->query($settingClass); + #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')] + public function testImplementsInterface(string $settingClass): void { + $setting = Server::get($settingClass); $this->assertInstanceOf(ISetting::class, $setting); } - /** - * @dataProvider dataSettings - * @param string $settingClass - */ - public function testGetIdentifier($settingClass) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')] + public function testGetIdentifier(string $settingClass): void { /** @var ISetting $setting */ - $setting = \OC::$server->query($settingClass); + $setting = Server::get($settingClass); $this->assertIsString($setting->getIdentifier()); } - /** - * @dataProvider dataSettings - * @param string $settingClass - */ - public function testGetName($settingClass) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')] + public function testGetName(string $settingClass): void { /** @var ISetting $setting */ - $setting = \OC::$server->query($settingClass); + $setting = Server::get($settingClass); $this->assertIsString($setting->getName()); } - /** - * @dataProvider dataSettings - * @param string $settingClass - */ - public function testGetPriority($settingClass) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')] + public function testGetPriority(string $settingClass): void { /** @var ISetting $setting */ - $setting = \OC::$server->query($settingClass); + $setting = Server::get($settingClass); $priority = $setting->getPriority(); $this->assertIsInt($setting->getPriority()); $this->assertGreaterThanOrEqual(0, $priority); $this->assertLessThanOrEqual(100, $priority); } - /** - * @dataProvider dataSettings - * @param string $settingClass - */ - public function testCanChangeStream($settingClass) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')] + public function testCanChangeStream(string $settingClass): void { /** @var ISetting $setting */ - $setting = \OC::$server->query($settingClass); + $setting = Server::get($settingClass); $this->assertIsBool($setting->canChangeStream()); } - /** - * @dataProvider dataSettings - * @param string $settingClass - */ - public function testIsDefaultEnabledStream($settingClass) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')] + public function testIsDefaultEnabledStream(string $settingClass): void { /** @var ISetting $setting */ - $setting = \OC::$server->query($settingClass); + $setting = Server::get($settingClass); $this->assertIsBool($setting->isDefaultEnabledStream()); } - /** - * @dataProvider dataSettings - * @param string $settingClass - */ - public function testCanChangeMail($settingClass) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')] + public function testCanChangeMail(string $settingClass): void { /** @var ISetting $setting */ - $setting = \OC::$server->query($settingClass); + $setting = Server::get($settingClass); $this->assertIsBool($setting->canChangeMail()); } - /** - * @dataProvider dataSettings - * @param string $settingClass - */ - public function testIsDefaultEnabledMail($settingClass) { + #[\PHPUnit\Framework\Attributes\DataProvider('dataSettings')] + public function testIsDefaultEnabledMail(string $settingClass): void { /** @var ISetting $setting */ - $setting = \OC::$server->query($settingClass); + $setting = Server::get($settingClass); $this->assertIsBool($setting->isDefaultEnabledMail()); } } diff --git a/apps/files/tests/AdvancedCapabilitiesTest.php b/apps/files/tests/AdvancedCapabilitiesTest.php new file mode 100644 index 00000000000..f39ac1c873f --- /dev/null +++ b/apps/files/tests/AdvancedCapabilitiesTest.php @@ -0,0 +1,46 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\Files; + +use OCA\Files\Service\SettingsService; +use PHPUnit\Framework\MockObject\MockObject; +use Test\TestCase; + +class AdvancedCapabilitiesTest extends TestCase { + + protected SettingsService&MockObject $service; + protected AdvancedCapabilities $capabilities; + + protected function setUp(): void { + parent::setUp(); + $this->service = $this->createMock(SettingsService::class); + $this->capabilities = new AdvancedCapabilities($this->service); + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataGetCapabilities')] + public function testGetCapabilities(bool $wcf): void { + $this->service + ->expects(self::once()) + ->method('hasFilesWindowsSupport') + ->willReturn($wcf); + + self::assertEqualsCanonicalizing(['files' => [ 'windows_compatible_filenames' => $wcf ]], $this->capabilities->getCapabilities()); + } + + public static function dataGetCapabilities(): array { + return [ + 'WCF enabled' => [ + true, + ], + 'WCF disabled' => [ + false, + ], + ]; + } +} diff --git a/apps/files/tests/BackgroundJob/DeleteOrphanedItemsJobTest.php b/apps/files/tests/BackgroundJob/DeleteOrphanedItemsJobTest.php index fcc665a80ca..3f811fca407 100644 --- a/apps/files/tests/BackgroundJob/DeleteOrphanedItemsJobTest.php +++ b/apps/files/tests/BackgroundJob/DeleteOrphanedItemsJobTest.php @@ -1,25 +1,10 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @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: 2019-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ namespace OCA\Files\Tests\BackgroundJob; @@ -27,6 +12,7 @@ use OCA\Files\BackgroundJob\DeleteOrphanedItems; use OCP\AppFramework\Utility\ITimeFactory; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; +use OCP\Server; use Psr\Log\LoggerInterface; /** @@ -43,21 +29,21 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { protected function setUp(): void { parent::setUp(); - $this->connection = \OC::$server->get(IDBConnection::class); + $this->connection = Server::get(IDBConnection::class); $this->timeFactory = $this->createMock(ITimeFactory::class); - $this->logger = \OC::$server->get(LoggerInterface::class); + $this->logger = Server::get(LoggerInterface::class); } - protected function cleanMapping($table) { + protected function cleanMapping(string $table): void { $query = $this->connection->getQueryBuilder(); - $query->delete($table)->execute(); + $query->delete($table)->executeStatement(); } - protected function getMappings($table) { + protected function getMappings(string $table): array { $query = $this->connection->getQueryBuilder(); $query->select('*') ->from($table); - $result = $query->execute(); + $result = $query->executeQuery(); $mapping = $result->fetchAll(); $result->closeCursor(); @@ -67,7 +53,7 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { /** * Test clearing orphaned system tag mappings */ - public function testClearSystemTagMappings() { + public function testClearSystemTagMappings(): void { $this->cleanMapping('systemtag_object_mapping'); $query = $this->connection->getQueryBuilder(); @@ -76,7 +62,7 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { 'storage' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT), 'path' => $query->createNamedParameter('apps/files/tests/deleteorphanedtagsjobtest.php'), 'path_hash' => $query->createNamedParameter(md5('apps/files/tests/deleteorphanedtagsjobtest.php')), - ])->execute(); + ])->executeStatement(); $fileId = $query->getLastInsertId(); // Existing file @@ -86,7 +72,7 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { 'objectid' => $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT), 'objecttype' => $query->createNamedParameter('files'), 'systemtagid' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT), - ])->execute(); + ])->executeStatement(); // Non-existing file $query = $this->connection->getQueryBuilder(); @@ -95,13 +81,13 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { 'objectid' => $query->createNamedParameter($fileId + 1, IQueryBuilder::PARAM_INT), 'objecttype' => $query->createNamedParameter('files'), 'systemtagid' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT), - ])->execute(); + ])->executeStatement(); $mapping = $this->getMappings('systemtag_object_mapping'); $this->assertCount(2, $mapping); $job = new DeleteOrphanedItems($this->timeFactory, $this->connection, $this->logger); - $this->invokePrivate($job, 'cleanSystemTags'); + self::invokePrivate($job, 'cleanSystemTags'); $mapping = $this->getMappings('systemtag_object_mapping'); $this->assertCount(1, $mapping); @@ -109,14 +95,14 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { $query = $this->connection->getQueryBuilder(); $query->delete('filecache') ->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))) - ->execute(); + ->executeStatement(); $this->cleanMapping('systemtag_object_mapping'); } /** * Test clearing orphaned system tag mappings */ - public function testClearUserTagMappings() { + public function testClearUserTagMappings(): void { $this->cleanMapping('vcategory_to_object'); $query = $this->connection->getQueryBuilder(); @@ -125,7 +111,7 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { 'storage' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT), 'path' => $query->createNamedParameter('apps/files/tests/deleteorphanedtagsjobtest.php'), 'path_hash' => $query->createNamedParameter(md5('apps/files/tests/deleteorphanedtagsjobtest.php')), - ])->execute(); + ])->executeStatement(); $fileId = $query->getLastInsertId(); // Existing file @@ -135,7 +121,7 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { 'objid' => $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT), 'type' => $query->createNamedParameter('files'), 'categoryid' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT), - ])->execute(); + ])->executeStatement(); // Non-existing file $query = $this->connection->getQueryBuilder(); @@ -144,13 +130,13 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { 'objid' => $query->createNamedParameter($fileId + 1, IQueryBuilder::PARAM_INT), 'type' => $query->createNamedParameter('files'), 'categoryid' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT), - ])->execute(); + ])->executeStatement(); $mapping = $this->getMappings('vcategory_to_object'); $this->assertCount(2, $mapping); $job = new DeleteOrphanedItems($this->timeFactory, $this->connection, $this->logger); - $this->invokePrivate($job, 'cleanUserTags'); + self::invokePrivate($job, 'cleanUserTags'); $mapping = $this->getMappings('vcategory_to_object'); $this->assertCount(1, $mapping); @@ -158,14 +144,14 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { $query = $this->connection->getQueryBuilder(); $query->delete('filecache') ->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))) - ->execute(); + ->executeStatement(); $this->cleanMapping('vcategory_to_object'); } /** * Test clearing orphaned system tag mappings */ - public function testClearComments() { + public function testClearComments(): void { $this->cleanMapping('comments'); $query = $this->connection->getQueryBuilder(); @@ -174,7 +160,7 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { 'storage' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT), 'path' => $query->createNamedParameter('apps/files/tests/deleteorphanedtagsjobtest.php'), 'path_hash' => $query->createNamedParameter(md5('apps/files/tests/deleteorphanedtagsjobtest.php')), - ])->execute(); + ])->executeStatement(); $fileId = $query->getLastInsertId(); // Existing file @@ -185,7 +171,7 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { 'object_type' => $query->createNamedParameter('files'), 'actor_id' => $query->createNamedParameter('Alice', IQueryBuilder::PARAM_INT), 'actor_type' => $query->createNamedParameter('users'), - ])->execute(); + ])->executeStatement(); // Non-existing file $query = $this->connection->getQueryBuilder(); @@ -195,13 +181,13 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { 'object_type' => $query->createNamedParameter('files'), 'actor_id' => $query->createNamedParameter('Alice', IQueryBuilder::PARAM_INT), 'actor_type' => $query->createNamedParameter('users'), - ])->execute(); + ])->executeStatement(); $mapping = $this->getMappings('comments'); $this->assertCount(2, $mapping); $job = new DeleteOrphanedItems($this->timeFactory, $this->connection, $this->logger); - $this->invokePrivate($job, 'cleanComments'); + self::invokePrivate($job, 'cleanComments'); $mapping = $this->getMappings('comments'); $this->assertCount(1, $mapping); @@ -209,14 +195,14 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { $query = $this->connection->getQueryBuilder(); $query->delete('filecache') ->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))) - ->execute(); + ->executeStatement(); $this->cleanMapping('comments'); } /** * Test clearing orphaned system tag mappings */ - public function testClearCommentReadMarks() { + public function testClearCommentReadMarks(): void { $this->cleanMapping('comments_read_markers'); $query = $this->connection->getQueryBuilder(); @@ -225,7 +211,7 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { 'storage' => $query->createNamedParameter(1337, IQueryBuilder::PARAM_INT), 'path' => $query->createNamedParameter('apps/files/tests/deleteorphanedtagsjobtest.php'), 'path_hash' => $query->createNamedParameter(md5('apps/files/tests/deleteorphanedtagsjobtest.php')), - ])->execute(); + ])->executeStatement(); $fileId = $query->getLastInsertId(); // Existing file @@ -235,7 +221,7 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { 'object_id' => $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT), 'object_type' => $query->createNamedParameter('files'), 'user_id' => $query->createNamedParameter('Alice', IQueryBuilder::PARAM_INT), - ])->execute(); + ])->executeStatement(); // Non-existing file $query = $this->connection->getQueryBuilder(); @@ -244,13 +230,13 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { 'object_id' => $query->createNamedParameter($fileId + 1, IQueryBuilder::PARAM_INT), 'object_type' => $query->createNamedParameter('files'), 'user_id' => $query->createNamedParameter('Alice', IQueryBuilder::PARAM_INT), - ])->execute(); + ])->executeStatement(); $mapping = $this->getMappings('comments_read_markers'); $this->assertCount(2, $mapping); $job = new DeleteOrphanedItems($this->timeFactory, $this->connection, $this->logger); - $this->invokePrivate($job, 'cleanCommentMarkers'); + self::invokePrivate($job, 'cleanCommentMarkers'); $mapping = $this->getMappings('comments_read_markers'); $this->assertCount(1, $mapping); @@ -258,7 +244,7 @@ class DeleteOrphanedItemsJobTest extends \Test\TestCase { $query = $this->connection->getQueryBuilder(); $query->delete('filecache') ->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))) - ->execute(); + ->executeStatement(); $this->cleanMapping('comments_read_markers'); } } diff --git a/apps/files/tests/BackgroundJob/ScanFilesTest.php b/apps/files/tests/BackgroundJob/ScanFilesTest.php index cf0120da09d..00d9ed823f9 100644 --- a/apps/files/tests/BackgroundJob/ScanFilesTest.php +++ b/apps/files/tests/BackgroundJob/ScanFilesTest.php @@ -1,25 +1,10 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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 OCA\Files\Tests\BackgroundJob; @@ -28,8 +13,11 @@ use OC\Files\Storage\Temporary; use OCA\Files\BackgroundJob\ScanFiles; use OCP\AppFramework\Utility\ITimeFactory; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Config\IUserMountCache; use OCP\IConfig; +use OCP\IDBConnection; use OCP\IUser; +use OCP\Server; use Psr\Log\LoggerInterface; use Test\TestCase; use Test\Traits\MountProviderTrait; @@ -45,10 +33,8 @@ class ScanFilesTest extends TestCase { use UserTrait; use MountProviderTrait; - /** @var ScanFiles */ - private $scanFiles; - /** @var \OCP\Files\Config\IUserMountCache */ - private $mountCache; + private ScanFiles $scanFiles; + private IUserMountCache $mountCache; protected function setUp(): void { parent::setUp(); @@ -56,10 +42,10 @@ class ScanFilesTest extends TestCase { $config = $this->createMock(IConfig::class); $dispatcher = $this->createMock(IEventDispatcher::class); $logger = $this->createMock(LoggerInterface::class); - $connection = \OC::$server->getDatabaseConnection(); - $this->mountCache = \OC::$server->getUserMountCache(); + $connection = Server::get(IDBConnection::class); + $this->mountCache = Server::get(IUserMountCache::class); - $this->scanFiles = $this->getMockBuilder('\OCA\Files\BackgroundJob\ScanFiles') + $this->scanFiles = $this->getMockBuilder(ScanFiles::class) ->setConstructorArgs([ $config, $dispatcher, @@ -67,12 +53,12 @@ class ScanFilesTest extends TestCase { $connection, $this->createMock(ITimeFactory::class) ]) - ->setMethods(['runScanner']) + ->onlyMethods(['runScanner']) ->getMock(); } - private function runJob() { - $this->invokePrivate($this->scanFiles, 'run', [[]]); + private function runJob(): void { + self::invokePrivate($this->scanFiles, 'run', [[]]); } private function getUser(string $userId): IUser { @@ -95,7 +81,7 @@ class ScanFilesTest extends TestCase { return $storage; } - public function testAllScanned() { + public function testAllScanned(): void { $this->setupStorage('foouser', '/foousers/files/foo'); $this->scanFiles->expects($this->never()) @@ -103,7 +89,7 @@ class ScanFilesTest extends TestCase { $this->runJob(); } - public function testUnscanned() { + public function testUnscanned(): void { $storage = $this->setupStorage('foouser', '/foousers/files/foo'); $storage->getCache()->put('foo', ['size' => -1]); diff --git a/apps/files/tests/Command/DeleteOrphanedFilesTest.php b/apps/files/tests/Command/DeleteOrphanedFilesTest.php index ee1144963ac..a488915e0cb 100644 --- a/apps/files/tests/Command/DeleteOrphanedFilesTest.php +++ b/apps/files/tests/Command/DeleteOrphanedFilesTest.php @@ -1,34 +1,20 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Julius Härtl <jus@bitgrid.net> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @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 OCA\Files\Tests\Command; use OC\Files\View; use OCA\Files\Command\DeleteOrphanedFiles; +use OCP\Files\IRootFolder; use OCP\Files\StorageNotAvailableException; +use OCP\IDBConnection; +use OCP\IUserManager; +use OCP\Server; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Test\TestCase; @@ -42,36 +28,25 @@ use Test\TestCase; */ class DeleteOrphanedFilesTest extends TestCase { - /** - * @var DeleteOrphanedFiles - */ - private $command; - - /** - * @var \OCP\IDBConnection - */ - private $connection; - - /** - * @var string - */ - private $user1; + private DeleteOrphanedFiles $command; + private IDBConnection $connection; + private string $user1; protected function setUp(): void { parent::setUp(); - $this->connection = \OC::$server->getDatabaseConnection(); + $this->connection = Server::get(IDBConnection::class); $this->user1 = $this->getUniqueID('user1_'); - $userManager = \OC::$server->getUserManager(); + $userManager = Server::get(IUserManager::class); $userManager->createUser($this->user1, 'pass'); $this->command = new DeleteOrphanedFiles($this->connection); } protected function tearDown(): void { - $userManager = \OC::$server->getUserManager(); + $userManager = Server::get(IUserManager::class); $user1 = $userManager->get($this->user1); if ($user1) { $user1->delete(); @@ -82,33 +57,36 @@ class DeleteOrphanedFilesTest extends TestCase { parent::tearDown(); } - protected function getFile($fileId) { - $stmt = $this->connection->executeQuery('SELECT * FROM `*PREFIX*filecache` WHERE `fileid` = ?', [$fileId]); - return $stmt->fetchAll(); + protected function getFile(int $fileId): array { + $query = $this->connection->getQueryBuilder(); + $query->select('*') + ->from('filecache') + ->where($query->expr()->eq('fileid', $query->createNamedParameter($fileId))); + return $query->executeQuery()->fetchAll(); } - protected function getMounts($storageId) { - $stmt = $this->connection->executeQuery('SELECT * FROM `*PREFIX*mounts` WHERE `storage_id` = ?', [$storageId]); - return $stmt->fetchAll(); + protected function getMounts(int $storageId): array { + $query = $this->connection->getQueryBuilder(); + $query->select('*') + ->from('mounts') + ->where($query->expr()->eq('storage_id', $query->createNamedParameter($storageId))); + return $query->executeQuery()->fetchAll(); } /** * Test clearing orphaned files */ - public function testClearFiles() { - $input = $this->getMockBuilder(InputInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $output = $this->getMockBuilder(OutputInterface::class) - ->disableOriginalConstructor() - ->getMock(); + public function testClearFiles(): void { + $input = $this->createMock(InputInterface::class); + $output = $this->createMock(OutputInterface::class); + + $rootFolder = Server::get(IRootFolder::class); // scan home storage so that mounts are properly setup - \OC::$server->getRootFolder()->getUserFolder($this->user1)->getStorage()->getScanner()->scan(''); + $rootFolder->getUserFolder($this->user1)->getStorage()->getScanner()->scan(''); $this->loginAsUser($this->user1); - $view = new View('/' . $this->user1 . '/'); $view->mkdir('files/test'); @@ -131,20 +109,26 @@ class DeleteOrphanedFilesTest extends TestCase { $this->assertSame(1, $deletedRows, 'Asserts that storage got deleted'); // parent folder, `files`, ´test` and `welcome.txt` => 4 elements + $calls = [ + '3 orphaned file cache entries deleted', + '0 orphaned file cache extended entries deleted', + '1 orphaned mount entries deleted', + ]; $output ->expects($this->exactly(3)) ->method('writeln') - ->withConsecutive( - ['3 orphaned file cache entries deleted'], - ['0 orphaned file cache extended entries deleted'], - ['1 orphaned mount entries deleted'], - ); + ->willReturnCallback(function (string $message) use (&$calls): void { + $expected = array_shift($calls); + $this->assertSame($expected, $message); + }); $this->command->execute($input, $output); $this->assertCount(0, $this->getFile($fileInfo->getId()), 'Asserts that file gets cleaned up'); $this->assertCount(0, $this->getMounts($numericStorageId), 'Asserts that mount gets cleaned up'); + // Rescan folder to add back to cache before deleting + $rootFolder->getUserFolder($this->user1)->getStorage()->getScanner()->scan(''); // since we deleted the storage it might throw a (valid) StorageNotAvailableException try { $view->unlink('files/test'); diff --git a/apps/files/tests/Controller/ApiControllerTest.php b/apps/files/tests/Controller/ApiControllerTest.php index 269977350f7..e74989eb2f5 100644 --- a/apps/files/tests/Controller/ApiControllerTest.php +++ b/apps/files/tests/Controller/ApiControllerTest.php @@ -1,29 +1,10 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Nina Pypchenko <22447785+nina-py@users.noreply.github.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @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 OCA\Files\Controller; @@ -32,17 +13,26 @@ use OCA\Files\Service\UserConfig; use OCA\Files\Service\ViewConfig; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\FileDisplayResponse; +use OCP\AppFramework\Http\Response; use OCP\Files\File; 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\Files\StorageNotAvailableException; use OCP\IConfig; +use OCP\IL10N; use OCP\IPreview; use OCP\IRequest; use OCP\IUser; use OCP\IUserSession; use OCP\Share\IManager; +use OCP\Share\IShare; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use Test\TestCase; /** @@ -51,35 +41,25 @@ use Test\TestCase; * @package OCA\Files\Controller */ class ApiControllerTest extends TestCase { - /** @var string */ - private $appName = 'files'; - /** @var \OCP\IUser */ - private $user; - /** @var IRequest */ - private $request; - /** @var TagService */ - private $tagService; - /** @var IPreview|\PHPUnit\Framework\MockObject\MockObject */ - private $preview; - /** @var ApiController */ - private $apiController; - /** @var \OCP\Share\IManager */ - private $shareManager; - /** @var \OCP\IConfig */ - private $config; - /** @var Folder|\PHPUnit\Framework\MockObject\MockObject */ - private $userFolder; - /** @var UserConfig|\PHPUnit\Framework\MockObject\MockObject */ - private $userConfig; - /** @var ViewConfig|\PHPUnit\Framework\MockObject\MockObject */ - private $viewConfig; + private string $appName = 'files'; + private IUser $user; + private IRequest $request; + private TagService $tagService; + private IPreview&MockObject $preview; + private ApiController $apiController; + private IManager $shareManager; + private IConfig $config; + private Folder&MockObject $userFolder; + private UserConfig&MockObject $userConfig; + private ViewConfig&MockObject $viewConfig; + private IL10N&MockObject $l10n; + private IRootFolder&MockObject $rootFolder; + private LoggerInterface&MockObject $logger; protected function setUp(): void { parent::setUp(); - $this->request = $this->getMockBuilder(IRequest::class) - ->disableOriginalConstructor() - ->getMock(); + $this->request = $this->createMock(IRequest::class); $this->user = $this->createMock(IUser::class); $this->user->expects($this->any()) ->method('getUID') @@ -88,21 +68,16 @@ class ApiControllerTest extends TestCase { $userSession->expects($this->any()) ->method('getUser') ->willReturn($this->user); - $this->tagService = $this->getMockBuilder(TagService::class) - ->disableOriginalConstructor() - ->getMock(); - $this->shareManager = $this->getMockBuilder(IManager::class) - ->disableOriginalConstructor() - ->getMock(); - $this->preview = $this->getMockBuilder(IPreview::class) - ->disableOriginalConstructor() - ->getMock(); + $this->tagService = $this->createMock(TagService::class); + $this->shareManager = $this->createMock(IManager::class); + $this->preview = $this->createMock(IPreview::class); $this->config = $this->createMock(IConfig::class); - $this->userFolder = $this->getMockBuilder(Folder::class) - ->disableOriginalConstructor() - ->getMock(); + $this->userFolder = $this->createMock(Folder::class); $this->userConfig = $this->createMock(UserConfig::class); $this->viewConfig = $this->createMock(ViewConfig::class); + $this->l10n = $this->createMock(IL10N::class); + $this->rootFolder = $this->createMock(IRootFolder::class); + $this->logger = $this->createMock(LoggerInterface::class); $this->apiController = new ApiController( $this->appName, @@ -114,16 +89,19 @@ class ApiControllerTest extends TestCase { $this->config, $this->userFolder, $this->userConfig, - $this->viewConfig + $this->viewConfig, + $this->l10n, + $this->rootFolder, + $this->logger, ); } - public function testUpdateFileTagsEmpty() { + public function testUpdateFileTagsEmpty(): void { $expected = new DataResponse([]); $this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt')); } - public function testUpdateFileTagsWorking() { + public function testUpdateFileTagsWorking(): void { $this->tagService->expects($this->once()) ->method('updateFileTags') ->with('/path.txt', ['Tag1', 'Tag2']); @@ -137,37 +115,37 @@ class ApiControllerTest extends TestCase { $this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt', ['Tag1', 'Tag2'])); } - public function testUpdateFileTagsNotFoundException() { + public function testUpdateFileTagsNotFoundException(): void { $this->tagService->expects($this->once()) ->method('updateFileTags') ->with('/path.txt', ['Tag1', 'Tag2']) - ->will($this->throwException(new NotFoundException('My error message'))); + ->willThrowException(new NotFoundException('My error message')); $expected = new DataResponse(['message' => 'My error message'], Http::STATUS_NOT_FOUND); $this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt', ['Tag1', 'Tag2'])); } - public function testUpdateFileTagsStorageNotAvailableException() { + public function testUpdateFileTagsStorageNotAvailableException(): void { $this->tagService->expects($this->once()) ->method('updateFileTags') ->with('/path.txt', ['Tag1', 'Tag2']) - ->will($this->throwException(new StorageNotAvailableException('My error message'))); + ->willThrowException(new StorageNotAvailableException('My error message')); $expected = new DataResponse(['message' => 'My error message'], Http::STATUS_SERVICE_UNAVAILABLE); $this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt', ['Tag1', 'Tag2'])); } - public function testUpdateFileTagsStorageGenericException() { + public function testUpdateFileTagsStorageGenericException(): void { $this->tagService->expects($this->once()) ->method('updateFileTags') ->with('/path.txt', ['Tag1', 'Tag2']) - ->will($this->throwException(new \Exception('My error message'))); + ->willThrowException(new \Exception('My error message')); $expected = new DataResponse(['message' => 'My error message'], Http::STATUS_NOT_FOUND); $this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt', ['Tag1', 'Tag2'])); } - public function testGetThumbnailInvalidSize() { + public function testGetThumbnailInvalidSize(): void { $this->userFolder->method('get') ->with($this->equalTo('')) ->willThrowException(new NotFoundException()); @@ -175,8 +153,13 @@ class ApiControllerTest extends TestCase { $this->assertEquals($expected, $this->apiController->getThumbnail(0, 0, '')); } - public function testGetThumbnailInvalidImage() { + public function testGetThumbnailInvalidImage(): void { + $storage = $this->createMock(IStorage::class); + $storage->method('instanceOfStorage')->with(ISharedStorage::class)->willReturn(false); + $file = $this->createMock(File::class); + $file->method('getId')->willReturn(123); + $file->method('getStorage')->willReturn($storage); $this->userFolder->method('get') ->with($this->equalTo('unknown.jpg')) ->willReturn($file); @@ -188,8 +171,90 @@ class ApiControllerTest extends TestCase { $this->assertEquals($expected, $this->apiController->getThumbnail(10, 10, 'unknown.jpg')); } - public function testGetThumbnail() { + public function testGetThumbnailInvalidPartFile(): void { + $file = $this->createMock(File::class); + $file->method('getId')->willReturn(0); + $this->userFolder->method('get') + ->with($this->equalTo('unknown.jpg')) + ->willReturn($file); + $expected = new DataResponse(['message' => 'File not found.'], Http::STATUS_NOT_FOUND); + $this->assertEquals($expected, $this->apiController->getThumbnail(10, 10, 'unknown.jpg')); + } + + public function testGetThumbnailSharedNoDownload(): void { + $share = $this->createMock(IShare::class); + $share->expects(self::once()) + ->method('canSeeContent') + ->willReturn(false); + + $storage = $this->createMock(ISharedStorage::class); + $storage->expects(self::once()) + ->method('instanceOfStorage') + ->with(ISharedStorage::class) + ->willReturn(true); + $storage->expects(self::once()) + ->method('getShare') + ->willReturn($share); + + $file = $this->createMock(File::class); + $file->method('getId')->willReturn(123); + $file->method('getStorage')->willReturn($storage); + + $this->userFolder->method('get') + ->with('unknown.jpg') + ->willReturn($file); + + $this->preview->expects($this->never()) + ->method('getPreview'); + + $expected = new DataResponse(['message' => 'File not found.'], Http::STATUS_NOT_FOUND); + $this->assertEquals($expected, $this->apiController->getThumbnail(10, 10, 'unknown.jpg')); + } + + public function testGetThumbnailShared(): void { + $share = $this->createMock(IShare::class); + $share->expects(self::once()) + ->method('canSeeContent') + ->willReturn(true); + + $storage = $this->createMock(ISharedStorage::class); + $storage->expects(self::once()) + ->method('instanceOfStorage') + ->with(ISharedStorage::class) + ->willReturn(true); + $storage->expects(self::once()) + ->method('getShare') + ->willReturn($share); + $file = $this->createMock(File::class); + $file->method('getId')->willReturn(123); + $file->method('getStorage')->willReturn($storage); + + $this->userFolder->method('get') + ->with($this->equalTo('known.jpg')) + ->willReturn($file); + $preview = $this->createMock(ISimpleFile::class); + $preview->method('getName')->willReturn('my name'); + $preview->method('getMTime')->willReturn(42); + $this->preview->expects($this->once()) + ->method('getPreview') + ->with($this->equalTo($file), 10, 10, true) + ->willReturn($preview); + + $ret = $this->apiController->getThumbnail(10, 10, 'known.jpg'); + + $this->assertEquals(Http::STATUS_OK, $ret->getStatus()); + $this->assertInstanceOf(FileDisplayResponse::class, $ret); + } + + public function testGetThumbnail(): void { + $storage = $this->createMock(IStorage::class); + $storage->method('instanceOfStorage')->with(ISharedStorage::class)->willReturn(false); + + $file = $this->createMock(File::class); + $file->method('getId')->willReturn(123); + $file->method('getStorage')->willReturn($storage); + $this->userFolder->method('get') ->with($this->equalTo('known.jpg')) ->willReturn($file); @@ -204,30 +269,30 @@ class ApiControllerTest extends TestCase { $ret = $this->apiController->getThumbnail(10, 10, 'known.jpg'); $this->assertEquals(Http::STATUS_OK, $ret->getStatus()); - $this->assertInstanceOf(Http\FileDisplayResponse::class, $ret); + $this->assertInstanceOf(FileDisplayResponse::class, $ret); } - public function testShowHiddenFiles() { + public function testShowHiddenFiles(): void { $show = false; $this->config->expects($this->once()) ->method('setUserValue') ->with($this->user->getUID(), 'files', 'show_hidden', '0'); - $expected = new Http\Response(); + $expected = new Response(); $actual = $this->apiController->showHiddenFiles($show); $this->assertEquals($expected, $actual); } - public function testCropImagePreviews() { + public function testCropImagePreviews(): void { $crop = true; $this->config->expects($this->once()) ->method('setUserValue') ->with($this->user->getUID(), 'files', 'crop_image_previews', '1'); - $expected = new Http\Response(); + $expected = new Response(); $actual = $this->apiController->cropImagePreviews($crop); $this->assertEquals($expected, $actual); diff --git a/apps/files/tests/Controller/ConversionApiControllerTest.php b/apps/files/tests/Controller/ConversionApiControllerTest.php new file mode 100644 index 00000000000..659fbe1a956 --- /dev/null +++ b/apps/files/tests/Controller/ConversionApiControllerTest.php @@ -0,0 +1,96 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCA\Files\Controller; + +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCS\OCSException; +use OCP\AppFramework\OCS\OCSNotFoundException; +use OCP\Files\Conversion\IConversionManager; +use OCP\Files\File; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\IL10N; +use OCP\IRequest; +use PHPUnit\Framework\MockObject\MockObject; +use Test\TestCase; + +/** + * Class ConversionApiController + * + * @package OCA\Files\Controller + */ +class ConversionApiControllerTest extends TestCase { + private string $appName = 'files'; + private ConversionApiController $conversionApiController; + private IRequest&MockObject $request; + private IConversionManager&MockObject $fileConversionManager; + private IRootFolder&MockObject $rootFolder; + private File&MockObject $file; + private Folder&MockObject $userFolder; + private IL10N&MockObject $l10n; + private string $user; + + protected function setUp(): void { + parent::setUp(); + + $this->request = $this->createMock(IRequest::class); + $this->fileConversionManager = $this->createMock(IConversionManager::class); + $this->file = $this->createMock(File::class); + $this->l10n = $this->createMock(IL10N::class); + $this->user = 'userid'; + + $this->userFolder = $this->createMock(Folder::class); + + $this->rootFolder = $this->createMock(IRootFolder::class); + $this->rootFolder->method('getUserFolder')->with($this->user)->willReturn($this->userFolder); + + $this->conversionApiController = new ConversionApiController( + $this->appName, + $this->request, + $this->fileConversionManager, + $this->rootFolder, + $this->l10n, + $this->user, + ); + } + + public function testThrowsNotFoundException(): void { + $this->expectException(OCSNotFoundException::class); + $this->conversionApiController->convert(42, 'image/png'); + } + + public function testThrowsOcsException(): void { + $this->userFolder->method('getFirstNodeById')->with(42)->willReturn($this->file); + $this->fileConversionManager->method('convert')->willThrowException(new \Exception()); + + $this->expectException(OCSException::class); + $this->conversionApiController->convert(42, 'image/png'); + } + + public function testConvert(): void { + $convertedFileAbsolutePath = $this->user . '/files/test.png'; + + $this->userFolder->method('getFirstNodeById')->with(42)->willReturn($this->file); + $this->userFolder->method('getRelativePath')->with($convertedFileAbsolutePath)->willReturn('/test.png'); + $this->userFolder->method('get')->with('/test.png')->willReturn($this->file); + + $this->file->method('getId')->willReturn(42); + + $this->fileConversionManager->method('convert')->with($this->file, 'image/png', null)->willReturn($convertedFileAbsolutePath); + + $actual = $this->conversionApiController->convert(42, 'image/png', null); + $expected = new DataResponse([ + 'path' => '/test.png', + 'fileId' => 42, + ], Http::STATUS_CREATED); + + $this->assertEquals($expected, $actual); + } +} diff --git a/apps/files/tests/Controller/ViewControllerTest.php b/apps/files/tests/Controller/ViewControllerTest.php index 2714a6b25c0..01aa955a13e 100644 --- a/apps/files/tests/Controller/ViewControllerTest.php +++ b/apps/files/tests/Controller/ViewControllerTest.php @@ -1,106 +1,88 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Kesselberg <mail@danielkesselberg.de> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Julius Härtl <jus@bitgrid.net> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Michael Weimann <mail@michael-weimann.eu> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Nina Pypchenko <22447785+nina-py@users.noreply.github.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @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 OCA\Files\Tests\Controller; -use OCA\Files\Activity\Helper; +use OC\Files\FilenameValidator; +use OC\Route\Router; +use OC\URLGenerator; use OCA\Files\Controller\ViewController; use OCA\Files\Service\UserConfig; use OCA\Files\Service\ViewConfig; use OCP\App\IAppManager; -use OCP\AppFramework\Http; +use OCP\AppFramework\Http\ContentSecurityPolicy; +use OCP\AppFramework\Http\RedirectResponse; +use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; +use OCP\Authentication\TwoFactorAuth\IRegistry; +use OCP\Diagnostics\IEventLogger; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\File; use OCP\Files\Folder; use OCP\Files\IRootFolder; use OCP\Files\Template\ITemplateManager; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUser; use OCP\IUserSession; -use OCP\Share\IManager; +use PHPUnit\Framework\MockObject\MockObject; +use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; use Test\TestCase; /** * Class ViewControllerTest * + * @group RoutingWeirdness + * * @package OCA\Files\Tests\Controller */ class ViewControllerTest extends TestCase { - /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */ - private $request; - /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */ - private $urlGenerator; - /** @var IL10N */ - private $l10n; - /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ - private $config; - /** @var IEventDispatcher */ - private $eventDispatcher; - /** @var ViewController|\PHPUnit\Framework\MockObject\MockObject */ - private $viewController; - /** @var IUser|\PHPUnit\Framework\MockObject\MockObject */ - private $user; - /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */ - private $userSession; - /** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */ - private $appManager; - /** @var IRootFolder|\PHPUnit\Framework\MockObject\MockObject */ - private $rootFolder; - /** @var Helper|\PHPUnit\Framework\MockObject\MockObject */ - private $activityHelper; - /** @var IInitialState|\PHPUnit\Framework\MockObject\MockObject */ - private $initialState; - /** @var ITemplateManager|\PHPUnit\Framework\MockObject\MockObject */ - private $templateManager; - /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */ - private $shareManager; - /** @var UserConfig|\PHPUnit\Framework\MockObject\MockObject */ - private $userConfig; - /** @var ViewConfig|\PHPUnit\Framework\MockObject\MockObject */ - private $viewConfig; + private ContainerInterface&MockObject $container; + private IAppManager&MockObject $appManager; + private ICacheFactory&MockObject $cacheFactory; + private IConfig&MockObject $config; + private IEventDispatcher $eventDispatcher; + private IEventLogger&MockObject $eventLogger; + private IInitialState&MockObject $initialState; + private IL10N&MockObject $l10n; + private IRequest&MockObject $request; + private IRootFolder&MockObject $rootFolder; + private ITemplateManager&MockObject $templateManager; + private IURLGenerator $urlGenerator; + private IUser&MockObject $user; + private IUserSession&MockObject $userSession; + private LoggerInterface&MockObject $logger; + private UserConfig&MockObject $userConfig; + private ViewConfig&MockObject $viewConfig; + private Router $router; + private IRegistry&MockObject $twoFactorRegistry; + + private ViewController&MockObject $viewController; protected function setUp(): void { parent::setUp(); - $this->request = $this->getMockBuilder(IRequest::class)->getMock(); - $this->urlGenerator = $this->getMockBuilder(IURLGenerator::class)->getMock(); - $this->l10n = $this->getMockBuilder(IL10N::class)->getMock(); - $this->config = $this->getMockBuilder(IConfig::class)->getMock(); + $this->appManager = $this->createMock(IAppManager::class); + $this->config = $this->createMock(IConfig::class); $this->eventDispatcher = $this->createMock(IEventDispatcher::class); - $this->userSession = $this->getMockBuilder(IUserSession::class)->getMock(); - $this->appManager = $this->getMockBuilder('\OCP\App\IAppManager')->getMock(); + $this->initialState = $this->createMock(IInitialState::class); + $this->l10n = $this->createMock(IL10N::class); + $this->request = $this->createMock(IRequest::class); + $this->rootFolder = $this->createMock(IRootFolder::class); + $this->templateManager = $this->createMock(ITemplateManager::class); + $this->userConfig = $this->createMock(UserConfig::class); + $this->userSession = $this->createMock(IUserSession::class); + $this->viewConfig = $this->createMock(ViewConfig::class); + $this->twoFactorRegistry = $this->createMock(IRegistry::class); + $this->user = $this->getMockBuilder(IUser::class)->getMock(); $this->user->expects($this->any()) ->method('getUID') @@ -108,14 +90,42 @@ class ViewControllerTest extends TestCase { $this->userSession->expects($this->any()) ->method('getUser') ->willReturn($this->user); - $this->rootFolder = $this->getMockBuilder('\OCP\Files\IRootFolder')->getMock(); - $this->activityHelper = $this->createMock(Helper::class); - $this->initialState = $this->createMock(IInitialState::class); - $this->templateManager = $this->createMock(ITemplateManager::class); - $this->shareManager = $this->createMock(IManager::class); - $this->userConfig = $this->createMock(UserConfig::class); - $this->viewConfig = $this->createMock(ViewConfig::class); - $this->viewController = $this->getMockBuilder('\OCA\Files\Controller\ViewController') + + // Make sure we know the app is enabled + $this->appManager->expects($this->any()) + ->method('cleanAppId') + ->willReturnArgument(0); + $this->appManager->expects($this->any()) + ->method('getAppPath') + ->willReturnCallback(fn (string $appid): string => \OC::$SERVERROOT . '/apps/' . $appid); + $this->appManager->expects($this->any()) + ->method('isAppLoaded') + ->willReturn(true); + + $this->cacheFactory = $this->createMock(ICacheFactory::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->eventLogger = $this->createMock(IEventLogger::class); + $this->container = $this->createMock(ContainerInterface::class); + $this->router = new Router( + $this->logger, + $this->request, + $this->config, + $this->eventLogger, + $this->container, + $this->appManager, + ); + + // Create a real URLGenerator instance to generate URLs + $this->urlGenerator = new URLGenerator( + $this->config, + $this->userSession, + $this->cacheFactory, + $this->request, + $this->router + ); + + $filenameValidator = $this->createMock(FilenameValidator::class); + $this->viewController = $this->getMockBuilder(ViewController::class) ->setConstructorArgs([ 'files', $this->request, @@ -126,20 +136,20 @@ class ViewControllerTest extends TestCase { $this->userSession, $this->appManager, $this->rootFolder, - $this->activityHelper, $this->initialState, $this->templateManager, - $this->shareManager, $this->userConfig, $this->viewConfig, + $filenameValidator, + $this->twoFactorRegistry, + ]) + ->onlyMethods([ + 'getStorageInfo', ]) - ->setMethods([ - 'getStorageInfo', - ]) - ->getMock(); + ->getMock(); } - public function testIndexWithRegularBrowser() { + public function testIndexWithRegularBrowser(): void { $this->viewController ->expects($this->any()) ->method('getStorageInfo') @@ -153,11 +163,6 @@ class ViewControllerTest extends TestCase { ]); $this->config - ->expects($this->any()) - ->method('getSystemValue') - ->with('forbidden_chars', []) - ->willReturn([]); - $this->config ->method('getUserValue') ->willReturnMap([ [$this->user->getUID(), 'files', 'file_sorting', 'name', 'name'], @@ -180,43 +185,79 @@ class ViewControllerTest extends TestCase { ->method('getAppValue') ->willReturnArgument(2); - $expected = new Http\TemplateResponse( + $expected = new TemplateResponse( 'files', 'index', ); - $policy = new Http\ContentSecurityPolicy(); + $policy = new ContentSecurityPolicy(); $policy->addAllowedWorkerSrcDomain('\'self\''); $policy->addAllowedFrameDomain('\'self\''); $expected->setContentSecurityPolicy($policy); - $this->activityHelper->method('getFavoriteFilePaths') - ->with($this->user->getUID()) - ->willReturn([ - 'item' => [], - 'folders' => [ - '/test1', - '/test2/', - '/test3/sub4', - '/test5/sub6/', - ], - ]); - $this->assertEquals($expected, $this->viewController->index('MyDir', 'MyView')); } - public function testShowFileRouteWithTrashedFile() { - $this->appManager->expects($this->once()) + public static function dataTestShortRedirect(): array { + // openfile is true by default + // opendetails is undefined by default + // both will be evaluated as truthy + return [ + [null, null, '/index.php/apps/files/files/123456?openfile=true'], + ['', null, '/index.php/apps/files/files/123456?openfile=true'], + [null, '', '/index.php/apps/files/files/123456?openfile=true&opendetails=true'], + ['', '', '/index.php/apps/files/files/123456?openfile=true&opendetails=true'], + ['false', '', '/index.php/apps/files/files/123456?openfile=false'], + [null, 'false', '/index.php/apps/files/files/123456?openfile=true&opendetails=false'], + ['true', 'false', '/index.php/apps/files/files/123456?openfile=true&opendetails=false'], + ['false', 'true', '/index.php/apps/files/files/123456?openfile=false&opendetails=true'], + ['false', 'false', '/index.php/apps/files/files/123456?openfile=false&opendetails=false'], + ]; + } + + #[\PHPUnit\Framework\Attributes\DataProvider('dataTestShortRedirect')] + public function testShortRedirect(?string $openfile, ?string $opendetails, string $result): void { + $this->appManager->expects($this->any()) ->method('isEnabledForUser') - ->with('files_trashbin') + ->with('files') ->willReturn(true); + $baseFolderFiles = $this->getMockBuilder(Folder::class)->getMock(); + $this->rootFolder->expects($this->any()) + ->method('getUserFolder') + ->with('testuser1') + ->willReturn($baseFolderFiles); + $parentNode = $this->getMockBuilder(Folder::class)->getMock(); $parentNode->expects($this->once()) ->method('getPath') + ->willReturn('testuser1/files/Folder'); + + $node = $this->getMockBuilder(File::class)->getMock(); + $node->expects($this->once()) + ->method('getParent') + ->willReturn($parentNode); + + $baseFolderFiles->expects($this->any()) + ->method('getFirstNodeById') + ->with(123456) + ->willReturn($node); + + $response = $this->viewController->showFile('123456', $opendetails, $openfile); + $this->assertStringContainsString($result, $response->getHeaders()['Location']); + } + + public function testShowFileRouteWithTrashedFile(): void { + $this->appManager->expects($this->exactly(2)) + ->method('isEnabledForUser') + ->willReturn(true); + + $parentNode = $this->createMock(Folder::class); + $parentNode->expects($this->once()) + ->method('getPath') ->willReturn('testuser1/files_trashbin/files/test.d1462861890/sub'); - $baseFolderFiles = $this->getMockBuilder(Folder::class)->getMock(); - $baseFolderTrash = $this->getMockBuilder(Folder::class)->getMock(); + $baseFolderFiles = $this->createMock(Folder::class); + $baseFolderTrash = $this->createMock(Folder::class); $this->rootFolder->expects($this->any()) ->method('getUserFolder') @@ -232,7 +273,7 @@ class ViewControllerTest extends TestCase { ->with(123) ->willReturn(null); - $node = $this->getMockBuilder(File::class)->getMock(); + $node = $this->createMock(File::class); $node->expects($this->once()) ->method('getParent') ->willReturn($parentNode); @@ -246,13 +287,27 @@ class ViewControllerTest extends TestCase { ->with('testuser1/files_trashbin/files/test.d1462861890/sub') ->willReturn('/test.d1462861890/sub'); - $this->urlGenerator - ->expects($this->once()) - ->method('linkToRoute') - ->with('files.view.indexViewFileid', ['view' => 'trashbin', 'dir' => '/test.d1462861890/sub', 'fileid' => '123']) - ->willReturn('/apps/files/trashbin/123?dir=/test.d1462861890/sub'); - - $expected = new Http\RedirectResponse('/apps/files/trashbin/123?dir=/test.d1462861890/sub'); + $expected = new RedirectResponse('/index.php/apps/files/trashbin/123?dir=/test.d1462861890/sub'); $this->assertEquals($expected, $this->viewController->index('', '', '123')); } + + public function testTwoFactorAuthEnabled(): void { + $this->twoFactorRegistry->method('getProviderStates') + ->willReturn([ + 'totp' => true, + 'backup_codes' => true, + ]); + + $invokedCountProvideInitialState = $this->exactly(9); + $this->initialState->expects($invokedCountProvideInitialState) + ->method('provideInitialState') + ->willReturnCallback(function ($key, $data) use ($invokedCountProvideInitialState) { + if ($invokedCountProvideInitialState->numberOfInvocations() === 9) { + $this->assertEquals('isTwoFactorEnabled', $key); + $this->assertTrue($data); + } + }); + + $this->viewController->index('', '', null); + } } diff --git a/apps/files/tests/HelperTest.php b/apps/files/tests/HelperTest.php index 423fd855a9e..ba93fa0efdf 100644 --- a/apps/files/tests/HelperTest.php +++ b/apps/files/tests/HelperTest.php @@ -1,32 +1,18 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author brumsel <brumsel@losecatcher.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @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: 2017-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ + +use OC\Files\FileInfo; +use OCA\Files\Helper; + class HelperTest extends \Test\TestCase { - private function makeFileInfo($name, $size, $mtime, $isDir = false) { - return new \OC\Files\FileInfo( + private static function makeFileInfo($name, $size, $mtime, $isDir = false): FileInfo { + return new FileInfo( '/' . $name, null, '/', @@ -44,7 +30,7 @@ class HelperTest extends \Test\TestCase { /** * Returns a file list for testing */ - private function getTestFileList() { + private static function getTestFileList(): array { return [ self::makeFileInfo('a.txt', 4, 2.3 * pow(10, 9)), self::makeFileInfo('q.txt', 5, 150), @@ -55,7 +41,7 @@ class HelperTest extends \Test\TestCase { ]; } - public function sortDataProvider() { + public static function sortDataProvider(): array { return [ [ 'name', @@ -90,15 +76,13 @@ class HelperTest extends \Test\TestCase { ]; } - /** - * @dataProvider sortDataProvider - */ - public function testSortByName(string $sort, bool $sortDescending, array $expectedOrder) { + #[\PHPUnit\Framework\Attributes\DataProvider('sortDataProvider')] + public function testSortByName(string $sort, bool $sortDescending, array $expectedOrder): void { if (($sort === 'mtime') && (PHP_INT_SIZE < 8)) { $this->markTestSkipped('Skip mtime sorting on 32bit'); } $files = self::getTestFileList(); - $files = \OCA\Files\Helper::sortFiles($files, $sort, $sortDescending); + $files = Helper::sortFiles($files, $sort, $sortDescending); $fileNames = []; foreach ($files as $fileInfo) { $fileNames[] = $fileInfo->getName(); @@ -108,36 +92,4 @@ class HelperTest extends \Test\TestCase { $fileNames ); } - - public function testPopulateTags() { - $tagManager = $this->createMock(\OCP\ITagManager::class); - $tagger = $this->createMock(\OCP\ITags::class); - - $tagManager->method('load') - ->with('files') - ->willReturn($tagger); - - $data = [ - ['id' => 10], - ['id' => 22, 'foo' => 'bar'], - ['id' => 42, 'x' => 'y'], - ]; - - $tags = [ - 10 => ['tag3'], - 42 => ['tag1', 'tag2'], - ]; - - $tagger->method('getTagsForObjects') - ->with([10, 22, 42]) - ->willReturn($tags); - - $result = \OCA\Files\Helper::populateTags($data, 'id', $tagManager); - - $this->assertSame([ - ['id' => 10, 'tags' => ['tag3']], - ['id' => 22, 'foo' => 'bar', 'tags' => []], - ['id' => 42, 'x' => 'y', 'tags' => ['tag1', 'tag2']], - ], $result); - } } diff --git a/apps/files/tests/Service/TagServiceTest.php b/apps/files/tests/Service/TagServiceTest.php index 2b9bc5be460..424e483102c 100644 --- a/apps/files/tests/Service/TagServiceTest.php +++ b/apps/files/tests/Service/TagServiceTest.php @@ -1,38 +1,25 @@ <?php + +declare(strict_types=1); /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Kesselberg <mail@danielkesselberg.de> - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @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 OCA\Files\Tests\Service; use OCA\Files\Service\TagService; use OCP\Activity\IManager; -use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\Files\NotFoundException; +use OCP\ITagManager; use OCP\ITags; use OCP\IUser; +use OCP\IUserManager; use OCP\IUserSession; +use OCP\Server; +use PHPUnit\Framework\MockObject\MockObject; /** * Class TagServiceTest @@ -42,46 +29,23 @@ use OCP\IUserSession; * @package OCA\Files */ class TagServiceTest extends \Test\TestCase { - - /** - * @var string - */ - private $user; - - /** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */ - private $userSession; - - /** @var IManager|\PHPUnit\Framework\MockObject\MockObject */ - private $activityManager; - - /** - * @var \OCP\Files\Folder - */ - private $root; - - /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */ - private $dispatcher; - - /** - * @var \OCA\Files\Service\TagService|\PHPUnit\Framework\MockObject\MockObject - */ - private $tagService; - - /** - * @var \OCP\ITags - */ - private $tagger; + private string $user; + private IUserSession&MockObject $userSession; + private IManager&MockObject $activityManager; + private Folder $root; + private TagService&MockObject $tagService; + private ITags $tagger; protected function setUp(): void { parent::setUp(); $this->user = static::getUniqueID('user'); $this->activityManager = $this->createMock(IManager::class); - \OC::$server->getUserManager()->createUser($this->user, 'test'); + Server::get(IUserManager::class)->createUser($this->user, 'test'); \OC_User::setUserId($this->user); \OC_Util::setupFS($this->user); $user = $this->createMock(IUser::class); /** - * @var \OCP\IUserSession + * @var IUserSession */ $this->userSession = $this->createMock(IUserSession::class); $this->userSession->expects($this->any()) @@ -89,45 +53,38 @@ class TagServiceTest extends \Test\TestCase { ->withAnyParameters() ->willReturn($user); - $this->root = \OC::$server->getUserFolder(); - $this->dispatcher = $this->createMock(IEventDispatcher::class); + $this->root = Server::get(IRootFolder::class)->getUserFolder($this->user); - $this->tagger = \OC::$server->getTagManager()->load('files'); - $this->tagService = $this->getTagService(['addActivity']); + $this->tagger = Server::get(ITagManager::class)->load('files'); + $this->tagService = $this->getTagService(); } - /** - * @param array $methods - * @return TagService|\PHPUnit\Framework\MockObject\MockObject - */ - protected function getTagService(array $methods = []) { + protected function getTagService(array $methods = []): TagService&MockObject { return $this->getMockBuilder(TagService::class) ->setConstructorArgs([ $this->userSession, $this->activityManager, $this->tagger, $this->root, - $this->dispatcher, ]) - ->setMethods($methods) + ->onlyMethods($methods) ->getMock(); } protected function tearDown(): void { \OC_User::setUserId(''); - $user = \OC::$server->getUserManager()->get($this->user); + $user = Server::get(IUserManager::class)->get($this->user); if ($user !== null) { $user->delete(); } + + parent::tearDown(); } - public function testUpdateFileTags() { + public function testUpdateFileTags(): void { $tag1 = 'tag1'; $tag2 = 'tag2'; - $this->tagService->expects($this->never()) - ->method('addActivity'); - $subdir = $this->root->newFolder('subdir'); $testFile = $subdir->newFile('test.txt'); $testFile->putContent('test contents'); @@ -154,32 +111,11 @@ class TagServiceTest extends \Test\TestCase { $caught = false; try { $this->tagService->updateFileTags('subdir/unexist.txt', [$tag1]); - } catch (\OCP\Files\NotFoundException $e) { + } catch (NotFoundException $e) { $caught = true; } $this->assertTrue($caught); $subdir->delete(); } - - public function testFavoriteActivity() { - $subdir = $this->root->newFolder('subdir'); - $file = $subdir->newFile('test.txt'); - - $this->tagService->expects($this->exactly(2)) - ->method('addActivity') - ->withConsecutive( - [true, $file->getId(), 'subdir/test.txt'], - [false, $file->getId(), 'subdir/test.txt'] - ); - - // set tags - $this->tagService->updateFileTags('subdir/test.txt', [ITags::TAG_FAVORITE]); - - // remove tag - $this->tagService->updateFileTags('subdir/test.txt', []); - - - $subdir->delete(); - } } diff --git a/apps/files/tests/js/breadcrumbSpec.js b/apps/files/tests/js/breadcrumbSpec.js deleted file mode 100644 index 6bc7eb0a54d..00000000000 --- a/apps/files/tests/js/breadcrumbSpec.js +++ /dev/null @@ -1,667 +0,0 @@ -/** -* @copyright 2014 Vincent Petry <pvince81@owncloud.com> - * - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0-or-later - * - * 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/>. - * - */ - -describe('OCA.Files.BreadCrumb tests', function() { - var BreadCrumb = OCA.Files.BreadCrumb; - - describe('Rendering', function() { - var bc; - beforeEach(function() { - bc = new BreadCrumb({ - getCrumbUrl: function(part, index) { - // for testing purposes - return part.dir + '#' + index; - } - }); - }); - afterEach(function() { - bc = null; - }); - it('Renders its own container', function() { - bc.render(); - expect(bc.$el.find("ul").hasClass('breadcrumb')).toEqual(true); - }); - it('Renders root by default', function() { - var $crumbs; - bc.render(); - $crumbs = bc.$el.find('.crumb'); - // menu and home - expect($crumbs.length).toEqual(2); - expect($crumbs.eq(0).find('a').hasClass('icon-more')).toEqual(true); - expect($crumbs.eq(0).find('div.popovermenu').length).toEqual(1); - expect($crumbs.eq(0).data('dir')).not.toBeDefined(); - expect($crumbs.eq(1).find('a').attr('href')).toEqual('/#1'); - expect($crumbs.eq(1).find('a').hasClass('icon-home')).toEqual(true); - expect($crumbs.eq(1).data('dir')).toEqual('/'); - }); - it('Renders root when switching to root', function() { - var $crumbs; - bc.setDirectory('/somedir'); - bc.setDirectory('/'); - $crumbs = bc.$el.find('.crumb'); - expect($crumbs.length).toEqual(2); - expect($crumbs.eq(1).data('dir')).toEqual('/'); - }); - it('Renders single path section', function() { - var $crumbs; - bc.setDirectory('/somedir'); - $crumbs = bc.$el.find('.crumb'); - expect($crumbs.length).toEqual(3); - expect($crumbs.eq(0).find('a').hasClass('icon-more')).toEqual(true); - expect($crumbs.eq(0).find('div.popovermenu').length).toEqual(1); - expect($crumbs.eq(0).data('dir')).not.toBeDefined(); - - expect($crumbs.eq(1).find('a').attr('href')).toEqual('/#1'); - expect($crumbs.eq(1).find('a').hasClass('icon-home')).toEqual(true); - expect($crumbs.eq(1).data('dir')).toEqual('/'); - - expect($crumbs.eq(2).find('a').attr('href')).toEqual('/somedir#2'); - expect($crumbs.eq(2).find('img').length).toEqual(0); - expect($crumbs.eq(2).data('dir')).toEqual('/somedir'); - }); - it('Renders multiple path sections and special chars', function() { - var $crumbs; - bc.setDirectory('/somedir/with space/abc'); - $crumbs = bc.$el.find('.crumb'); - expect($crumbs.length).toEqual(5); - expect($crumbs.eq(0).find('a').hasClass('icon-more')).toEqual(true); - expect($crumbs.eq(0).find('div.popovermenu').length).toEqual(1); - expect($crumbs.eq(0).data('dir')).not.toBeDefined(); - - expect($crumbs.eq(1).find('a').attr('href')).toEqual('/#1'); - expect($crumbs.eq(1).find('a').hasClass('icon-home')).toEqual(true); - expect($crumbs.eq(1).data('dir')).toEqual('/'); - - expect($crumbs.eq(2).find('a').attr('href')).toEqual('/somedir#2'); - expect($crumbs.eq(2).find('img').length).toEqual(0); - expect($crumbs.eq(2).data('dir')).toEqual('/somedir'); - - expect($crumbs.eq(3).find('a').attr('href')).toEqual('/somedir/with space#3'); - expect($crumbs.eq(3).find('img').length).toEqual(0); - expect($crumbs.eq(3).data('dir')).toEqual('/somedir/with space'); - - expect($crumbs.eq(4).find('a').attr('href')).toEqual('/somedir/with space/abc#4'); - expect($crumbs.eq(4).find('img').length).toEqual(0); - expect($crumbs.eq(4).data('dir')).toEqual('/somedir/with space/abc'); - }); - it('Renders backslashes as regular directory separator', function() { - var $crumbs; - bc.setDirectory('/somedir\\with/mixed\\separators'); - $crumbs = bc.$el.find('.crumb'); - expect($crumbs.length).toEqual(6); - expect($crumbs.eq(0).find('a').hasClass('icon-more')).toEqual(true); - expect($crumbs.eq(0).find('div.popovermenu').length).toEqual(1); - expect($crumbs.eq(0).data('dir')).not.toBeDefined(); - - expect($crumbs.eq(1).find('a').attr('href')).toEqual('/#1'); - expect($crumbs.eq(1).find('a').hasClass('icon-home')).toEqual(true); - expect($crumbs.eq(1).data('dir')).toEqual('/'); - - expect($crumbs.eq(2).find('a').attr('href')).toEqual('/somedir#2'); - expect($crumbs.eq(2).find('img').length).toEqual(0); - expect($crumbs.eq(2).data('dir')).toEqual('/somedir'); - - expect($crumbs.eq(3).find('a').attr('href')).toEqual('/somedir/with#3'); - expect($crumbs.eq(3).find('img').length).toEqual(0); - expect($crumbs.eq(3).data('dir')).toEqual('/somedir/with'); - - expect($crumbs.eq(4).find('a').attr('href')).toEqual('/somedir/with/mixed#4'); - expect($crumbs.eq(4).find('img').length).toEqual(0); - expect($crumbs.eq(4).data('dir')).toEqual('/somedir/with/mixed'); - - expect($crumbs.eq(5).find('a').attr('href')).toEqual('/somedir/with/mixed/separators#5'); - expect($crumbs.eq(5).find('img').length).toEqual(0); - expect($crumbs.eq(5).data('dir')).toEqual('/somedir/with/mixed/separators'); - }); - }); - describe('Events', function() { - it('Calls onClick handler when clicking on a crumb', function() { - var handler = sinon.stub(); - var bc = new BreadCrumb({ - onClick: handler - }); - bc.setDirectory('/one/two/three/four'); - // Click on crumb does not work, only link - bc.$el.find('.crumb:eq(4)').click(); - expect(handler.calledOnce).toEqual(false); - - handler.reset(); - // Click on crumb link works - bc.$el.find('.crumb:eq(1) a').click(); - expect(handler.calledOnce).toEqual(true); - expect(handler.getCall(0).thisValue).toEqual(bc.$el.find('.crumb > a').get(1)); - }); - it('Calls onDrop handler when dropping on a crumb', function() { - var droppableStub = sinon.stub($.fn, 'droppable'); - var handler = sinon.stub(); - var bc = new BreadCrumb({ - onDrop: handler - }); - bc.setDirectory('/one/two/three/four'); - expect(droppableStub.calledOnce).toEqual(true); - - expect(droppableStub.getCall(0).args[0].drop).toBeDefined(); - // simulate drop - droppableStub.getCall(0).args[0].drop({dummy: true}); - - expect(handler.calledOnce).toEqual(true); - expect(handler.getCall(0).args[0]).toEqual({dummy: true}); - - droppableStub.restore(); - }); - }); - - describe('Menu tests', function() { - var bc, dummyDir, $crumbmenuLink, $popovermenu; - - beforeEach(function() { - dummyDir = '/one/two/three/four/five' - - bc = new BreadCrumb(); - // append dummy navigation and controls - // as they are currently used for measurements - $('#testArea').append( - '<div class="files-controls"></div>' - ); - $('.files-controls').append(bc.$el); - - bc.setDirectory(dummyDir); - - $('li.crumb').each(function(index){ - $(this).css('width', 50); - $(this).css('padding', 0); - $(this).css('margin', 0); - }); - $('div.crumbhome').css('width', 51); - $('div.crumbmenu').css('width', 51); - - $('.files-controls').width(1000); - bc._resize(); - - // Shrink to show popovermenu - $('.files-controls').width(300); - bc._resize(); - - $crumbmenuLink = bc.$el.find('.crumbmenu > a'); - $popovermenu = $crumbmenuLink.next('.popovermenu'); - }); - afterEach(function() { - bc = null; - }); - - it('Shows only items not in the breadcrumb', function() { - var hiddenCrumbs = bc.$el.find('.crumb:not(.crumbmenu).hidden'); - expect($popovermenu.find('li:not(.in-breadcrumb)').length).toEqual(hiddenCrumbs.length); - }); - }); - - describe('Resizing', function() { - var bc, dummyDir, widths, paddings, margins; - - // cit() will skip tests if running on PhantomJS because it does not - // have proper support for flexboxes. - var cit = window.isPhantom?xit:it; - - beforeEach(function() { - dummyDir = '/short name/longer name/looooooooooooonger/' + - 'even longer long long long longer long/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/last one'; - - bc = new BreadCrumb(); - // append dummy navigation and controls - // as they are currently used for measurements - $('#testArea').append( - '<div class="files-controls"></div>' - ); - $('.files-controls').append(bc.$el); - - // triggers resize implicitly - bc.setDirectory(dummyDir); - - // using hard-coded widths (pre-measured) to avoid getting different - // results on different browsers due to font engine differences - // 51px is default size for menu and home - widths = [51, 51, 106, 112, 160, 257, 251, 91]; - // using hard-coded paddings and margins to avoid depending on the - // current CSS values used in the server - paddings = [0, 0, 0, 0, 0, 0, 0, 0]; - margins = [0, 0, 0, 0, 0, 0, 0, 0]; - - $('li.crumb').each(function(index){ - $(this).css('width', widths[index]); - $(this).css('padding', paddings[index]); - $(this).css('margin', margins[index]); - }); - }); - afterEach(function() { - bc = null; - }); - it('Hides breadcrumbs to fit available width', function() { - var $crumbs; - - $('.files-controls').width(500); - bc._resize(); - - $crumbs = bc.$el.find('.crumb'); - - // Second, third, fourth and fifth crumb are hidden and everything - // else is visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - }); - it('Hides breadcrumbs to fit available width', function() { - var $crumbs; - - $('.files-controls').width(700); - bc._resize(); - - $crumbs = bc.$el.find('.crumb'); - - // Third and fourth crumb are hidden and everything else is visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - }); - it('Hides breadcrumbs to fit available width taking paddings into account', function() { - var $crumbs; - - // Each element is 20px wider - paddings = [10, 10, 10, 10, 10, 10, 10, 10]; - - $('li.crumb').each(function(index){ - $(this).css('padding', paddings[index]); - }); - - $('.files-controls').width(700); - bc._resize(); - - $crumbs = bc.$el.find('.crumb'); - - // Second, third and fourth crumb are hidden and everything else is - // visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - }); - it('Hides breadcrumbs to fit available width taking margins into account', function() { - var $crumbs; - - // Each element is 20px wider - margins = [10, 10, 10, 10, 10, 10, 10, 10]; - - $('li.crumb').each(function(index){ - $(this).css('margin', margins[index]); - }); - - $('.files-controls').width(700); - bc._resize(); - - $crumbs = bc.$el.find('.crumb'); - - // Second, third and fourth crumb are hidden and everything else is - // visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - }); - it('Hides breadcrumbs to fit available width left by siblings', function() { - var $crumbs; - - $('.files-controls').width(700); - bc._resize(); - - $crumbs = bc.$el.find('.crumb'); - - // Third and fourth crumb are hidden and everything else is visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - - // Visible sibling widths add up to 200px - var $previousSibling = $('<div class="otherSibling"></div>'); - // Set both the width and the min-width to even differences in width - // handling in the browsers used to run the tests. - $previousSibling.css('width', '50px'); - $previousSibling.css('min-width', '50px'); - $('.files-controls').prepend($previousSibling); - - var $creatableActions = $('<div class="actions creatable"></div>'); - // Set both the width and the min-width to even differences in width - // handling in the browsers used to run the tests. - $creatableActions.css('width', '100px'); - $creatableActions.css('min-width', '100px'); - $('.files-controls').append($creatableActions); - - var $nextHiddenSibling = $('<div class="otherSibling hidden"></div>'); - // Set both the width and the min-width to even differences in width - // handling in the browsers used to run the tests. - $nextHiddenSibling.css('width', '200px'); - $nextHiddenSibling.css('min-width', '200px'); - $('.files-controls').append($nextHiddenSibling); - - var $nextSibling = $('<div class="otherSibling"></div>'); - // Set both the width and the min-width to even differences in width - // handling in the browsers used to run the tests. - $nextSibling.css('width', '50px'); - $nextSibling.css('min-width', '50px'); - $('.files-controls').append($nextSibling); - - bc._resize(); - - // Second, third, fourth and fifth crumb are hidden and everything - // else is visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - }); - it('Hides breadcrumbs to fit available width left by siblings with paddings and margins', function() { - var $crumbs; - - $('.files-controls').width(700); - bc._resize(); - - $crumbs = bc.$el.find('.crumb'); - - // Third and fourth crumb are hidden and everything else is visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - - // Visible sibling widths add up to 200px - var $previousSibling = $('<div class="otherSibling"></div>'); - // Set both the width and the min-width to even differences in width - // handling in the browsers used to run the tests. - $previousSibling.css('width', '10px'); - $previousSibling.css('min-width', '10px'); - $previousSibling.css('margin', '20px'); - $('.files-controls').prepend($previousSibling); - - var $creatableActions = $('<div class="actions creatable"></div>'); - // Set both the width and the min-width to even differences in width - // handling in the browsers used to run the tests. - $creatableActions.css('width', '20px'); - $creatableActions.css('min-width', '20px'); - $creatableActions.css('margin-left', '40px'); - $creatableActions.css('padding-right', '40px'); - $('.files-controls').append($creatableActions); - - var $nextHiddenSibling = $('<div class="otherSibling hidden"></div>'); - // Set both the width and the min-width to even differences in width - // handling in the browsers used to run the tests. - $nextHiddenSibling.css('width', '200px'); - $nextHiddenSibling.css('min-width', '200px'); - $('.files-controls').append($nextHiddenSibling); - - var $nextSibling = $('<div class="otherSibling"></div>'); - // Set both the width and the min-width to even differences in width - // handling in the browsers used to run the tests. - $nextSibling.css('width', '10px'); - $nextSibling.css('min-width', '10px'); - $nextSibling.css('padding', '20px'); - $('.files-controls').append($nextSibling); - - bc._resize(); - - // Second, third, fourth and fifth crumb are hidden and everything - // else is visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - }); - it('Updates the breadcrumbs when reducing available width', function() { - var $crumbs; - - // enough space - $('.files-controls').width(1800); - bc._resize(); - - $crumbs = bc.$el.find('.crumb'); - - // Menu is hidden - expect($crumbs.eq(0).hasClass('hidden')).toEqual(true); - - // simulate decrease - $('.files-controls').width(950); - bc._resize(); - - // Third crumb is hidden and everything else is visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - }); - it('Updates the breadcrumbs when reducing available width taking into account the menu width', function() { - var $crumbs; - - // enough space - $('.files-controls').width(1800); - bc._resize(); - - $crumbs = bc.$el.find('.crumb'); - - // Menu is hidden - expect($crumbs.eq(0).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - - // simulate decrease - // 650 is enough for all the crumbs except the third and fourth - // ones, but not enough for the menu and all the crumbs except the - // third and fourth ones; the second one has to be hidden too. - $('.files-controls').width(650); - bc._resize(); - - // Second, third and fourth crumb are hidden and everything else is - // visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - }); - it('Updates the breadcrumbs when increasing available width', function() { - var $crumbs; - - // limited space - $('.files-controls').width(850); - bc._resize(); - - $crumbs = bc.$el.find('.crumb'); - - // Third and fourth crumb are hidden and everything else is visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - - // simulate increase - $('.files-controls').width(1000); - bc._resize(); - - // Third crumb is hidden and everything else is visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - }); - it('Updates the breadcrumbs when increasing available width taking into account the menu width', function() { - var $crumbs; - - // limited space - $('.files-controls').width(850); - bc._resize(); - - $crumbs = bc.$el.find('.crumb'); - - // Third and fourth crumb are hidden and everything else is visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - - // simulate increase - // 1030 is enough for all the crumbs if the menu is hidden. - $('.files-controls').width(1030); - bc._resize(); - - // Menu is hidden and everything else is visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - }); - cit('Updates the breadcrumbs when increasing available width with an expanding sibling', function() { - var $crumbs; - - // The sibling expands to fill all the width left by the breadcrumbs - var $nextSibling = $('<div class="sibling"></div>'); - // Set both the width and the min-width to even differences in width - // handling in the browsers used to run the tests. - $nextSibling.css('width', '10px'); - $nextSibling.css('min-width', '10px'); - $nextSibling.css('display', 'flex'); - $nextSibling.css('flex', '1 1'); - var $nextSiblingChild = $('<div class="siblingChild"></div>'); - $nextSiblingChild.css('margin-left', 'auto'); - $nextSibling.append($nextSiblingChild); - $('.files-controls').append($nextSibling); - - // limited space - $('.files-controls').width(850); - bc._resize(); - - $crumbs = bc.$el.find('.crumb'); - - // Third and fourth crumb are hidden and everything else is visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - - // simulate increase - $('.files-controls').width(1000); - bc._resize(); - - // Third crumb is hidden and everything else is visible - expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); - - expect($crumbs.eq(2).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(3).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); - expect($crumbs.eq(5).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); - expect($crumbs.eq(7).hasClass('hidden')).toEqual(false); - }); - }); -}); diff --git a/apps/files/tests/js/detailsviewSpec.js b/apps/files/tests/js/detailsviewSpec.js deleted file mode 100644 index d375c4c9282..00000000000 --- a/apps/files/tests/js/detailsviewSpec.js +++ /dev/null @@ -1,257 +0,0 @@ -/** -* @copyright 2015 Vincent Petry <pvince81@owncloud.com> - * - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0-or-later - * - * 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/>. - * - */ - -describe('OCA.Files.DetailsView tests', function() { - var detailsView; - - beforeEach(function() { - detailsView = new OCA.Files.DetailsView(); - }); - afterEach(function() { - detailsView.remove(); - detailsView = undefined; - }); - it('renders itself empty when nothing registered', function() { - detailsView.render(); - expect(detailsView.$el.find('.detailFileInfoContainer').length).toEqual(1); - expect(detailsView.$el.find('.tabsContainer').length).toEqual(1); - }); - describe('file info detail view', function() { - it('returns registered view', function() { - var testView = new OCA.Files.DetailFileInfoView(); - var testView2 = new OCA.Files.DetailFileInfoView(); - detailsView.addDetailView(testView); - detailsView.addDetailView(testView2); - - detailViews = detailsView.getDetailViews(); - - expect(detailViews).toContain(testView); - expect(detailViews).toContain(testView2); - - // Modify array and check that registered detail views are not - // modified - detailViews.pop(); - detailViews.pop(); - - detailViews = detailsView.getDetailViews(); - - expect(detailViews).toContain(testView); - expect(detailViews).toContain(testView2); - }); - it('renders registered view', function() { - var testView = new OCA.Files.DetailFileInfoView(); - var testView2 = new OCA.Files.DetailFileInfoView(); - detailsView.addDetailView(testView); - detailsView.addDetailView(testView2); - detailsView.render(); - - expect(detailsView.$el.find('.detailFileInfoContainer .detailFileInfoView').length).toEqual(2); - }); - it('updates registered tabs when fileinfo is updated', function() { - var viewRenderStub = sinon.stub(OCA.Files.DetailFileInfoView.prototype, 'render'); - var testView = new OCA.Files.DetailFileInfoView(); - var testView2 = new OCA.Files.DetailFileInfoView(); - detailsView.addDetailView(testView); - detailsView.addDetailView(testView2); - detailsView.render(); - - var fileInfo = {id: 5, name: 'test.txt'}; - viewRenderStub.reset(); - detailsView.setFileInfo(fileInfo); - - expect(testView.getFileInfo()).toEqual(fileInfo); - expect(testView2.getFileInfo()).toEqual(fileInfo); - - expect(viewRenderStub.callCount).toEqual(2); - viewRenderStub.restore(); - }); - }); - describe('tabs', function() { - var testView, testView2; - - beforeEach(function() { - testView = new OCA.Files.DetailTabView({id: 'test1'}); - testView2 = new OCA.Files.DetailTabView({id: 'test2'}); - detailsView.addTabView(testView); - detailsView.addTabView(testView2); - detailsView.render(); - }); - it('initially renders only the selected tab', function() { - expect(detailsView.$el.find('.tab').length).toEqual(1); - expect(detailsView.$el.find('.tab').attr('id')).toEqual('test1'); - }); - it('updates tab model and rerenders on-demand as soon as it gets selected', function() { - var tab1RenderStub = sinon.stub(testView, 'render'); - var tab2RenderStub = sinon.stub(testView2, 'render'); - var fileInfo1 = new OCA.Files.FileInfoModel({id: 5, name: 'test.txt'}); - var fileInfo2 = new OCA.Files.FileInfoModel({id: 8, name: 'test2.txt'}); - - detailsView.setFileInfo(fileInfo1); - - // first tab renders, not the second one - expect(tab1RenderStub.calledOnce).toEqual(true); - expect(tab2RenderStub.notCalled).toEqual(true); - - // info got set only to the first visible tab - expect(testView.getFileInfo()).toEqual(fileInfo1); - expect(testView2.getFileInfo()).toBeUndefined(); - - // select second tab for first render - detailsView.$el.find('.tabHeader').eq(1).click(); - - // second tab got rendered - expect(tab2RenderStub.calledOnce).toEqual(true); - expect(testView2.getFileInfo()).toEqual(fileInfo1); - - // select the first tab again - detailsView.$el.find('.tabHeader').eq(0).click(); - - // no re-render - expect(tab1RenderStub.calledOnce).toEqual(true); - expect(tab2RenderStub.calledOnce).toEqual(true); - - tab1RenderStub.reset(); - tab2RenderStub.reset(); - - // switch to another file - detailsView.setFileInfo(fileInfo2); - - // only the visible tab was updated and rerendered - expect(tab1RenderStub.calledOnce).toEqual(true); - expect(testView.getFileInfo()).toEqual(fileInfo2); - - // second/invisible tab still has old info, not rerendered - expect(tab2RenderStub.notCalled).toEqual(true); - expect(testView2.getFileInfo()).toEqual(fileInfo1); - - // reselect the second one - detailsView.$el.find('.tabHeader').eq(1).click(); - - // second tab becomes visible, updated and rendered - expect(testView2.getFileInfo()).toEqual(fileInfo2); - expect(tab2RenderStub.calledOnce).toEqual(true); - - tab1RenderStub.restore(); - tab2RenderStub.restore(); - }); - it('selects the first tab by default', function() { - expect(detailsView.$el.find('.tabHeader').eq(0).hasClass('selected')).toEqual(true); - expect(detailsView.$el.find('.tabHeader').eq(1).hasClass('selected')).toEqual(false); - expect(detailsView.$el.find('.tab').eq(0).hasClass('hidden')).toEqual(false); - expect(detailsView.$el.find('.tab').eq(1).length).toEqual(0); - }); - it('switches the current tab when clicking on tab header', function() { - detailsView.$el.find('.tabHeader').eq(1).click(); - expect(detailsView.$el.find('.tabHeader').eq(0).hasClass('selected')).toEqual(false); - expect(detailsView.$el.find('.tabHeader').eq(1).hasClass('selected')).toEqual(true); - expect(detailsView.$el.find('.tab').eq(0).hasClass('hidden')).toEqual(true); - expect(detailsView.$el.find('.tab').eq(1).hasClass('hidden')).toEqual(false); - }); - describe('tab visibility', function() { - beforeEach(function() { - detailsView.remove(); - detailsView = new OCA.Files.DetailsView(); - }); - it('does not display tab headers when only one tab exists', function() { - testView = new OCA.Files.DetailTabView({id: 'test1'}); - detailsView.addTabView(testView); - detailsView.render(); - - expect(detailsView.$el.find('.tabHeaders').hasClass('hidden')).toEqual(true); - expect(detailsView.$el.find('.tabHeader').length).toEqual(1); - }); - it('does not display tab that do not pass visibility check', function() { - testView = new OCA.Files.DetailTabView({id: 'test1'}); - testView.canDisplay = sinon.stub().returns(false); - testView2 = new OCA.Files.DetailTabView({id: 'test2'}); - var testView3 = new OCA.Files.DetailTabView({id: 'test3'}); - detailsView.addTabView(testView); - detailsView.addTabView(testView2); - detailsView.addTabView(testView3); - - var fileInfo = {id: 5, name: 'test.txt'}; - detailsView.setFileInfo(fileInfo); - - expect(testView.canDisplay.calledOnce).toEqual(true); - expect(testView.canDisplay.calledWith(fileInfo)).toEqual(true); - - expect(detailsView.$el.find('.tabHeaders').hasClass('hidden')).toEqual(false); - expect(detailsView.$el.find('.tabHeader[data-tabid=test1]').hasClass('hidden')).toEqual(true); - expect(detailsView.$el.find('.tabHeader[data-tabid=test2]').hasClass('hidden')).toEqual(false); - expect(detailsView.$el.find('.tabHeader[data-tabid=test3]').hasClass('hidden')).toEqual(false); - }); - it('does not show tab headers if only one header is visible due to visibility check', function() { - testView = new OCA.Files.DetailTabView({id: 'test1'}); - testView.canDisplay = sinon.stub().returns(false); - testView2 = new OCA.Files.DetailTabView({id: 'test2'}); - detailsView.addTabView(testView); - detailsView.addTabView(testView2); - - var fileInfo = {id: 5, name: 'test.txt'}; - detailsView.setFileInfo(fileInfo); - - expect(testView.canDisplay.calledOnce).toEqual(true); - expect(testView.canDisplay.calledWith(fileInfo)).toEqual(true); - - expect(detailsView.$el.find('.tabHeaders').hasClass('hidden')).toEqual(true); - expect(detailsView.$el.find('.tabHeader[data-tabid=test1]').hasClass('hidden')).toEqual(true); - expect(detailsView.$el.find('.tabHeader[data-tabid=test2]').hasClass('hidden')).toEqual(false); - }); - it('deselects the current tab if a model update does not pass the visibility check', function() { - testView = new OCA.Files.DetailTabView({id: 'test1'}); - testView.canDisplay = function(fileInfo) { - return fileInfo.mimetype !== 'httpd/unix-directory'; - }; - testView2 = new OCA.Files.DetailTabView({id: 'test2'}); - detailsView.addTabView(testView); - detailsView.addTabView(testView2); - - var fileInfo = {id: 5, name: 'test.txt', mimetype: 'text/plain'}; - detailsView.setFileInfo(fileInfo); - - expect(detailsView.$el.find('.tabHeader[data-tabid=test1]').hasClass('selected')).toEqual(true); - expect(detailsView.$el.find('.tabHeader[data-tabid=test2]').hasClass('selected')).toEqual(false); - - detailsView.setFileInfo({id: 10, name: 'folder', mimetype: 'httpd/unix-directory'}); - - expect(detailsView.$el.find('.tabHeader[data-tabid=test1]').hasClass('selected')).toEqual(false); - expect(detailsView.$el.find('.tabHeader[data-tabid=test2]').hasClass('selected')).toEqual(true); - }); - }); - it('sorts by order and then label', function() { - detailsView.remove(); - detailsView = new OCA.Files.DetailsView(); - detailsView.addTabView(new OCA.Files.DetailTabView({id: 'abc', order: 20})); - detailsView.addTabView(new OCA.Files.DetailTabView({id: 'def', order: 10})); - detailsView.addTabView(new OCA.Files.DetailTabView({id: 'jkl'})); - detailsView.addTabView(new OCA.Files.DetailTabView({id: 'ghi'})); - detailsView.render(); - - var tabs = detailsView.$el.find('.tabHeader').map(function() { - return $(this).attr('data-tabid'); - }).toArray(); - - expect(tabs).toEqual(['ghi', 'jkl', 'def', 'abc']); - }); - }); -}); diff --git a/apps/files/tests/js/fileactionsSpec.js b/apps/files/tests/js/fileactionsSpec.js deleted file mode 100644 index 7ec9efc43d0..00000000000 --- a/apps/files/tests/js/fileactionsSpec.js +++ /dev/null @@ -1,761 +0,0 @@ -/** -* @copyright 2014 Vincent Petry <pvince81@owncloud.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Jan-Christoph Borchardt <hey@jancborchardt.net> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Vincent Chan <plus.vincchan@gmail.com> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0-or-later - * - * 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/>. - * - */ - -describe('OCA.Files.FileActions tests', function() { - var fileList, fileActions, clock; - - beforeEach(function() { - clock = sinon.useFakeTimers(); - // init horrible parameters - var $body = $('#testArea'); - $body.append('<input type="hidden" id="permissions" value="31"></input>'); - $body.append('<table class="files-filestable list-container view-grid"><tbody class="files-fileList"></tbody></table>'); - // dummy files table - fileActions = new OCA.Files.FileActions(); - fileActions.registerAction({ - name: 'Testdropdown', - displayName: 'Testdropdowndisplay', - mime: 'all', - permissions: OC.PERMISSION_READ, - icon: function () { - return OC.imagePath('core', 'actions/download'); - } - }); - - fileActions.registerAction({ - name: 'Testinline', - displayName: 'Testinlinedisplay', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - permissions: OC.PERMISSION_READ - }); - - fileActions.registerAction({ - name: 'Testdefault', - displayName: 'Testdefaultdisplay', - mime: 'all', - permissions: OC.PERMISSION_READ - }); - fileActions.setDefault('all', 'Testdefault'); - fileList = new OCA.Files.FileList($body, { - fileActions: fileActions - }); - fileList.changeDirectory('/subdir', false, true); - }); - afterEach(function() { - fileActions = null; - fileList.destroy(); - fileList = undefined; - clock.restore(); - $('#permissions, .files-filestable').remove(); - }); - it('calling clear() clears file actions', function() { - fileActions.clear(); - expect(fileActions.actions).toEqual({}); - expect(fileActions.defaults).toEqual({}); - expect(fileActions.icons).toEqual({}); - expect(fileActions.currentFile).toBe(null); - }); - describe('displaying actions', function() { - var $tr; - - beforeEach(function() { - var fileData = { - id: 18, - type: 'file', - name: 'testName.txt', - mimetype: 'text/plain', - size: '1234', - etag: 'a01234c', - mtime: '123456', - permissions: OC.PERMISSION_READ | OC.PERMISSION_UPDATE - }; - - // note: FileActions.display() is called implicitly - $tr = fileList.add(fileData); - }); - it('renders inline file actions', function() { - // actions defined after call - expect($tr.find('.action.action-testinline').length).toEqual(1); - expect($tr.find('.action.action-testinline').attr('data-action')).toEqual('Testinline'); - }); - it('does not render dropdown actions', function() { - expect($tr.find('.action.action-testdropdown').length).toEqual(0); - }); - it('does not render default action', function() { - expect($tr.find('.action.action-testdefault').length).toEqual(0); - }); - it('replaces file actions when displayed twice', function() { - fileActions.display($tr.find('td.filename'), true, fileList); - fileActions.display($tr.find('td.filename'), true, fileList); - - expect($tr.find('.action.action-testinline').length).toEqual(1); - }); - it('renders actions menu trigger', function() { - expect($tr.find('.action.action-menu').length).toEqual(1); - expect($tr.find('.action.action-menu').attr('data-action')).toEqual('menu'); - }); - it('only renders actions relevant to the mime type', function() { - fileActions.registerAction({ - name: 'Match', - displayName: 'MatchDisplay', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'text/plain', - permissions: OC.PERMISSION_READ - }); - fileActions.registerAction({ - name: 'Nomatch', - displayName: 'NoMatchDisplay', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'application/octet-stream', - permissions: OC.PERMISSION_READ - }); - - fileActions.display($tr.find('td.filename'), true, fileList); - expect($tr.find('.action.action-match').length).toEqual(1); - expect($tr.find('.action.action-nomatch').length).toEqual(0); - }); - it('only renders actions relevant to the permissions', function() { - fileActions.registerAction({ - name: 'Match', - displayName: 'MatchDisplay', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'text/plain', - permissions: OC.PERMISSION_UPDATE - }); - fileActions.registerAction({ - name: 'Nomatch', - displayName: 'NoMatchDisplay', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'text/plain', - permissions: OC.PERMISSION_DELETE - }); - - fileActions.display($tr.find('td.filename'), true, fileList); - expect($tr.find('.action.action-match').length).toEqual(1); - expect($tr.find('.action.action-nomatch').length).toEqual(0); - }); - it('display inline icon with image path', function() { - fileActions.registerAction({ - name: 'Icon', - displayName: 'IconDisplay', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - icon: OC.imagePath('core', 'actions/icon'), - permissions: OC.PERMISSION_READ - }); - fileActions.registerAction({ - name: 'NoIcon', - displayName: 'NoIconDisplay', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - permissions: OC.PERMISSION_READ - }); - - fileActions.display($tr.find('td.filename'), true, fileList); - - expect($tr.find('.action.action-icon').length).toEqual(1); - expect($tr.find('.action.action-icon').find('img').length).toEqual(1); - expect($tr.find('.action.action-icon').find('img').eq(0).attr('src')).toEqual(OC.imagePath('core', 'actions/icon')); - - expect($tr.find('.action.action-noicon').length).toEqual(1); - expect($tr.find('.action.action-noicon').find('img').length).toEqual(0); - }); - it('display alt text on inline icon with image path', function() { - fileActions.registerAction({ - name: 'IconAltText', - displayName: 'IconAltTextDisplay', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - icon: OC.imagePath('core', 'actions/iconAltText'), - altText: 'alt icon text', - permissions: OC.PERMISSION_READ - }); - - fileActions.registerAction({ - name: 'IconNoAltText', - displayName: 'IconNoAltTextDisplay', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - icon: OC.imagePath('core', 'actions/iconNoAltText'), - permissions: OC.PERMISSION_READ - }); - - fileActions.display($tr.find('td.filename'), true, fileList); - - expect($tr.find('.action.action-iconalttext').length).toEqual(1); - expect($tr.find('.action.action-iconalttext').find('img').length).toEqual(1); - expect($tr.find('.action.action-iconalttext').find('img').eq(0).attr('alt')).toEqual('alt icon text'); - - expect($tr.find('.action.action-iconnoalttext').length).toEqual(1); - expect($tr.find('.action.action-iconnoalttext').find('img').length).toEqual(1); - expect($tr.find('.action.action-iconnoalttext').find('img').eq(0).attr('alt')).toEqual(''); - }); - it('display inline icon with iconClass', function() { - fileActions.registerAction({ - name: 'Icon', - displayName: 'IconDisplay', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - iconClass: 'icon-test', - permissions: OC.PERMISSION_READ - }); - fileActions.registerAction({ - name: 'NoIcon', - displayName: 'NoIconDisplay', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - permissions: OC.PERMISSION_READ - }); - - fileActions.display($tr.find('td.filename'), true, fileList); - - expect($tr.find('.action.action-icon').length).toEqual(1); - expect($tr.find('.action.action-icon').find('.icon').length).toEqual(1); - expect($tr.find('.action.action-icon').find('.icon').hasClass('icon-test')).toEqual(true); - - expect($tr.find('.action.action-noicon').length).toEqual(1); - expect($tr.find('.action.action-noicon').find('.icon').length).toEqual(0); - }); - it('display alt text on inline icon with iconClass when no display name exists', function() { - fileActions.registerAction({ - name: 'IconAltText', - displayName: '', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - iconClass: 'icon-alttext', - altText: 'alt icon text', - permissions: OC.PERMISSION_READ - }); - - fileActions.registerAction({ - name: 'IconNoAltText', - displayName: 'IconNoAltTextDisplay', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - altText: 'useless alt text', - iconClass: 'icon-noalttext', - permissions: OC.PERMISSION_READ - }); - - fileActions.display($tr.find('td.filename'), true, fileList); - - expect($tr.find('.action.action-iconalttext').length).toEqual(1); - expect($tr.find('.action.action-iconalttext').find('.icon').length).toEqual(1); - expect($tr.find('.action.action-iconalttext').find('.hidden-visually').text()).toEqual('alt icon text'); - - expect($tr.find('.action.action-iconnoalttext').length).toEqual(1); - expect($tr.find('.action.action-iconnoalttext').find('.icon').length).toEqual(1); - expect($tr.find('.action.action-iconnoalttext').find('.hidden-visually').length).toEqual(0); - }); - }); - describe('action handler', function() { - var actionStub, $tr, clock; - - beforeEach(function() { - clock = sinon.useFakeTimers(); - var fileData = { - id: 18, - type: 'file', - name: 'testName.txt', - mimetype: 'text/plain', - size: '1234', - etag: 'a01234c', - mtime: '123456' - }; - actionStub = sinon.stub(); - fileActions.registerAction({ - name: 'Test', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - icon: OC.imagePath('core', 'actions/test'), - permissions: OC.PERMISSION_READ, - actionHandler: actionStub - }); - $tr = fileList.add(fileData); - }); - afterEach(function() { - OC.hideMenus(); - // jump past animations - clock.tick(1000); - clock.restore(); - }); - it('passes context to action handler', function() { - var notifyUpdateListenersSpy = sinon.spy(fileList.fileActions, '_notifyUpdateListeners'); - expect($tr.length).toEqual(1); - expect($tr.find('.action-test').length).toEqual(1); - $tr.find('.action-test').click(); - expect(actionStub.calledOnce).toEqual(true); - expect(actionStub.getCall(0).args[0]).toEqual('testName.txt'); - var context = actionStub.getCall(0).args[1]; - expect(context.$file.is($tr)).toEqual(true); - expect(context.fileList).toBeDefined(); - expect(context.fileActions).toBeDefined(); - expect(context.dir).toEqual('/subdir'); - expect(context.fileInfoModel.get('name')).toEqual('testName.txt'); - - expect(notifyUpdateListenersSpy.calledTwice).toEqual(true); - expect(notifyUpdateListenersSpy.calledBefore(actionStub)).toEqual(true); - expect(notifyUpdateListenersSpy.calledAfter(actionStub)).toEqual(true); - expect(notifyUpdateListenersSpy.getCall(0).args[0]).toEqual('beforeTriggerAction'); - expect(notifyUpdateListenersSpy.getCall(0).args[1]).toEqual({ - action: fileActions.getActions('all', OCA.Files.FileActions.TYPE_INLINE, OC.PERMISSION_READ)['Test'], - fileName: 'testName.txt', - context: context - }); - expect(notifyUpdateListenersSpy.getCall(1).args[0]).toEqual('afterTriggerAction'); - expect(notifyUpdateListenersSpy.getCall(1).args[1]).toEqual({ - action: fileActions.getActions('all', OCA.Files.FileActions.TYPE_INLINE, OC.PERMISSION_READ)['Test'], - fileName: 'testName.txt', - context: context - }); - - // when data-path is defined - actionStub.reset(); - $tr.attr('data-path', '/somepath'); - $tr.find('.action-test').click(); - context = actionStub.getCall(0).args[1]; - expect(context.dir).toEqual('/somepath'); - }); - it('also triggers action handler when calling triggerAction()', function() { - var notifyUpdateListenersSpy = sinon.spy(fileList.fileActions, '_notifyUpdateListeners'); - var model = new OCA.Files.FileInfoModel({ - id: 1, - name: 'Test.txt', - path: '/subdir', - mime: 'text/plain', - permissions: 31 - }); - fileActions.triggerAction('Test', model, fileList); - - expect(actionStub.calledOnce).toEqual(true); - expect(actionStub.getCall(0).args[0]).toEqual('Test.txt'); - expect(actionStub.getCall(0).args[1].fileList).toEqual(fileList); - expect(actionStub.getCall(0).args[1].fileActions).toEqual(fileActions); - expect(actionStub.getCall(0).args[1].fileInfoModel).toEqual(model); - - expect(notifyUpdateListenersSpy.calledTwice).toEqual(true); - expect(notifyUpdateListenersSpy.calledBefore(actionStub)).toEqual(true); - expect(notifyUpdateListenersSpy.calledAfter(actionStub)).toEqual(true); - expect(notifyUpdateListenersSpy.getCall(0).args[0]).toEqual('beforeTriggerAction'); - expect(notifyUpdateListenersSpy.getCall(0).args[1]).toEqual({ - action: fileActions.getActions('all', OCA.Files.FileActions.TYPE_INLINE, OC.PERMISSION_READ)['Test'], - fileName: 'Test.txt', - context: { - fileActions: fileActions, - fileInfoModel: model, - dir: '/subdir', - fileList: fileList, - $file: fileList.findFileEl('Test.txt') - } - }); - expect(notifyUpdateListenersSpy.getCall(1).args[0]).toEqual('afterTriggerAction'); - expect(notifyUpdateListenersSpy.getCall(1).args[1]).toEqual({ - action: fileActions.getActions('all', OCA.Files.FileActions.TYPE_INLINE, OC.PERMISSION_READ)['Test'], - fileName: 'Test.txt', - context: { - fileActions: fileActions, - fileInfoModel: model, - dir: '/subdir', - fileList: fileList, - $file: fileList.findFileEl('Test.txt') - } - }); - }); - it('triggers listener events when invoked directly', function() { - var context = {fileActions: new OCA.Files.FileActions()} - var notifyUpdateListenersSpy = sinon.spy(context.fileActions, '_notifyUpdateListeners'); - var testAction = fileActions.get('all', OCA.Files.FileActions.TYPE_INLINE, OC.PERMISSION_READ)['Test']; - - testAction('Test.txt', context); - - expect(actionStub.calledOnce).toEqual(true); - expect(actionStub.getCall(0).args[0]).toEqual('Test.txt'); - expect(actionStub.getCall(0).args[1]).toBe(context); - - expect(notifyUpdateListenersSpy.calledTwice).toEqual(true); - expect(notifyUpdateListenersSpy.calledBefore(actionStub)).toEqual(true); - expect(notifyUpdateListenersSpy.calledAfter(actionStub)).toEqual(true); - expect(notifyUpdateListenersSpy.getCall(0).args[0]).toEqual('beforeTriggerAction'); - expect(notifyUpdateListenersSpy.getCall(0).args[1]).toEqual({ - action: fileActions.getActions('all', OCA.Files.FileActions.TYPE_INLINE, OC.PERMISSION_READ)['Test'], - fileName: 'Test.txt', - context: context - }); - expect(notifyUpdateListenersSpy.getCall(1).args[0]).toEqual('afterTriggerAction'); - expect(notifyUpdateListenersSpy.getCall(1).args[1]).toEqual({ - action: fileActions.getActions('all', OCA.Files.FileActions.TYPE_INLINE, OC.PERMISSION_READ)['Test'], - fileName: 'Test.txt', - context: context - }); - }), - describe('actions menu', function() { - it('shows actions menu inside row when clicking the menu trigger', function() { - expect($tr.find('td.filename .fileActionsMenu').length).toEqual(0); - $tr.find('.action-menu').click(); - expect($tr.find('td.filename .fileActionsMenu').length).toEqual(1); - }); - it('shows highlight on current row', function() { - $tr.find('.action-menu').click(); - expect($tr.hasClass('mouseOver')).toEqual(true); - }); - it('cleans up after hiding', function() { - var slideUpStub = sinon.stub($.fn, 'slideUp'); - $tr.find('.action-menu').click(); - expect($tr.find('.fileActionsMenu').length).toEqual(1); - OC.hideMenus(); - // sliding animation - expect(slideUpStub.calledOnce).toEqual(true); - slideUpStub.getCall(0).args[1](); - expect($tr.hasClass('mouseOver')).toEqual(false); - expect($tr.find('.fileActionsMenu').length).toEqual(0); - }); - }); - }); - describe('custom rendering', function() { - var $tr; - beforeEach(function() { - var fileData = { - id: 18, - type: 'file', - name: 'testName.txt', - mimetype: 'text/plain', - size: '1234', - etag: 'a01234c', - mtime: '123456' - }; - $tr = fileList.add(fileData); - }); - it('regular function', function() { - var actionStub = sinon.stub(); - fileActions.registerAction({ - name: 'Test', - displayName: '', - mime: 'all', - type: OCA.Files.FileActions.TYPE_INLINE, - permissions: OC.PERMISSION_READ, - render: function(actionSpec, isDefault, context) { - expect(actionSpec.name).toEqual('Test'); - expect(actionSpec.displayName).toEqual(''); - expect(actionSpec.permissions).toEqual(OC.PERMISSION_READ); - expect(actionSpec.mime).toEqual('all'); - expect(isDefault).toEqual(false); - - expect(context.fileList).toEqual(fileList); - expect(context.$file[0]).toEqual($tr[0]); - - var $customEl = $('<a class="action action-test" href="#"><span>blabli</span><span>blabla</span></a>'); - $tr.find('td:first').append($customEl); - return $customEl; - }, - actionHandler: actionStub - }); - fileActions.display($tr.find('td.filename'), true, fileList); - - var $actionEl = $tr.find('td:first .action-test'); - expect($actionEl.length).toEqual(1); - expect($actionEl.hasClass('action')).toEqual(true); - - $actionEl.click(); - expect(actionStub.calledOnce).toEqual(true); - expect(actionStub.getCall(0).args[0]).toEqual('testName.txt'); - }); - }); - describe('merging', function() { - var $tr; - beforeEach(function() { - var fileData = { - id: 18, - type: 'file', - name: 'testName.txt', - path: '/anotherpath/there', - mimetype: 'text/plain', - size: '1234', - etag: 'a01234c', - mtime: '123456' - }; - $tr = fileList.add(fileData); - }); - afterEach(function() { - $tr = null; - }); - it('copies all actions to target file actions', function() { - var actions1 = new OCA.Files.FileActions(); - var actions2 = new OCA.Files.FileActions(); - var actionStub1 = sinon.stub(); - var actionStub2 = sinon.stub(); - actions1.registerAction({ - name: 'Test', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('core', 'actions/test'), - actionHandler: actionStub1 - }); - actions2.registerAction({ - name: 'Test2', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('core', 'actions/test'), - actionHandler: actionStub2 - }); - actions2.merge(actions1); - - actions2.display($tr.find('td.filename'), true, fileList); - - expect($tr.find('.action-test').length).toEqual(1); - expect($tr.find('.action-test2').length).toEqual(1); - - $tr.find('.action-test').click(); - expect(actionStub1.calledOnce).toEqual(true); - expect(actionStub2.notCalled).toEqual(true); - - actionStub1.reset(); - - $tr.find('.action-test2').click(); - expect(actionStub1.notCalled).toEqual(true); - expect(actionStub2.calledOnce).toEqual(true); - }); - it('overrides existing actions on merge', function() { - var actions1 = new OCA.Files.FileActions(); - var actions2 = new OCA.Files.FileActions(); - var actionStub1 = sinon.stub(); - var actionStub2 = sinon.stub(); - actions1.registerAction({ - name: 'Test', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('core', 'actions/test'), - actionHandler: actionStub1 - }); - actions2.registerAction({ - name: 'Test', // override - mime: 'all', - type: OCA.Files.FileActions.TYPE_INLINE, - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('core', 'actions/test'), - actionHandler: actionStub2 - }); - actions1.merge(actions2); - - actions1.display($tr.find('td.filename'), true, fileList); - - expect($tr.find('.action-test').length).toEqual(1); - - $tr.find('.action-test').click(); - expect(actionStub1.notCalled).toEqual(true); - expect(actionStub2.calledOnce).toEqual(true); - }); - it('overrides existing action when calling register after merge', function() { - var actions1 = new OCA.Files.FileActions(); - var actions2 = new OCA.Files.FileActions(); - var actionStub1 = sinon.stub(); - var actionStub2 = sinon.stub(); - actions1.registerAction({ - mime: 'all', - name: 'Test', - type: OCA.Files.FileActions.TYPE_INLINE, - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('core', 'actions/test'), - actionHandler: actionStub1 - }); - - actions1.merge(actions2); - - // late override - actions1.registerAction({ - mime: 'all', - name: 'Test', // override - type: OCA.Files.FileActions.TYPE_INLINE, - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('core', 'actions/test'), - actionHandler: actionStub2 - }); - - actions1.display($tr.find('td.filename'), true, fileList); - - expect($tr.find('.action-test').length).toEqual(1); - - $tr.find('.action-test').click(); - expect(actionStub1.notCalled).toEqual(true); - expect(actionStub2.calledOnce).toEqual(true); - }); - it('leaves original file actions untouched (clean copy)', function() { - var actions1 = new OCA.Files.FileActions(); - var actions2 = new OCA.Files.FileActions(); - var actionStub1 = sinon.stub(); - var actionStub2 = sinon.stub(); - actions1.registerAction({ - mime: 'all', - name: 'Test', - type: OCA.Files.FileActions.TYPE_INLINE, - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('core', 'actions/test'), - actionHandler: actionStub1 - }); - - // copy the Test action to actions2 - actions2.merge(actions1); - - // late override - actions2.registerAction({ - mime: 'all', - name: 'Test', // override - type: OCA.Files.FileActions.TYPE_INLINE, - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('core', 'actions/test'), - actionHandler: actionStub2 - }); - - // check if original actions still call the correct handler - actions1.display($tr.find('td.filename'), true, fileList); - - expect($tr.find('.action-test').length).toEqual(1); - - $tr.find('.action-test').click(); - expect(actionStub1.calledOnce).toEqual(true); - expect(actionStub2.notCalled).toEqual(true); - }); - }); - describe('events', function() { - var clock; - beforeEach(function() { - clock = sinon.useFakeTimers(); - }); - afterEach(function() { - clock.restore(); - }); - it('notifies update event handlers once after multiple changes', function() { - var actionStub = sinon.stub(); - var handler = sinon.stub(); - fileActions.on('registerAction', handler); - fileActions.registerAction({ - mime: 'all', - name: 'Test', - type: OCA.Files.FileActions.TYPE_INLINE, - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('core', 'actions/test'), - actionHandler: actionStub - }); - fileActions.registerAction({ - mime: 'all', - name: 'Test2', - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('core', 'actions/test'), - actionHandler: actionStub - }); - expect(handler.calledTwice).toEqual(true); - }); - it('does not notifies update event handlers after unregistering', function() { - var actionStub = sinon.stub(); - var handler = sinon.stub(); - fileActions.on('registerAction', handler); - fileActions.off('registerAction', handler); - fileActions.registerAction({ - mime: 'all', - name: 'Test', - type: OCA.Files.FileActions.TYPE_INLINE, - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('core', 'actions/test'), - actionHandler: actionStub - }); - fileActions.registerAction({ - mime: 'all', - name: 'Test2', - type: OCA.Files.FileActions.TYPE_INLINE, - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('core', 'actions/test'), - actionHandler: actionStub - }); - expect(handler.notCalled).toEqual(true); - }); - }); - describe('default actions', function() { - describe('download', function() { - it('redirects to URL and sets busy state to list', function() { - var handleDownloadStub = sinon.stub(OCA.Files.Files, 'handleDownload'); - var busyStub = sinon.stub(fileList, 'showFileBusyState'); - var fileData = { - id: 18, - type: 'file', - name: 'testName.txt', - mimetype: 'text/plain', - size: '1234', - etag: 'a01234c', - mtime: '123456', - permissions: OC.PERMISSION_READ | OC.PERMISSION_UPDATE - }; - - // note: FileActions.display() is called implicitly - fileList.add(fileData); - - var model = fileList.getModelForFile('testName.txt'); - - fileActions.registerDefaultActions(); - fileActions.triggerAction('Download', model, fileList); - - expect(busyStub.calledOnce).toEqual(true); - expect(busyStub.calledWith('testName.txt', true)).toEqual(true); - expect(handleDownloadStub.calledOnce).toEqual(true); - expect(handleDownloadStub.getCall(0).args[0]).toEqual( - OC.getRootPath() + '/remote.php/webdav/subdir/testName.txt' - ); - busyStub.reset(); - handleDownloadStub.yield(); - - expect(busyStub.calledOnce).toEqual(true); - expect(busyStub.calledWith('testName.txt', false)).toEqual(true); - - busyStub.restore(); - handleDownloadStub.restore(); - }); - }); - }); - describe('download spinner', function() { - var FileActions = OCA.Files.FileActions; - var $el; - - beforeEach(function() { - $el = $('<a href="#"><span class="icon icon-download"></span><span>Download</span></a>'); - }); - - it('replaces download icon with spinner', function() { - FileActions.updateFileActionSpinner($el, true); - expect($el.find('.icon.icon-loading-small').length).toEqual(1); - expect($el.find('.icon.icon-download').hasClass('hidden')).toEqual(true); - }); - it('replaces spinner back with download icon with spinner', function() { - FileActions.updateFileActionSpinner($el, true); - FileActions.updateFileActionSpinner($el, false); - expect($el.find('.icon.icon-loading-small').length).toEqual(0); - expect($el.find('.icon.icon-download').hasClass('hidden')).toEqual(false); - }); - }); -}); diff --git a/apps/files/tests/js/fileactionsmenuSpec.js b/apps/files/tests/js/fileactionsmenuSpec.js deleted file mode 100644 index a252e75c5e2..00000000000 --- a/apps/files/tests/js/fileactionsmenuSpec.js +++ /dev/null @@ -1,365 +0,0 @@ -/** -* @copyright 2015 Vincent Petry <pvince81@owncloud.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Julius Härtl <jus@bitgrid.net> - * @author Roland Tapken <roland@bitarbeiter.net> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0-or-later - * - * 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/>. - * - */ - -describe('OCA.Files.FileActionsMenu tests', function() { - var fileList, fileActions, menu, actionStub, menuContext, $tr; - - beforeEach(function() { - // init horrible parameters - var $body = $('#testArea'); - $body.append('<input type="hidden" id="permissions" value="31"></input>'); - // dummy files table - actionStub = sinon.stub(); - fileActions = new OCA.Files.FileActions(); - fileList = new OCA.Files.FileList($body, { - fileActions: fileActions - }); - fileList.changeDirectory('/subdir', false, true); - - fileActions.registerAction({ - name: 'Testdropdown', - displayName: 'Testdropdowndisplay', - mime: 'all', - permissions: OC.PERMISSION_READ, - icon: function () { - return OC.imagePath('core', 'actions/download'); - }, - actionHandler: actionStub - }); - - fileActions.registerAction({ - name: 'Testdropdownnoicon', - displayName: 'Testdropdowndisplaynoicon', - mime: 'all', - permissions: OC.PERMISSION_READ, - actionHandler: actionStub - }); - - fileActions.registerAction({ - name: 'Testinline', - displayName: 'Testinlinedisplay', - type: OCA.Files.FileActions.TYPE_INLINE, - mime: 'all', - permissions: OC.PERMISSION_READ - }); - - fileActions.registerAction({ - name: 'Testdefault', - displayName: 'Testdefaultdisplay', - mime: 'all', - permissions: OC.PERMISSION_READ - }); - fileActions.setDefault('all', 'Testdefault'); - - var fileData = { - id: 18, - type: 'file', - name: 'testName.txt', - mimetype: 'text/plain', - size: '1234', - etag: 'a01234c', - mtime: '123456' - }; - $tr = fileList.add(fileData); - - menuContext = { - $file: $tr, - fileList: fileList, - fileActions: fileActions, - dir: fileList.getCurrentDirectory() - }; - menu = new OCA.Files.FileActionsMenu(); - menu.show(menuContext); - }); - afterEach(function() { - fileActions = null; - fileList.destroy(); - fileList = undefined; - menu.remove(); - $('#permissions, .files-filestable').remove(); - }); - - describe('rendering', function() { - it('renders dropdown actions in menu', function() { - var $action = menu.$el.find('a[data-action=Testdropdown]'); - expect($action.length).toEqual(1); - expect($action.find('img').attr('src')) - .toEqual(OC.imagePath('core', 'actions/download')); - expect($action.find('.no-icon').length).toEqual(0); - - $action = menu.$el.find('a[data-action=Testdropdownnoicon]'); - expect($action.length).toEqual(1); - expect($action.find('img').length).toEqual(0); - expect($action.find('.no-icon').length).toEqual(1); - }); - it('does not render default actions', function() { - expect(menu.$el.find('a[data-action=Testdefault]').length).toEqual(0); - }); - it('render inline actions', function() { - expect(menu.$el.find('a[data-action=Testinline]').length).toEqual(1); - }); - it('render inline actions but it is hidden', function() { - expect(menu.$el.find('a[data-action=Testinline]').parent().hasClass('hidden')).toEqual(true); - }); - it('only renders actions relevant to the mime type', function() { - fileActions.registerAction({ - name: 'Match', - displayName: 'MatchDisplay', - mime: 'text/plain', - permissions: OC.PERMISSION_READ - }); - fileActions.registerAction({ - name: 'Nomatch', - displayName: 'NoMatchDisplay', - mime: 'application/octet-stream', - permissions: OC.PERMISSION_READ - }); - - menu.render(); - expect(menu.$el.find('a[data-action=Match]').length).toEqual(1); - expect(menu.$el.find('a[data-action=NoMatch]').length).toEqual(0); - }); - it('only renders actions relevant to the permissions', function() { - fileActions.registerAction({ - name: 'Match', - displayName: 'MatchDisplay', - mime: 'text/plain', - permissions: OC.PERMISSION_UPDATE - }); - fileActions.registerAction({ - name: 'Nomatch', - displayName: 'NoMatchDisplay', - mime: 'text/plain', - permissions: OC.PERMISSION_DELETE - }); - - menu.render(); - expect(menu.$el.find('a[data-action=Match]').length).toEqual(1); - expect(menu.$el.find('a[data-action=NoMatch]').length).toEqual(0); - }); - it('sorts by order attribute, then name', function() { - fileActions.registerAction({ - name: 'Baction', - displayName: 'Baction', - order: 2, - mime: 'text/plain', - permissions: OC.PERMISSION_ALL - }); - fileActions.registerAction({ - name: 'Zaction', - displayName: 'Zaction', - order: 1, - mime: 'text/plain', - permissions: OC.PERMISSION_ALL - }); - fileActions.registerAction({ - name: 'Yaction', - displayName: 'Yaction', - mime: 'text/plain', - permissions: OC.PERMISSION_ALL - }); - fileActions.registerAction({ - name: 'Waction', - displayName: 'Waction', - mime: 'text/plain', - permissions: OC.PERMISSION_ALL - }); - - menu.render(); - var zactionIndex = menu.$el.find('a[data-action=Zaction]').closest('li').index(); - var bactionIndex = menu.$el.find('a[data-action=Baction]').closest('li').index(); - expect(zactionIndex).toBeLessThan(bactionIndex); - - var wactionIndex = menu.$el.find('a[data-action=Waction]').closest('li').index(); - var yactionIndex = menu.$el.find('a[data-action=Yaction]').closest('li').index(); - expect(wactionIndex).toBeLessThan(yactionIndex); - }); - it('calls displayName function', function() { - var displayNameStub = sinon.stub().returns('Test'); - - fileActions.registerAction({ - name: 'Something', - displayName: displayNameStub, - mime: 'text/plain', - permissions: OC.PERMISSION_ALL - }); - - menu.render(); - - expect(displayNameStub.calledOnce).toEqual(true); - expect(displayNameStub.calledWith(menuContext)).toEqual(true); - expect(menu.$el.find('a[data-action=Something] span:not(.icon)').text()).toEqual('Test'); - }); - it('uses plain iconClass', function() { - fileActions.registerAction({ - name: 'Something', - mime: 'text/plain', - permissions: OC.PERMISSION_ALL, - iconClass: 'test' - }); - - menu.render(); - - expect(menu.$el.find('a[data-action=Something]').children('span.icon').hasClass('test')).toEqual(true); - }); - it('calls iconClass function', function() { - var iconClassStub = sinon.stub().returns('test'); - - fileActions.registerAction({ - name: 'Something', - mime: 'text/plain', - permissions: OC.PERMISSION_ALL, - iconClass: iconClassStub - }); - - menu.render(); - - expect(iconClassStub.calledOnce).toEqual(true); - expect(iconClassStub.calledWith(menuContext.$file.attr('data-file'), menuContext)).toEqual(true); - expect(menu.$el.find('a[data-action=Something]').children('span.icon').hasClass('test')).toEqual(true); - }); - }); - - describe('action handler', function() { - it('calls action handler when clicking menu item', function() { - var $action = menu.$el.find('a[data-action=Testdropdown]'); - $action.click(); - - expect(actionStub.calledOnce).toEqual(true); - expect(actionStub.getCall(0).args[0]).toEqual('testName.txt'); - expect(actionStub.getCall(0).args[1].$file[0]).toEqual($tr[0]); - expect(actionStub.getCall(0).args[1].fileList).toEqual(fileList); - expect(actionStub.getCall(0).args[1].fileActions).toEqual(fileActions); - expect(actionStub.getCall(0).args[1].dir).toEqual('/subdir'); - }); - }); - describe('default actions from registerDefaultActions', function() { - beforeEach(function() { - fileActions.clear(); - fileActions.registerDefaultActions(); - }); - it('redirects to download URL when clicking download', function() { - var redirectStub = sinon.stub(OC, 'redirect'); - var fileData = { - id: 18, - type: 'file', - name: 'testName.txt', - mimetype: 'text/plain', - size: '1234', - etag: 'a01234c', - mtime: '123456' - }; - var $tr = fileList.add(fileData); - fileActions.display($tr.find('td.filename'), true, fileList); - - var menuContext = { - $file: $tr, - fileList: fileList, - fileActions: fileActions, - fileInfoModel: new OCA.Files.FileInfoModel(fileData), - dir: fileList.getCurrentDirectory() - }; - menu = new OCA.Files.FileActionsMenu(); - menu.show(menuContext); - - menu.$el.find('.action-download').click(); - - expect(redirectStub.calledOnce).toEqual(true); - expect(redirectStub.getCall(0).args[0]).toContain( - OC.getRootPath() + - '/remote.php/webdav/subdir/testName.txt' - ); - redirectStub.restore(); - }); - it('takes the file\'s path into account when clicking download', function() { - var redirectStub = sinon.stub(OC, 'redirect'); - var fileData = { - id: 18, - type: 'file', - name: 'testName.txt', - path: '/anotherpath/there', - mimetype: 'text/plain', - size: '1234', - etag: 'a01234c', - mtime: '123456' - }; - var $tr = fileList.add(fileData); - fileActions.display($tr.find('td.filename'), true, fileList); - - var menuContext = { - $file: $tr, - fileList: fileList, - fileActions: fileActions, - fileInfoModel: new OCA.Files.FileInfoModel(fileData), - dir: '/anotherpath/there' - }; - menu = new OCA.Files.FileActionsMenu(); - menu.show(menuContext); - - menu.$el.find('.action-download').click(); - - expect(redirectStub.calledOnce).toEqual(true); - expect(redirectStub.getCall(0).args[0]).toContain( - OC.getRootPath() + '/remote.php/webdav/anotherpath/there/testName.txt' - ); - redirectStub.restore(); - }); - it('deletes file when clicking delete', function() { - var deleteStub = sinon.stub(fileList, 'do_delete'); - var fileData = { - id: 18, - type: 'file', - name: 'testName.txt', - path: '/somepath/dir', - mimetype: 'text/plain', - size: '1234', - etag: 'a01234c', - mtime: '123456' - }; - var $tr = fileList.add(fileData); - fileActions.display($tr.find('td.filename'), true, fileList); - - var menuContext = { - $file: $tr, - fileList: fileList, - fileActions: fileActions, - fileInfoModel: new OCA.Files.FileInfoModel(fileData), - dir: '/somepath/dir' - }; - menu = new OCA.Files.FileActionsMenu(); - menu.show(menuContext); - - menu.$el.find('.action-delete').click(); - - expect(deleteStub.calledOnce).toEqual(true); - expect(deleteStub.getCall(0).args[0]).toEqual('testName.txt'); - expect(deleteStub.getCall(0).args[1]).toEqual('/somepath/dir'); - deleteStub.restore(); - }); - }); -}); - diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js deleted file mode 100644 index cd3510c2faa..00000000000 --- a/apps/files/tests/js/filelistSpec.js +++ /dev/null @@ -1,3447 +0,0 @@ -/** -* @copyright 2014 Vincent Petry <pvince81@owncloud.com> - * - * @author Abijeet <abijeetpatro@gmail.com> - * @author Azul <azul@riseup.net> - * @author Bernd Stellwag <burned@zerties.org> - * @author Bjoern Schiessle <bjoern@schiessle.org> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Clark Tomlinson <fallen013@gmail.com> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Hasso Tepper <hasso@zone.ee> - * @author Jan-Christoph Borchardt <hey@jancborchardt.net> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Jörn Friedrich Dreyer <jfd@butonic.de> - * @author Julius Härtl <jus@bitgrid.net> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Michael Weimann <mail@michael-weimann.eu> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Nazar Mokrynskyi <nazar@mokrynskyi.com> - * @author noveens <noveen.sachdeva@research.iiit.ac.in> - * @author Remco Brenninkmeijer <requist1@starmail.nl> - * @author Robin Appelman <robin@icewind.nl> - * @author Robin McCorkell <robin@mccorkell.me.uk> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Roland Tapken <roland@bitarbeiter.net> - * @author Thomas Citharel <nextcloud@tcit.fr> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Tomasz Grobelny <tomasz@grobelny.net> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0-or-later - * - * 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/>. - * - */ - -describe('OCA.Files.FileList tests', function() { - var FileInfo = OC.Files.FileInfo; - var testFiles, testRoot, notificationStub, fileList, pageSizeStub; - var bcResizeStub; - var filesClient; - var filesConfig; - var redirectStub; - - /** - * Generate test file data - */ - function generateFiles(startIndex, endIndex) { - var files = []; - var name; - for (var i = startIndex; i <= endIndex; i++) { - name = 'File with index '; - if (i < 10) { - // do not rely on localeCompare here - // and make the sorting predictable - // cross-browser - name += '0'; - } - name += i + '.txt'; - files.push(new FileInfo({ - id: i, - type: 'file', - name: name, - mimetype: 'text/plain', - size: i * 2, - etag: 'abc' - })); - } - return files; - } - - beforeEach(function() { - filesConfig = new OC.Backbone.Model({ - showhidden: true - }); - - filesClient = new OC.Files.Client({ - host: 'localhost', - port: 80, - // FIXME: uncomment after fixing the test OC.getRootPath() - //root: OC.getRootPath() + '/remote.php/webdav', - root: '/remote.php/webdav', - useHTTPS: false - }); - redirectStub = sinon.stub(OC, 'redirect'); - notificationStub = sinon.stub(OC.Notification, 'show'); - // prevent resize algo to mess up breadcrumb order while - // testing - bcResizeStub = sinon.stub(OCA.Files.BreadCrumb.prototype, '_resize'); - - // init parameters and test table elements - $('#testArea').append( - '<div id="app-content-files">' + - // init horrible parameters - '<input type="hidden" id="permissions" value="31"/>' + - // dummy controls - '<div class="files-controls">' + - ' <div class="actions creatable"></div>' + - ' <div class="notCreatable"></div>' + - '</div>' + - // uploader - '<input type="file" id="file_upload_start" name="files[]" multiple="multiple">' + - // dummy table - // TODO: at some point this will be rendered by the fileList class itself! - '<table class="files-filestable list-container view-grid">' + - '<thead><tr>' + - '<th class="hidden column-name">' + - '<input type="checkbox" id="select_all_files" class="select-all checkbox">' + - '<a class="name columntitle" href="#" onclick="event.preventDefault()" data-sort="name"><span>Name</span><span class="sort-indicator"></span></a>' + - '<span class="selectedActions hidden">' + - '<a class="actions-selected" href="#" onclick="event.preventDefault()"><span class="icon icon-more"></span><span>Actions</span></a>' + - '</th>' + - '<th class="hidden column-size"><a class="columntitle" href="#" onclick="event.preventDefault()" data-sort="size"><span class="sort-indicator"></span></a></th>' + - '<th class="hidden column-mtime"><a class="columntitle" href="#" onclick="event.preventDefault()" data-sort="mtime"><span class="sort-indicator"></span></a></th>' + - '</tr></thead>' + - '<tbody class="files-fileList"></tbody>' + - '<tfoot></tfoot>' + - '</table>' + - // TODO: move to handlebars template - '<div class="emptyfilelist emptycontent"><h2>Empty content message</h2><p class="uploadmessage">Upload message</p></div>' + - '<div class="nofilterresults hidden"></div>' + - '</div>' - ); - - testRoot = new FileInfo({ - // root entry - id: 99, - type: 'dir', - name: '/subdir', - mimetype: 'httpd/unix-directory', - size: 1200000, - etag: 'a0b0c0d0', - permissions: OC.PERMISSION_ALL - }); - testFiles = [new FileInfo({ - id: 1, - type: 'file', - name: 'One.txt', - mimetype: 'text/plain', - mtime: 123456789, - size: 12, - etag: 'abc', - permissions: OC.PERMISSION_ALL - }), new FileInfo({ - id: 2, - type: 'file', - name: 'Two.jpg', - mimetype: 'image/jpeg', - mtime: 234567890, - size: 12049, - etag: 'def', - permissions: OC.PERMISSION_ALL - }), new FileInfo({ - id: 3, - type: 'file', - name: 'Three.pdf', - mimetype: 'application/pdf', - mtime: 234560000, - size: 58009, - etag: '123', - permissions: OC.PERMISSION_ALL - }), new FileInfo({ - id: 4, - type: 'dir', - name: 'somedir', - mimetype: 'httpd/unix-directory', - mtime: 134560000, - size: 250, - etag: '456', - permissions: OC.PERMISSION_ALL - })]; - pageSizeStub = sinon.stub(OCA.Files.FileList.prototype, 'pageSize').returns(20); - fileList = new OCA.Files.FileList($('#app-content-files'), { - filesClient: filesClient, - config: filesConfig, - dir: '/subdir', - enableUpload: true, - multiSelectMenu: [{ - name: 'copyMove', - displayName: t('files', 'Move or copy'), - iconClass: 'icon-external', - }, - { - name: 'download', - displayName: t('files', 'Download'), - iconClass: 'icon-download', - }, - { - name: 'delete', - displayName: t('files', 'Delete'), - iconClass: 'icon-delete', - }] - }); - }); - afterEach(function() { - testFiles = undefined; - if (fileList) { - fileList.destroy(); - } - fileList = undefined; - - notificationStub.restore(); - bcResizeStub.restore(); - pageSizeStub.restore(); - redirectStub.restore(); - }); - describe('Getters', function() { - it('Returns the current directory', function() { - fileList.changeDirectory('/one/two/three', false, true); - expect(fileList.getCurrentDirectory()).toEqual('/one/two/three'); - }); - it('Returns the directory permissions as int', function() { - $('#permissions').val('23'); - expect(fileList.getDirectoryPermissions()).toEqual(23); - }); - }); - describe('Adding files', function() { - it('generates file element with correct attributes when calling add() with file data', function() { - var fileData = new FileInfo({ - id: 18, - name: 'testName.txt', - mimetype: 'text/plain', - size: 1234, - etag: 'a01234c', - mtime: 123456 - }); - var $tr = fileList.add(fileData); - - expect($tr).toBeDefined(); - expect($tr[0].tagName.toLowerCase()).toEqual('tr'); - expect($tr.attr('data-id')).toEqual('18'); - expect($tr.attr('data-type')).toEqual('file'); - expect($tr.attr('data-file')).toEqual('testName.txt'); - expect($tr.attr('data-size')).toEqual('1234'); - expect($tr.attr('data-etag')).toEqual('a01234c'); - expect($tr.attr('data-permissions')).toEqual('31'); - expect($tr.attr('data-mime')).toEqual('text/plain'); - expect($tr.attr('data-mtime')).toEqual('123456'); - expect($tr.attr('data-e2eencrypted')).toEqual('false'); - expect($tr.find('a.name').attr('href')) - .toEqual(OC.getRootPath() + '/remote.php/webdav/subdir/testName.txt'); - expect($tr.find('.nametext').text().trim()).toEqual('testName.txt'); - - expect($tr.find('.filesize').text()).toEqual('1 KB'); - expect($tr.find('.date').text()).not.toEqual('?'); - expect(fileList.findFileEl('testName.txt')[0]).toEqual($tr[0]); - }); - it('generates file element with url for default action when one is defined', function() { - var actionStub = sinon.stub(); - fileList.setFiles(testFiles); - fileList.fileActions.registerAction({ - mime: 'text/plain', - name: 'Test', - type: OCA.Files.FileActions.TYPE_INLINE, - permissions: OC.PERMISSION_ALL, - icon: function() { - // Specify icon for history button - return OC.imagePath('core','actions/history'); - }, - actionHandler: actionStub - }); - fileList.fileActions.setDefault('text/plain', 'Test'); - var fileData = new FileInfo({ - id: 18, - name: 'testName.txt', - mimetype: 'text/plain', - size: 1234, - etag: 'a01234c', - mtime: 123456 - }); - var $tr = fileList.add(fileData); - expect($tr.find('a.name').attr('href')) - .toEqual(OC.getRootPath() + '/index.php/apps/files?dir=&openfile=18'); - }); - it('generates dir element with correct attributes when calling add() with dir data', function() { - var fileData = new FileInfo({ - id: 19, - name: 'testFolder', - mimetype: 'httpd/unix-directory', - size: 1234, - etag: 'a01234c', - mtime: 123456 - }); - var $tr = fileList.add(fileData); - - expect($tr).toBeDefined(); - expect($tr[0].tagName.toLowerCase()).toEqual('tr'); - expect($tr.attr('data-id')).toEqual('19'); - expect($tr.attr('data-type')).toEqual('dir'); - expect($tr.attr('data-file')).toEqual('testFolder'); - expect($tr.attr('data-size')).toEqual('1234'); - expect($tr.attr('data-etag')).toEqual('a01234c'); - expect($tr.attr('data-permissions')).toEqual('31'); - expect($tr.attr('data-mime')).toEqual('httpd/unix-directory'); - expect($tr.attr('data-mtime')).toEqual('123456'); - expect($tr.attr('data-e2eencrypted')).toEqual('false'); - - expect($tr.find('.filesize').text()).toEqual('1 KB'); - expect($tr.find('.date').text()).not.toEqual('?'); - - expect(fileList.findFileEl('testFolder')[0]).toEqual($tr[0]); - }); - it('generates file element with default attributes when calling add() with minimal data', function() { - var fileData = { - type: 'file', - name: 'testFile.txt' - }; - - var $tr = fileList.add(fileData); - - expect($tr).toBeDefined(); - expect($tr[0].tagName.toLowerCase()).toEqual('tr'); - expect($tr.attr('data-id')).toBeUndefined(); - expect($tr.attr('data-type')).toEqual('file'); - expect($tr.attr('data-file')).toEqual('testFile.txt'); - expect($tr.attr('data-size')).toBeUndefined(); - expect($tr.attr('data-etag')).toBeUndefined(); - expect($tr.attr('data-permissions')).toEqual('31'); - expect($tr.attr('data-mime')).toBeUndefined(); - expect($tr.attr('data-e2eencrypted')).toEqual('false'); - - expect($tr.find('.filesize').text()).toEqual('Pending'); - expect($tr.find('.date').text()).not.toEqual('?'); - }); - it('generates dir element with default attributes when calling add() with minimal data', function() { - var fileData = { - type: 'dir', - name: 'testFolder' - }; - var $tr = fileList.add(fileData); - - expect($tr).toBeDefined(); - expect($tr[0].tagName.toLowerCase()).toEqual('tr'); - expect($tr.attr('data-id')).toBeUndefined(); - expect($tr.attr('data-type')).toEqual('dir'); - expect($tr.attr('data-file')).toEqual('testFolder'); - expect($tr.attr('data-size')).toBeUndefined(); - expect($tr.attr('data-etag')).toBeUndefined(); - expect($tr.attr('data-permissions')).toEqual('31'); - expect($tr.attr('data-mime')).toEqual('httpd/unix-directory'); - expect($tr.attr('data-e2eencrypted')).toEqual('false'); - - expect($tr.find('.filesize').text()).toEqual('Pending'); - expect($tr.find('.date').text()).not.toEqual('?'); - }); - it('generates dir element with true e2eencrypted attribute when calling add() with minimal data including isEncrypted', function() { - var fileData = { - type: 'dir', - name: 'testFolder', - isEncrypted: true - }; - var $tr = fileList.add(fileData); - expect($tr.attr('data-e2eencrypted')).toEqual('true'); - }); - it('generates file element with no permissions when permissions are explicitly none', function() { - var fileData = { - type: 'dir', - name: 'testFolder', - permissions: OC.PERMISSION_NONE - }; - var $tr = fileList.add(fileData); - expect($tr.attr('data-permissions')).toEqual('0'); - }); - it('generates file element with zero size when size is explicitly zero', function() { - var fileData = { - type: 'dir', - name: 'testFolder', - size: '0' - }; - var $tr = fileList.add(fileData); - expect($tr.find('.filesize').text()).toEqual('0 KB'); - }); - it('generates file element with unknown date when mtime invalid', function() { - var fileData = { - type: 'dir', - name: 'testFolder', - mtime: -1 - }; - var $tr = fileList.add(fileData); - expect($tr.find('.date .modified').text()).toEqual('?'); - }); - it('adds new file to the end of the list', function() { - var $tr; - var fileData = { - type: 'file', - name: 'ZZZ.txt' - }; - fileList.setFiles(testFiles); - $tr = fileList.add(fileData); - expect($tr.index()).toEqual(4); - }); - it('inserts files in a sorted manner when insert option is enabled', function() { - for (var i = 0; i < testFiles.length; i++) { - fileList.add(testFiles[i]); - } - expect(fileList.files[0].name).toEqual('somedir'); - expect(fileList.files[1].name).toEqual('One.txt'); - expect(fileList.files[2].name).toEqual('Three.pdf'); - expect(fileList.files[3].name).toEqual('Two.jpg'); - }); - it('inserts new file at correct position', function() { - var $tr; - var fileData = { - type: 'file', - name: 'P comes after O.txt' - }; - for (var i = 0; i < testFiles.length; i++) { - fileList.add(testFiles[i]); - } - $tr = fileList.add(fileData); - // after "One.txt" - expect($tr.index()).toEqual(2); - expect(fileList.files[2]).toEqual(fileData); - }); - it('inserts new folder at correct position in insert mode', function() { - var $tr; - var fileData = { - type: 'dir', - name: 'somedir2 comes after somedir' - }; - for (var i = 0; i < testFiles.length; i++) { - fileList.add(testFiles[i]); - } - $tr = fileList.add(fileData); - expect($tr.index()).toEqual(1); - expect(fileList.files[1]).toEqual(fileData); - }); - it('inserts new file at the end correctly', function() { - var $tr; - var fileData = { - type: 'file', - name: 'zzz.txt' - }; - for (var i = 0; i < testFiles.length; i++) { - fileList.add(testFiles[i]); - } - $tr = fileList.add(fileData); - expect($tr.index()).toEqual(4); - expect(fileList.files[4]).toEqual(fileData); - }); - it('removes empty content message and shows summary when adding first file', function() { - var $summary; - var fileData = { - type: 'file', - name: 'first file.txt', - size: 12 - }; - fileList.setFiles([]); - expect(fileList.isEmpty).toEqual(true); - fileList.add(fileData); - $summary = $('.files-filestable .summary'); - expect($summary.hasClass('hidden')).toEqual(false); - // yes, ugly... - expect($summary.find('.fileinfo').text()).toEqual('1 file'); - expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true); - expect($summary.find('.connector').hasClass('hidden')).toEqual(true); - expect($summary.find('.fileinfo').hasClass('hidden')).toEqual(false); - expect($summary.find('.filesize').text()).toEqual('12 B'); - expect($('.files-filestable thead th').hasClass('hidden')).toEqual(false); - expect($('.emptyfilelist.emptycontent').hasClass('hidden')).toEqual(true); - expect(fileList.isEmpty).toEqual(false); - }); - it('correctly adds the extension markup and show hidden files completely in gray', function() { - var $tr; - var testDataAndExpectedResult = [ - {file: {type: 'file', name: 'ZZZ.txt'}, extension: '.txt'}, - {file: {type: 'file', name: 'ZZZ.tar.gz'}, extension: '.gz'}, - {file: {type: 'file', name: 'test.with.some.dots.in.it.txt'}, extension: '.txt'}, - // we render hidden files completely in gray - {file: {type: 'file', name: '.test.with.some.dots.in.it.txt'}, extension: '.test.with.some.dots.in.it.txt'}, - {file: {type: 'file', name: '.hidden'}, extension: '.hidden'}, - ]; - fileList.setFiles(testFiles); - - for(var i = 0; i < testDataAndExpectedResult.length; i++) { - var testSet = testDataAndExpectedResult[i]; - var fileData = testSet['file']; - $tr = fileList.add(fileData); - expect($tr.find('.nametext .extension').text()).toEqual(testSet['extension']); - } - }); - }); - describe('Hidden files', function() { - it('sets the class hidden-file for hidden files', function() { - var fileData = { - type: 'dir', - name: '.testFolder' - }; - var $tr = fileList.add(fileData); - - expect($tr).toBeDefined(); - expect($tr.hasClass('hidden-file')).toEqual(true); - }); - it('does not set the class hidden-file for visible files', function() { - var fileData = { - type: 'dir', - name: 'testFolder' - }; - var $tr = fileList.add(fileData); - - expect($tr).toBeDefined(); - expect($tr.hasClass('hidden-file')).toEqual(false); - }); - it('toggles the list\'s class when toggling hidden files', function() { - expect(fileList.$el.hasClass('hide-hidden-files')).toEqual(false); - window._nc_event_bus.emit('files:config:updated', { key: 'show_hidden', value: false }); - expect(fileList.$el.hasClass('hide-hidden-files')).toEqual(true); - window._nc_event_bus.emit('files:config:updated', { key: 'show_hidden', value: true }) - expect(fileList.$el.hasClass('hide-hidden-files')).toEqual(false); - }); - }); - describe('Removing files from the list', function() { - it('Removes file from list when calling remove() and updates summary', function() { - var $summary; - var $removedEl; - fileList.setFiles(testFiles); - $removedEl = fileList.remove('One.txt'); - expect($removedEl).toBeDefined(); - expect($removedEl.attr('data-file')).toEqual('One.txt'); - expect($('.files-fileList tr').length).toEqual(3); - expect(fileList.files.length).toEqual(3); - expect(fileList.findFileEl('One.txt').length).toEqual(0); - - $summary = $('.files-filestable .summary'); - expect($summary.hasClass('hidden')).toEqual(false); - expect($summary.find('.dirinfo').text()).toEqual('1 folder'); - expect($summary.find('.fileinfo').text()).toEqual('2 files'); - expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(false); - expect($summary.find('.fileinfo').hasClass('hidden')).toEqual(false); - expect($summary.find('.filesize').text()).toEqual('69 KB'); - expect(fileList.isEmpty).toEqual(false); - }); - it('Shows empty content when removing last file', function() { - var $summary; - fileList.setFiles([testFiles[0]]); - fileList.remove('One.txt'); - expect($('.files-fileList tr').length).toEqual(0); - expect(fileList.files.length).toEqual(0); - expect(fileList.findFileEl('One.txt').length).toEqual(0); - - $summary = $('.files-filestable .summary'); - expect($summary.hasClass('hidden')).toEqual(true); - expect($('.files-filestable thead th').hasClass('hidden')).toEqual(true); - expect($('.emptyfilelist.emptycontent').hasClass('hidden')).toEqual(false); - expect(fileList.isEmpty).toEqual(true); - }); - }); - describe('Deleting files', function() { - var deferredDelete; - var deleteStub; - - beforeEach(function() { - deferredDelete = $.Deferred(); - deleteStub = sinon.stub(filesClient, 'remove'); - }); - afterEach(function() { - deleteStub.restore(); - }); - - function doDelete() { - // note: normally called from FileActions - return fileList.do_delete(['One.txt', 'Two.jpg']).then(function(){ - - expect(deleteStub.calledTwice).toEqual(true); - expect(deleteStub.getCall(0).args[0]).toEqual('/subdir/One.txt'); - expect(deleteStub.getCall(1).args[0]).toEqual('/subdir/Two.jpg'); - }); - } - it('calls delete.php, removes the deleted entries and updates summary', function(done) { - var $summary; - fileList.setFiles(testFiles); - deferredDelete1 = $.Deferred(); - deferredDelete2 = $.Deferred(); - deleteStub.onCall(0).callsFake(function(src){ - expect(deleteStub.calledOnce).toEqual(true); - expect(src).toEqual('/subdir/One.txt'); - return deferredDelete1.promise(); - }); - deleteStub.onCall(1).callsFake(function(src){ - expect(deleteStub.calledTwice).toEqual(true); - expect(src).toEqual('/subdir/Two.jpg'); - return deferredDelete2.promise(); - }); - - var promise = fileList.do_delete(['One.txt', 'Two.jpg']); - deferredDelete1.resolve(200); - deferredDelete2.resolve(200); - return promise.then(function(){ - expect(fileList.findFileEl('One.txt').length).toEqual(0); - expect(fileList.findFileEl('Two.jpg').length).toEqual(0); - expect(fileList.findFileEl('Three.pdf').length).toEqual(1); - expect(fileList.$fileList.find('tr').length).toEqual(2); - - $summary = $('.files-filestable .summary'); - expect($summary.hasClass('hidden')).toEqual(false); - expect($summary.find('.dirinfo').text()).toEqual('1 folder'); - expect($summary.find('.fileinfo').text()).toEqual('1 file'); - expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(false); - expect($summary.find('.fileinfo').hasClass('hidden')).toEqual(false); - expect($summary.find('.filesize').text()).toEqual('57 KB'); - expect(fileList.isEmpty).toEqual(false); - expect($('.files-filestable thead th').hasClass('hidden')).toEqual(false); - expect($('.emptyfilelist.emptycontent').hasClass('hidden')).toEqual(true); - - expect(notificationStub.notCalled).toEqual(true); - }).then(done, done); - }); - it('shows busy state on files to be deleted', function(done) { - fileList.setFiles(testFiles); - deferredDelete1 = $.Deferred(); - deferredDelete2 = $.Deferred(); - deleteStub.onCall(0).callsFake(function(src){ - expect(fileList.findFileEl('One.txt').hasClass('busy')).toEqual(true); - expect(fileList.findFileEl('Three.pdf').hasClass('busy')).toEqual(false); - - expect(deleteStub.calledOnce).toEqual(true); - expect(src).toEqual('/subdir/One.txt'); - return deferredDelete1.promise(); - }); - deleteStub.onCall(1).callsFake(function(src){ - expect(fileList.findFileEl('Two.jpg').hasClass('busy')).toEqual(true); - expect(fileList.findFileEl('Three.pdf').hasClass('busy')).toEqual(false); - - expect(deleteStub.calledTwice).toEqual(true); - expect(src).toEqual('/subdir/Two.jpg'); - return deferredDelete2.promise(); - }); - var promise = fileList.do_delete(['One.txt', 'Two.jpg']).then(function(){ - expect(deleteStub.calledTwice).toEqual(true); - }); - deferredDelete1.resolve(200); - deferredDelete2.resolve(200); - return promise.then(function(){ - expect(fileList.findFileEl('One.txt').hasClass('busy')).toEqual(false); - expect(fileList.findFileEl('Two.jpg').hasClass('busy')).toEqual(false); - }).then(done, done); - }); - it('shows busy state on all files when deleting all', function(done) { - fileList.setFiles(testFiles); - var deferredDeleteArray = []; - var count = 0; - for (var i = 0; i < 4; i++) { - (function(i, fn){ - deferredDeleteArray.push($.Deferred()); - deleteStub.onCall(i).callsFake(function(src){ - expect(fileList.findFileEl(fn).hasClass('busy')).toEqual(true); - count++; - return deferredDeleteArray[i].promise(); - }); - })(i, testFiles[i].name); - } - var promise = fileList.do_delete(); - for (var i = 0; i < 4; i++) { - deferredDeleteArray[i].resolve(200); - } - return promise.then(function(){ - expect(count).toEqual(4); - }).then(done, done); - }); - it('updates summary when deleting last file', function(done) { - var $summary; - fileList.setFiles([testFiles[0], testFiles[1]]); - deleteStub.returns(deferredDelete.promise()); - deferredDelete.resolve(200); - - return doDelete().then(function(){ - expect(fileList.$fileList.find('tr').length).toEqual(0); - $summary = $('.files-filestable .summary'); - expect($summary.hasClass('hidden')).toEqual(true); - expect(fileList.isEmpty).toEqual(true); - expect(fileList.files.length).toEqual(0); - expect($('.files-filestable thead th').hasClass('hidden')).toEqual(true); - expect($('.emptyfilelist.emptycontent').hasClass('hidden')).toEqual(false); - }).then(done, done); - }); - it('bring back deleted item when delete call failed', function(done) { - fileList.setFiles(testFiles); - deleteStub.returns(deferredDelete.promise()); - var promise = doDelete(); - deferredDelete.reject(403); - return promise.then(function(){ - // files are still in the list - expect(fileList.findFileEl('One.txt').length).toEqual(1); - expect(fileList.findFileEl('Two.jpg').length).toEqual(1); - expect(fileList.$fileList.find('tr').length).toEqual(4); - - expect(notificationStub.calledTwice).toEqual(true); - }).then(done, done); - }); - it('remove file from list if delete call returned 404 not found', function(done) { - fileList.setFiles(testFiles); - deleteStub.returns(deferredDelete.promise()); - var promise = doDelete(); - deferredDelete.reject(404); - return promise.then(function(){ - expect(fileList.findFileEl('One.txt').length).toEqual(0); - expect(fileList.findFileEl('Two.jpg').length).toEqual(0); - expect(fileList.$fileList.find('tr').length).toEqual(2); - - expect(notificationStub.notCalled).toEqual(true); - }).then(done, done); - }); - }); - describe('Renaming files', function() { - var deferredRename; - var renameStub; - - beforeEach(function() { - deferredRename = $.Deferred(); - renameStub = sinon.stub(filesClient, 'move').returns(deferredRename.promise()); - - for (var i = 0; i < testFiles.length; i++) { - var file = testFiles[i]; - file.path = '/some/subdir'; - fileList.add(file, {silent: true}); - } - }); - afterEach(function() { - renameStub.restore(); - }); - - function doCancelRename() { - var $input; - - // trigger rename prompt - fileList.rename('One.txt'); - $input = fileList.$fileList.find('input.filename'); - // keep same name - $input.val('One.txt'); - // trigger submit because triggering blur doesn't work in all browsers - $input.closest('form').trigger('submit'); - - expect(renameStub.notCalled).toEqual(true); - } - function doRename() { - var $input; - - // trigger rename prompt - fileList.rename('One.txt'); - $input = fileList.$fileList.find('input.filename'); - $input.val('Tu_after_three.txt'); - // trigger submit because triggering blur doesn't work in all browsers - $input.closest('form').trigger('submit'); - - expect(renameStub.calledOnce).toEqual(true); - expect(renameStub.getCall(0).args[0]).toEqual('/some/subdir/One.txt'); - expect(renameStub.getCall(0).args[1]).toEqual('/some/subdir/Tu_after_three.txt'); - } - it('Inserts renamed file entry at correct position if rename ajax call suceeded', function() { - doRename(); - - deferredRename.resolve(201); - - // element stays renamed - expect(fileList.findFileEl('One.txt').length).toEqual(0); - expect(fileList.findFileEl('Tu_after_three.txt').length).toEqual(1); - expect(fileList.findFileEl('Tu_after_three.txt').index()).toEqual(2); // after Two.jpg - - expect(notificationStub.notCalled).toEqual(true); - }); - it('Reverts file entry if rename ajax call failed', function() { - doRename(); - - deferredRename.reject(403); - - // element was reverted - expect(fileList.findFileEl('One.txt').length).toEqual(1); - expect(fileList.findFileEl('One.txt').index()).toEqual(1); // after somedir - expect(fileList.findFileEl('Tu_after_three.txt').length).toEqual(0); - - expect(notificationStub.calledOnce).toEqual(true); - }); - it('Correctly updates file link after rename', function() { - var $tr; - doRename(); - - deferredRename.resolve(201); - - $tr = fileList.findFileEl('Tu_after_three.txt'); - expect($tr.find('a.name').attr('href')) - .toEqual(OC.getRootPath() + '/remote.php/webdav/some/subdir/Tu_after_three.txt'); - }); - it('Triggers "fileActionsReady" event after rename', function() { - var handler = sinon.stub(); - fileList.$fileList.on('fileActionsReady', handler); - doRename(); - expect(handler.notCalled).toEqual(true); - - deferredRename.resolve(201); - - expect(handler.calledOnce).toEqual(true); - expect(fileList.$fileList.find('.test').length).toEqual(0); - }); - it('Leaves the summary alone when reinserting renamed element', function() { - var $summary = $('.files-filestable .summary'); - doRename(); - - deferredRename.resolve(201); - - expect($summary.find('.dirinfo').text()).toEqual('1 folder'); - expect($summary.find('.fileinfo').text()).toEqual('3 files'); - }); - it('Leaves the summary alone when cancel renaming', function() { - var $summary = $('.files-filestable .summary'); - doCancelRename(); - expect($summary.find('.dirinfo').text()).toEqual('1 folder'); - expect($summary.find('.fileinfo').text()).toEqual('3 files'); - }); - it('Shows busy state while rename in progress', function() { - var $tr; - doRename(); - - // element is renamed before the request finishes - $tr = fileList.findFileEl('Tu_after_three.txt'); - expect($tr.length).toEqual(1); - expect(fileList.findFileEl('One.txt').length).toEqual(0); - // file actions are hidden - expect($tr.hasClass('busy')).toEqual(true); - - // input and form are gone - expect(fileList.$fileList.find('input.filename').length).toEqual(0); - expect(fileList.$fileList.find('form').length).toEqual(0); - }); - it('Validates the file name', function() { - var $input, $tr; - - $tr = fileList.findFileEl('One.txt'); - expect($tr.find('a.name').css('display')).not.toEqual('none'); - - // trigger rename prompt - fileList.rename('One.txt'); - - expect($tr.find('a.name .thumbnail-wrapper').css('display')).not.toEqual('none'); - expect($tr.find('a.name .nametext').css('display')).toEqual('none'); - - $input = fileList.$fileList.find('input.filename'); - $input.val('Two.jpg'); - - // simulate key to trigger validation - $input.trigger(new $.Event('keyup', {keyCode: 97})); - - // input is still there with error - expect(fileList.$fileList.find('input.filename').length).toEqual(1); - expect(fileList.$fileList.find('input.filename').hasClass('error')).toEqual(true); - - // trigger submit does not send server request - $input.closest('form').trigger('submit'); - expect(renameStub.notCalled).toEqual(true); - - // simulate escape key - $input.trigger(new $.Event('keyup', {keyCode: 27})); - - // element is added back with the correct name - $tr = fileList.findFileEl('One.txt'); - expect($tr.length).toEqual(1); - expect($tr.find('a .nametext').text().trim()).toEqual('One.txt'); - expect($tr.find('a.name').css('display')).not.toEqual('none'); - - $tr = fileList.findFileEl('Two.jpg'); - expect($tr.length).toEqual(1); - expect($tr.find('a .nametext').text().trim()).toEqual('Two.jpg'); - expect($tr.find('a.name').css('display')).not.toEqual('none'); - - // input and form are gone - expect(fileList.$fileList.find('input.filename').length).toEqual(0); - expect(fileList.$fileList.find('form').length).toEqual(0); - }); - it('Restores thumbnail when rename was cancelled', function(done) { - doRename(); - - expect(fileList.findFileEl('Tu_after_three.txt').find('.thumbnail').parent().attr('class')) - .toContain('icon-loading-small'); - - deferredRename.reject(409); - - return Promise.resolve().then(function() { - expect(fileList.findFileEl('One.txt').length).toEqual(1); - expect(OC.TestUtil.getImageUrl(fileList.findFileEl('One.txt').find('.thumbnail'))) - .toEqual(OC.imagePath('core', 'filetypes/text.svg')); - }).then(done, done); - }); - }); - describe('Moving files', function() { - var deferredMove; - var moveStub; - - beforeEach(function() { - deferredMove = $.Deferred(); - moveStub = sinon.stub(filesClient, 'move'); - - fileList.setFiles(testFiles); - }); - afterEach(function() { - moveStub.restore(); - }); - - it('Moves single file to target folder', function(done) { - var promise = fileList.move('One.txt', '/somedir'); - - moveStub.callsFake(function(src, dst){ - expect(moveStub.calledOnce).toEqual(true); - expect(src).toEqual('/subdir/One.txt'); - expect(dst).toEqual('/somedir/One.txt'); - return deferredMove.promise(); - }); - - deferredMove.resolve(201); - - return promise.then(function(){ - expect(fileList.findFileEl('One.txt').length).toEqual(0); - - // folder size has increased - expect(fileList.findFileEl('somedir').data('size')).toEqual(262); - expect(fileList.findFileEl('somedir').find('.filesize').text()).toEqual('262 B'); - - expect(notificationStub.notCalled).toEqual(true); - }).then(done, done); - }); - it('Moves list of files to target folder', function(done) { - var deferredMove1 = $.Deferred(); - var deferredMove2 = $.Deferred(); - moveStub.onCall(0).callsFake(function(src, dst){ - expect(moveStub.calledOnce).toEqual(true); - expect(src).toEqual('/subdir/One.txt'); - expect(dst).toEqual('/somedir/One.txt'); - return deferredMove1.promise(); - }); - moveStub.onCall(1).callsFake(function(src, dst){ - expect(fileList.findFileEl('One.txt').length).toEqual(0); - - // folder size has increased during move - expect(fileList.findFileEl('somedir').data('size')).toEqual(262); - expect(fileList.findFileEl('somedir').find('.filesize').text()).toEqual('262 B'); - - expect(src).toEqual('/subdir/Two.jpg'); - expect(dst).toEqual('/somedir/Two.jpg'); - return deferredMove2.promise(); - }); - - var promise = fileList.move(['One.txt', 'Two.jpg'], '/somedir'); - deferredMove1.resolve(201); - deferredMove2.resolve(201); - return promise.then(function(){ - expect(moveStub.calledTwice).toEqual(true); - - expect(fileList.findFileEl('Two.jpg').length).toEqual(0); - - // folder size has increased - expect(fileList.findFileEl('somedir').data('size')).toEqual(12311); - expect(fileList.findFileEl('somedir').find('.filesize').text()).toEqual('12 KB'); - - expect(notificationStub.notCalled).toEqual(true); - }).then(done, done); - }); - it('Shows notification if a file could not be moved', function(done) { - moveStub.callsFake(function(){ - expect(moveStub.calledOnce).toEqual(true); - return deferredMove.promise(); - }); - var promise = fileList.move('One.txt', '/somedir'); - deferredMove.reject(409); - return promise.then(function(){ - expect(fileList.findFileEl('One.txt').length).toEqual(1); - expect(notificationStub.calledOnce).toEqual(true); - expect(notificationStub.getCall(0).args[0]).toEqual('Could not move "One.txt"'); - }).then(done, done); - }); - it('Restores thumbnail if a file could not be moved', function(done) { - moveStub.callsFake(function(){ - expect(fileList.findFileEl('One.txt').find('.thumbnail').parent().attr('class')) - .toContain('icon-loading-small'); - expect(moveStub.calledOnce).toEqual(true); - return deferredMove.promise(); - }); - var promise = fileList.move('One.txt', '/somedir'); - deferredMove.reject(409); - return promise.then(function(){ - expect(fileList.findFileEl('One.txt').length).toEqual(1); - expect(notificationStub.calledOnce).toEqual(true); - expect(notificationStub.getCall(0).args[0]).toEqual('Could not move "One.txt"'); - expect(OC.TestUtil.getImageUrl(fileList.findFileEl('One.txt').find('.thumbnail'))) - .toEqual(OC.imagePath('core', 'filetypes/text.svg')); - }).then(done, done); - }); - }); - - describe('Copying files', function() { - var deferredCopy; - var copyStub; - - beforeEach(function() { - deferredCopy = $.Deferred(); - copyStub = sinon.stub(filesClient, 'copy'); - - fileList.setFiles(testFiles); - }); - afterEach(function() { - copyStub.restore(); - }); - - it('Copies single file to target folder', function(done) { - copyStub.callsFake(function(){ - expect(copyStub.calledOnce).toEqual(true); - expect(copyStub.getCall(0).args[0]).toEqual('/subdir/One.txt'); - expect(copyStub.getCall(0).args[1]).toEqual('/somedir/One.txt'); - - return deferredCopy.promise(); - }); - - var promise = fileList.copy('One.txt', '/somedir'); - deferredCopy.resolve(201); - return promise.then(function(){ - // File is still here - expect(fileList.findFileEl('One.txt').length).toEqual(1); - - // folder size has increased - expect(fileList.findFileEl('somedir').data('size')).toEqual(262); - expect(fileList.findFileEl('somedir').find('.filesize').text()).toEqual('262 B'); - - // Copying sents a notification to tell that we've successfully copied file - expect(notificationStub.notCalled).toEqual(false); - }).then(done, done); - }); - it('Copies list of files to target folder', function(done) { - var deferredCopy1 = $.Deferred(); - var deferredCopy2 = $.Deferred(); - copyStub.onCall(0).callsFake(function(src, dst){ - expect(src).toEqual('/subdir/One.txt'); - expect(dst).toEqual('/somedir/One.txt'); - return deferredCopy1.promise(); - }); - copyStub.onCall(1).callsFake(function(src, dst){ - // folder size has increased during copy - expect(fileList.findFileEl('somedir').data('size')).toEqual(262); - expect(fileList.findFileEl('somedir').find('.filesize').text()).toEqual('262 B'); - - expect(src).toEqual('/subdir/Two.jpg'); - expect(dst).toEqual('/somedir/Two.jpg'); - return deferredCopy2.promise(); - }); - - var promise = fileList.copy(['One.txt', 'Two.jpg'], '/somedir'); - deferredCopy1.resolve(201); - deferredCopy2.resolve(201); - - return promise.then(function(){ - expect(copyStub.calledTwice).toEqual(true); - expect(fileList.findFileEl('Two.jpg').length).toEqual(1); - expect(fileList.findFileEl('One.txt').length).toEqual(1); - - // folder size has increased - expect(fileList.findFileEl('somedir').data('size')).toEqual(12311); - expect(fileList.findFileEl('somedir').find('.filesize').text()).toEqual('12 KB'); - - expect(notificationStub.notCalled).toEqual(false); - }).then(done, done); - }); - it('Shows notification if a file could not be copied', function(done) { - copyStub.callsFake(function(){ - expect(copyStub.calledOnce).toEqual(true); - return deferredCopy.promise(); - }); - - var promise = fileList.copy('One.txt', '/somedir'); - deferredCopy.reject(409); - return promise.then(function(){ - expect(fileList.findFileEl('One.txt').length).toEqual(1); - expect(notificationStub.calledOnce).toEqual(true); - expect(notificationStub.getCall(0).args[0]).toEqual('Could not copy "One.txt"'); - }).then(done, done); - }); - it('Restores thumbnail if a file could not be copied', function(done) { - copyStub.callsFake(function(){ - expect(fileList.findFileEl('One.txt').find('.thumbnail').parent().attr('class')) - .toContain('icon-loading-small'); - expect(copyStub.calledOnce).toEqual(true); - return deferredCopy.promise(); - }); - - var promise = fileList.copy('One.txt', '/somedir'); - deferredCopy.reject(409); - return promise.then(function(){ - expect(fileList.findFileEl('One.txt').length).toEqual(1); - - expect(notificationStub.calledOnce).toEqual(true); - expect(notificationStub.getCall(0).args[0]).toEqual('Could not copy "One.txt"'); - - expect(OC.TestUtil.getImageUrl(fileList.findFileEl('One.txt').find('.thumbnail'))) - .toEqual(OC.imagePath('core', 'filetypes/text.svg')); - }).then(done, done); - }); - }); - - describe('Update file', function() { - it('does not change summary', function() { - var $summary = $('.files-filestable .summary'); - var fileData = new FileInfo({ - type: 'file', - name: 'test file', - }); - var $tr = fileList.add(fileData); - - expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true); - expect($summary.find('.fileinfo').text()).toEqual('1 file'); - - var model = fileList.getModelForFile('test file'); - model.set({size: '100'}); - - expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true); - expect($summary.find('.fileinfo').text()).toEqual('1 file'); - }); - }) - describe('List rendering', function() { - it('renders a list of files using add()', function() { - expect(fileList.files.length).toEqual(0); - expect(fileList.files).toEqual([]); - fileList.setFiles(testFiles); - expect($('.files-fileList tr').length).toEqual(4); - expect(fileList.files.length).toEqual(4); - expect(fileList.files).toEqual(testFiles); - }); - it('updates summary using the file sizes', function() { - var $summary; - fileList.setFiles(testFiles); - $summary = $('.files-filestable .summary'); - expect($summary.hasClass('hidden')).toEqual(false); - expect($summary.find('.dirinfo').text()).toEqual('1 folder'); - expect($summary.find('.fileinfo').text()).toEqual('3 files'); - expect($summary.find('.filesize').text()).toEqual('69 KB'); - }); - it('shows headers, summary and hide empty content message after setting files', function(){ - fileList.setFiles(testFiles); - expect($('.files-filestable thead th').hasClass('hidden')).toEqual(false); - expect($('.emptyfilelist.emptycontent').hasClass('hidden')).toEqual(true); - expect(fileList.$el.find('.summary').hasClass('hidden')).toEqual(false); - }); - it('hides headers, summary and show empty content message after setting empty file list', function(){ - fileList.setFiles([]); - expect($('.files-filestable thead th').hasClass('hidden')).toEqual(true); - expect($('.emptyfilelist.emptycontent').hasClass('hidden')).toEqual(false); - expect($('.emptyfilelist.emptycontent .uploadmessage').hasClass('hidden')).toEqual(false); - expect(fileList.$el.find('.summary').hasClass('hidden')).toEqual(true); - }); - it('hides headers, upload message, and summary when list is empty and user has no creation permission', function(){ - $('#permissions').val(0); - fileList.setFiles([]); - expect($('.files-filestable thead th').hasClass('hidden')).toEqual(true); - expect($('.emptyfilelist.emptycontent').hasClass('hidden')).toEqual(false); - expect($('.emptyfilelist.emptycontent .uploadmessage').hasClass('hidden')).toEqual(true); - expect(fileList.$el.find('.summary').hasClass('hidden')).toEqual(true); - }); - it('calling findFileEl() can find existing file element', function() { - fileList.setFiles(testFiles); - expect(fileList.findFileEl('Two.jpg').length).toEqual(1); - }); - it('calling findFileEl() returns empty when file not found in file', function() { - fileList.setFiles(testFiles); - expect(fileList.findFileEl('unexist.dat').length).toEqual(0); - }); - it('only add file if in same current directory', function() { - fileList.changeDirectory('/current dir', false, true); - var fileData = { - type: 'file', - name: 'testFile.txt', - directory: '/current dir' - }; - fileList.add(fileData); - expect(fileList.findFileEl('testFile.txt').length).toEqual(1); - }); - it('triggers "fileActionsReady" event after update', function() { - var handler = sinon.stub(); - fileList.$fileList.on('fileActionsReady', handler); - fileList.setFiles(testFiles); - expect(handler.calledOnce).toEqual(true); - expect(handler.getCall(0).args[0].$files.length).toEqual(testFiles.length); - }); - it('triggers "fileActionsReady" event after single add', function() { - var handler = sinon.stub(); - var $tr; - fileList.setFiles(testFiles); - fileList.$fileList.on('fileActionsReady', handler); - $tr = fileList.add({name: 'test.txt'}); - expect(handler.calledOnce).toEqual(true); - expect(handler.getCall(0).args[0].$files.is($tr)).toEqual(true); - }); - it('triggers "fileActionsReady" event after next page load with the newly appended files', function() { - var handler = sinon.stub(); - fileList.setFiles(generateFiles(0, 64)); - fileList.$fileList.on('fileActionsReady', handler); - fileList._nextPage(); - expect(handler.calledOnce).toEqual(true); - expect(handler.getCall(0).args[0].$files.length).toEqual(fileList.pageSize()); - }); - it('does not trigger "fileActionsReady" event after single add with silent argument', function() { - var handler = sinon.stub(); - fileList.setFiles(testFiles); - fileList.$fileList.on('fileActionsReady', handler); - fileList.add({name: 'test.txt'}, {silent: true}); - expect(handler.notCalled).toEqual(true); - }); - it('triggers "updated" event after update', function() { - var handler = sinon.stub(); - fileList.$fileList.on('updated', handler); - fileList.setFiles(testFiles); - expect(handler.calledOnce).toEqual(true); - }); - it('does not update summary when removing non-existing files', function() { - var $summary; - // single file - fileList.setFiles([testFiles[0]]); - $summary = $('.files-filestable .summary'); - expect($summary.hasClass('hidden')).toEqual(false); - expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true); - expect($summary.find('.fileinfo').text()).toEqual('1 file'); - fileList.remove('unexist.txt'); - expect($summary.hasClass('hidden')).toEqual(false); - expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true); - expect($summary.find('.fileinfo').text()).toEqual('1 file'); - }); - }); - describe('Filtered list rendering', function() { - it('filters the list of files using filter()', function() { - expect(fileList.files.length).toEqual(0); - expect(fileList.files).toEqual([]); - fileList.setFiles(testFiles); - var $summary = $('.files-filestable .summary'); - var $nofilterresults = fileList.$el.find(".nofilterresults"); - expect($nofilterresults.length).toEqual(1); - expect($summary.hasClass('hidden')).toEqual(false); - - expect($('.files-fileList tr:not(.hidden)').length).toEqual(4); - expect(fileList.files.length).toEqual(4); - expect($summary.hasClass('hidden')).toEqual(false); - expect($nofilterresults.hasClass('hidden')).toEqual(true); - - fileList.setFilter('e'); - expect($('.files-fileList tr:not(.hidden)').length).toEqual(3); - expect(fileList.files.length).toEqual(4); - expect($summary.hasClass('hidden')).toEqual(false); - expect($summary.find('.dirinfo').text()).toEqual('1 folder'); - expect($summary.find('.fileinfo').text()).toEqual('2 files'); - expect($summary.find('.filter').text()).toEqual(" match \"e\""); - expect($nofilterresults.hasClass('hidden')).toEqual(true); - - fileList.setFilter('ee'); - expect($('.files-fileList tr:not(.hidden)').length).toEqual(1); - expect(fileList.files.length).toEqual(4); - expect($summary.hasClass('hidden')).toEqual(false); - expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true); - expect($summary.find('.fileinfo').text()).toEqual('1 file'); - expect($summary.find('.filter').text()).toEqual(" matches \"ee\""); - expect($nofilterresults.hasClass('hidden')).toEqual(true); - - fileList.setFilter('eee'); - expect($('.files-fileList tr:not(.hidden)').length).toEqual(0); - expect(fileList.files.length).toEqual(4); - expect($summary.hasClass('hidden')).toEqual(true); - expect($nofilterresults.hasClass('hidden')).toEqual(false); - - fileList.setFilter('ee'); - expect($('.files-fileList tr:not(.hidden)').length).toEqual(1); - expect(fileList.files.length).toEqual(4); - expect($summary.hasClass('hidden')).toEqual(false); - expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true); - expect($summary.find('.fileinfo').text()).toEqual('1 file'); - expect($summary.find('.filter').text()).toEqual(" matches \"ee\""); - expect($nofilterresults.hasClass('hidden')).toEqual(true); - - fileList.setFilter('e'); - expect($('.files-fileList tr:not(.hidden)').length).toEqual(3); - expect(fileList.files.length).toEqual(4); - expect($summary.hasClass('hidden')).toEqual(false); - expect($summary.find('.dirinfo').text()).toEqual('1 folder'); - expect($summary.find('.fileinfo').text()).toEqual('2 files'); - expect($summary.find('.filter').text()).toEqual(" match \"e\""); - expect($nofilterresults.hasClass('hidden')).toEqual(true); - - fileList.setFilter(''); - expect($('.files-fileList tr:not(.hidden)').length).toEqual(4); - expect(fileList.files.length).toEqual(4); - expect($summary.hasClass('hidden')).toEqual(false); - expect($summary.find('.dirinfo').text()).toEqual('1 folder'); - expect($summary.find('.fileinfo').text()).toEqual('3 files'); - expect($nofilterresults.hasClass('hidden')).toEqual(true); - }); - it('filters the list of non-rendered rows using filter()', function() { - var $summary = $('.files-filestable .summary'); - var $nofilterresults = fileList.$el.find(".nofilterresults"); - fileList.setFiles(generateFiles(0, 64)); - - fileList.setFilter('63'); - expect($('.files-fileList tr:not(.hidden)').length).toEqual(1); - expect($summary.hasClass('hidden')).toEqual(false); - expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true); - expect($summary.find('.fileinfo').text()).toEqual('1 file'); - expect($summary.find('.filter').text()).toEqual(" matches \"63\""); - expect($nofilterresults.hasClass('hidden')).toEqual(true); - }); - it('hides the emptyfiles notice when using filter()', function() { - expect(fileList.files.length).toEqual(0); - expect(fileList.files).toEqual([]); - fileList.setFiles([]); - var $summary = $('.files-filestable .summary'); - var $emptycontent = fileList.$el.find(".emptyfilelist.emptycontent"); - var $nofilterresults = fileList.$el.find(".nofilterresults"); - expect($emptycontent.length).toEqual(1); - expect($nofilterresults.length).toEqual(1); - - expect($('.files-fileList tr:not(.hidden)').length).toEqual(0); - expect(fileList.files.length).toEqual(0); - expect($summary.hasClass('hidden')).toEqual(true); - expect($emptycontent.hasClass('hidden')).toEqual(false); - expect($nofilterresults.hasClass('hidden')).toEqual(true); - - fileList.setFilter('e'); - expect($('.files-fileList tr:not(.hidden)').length).toEqual(0); - expect(fileList.files.length).toEqual(0); - expect($summary.hasClass('hidden')).toEqual(true); - expect($emptycontent.hasClass('hidden')).toEqual(true); - expect($nofilterresults.hasClass('hidden')).toEqual(false); - - fileList.setFilter(''); - expect($('.files-fileList tr:not(.hidden)').length).toEqual(0); - expect(fileList.files.length).toEqual(0); - expect($summary.hasClass('hidden')).toEqual(true); - expect($emptycontent.hasClass('hidden')).toEqual(false); - expect($nofilterresults.hasClass('hidden')).toEqual(true); - }); - it('does not show the emptyfiles or nofilterresults notice when the mask is active', function() { - expect(fileList.files.length).toEqual(0); - expect(fileList.files).toEqual([]); - fileList.showMask(); - fileList.setFiles(testFiles); - var $emptycontent = fileList.$el.find(".emptyfilelist.emptycontent"); - var $nofilterresults = fileList.$el.find(".nofilterresults"); - expect($emptycontent.length).toEqual(1); - expect($nofilterresults.length).toEqual(1); - - expect($emptycontent.hasClass('hidden')).toEqual(true); - expect($nofilterresults.hasClass('hidden')).toEqual(true); - - /* - fileList.setFilter('e'); - expect($emptycontent.hasClass('hidden')).toEqual(true); - expect($nofilterresults.hasClass('hidden')).toEqual(false); - */ - - fileList.setFilter(''); - expect($emptycontent.hasClass('hidden')).toEqual(true); - expect($nofilterresults.hasClass('hidden')).toEqual(true); - }); - }); - describe('Rendering next page on scroll', function() { - beforeEach(function() { - fileList.setFiles(generateFiles(0, 64)); - }); - it('renders only the first page', function() { - expect(fileList.files.length).toEqual(65); - expect($('.files-fileList tr').length).toEqual(20); - }); - it('renders the full first page despite hidden rows', function() { - window._nc_event_bus.emit('files:config:updated', { key: 'show_hidden', value: false }); - var files = _.map(generateFiles(0, 23), function(data) { - return _.extend(data, { - name: '.' + data.name - }); - }); - // only hidden files + one visible - files.push(testFiles[0]); - fileList.setFiles(files); - expect(fileList.files.length).toEqual(25); - // render 24 hidden elements + the visible one - expect($('.files-fileList tr').length).toEqual(25); - }); - it('renders the full first page despite hidden rows', function() { - window._nc_event_bus.emit('files:config:updated', { key: 'show_hidden', value: true }); - var files = _.map(generateFiles(0, 23), function(data) { - return _.extend(data, { - name: '.' + data.name - }); - }); - // only hidden files + one visible - files.push(testFiles[0]); - fileList.setFiles(files); - expect(fileList.files.length).toEqual(25); - // render 20 first hidden elements as visible - expect($('.files-fileList tr').length).toEqual(20); - }); - it('renders the second page when scrolling down (trigger nextPage)', function() { - // TODO: can't simulate scrolling here, so calling nextPage directly - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(40); - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(60); - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(65); - fileList._nextPage(true); - // stays at 65 - expect($('.files-fileList tr').length).toEqual(65); - }); - it('inserts into the DOM if insertion point is in the visible page ', function() { - fileList.add({ - id: 2000, - type: 'file', - name: 'File with index 15b.txt' - }); - expect($('.files-fileList tr').length).toEqual(21); - expect(fileList.findFileEl('File with index 15b.txt').index()).toEqual(16); - }); - it('does not inserts into the DOM if insertion point is not the visible page ', function() { - fileList.add({ - id: 2000, - type: 'file', - name: 'File with index 28b.txt' - }); - expect($('.files-fileList tr').length).toEqual(20); - expect(fileList.findFileEl('File with index 28b.txt').length).toEqual(0); - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(40); - expect(fileList.findFileEl('File with index 28b.txt').index()).toEqual(29); - }); - it('appends into the DOM when inserting a file after the last visible element', function() { - fileList.add({ - id: 2000, - type: 'file', - name: 'File with index 19b.txt' - }); - expect($('.files-fileList tr').length).toEqual(21); - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(41); - }); - it('appends into the DOM when inserting a file on the last page when visible', function() { - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(40); - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(60); - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(65); - fileList._nextPage(true); - fileList.add({ - id: 2000, - type: 'file', - name: 'File with index 88.txt' - }); - expect($('.files-fileList tr').length).toEqual(66); - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(66); - }); - it('shows additional page when appending a page of files and scrolling down', function() { - var newFiles = generateFiles(66, 81); - for (var i = 0; i < newFiles.length; i++) { - fileList.add(newFiles[i]); - } - expect($('.files-fileList tr').length).toEqual(20); - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(40); - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(60); - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(80); - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(81); - fileList._nextPage(true); - expect($('.files-fileList tr').length).toEqual(81); - }); - it('automatically renders next page when there are not enough elements visible', function() { - // delete the 15 first elements - for (var i = 0; i < 15; i++) { - fileList.remove(fileList.files[0].name); - } - // still makes sure that there are 20 elements visible, if any - expect($('.files-fileList tr').length).toEqual(25); - }); - }); - describe('file previews', function() { - var previewLoadStub; - - beforeEach(function() { - previewLoadStub = sinon.stub(OCA.Files.FileList.prototype, 'lazyLoadPreview'); - }); - afterEach(function() { - previewLoadStub.restore(); - }); - it('renders default file icon when none provided and no mime type is set', function() { - var fileData = { - name: 'testFile.txt' - }; - var $tr = fileList.add(fileData); - var $imgDiv = $tr.find('td.filename .thumbnail'); - expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.getRootPath() + '/core/img/filetypes/file.svg'); - // tries to load preview - expect(previewLoadStub.calledOnce).toEqual(true); - }); - it('renders default icon for folder when none provided', function() { - var fileData = { - name: 'test dir', - mimetype: 'httpd/unix-directory' - }; - - var $tr = fileList.add(fileData); - var $imgDiv = $tr.find('td.filename .thumbnail'); - expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.getRootPath() + '/core/img/filetypes/folder.svg'); - // no preview since it's a directory - expect(previewLoadStub.notCalled).toEqual(true); - }); - it('renders provided icon for file when provided', function() { - var fileData = new FileInfo({ - type: 'file', - name: 'test file', - icon: OC.getRootPath() + '/core/img/filetypes/application-pdf.svg', - mimetype: 'application/pdf' - }); - var $tr = fileList.add(fileData); - var $imgDiv = $tr.find('td.filename .thumbnail'); - expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.getRootPath() + '/core/img/filetypes/application-pdf.svg'); - // try loading preview - expect(previewLoadStub.calledOnce).toEqual(true); - }); - it('renders provided icon for file when provided', function() { - var fileData = new FileInfo({ - name: 'somefile.pdf', - icon: OC.getRootPath() + '/core/img/filetypes/application-pdf.svg' - }); - - var $tr = fileList.add(fileData); - var $imgDiv = $tr.find('td.filename .thumbnail'); - expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.getRootPath() + '/core/img/filetypes/application-pdf.svg'); - // try loading preview - expect(previewLoadStub.calledOnce).toEqual(true); - }); - it('renders provided icon for folder when provided', function() { - var fileData = new FileInfo({ - name: 'some folder', - mimetype: 'httpd/unix-directory', - icon: OC.getRootPath() + '/core/img/filetypes/folder-alt.svg' - }); - - var $tr = fileList.add(fileData); - var $imgDiv = $tr.find('td.filename .thumbnail'); - expect(OC.TestUtil.getImageUrl($imgDiv)).toEqual(OC.getRootPath() + '/core/img/filetypes/folder-alt.svg'); - // do not load preview for folders - expect(previewLoadStub.notCalled).toEqual(true); - }); - it('renders preview when no icon was provided', function() { - var fileData = { - type: 'file', - name: 'test file' - }; - var $tr = fileList.add(fileData); - var $td = $tr.find('td.filename'); - expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))) - .toEqual(OC.getRootPath() + '/core/img/filetypes/file.svg'); - expect(previewLoadStub.calledOnce).toEqual(true); - // third argument is callback - previewLoadStub.getCall(0).args[0].callback(OC.getRootPath() + '/somepath.png'); - expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))).toEqual(OC.getRootPath() + '/somepath.png'); - }); - it('does not render preview for directories', function() { - var fileData = { - type: 'dir', - mimetype: 'httpd/unix-directory', - name: 'test dir' - }; - var $tr = fileList.add(fileData); - var $td = $tr.find('td.filename'); - expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))).toEqual(OC.getRootPath() + '/core/img/filetypes/folder.svg'); - expect(previewLoadStub.notCalled).toEqual(true); - }); - it('render encrypted folder icon for encrypted root', function() { - var fileData = { - type: 'dir', - mimetype: 'httpd/unix-directory', - name: 'test dir', - isEncrypted: true - }; - var $tr = fileList.add(fileData); - var $td = $tr.find('td.filename'); - expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))).toEqual(OC.getRootPath() + '/core/img/filetypes/folder-encrypted.svg'); - expect(previewLoadStub.notCalled).toEqual(true); - }); - it('render encrypted folder icon for encrypted subdir', function() { - var fileData = { - type: 'dir', - mimetype: 'httpd/unix-directory', - name: 'test dir', - isEncrypted: true - }; - var $tr = fileList.add(fileData); - var $td = $tr.find('td.filename'); - expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))).toEqual(OC.getRootPath() + '/core/img/filetypes/folder-encrypted.svg'); - expect(previewLoadStub.notCalled).toEqual(true); - // default icon override - expect($tr.attr('data-icon')).toEqual(OC.getRootPath() + '/core/img/filetypes/folder-encrypted.svg'); - }); - it('render external storage icon for external storage root', function() { - var fileData = { - type: 'dir', - mimetype: 'httpd/unix-directory', - name: 'test dir', - mountType: 'external-root' - }; - var $tr = fileList.add(fileData); - var $td = $tr.find('td.filename'); - expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))).toEqual(OC.getRootPath() + '/core/img/filetypes/folder-external.svg'); - expect(previewLoadStub.notCalled).toEqual(true); - }); - it('render external storage icon for external storage subdir', function() { - var fileData = { - type: 'dir', - mimetype: 'httpd/unix-directory', - name: 'test dir', - mountType: 'external' - }; - var $tr = fileList.add(fileData); - var $td = $tr.find('td.filename'); - expect(OC.TestUtil.getImageUrl($td.find('.thumbnail'))).toEqual(OC.getRootPath() + '/core/img/filetypes/folder-external.svg'); - expect(previewLoadStub.notCalled).toEqual(true); - // default icon override - expect($tr.attr('data-icon')).toEqual(OC.getRootPath() + '/core/img/filetypes/folder-external.svg'); - }); - - }); - describe('viewer mode', function() { - it('enabling viewer mode hides files table and action buttons', function() { - fileList.setViewerMode(true); - expect($('.files-filestable').hasClass('hidden')).toEqual(true); - expect($('.actions').hasClass('hidden')).toEqual(true); - expect($('.notCreatable').hasClass('hidden')).toEqual(true); - }); - it('disabling viewer mode restores files table and action buttons', function() { - fileList.setViewerMode(true); - fileList.setViewerMode(false); - expect($('.files-filestable').hasClass('hidden')).toEqual(false); - expect($('.actions').hasClass('hidden')).toEqual(false); - expect($('.notCreatable').hasClass('hidden')).toEqual(true); - }); - it('disabling viewer mode restores files table and action buttons with correct permissions', function() { - $('#permissions').val(0); - fileList.setViewerMode(true); - fileList.setViewerMode(false); - expect($('.files-filestable').hasClass('hidden')).toEqual(false); - expect($('.actions').hasClass('hidden')).toEqual(true); - expect($('.notCreatable').hasClass('hidden')).toEqual(false); - }); - it('toggling viewer mode triggers event', function() { - var handler = sinon.stub(); - fileList.$el.on('changeViewerMode', handler); - fileList.setViewerMode(true); - expect(handler.calledOnce).toEqual(true); - expect(handler.getCall(0).args[0].viewerModeEnabled).toEqual(true); - - handler.reset(); - fileList.setViewerMode(false); - expect(handler.calledOnce).toEqual(true); - expect(handler.getCall(0).args[0].viewerModeEnabled).toEqual(false); - }); - }); - describe('loading file list', function() { - var deferredList; - var getFolderContentsStub; - - beforeEach(function() { - deferredList = $.Deferred(); - getFolderContentsStub = sinon.stub(filesClient, 'getFolderContents').returns(deferredList.promise()); - }); - afterEach(function() { - getFolderContentsStub.restore(); - }); - it('fetches file list from server and renders it when reload() is called', function(done) { - var reloading = fileList.reload(); - expect(getFolderContentsStub.calledOnce).toEqual(true); - expect(getFolderContentsStub.calledWith('/subdir')).toEqual(true); - deferredList.resolve(200, [testRoot].concat(testFiles)); - return reloading.then(function() { - expect($('.files-fileList tr').length).toEqual(4); - expect(fileList.findFileEl('One.txt').length).toEqual(1); - }).then(done, done); - }); - it('switches dir and fetches file list when calling changeDirectory()', function() { - fileList.changeDirectory('/anothersubdir'); - expect(fileList.getCurrentDirectory()).toEqual('/anothersubdir'); - expect(getFolderContentsStub.calledOnce).toEqual(true); - expect(getFolderContentsStub.calledWith('/anothersubdir')).toEqual(true); - }); - it('converts backslashes to slashes when calling changeDirectory()', function() { - fileList.changeDirectory('/another\\subdir'); - expect(fileList.getCurrentDirectory()).toEqual('/another/subdir'); - }); - it('switches to root dir when current directory is invalid', function() { - _.each([ - '..', - '/..', - '../', - '/../', - '/../abc', - '/abc/..', - '/abc/../', - '/../abc/', - '/foo%0Abar/', - '/foo%00bar/', - '/another\\subdir/../foo\\../bar\\..\\file/..\\folder/../' - ], function(path) { - fileList.changeDirectory(decodeURI(path)); - expect(fileList.getCurrentDirectory()).toEqual('/'); - }); - }); - it('allows paths with dotdot at the beginning or end', function() { - _.each([ - '/..abc', - '/def..', - '/...', - '/abc../def' - ], function(path) { - fileList.changeDirectory(path); - expect(fileList.getCurrentDirectory()).toEqual(path); - }); - }); - it('switches to root dir when current directory does not exist', function(done) { - var changing = fileList.changeDirectory('/unexist'); - - deferredList.reject(404); - - return changing.then(function() { - expect(fileList.getCurrentDirectory()).toEqual('/'); - }).then(done, done); - }); - it('switches to root dir when current directory returns 400', function(done) { - var changing = fileList.changeDirectory('/unexist'); - - deferredList.reject(400); - - return changing.then(function() { - expect(fileList.getCurrentDirectory()).toEqual('/'); - }).then(done, done); - }); - it('switches to root dir when current directory returns 405', function(done) { - var changing = fileList.changeDirectory('/unexist'); - - deferredList.reject(405); - - return changing.then(function() { - expect(fileList.getCurrentDirectory()).toEqual('/'); - }).then(done, done); - }); - it('switches to root dir when current directory is forbidden', function(done) { - var changing = fileList.changeDirectory('/unexist'); - - deferredList.reject(403); - - return changing.then(function() { - expect(fileList.getCurrentDirectory()).toEqual('/'); - }).then(done, done); - }); - it('switches to root dir when current directory is unavailable', function(done) { - var changing = fileList.changeDirectory('/unexist'); - - deferredList.reject(500); - - return changing.then(function() { - expect(fileList.getCurrentDirectory()).toEqual('/'); - }).then(done, done); - }); - it('shows mask before loading file list then hides it at the end', function(done) { - var showMaskStub = sinon.stub(fileList, 'showMask'); - var hideMaskStub = sinon.stub(fileList, 'hideMask'); - - var changing = fileList.changeDirectory('/anothersubdir'); - expect(showMaskStub.calledOnce).toEqual(true); - expect(hideMaskStub.calledOnce).toEqual(false); - deferredList.resolve(200, [testRoot].concat(testFiles)); - - return changing.then(function() { - expect(showMaskStub.calledOnce).toEqual(true); - expect(hideMaskStub.calledOnce).toEqual(true); - showMaskStub.restore(); - hideMaskStub.restore(); - }).then(done, done); - }); - it('triggers "changeDirectory" event when changing directory', function(done) { - var handler = sinon.stub(); - $('#app-content-files').on('changeDirectory', handler); - var changing = fileList.changeDirectory('/somedir'); - - deferredList.resolve(200, [testRoot].concat(testFiles)); - - return changing.then(function() { - expect(handler.calledOnce).toEqual(true); - expect(handler.getCall(0).args[0].dir).toEqual('/somedir'); - }).then(done, done); - }); - it('triggers "afterChangeDirectory" event with fileid after changing directory', function(done) { - var handler = sinon.stub(); - $('#app-content-files').on('afterChangeDirectory', handler); - var changing = fileList.changeDirectory('/somedir'); - - deferredList.resolve(200, [testRoot].concat(testFiles)); - - return changing.then(function() { - expect(handler.calledOnce).toEqual(true); - expect(handler.getCall(0).args[0].dir).toEqual('/somedir'); - expect(handler.getCall(0).args[0].fileId).toEqual(99); - }).then(done, done); - }); - it('changes the directory when receiving "urlChanged" event', function() { - $('#app-content-files').trigger(new $.Event('urlChanged', {view: 'files', dir: '/somedir'})); - expect(fileList.getCurrentDirectory()).toEqual('/somedir'); - }); - it('refreshes breadcrumb after update', function() { - var setDirSpy = sinon.spy(fileList.breadcrumb, 'setDirectory'); - fileList.changeDirectory('/anothersubdir'); - deferredList.resolve(200, [testRoot].concat(testFiles)); - // twice because setDirectory gets called by _setCurrentDir which - // gets called directly by changeDirectory and via reload() - expect(fileList.breadcrumb.setDirectory.calledTwice).toEqual(true); - expect(fileList.breadcrumb.setDirectory.calledWith('/anothersubdir')).toEqual(true); - setDirSpy.restore(); - getFolderContentsStub.restore(); - }); - it('prepends a slash to directory if none was given', function() { - fileList.changeDirectory(''); - expect(fileList.getCurrentDirectory()).toEqual('/'); - fileList.changeDirectory('noslash'); - expect(fileList.getCurrentDirectory()).toEqual('/noslash'); - }); - }); - describe('breadcrumb events', function() { - var deferredList; - var getFolderContentsStub; - - beforeEach(function() { - deferredList = $.Deferred(); - getFolderContentsStub = sinon.stub(filesClient, 'getFolderContents').returns(deferredList.promise()); - }); - afterEach(function() { - getFolderContentsStub.restore(); - }); - it('clicking on root breadcrumb changes directory to root', function() { - fileList.changeDirectory('/subdir/two/three with space/four/five'); - deferredList.resolve(200, [testRoot].concat(testFiles)); - var changeDirStub = sinon.stub(fileList, 'changeDirectory'); - fileList.breadcrumb.$el.find('.crumb:eq(1) > a').trigger({type: 'click', which: 1}); - - expect(changeDirStub.calledOnce).toEqual(true); - expect(changeDirStub.getCall(0).args[0]).toEqual('/'); - changeDirStub.restore(); - }); - it('clicking on breadcrumb changes directory', function() { - fileList.changeDirectory('/subdir/two/three with space/four/five'); - deferredList.resolve(200, [testRoot].concat(testFiles)); - var changeDirStub = sinon.stub(fileList, 'changeDirectory'); - fileList.breadcrumb.$el.find('.crumb:eq(4) > a').trigger({type: 'click', which: 1}); - - expect(changeDirStub.calledOnce).toEqual(true); - expect(changeDirStub.getCall(0).args[0]).toEqual('/subdir/two/three with space'); - changeDirStub.restore(); - }); - it('dropping files on breadcrumb calls move operation', function() { - var testDir = '/subdir/two/three with space/four/five'; - var moveStub = sinon.stub(filesClient, 'move'); - var deferredMove1 = $.Deferred(); - var deferredMove2 = $.Deferred(); - moveStub.onCall(0).returns(deferredMove1.promise()); - moveStub.onCall(1).returns(deferredMove2.promise()); - fileList.changeDirectory(testDir); - deferredList.resolve(200, [testRoot].concat(testFiles)); - var $crumb = fileList.breadcrumb.$el.find('.crumb:eq(4)'); - // no idea what this is but is required by the handler - var ui = { - helper: { - find: sinon.stub() - } - }; - // returns a list of tr that were dragged - ui.helper.find.returns([ - $('<tr data-file="One.txt" data-dir="' + testDir + '"></tr>'), - $('<tr data-file="Two.jpg" data-dir="' + testDir + '"></tr>') - ]); - // simulate drop event - var result = fileList._onDropOnBreadCrumb(new $.Event('drop', {target: $crumb}), ui).then(function(){ - expect(moveStub.callCount).toEqual(2); - expect(moveStub.getCall(0).args[0]).toEqual(testDir + '/One.txt'); - expect(moveStub.getCall(0).args[1]).toEqual('/subdir/two/three with space/One.txt'); - expect(moveStub.getCall(1).args[0]).toEqual(testDir + '/Two.jpg'); - expect(moveStub.getCall(1).args[1]).toEqual('/subdir/two/three with space/Two.jpg'); - moveStub.restore(); - }); - deferredMove1.resolve(201); - deferredMove2.resolve(201); - return result; - }); - it('dropping files on same dir breadcrumb does nothing', function() { - var testDir = '/subdir/two/three with space/four/five'; - var moveStub = sinon.stub(filesClient, 'move').returns($.Deferred().promise()); - fileList.changeDirectory(testDir); - deferredList.resolve(200, [testRoot].concat(testFiles)); - var $crumb = fileList.breadcrumb.$el.find('.crumb:last'); - // no idea what this is but is required by the handler - var ui = { - helper: { - find: sinon.stub() - } - }; - // returns a list of tr that were dragged - ui.helper.find.returns([ - $('<tr data-file="One.txt" data-dir="' + testDir + '"></tr>'), - $('<tr data-file="Two.jpg" data-dir="' + testDir + '"></tr>') - ]); - // simulate drop event - fileList._onDropOnBreadCrumb(new $.Event('drop', {target: $crumb}), ui); - - // no extra server request - expect(moveStub.notCalled).toEqual(true); - }); - }); - describe('Download Url', function() { - it('returns correct download URL for single files', function() { - expect(fileList.getDownloadUrl('some file.txt')) - .toEqual(OC.getRootPath() + '/remote.php/webdav/subdir/some%20file.txt'); - expect(fileList.getDownloadUrl('some file.txt', '/anotherpath/abc')) - .toEqual(OC.getRootPath() + '/remote.php/webdav/anotherpath/abc/some%20file.txt'); - fileList.changeDirectory('/', false, true); - expect(fileList.getDownloadUrl('some file.txt')) - .toEqual(OC.getRootPath() + '/remote.php/webdav/some%20file.txt'); - }); - it('returns correct download URL for multiple files', function() { - expect(fileList.getDownloadUrl(['a b c.txt', 'd e f.txt'])) - .toEqual(OC.getRootPath() + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22a%20b%20c.txt%22%2C%22d%20e%20f.txt%22%5D'); - }); - it('returns the correct ajax URL', function() { - expect(fileList.getAjaxUrl('test', {a:1, b:'x y'})) - .toEqual(OC.getRootPath() + '/index.php/apps/files/ajax/test.php?a=1&b=x%20y'); - }); - }); - describe('File selection', function() { - beforeEach(function() { - fileList.setFiles(testFiles); - }); - it('Selects a file when clicking its checkbox', function() { - var $tr = fileList.findFileEl('One.txt'); - expect($tr.find('input:checkbox').prop('checked')).toEqual(false); - $tr.find('td.selection input:checkbox').click(); - - expect($tr.find('input:checkbox').prop('checked')).toEqual(true); - }); - it('Selects a range when clicking on one file then Shift clicking on another one', function() { - var $tr = fileList.findFileEl('One.txt'); - var $tr2 = fileList.findFileEl('Three.pdf'); - var e; - $tr.find('td.selection input:checkbox').click(); - e = new $.Event('click'); - e.shiftKey = true; - $tr2.find('td.filename .name').trigger(e); - - expect($tr.find('input:checkbox').prop('checked')).toEqual(true); - expect($tr2.find('input:checkbox').prop('checked')).toEqual(true); - expect(fileList.findFileEl('Two.jpg').find('input:checkbox').prop('checked')).toEqual(true); - var selection = _.pluck(fileList.getSelectedFiles(), 'name'); - expect(selection.length).toEqual(3); - expect(selection).toContain('One.txt'); - expect(selection).toContain('Two.jpg'); - expect(selection).toContain('Three.pdf'); - }); - it('Selects a range when clicking on one file then Shift clicking on another one that is above the first one', function() { - var $tr = fileList.findFileEl('One.txt'); - var $tr2 = fileList.findFileEl('Three.pdf'); - var e; - $tr2.find('td.selection input:checkbox').click(); - e = new $.Event('click'); - e.shiftKey = true; - $tr.find('td.filename .name').trigger(e); - - expect($tr.find('input:checkbox').prop('checked')).toEqual(true); - expect($tr2.find('input:checkbox').prop('checked')).toEqual(true); - expect(fileList.findFileEl('Two.jpg').find('input:checkbox').prop('checked')).toEqual(true); - var selection = _.pluck(fileList.getSelectedFiles(), 'name'); - expect(selection.length).toEqual(3); - expect(selection).toContain('One.txt'); - expect(selection).toContain('Two.jpg'); - expect(selection).toContain('Three.pdf'); - }); - it('Selecting all files will automatically check "select all" checkbox', function() { - expect($('.select-all').prop('checked')).toEqual(false); - $('.files-fileList tr td.selection input:checkbox').click(); - expect($('.select-all').prop('checked')).toEqual(true); - }); - it('Selecting all files on the first visible page will not automatically check "select all" checkbox', function() { - fileList.setFiles(generateFiles(0, 41)); - expect($('.select-all').prop('checked')).toEqual(false); - $('.files-fileList tr td.selection input:checkbox').click(); - expect($('.select-all').prop('checked')).toEqual(false); - }); - it('Selecting all files also selects hidden files when invisible', function() { - window._nc_event_bus.emit('files:config:updated', { key: 'show_hidden', value: false }); - var $tr = fileList.add(new FileInfo({ - name: '.hidden', - type: 'dir', - mimetype: 'httpd/unix-directory', - size: 150 - })); - $('.select-all').click(); - expect($tr.find('td.selection input:checkbox').prop('checked')).toEqual(true); - expect(_.pluck(fileList.getSelectedFiles(), 'name')).toContain('.hidden'); - }); - it('Clicking "select all" will select/deselect all files', function() { - fileList.setFiles(generateFiles(0, 41)); - $('.select-all').click(); - expect($('.select-all').prop('checked')).toEqual(true); - $('.files-fileList tr input:checkbox').each(function() { - expect($(this).prop('checked')).toEqual(true); - }); - expect(_.pluck(fileList.getSelectedFiles(), 'name').length).toEqual(42); - - $('.select-all').click(); - expect($('.select-all').prop('checked')).toEqual(false); - - $('.files-fileList tr input:checkbox').each(function() { - expect($(this).prop('checked')).toEqual(false); - }); - expect(_.pluck(fileList.getSelectedFiles(), 'name').length).toEqual(0); - }); - it('Clicking "select all" then deselecting a file will uncheck "select all"', function() { - $('.select-all').click(); - expect($('.select-all').prop('checked')).toEqual(true); - - var $tr = fileList.findFileEl('One.txt'); - $tr.find('input:checkbox').click(); - - expect($('.select-all').prop('checked')).toEqual(false); - expect(_.pluck(fileList.getSelectedFiles(), 'name').length).toEqual(3); - }); - it('Updates the selection summary when doing a few manipulations with "Select all"', function() { - $('.select-all').click(); - expect($('.select-all').prop('checked')).toEqual(true); - - var $tr = fileList.findFileEl('One.txt'); - // unselect one - $tr.find('input:checkbox').click(); - - expect($('.select-all').prop('checked')).toEqual(false); - expect(_.pluck(fileList.getSelectedFiles(), 'name').length).toEqual(3); - - // select all - $('.select-all').click(); - expect($('.select-all').prop('checked')).toEqual(true); - expect(_.pluck(fileList.getSelectedFiles(), 'name').length).toEqual(4); - - // unselect one - $tr.find('input:checkbox').click(); - expect($('.select-all').prop('checked')).toEqual(false); - expect(_.pluck(fileList.getSelectedFiles(), 'name').length).toEqual(3); - - // re-select it - $tr.find('input:checkbox').click(); - expect($('.select-all').prop('checked')).toEqual(true); - expect(_.pluck(fileList.getSelectedFiles(), 'name').length).toEqual(4); - }); - it('Auto-selects files on next page when "select all" is checked', function() { - fileList.setFiles(generateFiles(0, 41)); - $('.select-all').click(); - - expect(fileList.$fileList.find('tr input:checkbox:checked').length).toEqual(20); - fileList._nextPage(true); - expect(fileList.$fileList.find('tr input:checkbox:checked').length).toEqual(40); - fileList._nextPage(true); - expect(fileList.$fileList.find('tr input:checkbox:checked').length).toEqual(42); - expect(_.pluck(fileList.getSelectedFiles(), 'name').length).toEqual(42); - }); - it('Selecting files updates selection summary', function() { - var $summary = $('.column-name a.name>span:first'); - expect($summary.text()).toEqual('Name'); - fileList.findFileEl('One.txt').find('input:checkbox').click(); - fileList.findFileEl('Three.pdf').find('input:checkbox').click(); - fileList.findFileEl('somedir').find('input:checkbox').click(); - expect($summary.text()).toEqual('1 folder and 2 files'); - }); - it('Unselecting files hides selection summary', function() { - var $summary = $('.column-name a.name>span:first'); - fileList.findFileEl('One.txt').find('input:checkbox').click().click(); - expect($summary.text()).toEqual('Name'); - }); - it('Displays the number of hidden files in selection summary if hidden files are invisible', function() { - window._nc_event_bus.emit('files:config:updated', { key: 'show_hidden', value: false }); - var $tr = fileList.add(new FileInfo({ - name: '.hidden', - type: 'dir', - mimetype: 'httpd/unix-directory', - size: 150 - })); - $('.select-all').click(); - var $summary = $('.column-name a.name>span:first'); - expect($summary.text()).toEqual('2 folders and 3 files (including 1 hidden)'); - }); - it('Does not displays the number of hidden files in selection summary if hidden files are visible', function() { - window._nc_event_bus.emit('files:config:updated', { key: 'show_hidden', value: true }); - var $tr = fileList.add(new FileInfo({ - name: '.hidden', - type: 'dir', - mimetype: 'httpd/unix-directory', - size: 150 - })); - $('.select-all').click(); - var $summary = $('.column-name a.name>span:first'); - expect($summary.text()).toEqual('2 folders and 3 files'); - }); - it('Toggling hidden file visibility updates selection summary', function() { - window._nc_event_bus.emit('files:config:updated', { key: 'show_hidden', value: false }); - var $tr = fileList.add(new FileInfo({ - name: '.hidden', - type: 'dir', - mimetype: 'httpd/unix-directory', - size: 150 - })); - $('.select-all').click(); - var $summary = $('.column-name a.name>span:first'); - expect($summary.text()).toEqual('2 folders and 3 files (including 1 hidden)'); - window._nc_event_bus.emit('files:config:updated', { key: 'show_hidden', value: true }); - expect($summary.text()).toEqual('2 folders and 3 files'); - }); - it('Select/deselect files shows/hides file actions', function() { - var $actions = $('.column-name .selectedActions'); - var $checkbox = fileList.findFileEl('One.txt').find('input:checkbox'); - expect($actions.hasClass('hidden')).toEqual(true); - $checkbox.click(); - expect($actions.hasClass('hidden')).toEqual(false); - $checkbox.click(); - expect($actions.hasClass('hidden')).toEqual(true); - }); - it('Selection is cleared when switching dirs', function() { - $('.select-all').click(); - var deferredList = $.Deferred(); - var getFolderContentsStub = sinon.stub(filesClient, 'getFolderContents').returns(deferredList.promise()); - - fileList.changeDirectory('/'); - - deferredList.resolve(200, [testRoot].concat(testFiles)); - - expect($('.select-all').prop('checked')).toEqual(false); - expect(_.pluck(fileList.getSelectedFiles(), 'name')).toEqual([]); - - getFolderContentsStub.restore(); - }); - it('getSelectedFiles returns the selected files even when they are on the next page', function() { - var selectedFiles; - fileList.setFiles(generateFiles(0, 41)); - $('.select-all').click(); - // unselect one to not have the "allFiles" case - fileList.$fileList.find('tr input:checkbox:first').click(); - - // only 20 files visible, must still return all the selected ones - selectedFiles = _.pluck(fileList.getSelectedFiles(), 'name'); - - expect(selectedFiles.length).toEqual(41); - }); - describe('clearing the selection', function() { - it('clears selected files selected individually calling setFiles()', function() { - var selectedFiles; - - fileList.setFiles(generateFiles(0, 41)); - fileList.$fileList.find('tr:eq(5) input:checkbox:first').click(); - fileList.$fileList.find('tr:eq(7) input:checkbox:first').click(); - - selectedFiles = _.pluck(fileList.getSelectedFiles(), 'name'); - expect(selectedFiles.length).toEqual(2); - - fileList.setFiles(generateFiles(0, 2)); - - selectedFiles = _.pluck(fileList.getSelectedFiles(), 'name'); - expect(selectedFiles.length).toEqual(0); - }); - it('clears selected files selected with select all when calling setFiles()', function() { - var selectedFiles; - - fileList.setFiles(generateFiles(0, 41)); - $('.select-all').click(); - - selectedFiles = _.pluck(fileList.getSelectedFiles(), 'name'); - expect(selectedFiles.length).toEqual(42); - - fileList.setFiles(generateFiles(0, 2)); - - selectedFiles = _.pluck(fileList.getSelectedFiles(), 'name'); - expect(selectedFiles.length).toEqual(0); - }); - }); - describe('Selection overlay', function() { - it('show doesnt show the copy/move action if one or more files are not copiable/movable', function () { - fileList.setFiles(testFiles); - $('#permissions').val(OC.PERMISSION_READ | OC.PERMISSION_UPDATE); - $('.select-all').click(); - expect(fileList.$el.find('.selectedActions .item-copyMove').hasClass('hidden')).toEqual(false); - expect(fileList.$el.find('.selectedActions .item-copyMove .label').text()).toEqual('Move or copy'); - testFiles[0].permissions = OC.PERMISSION_READ; - $('.select-all').click(); - fileList.setFiles(testFiles); - $('.select-all').click(); - expect(fileList.$el.find('.selectedActions .item-copyMove').hasClass('hidden')).toEqual(false); - expect(fileList.$el.find('.selectedActions .item-copyMove .label').text()).toEqual('Copy'); - testFiles[0].permissions = OC.PERMISSION_NONE; - $('.select-all').click(); - fileList.setFiles(testFiles); - $('.select-all').click(); - expect(fileList.$el.find('.selectedActions .item-copyMove').hasClass('hidden')).toEqual(true); - }); - it('show doesnt show the download action if one or more files are not downloadable', function () { - fileList.setFiles(testFiles); - $('#permissions').val(OC.PERMISSION_READ | OC.PERMISSION_UPDATE); - $('.select-all').click(); - expect(fileList.$el.find('.selectedActions .item-download').hasClass('hidden')).toEqual(false); - testFiles[0].permissions = OC.PERMISSION_UPDATE; - $('.select-all').click(); - fileList.setFiles(testFiles); - $('.select-all').click(); - expect(fileList.$el.find('.selectedActions .item-download').hasClass('hidden')).toEqual(true); - }); - it('show doesnt show the delete action if one or more files are not deletable', function () { - fileList.setFiles(testFiles); - $('#permissions').val(OC.PERMISSION_READ | OC.PERMISSION_DELETE); - $('.select-all').click(); - expect(fileList.$el.find('.selectedActions .item-delete').hasClass('hidden')).toEqual(false); - testFiles[0].permissions = OC.PERMISSION_READ; - $('.select-all').click(); - fileList.setFiles(testFiles); - $('.select-all').click(); - expect(fileList.$el.find('.selectedActions .item-delete').hasClass('hidden')).toEqual(true); - }); - }); - describe('Actions', function() { - beforeEach(function() { - fileList.findFileEl('One.txt').find('input:checkbox').click(); - fileList.findFileEl('Three.pdf').find('input:checkbox').click(); - fileList.findFileEl('somedir').find('input:checkbox').click(); - }); - it('getSelectedFiles returns the selected file data', function() { - var files = fileList.getSelectedFiles(); - expect(files.length).toEqual(3); - expect(files[0]).toEqual({ - id: 1, - name: 'One.txt', - mimetype: 'text/plain', - mtime: 123456789, - type: 'file', - size: 12, - etag: 'abc', - quotaAvailableBytes: '-1', - permissions: OC.PERMISSION_ALL, - hasPreview: true, - isEncrypted: false - }); - expect(files[1]).toEqual({ - id: 3, - type: 'file', - name: 'Three.pdf', - mimetype: 'application/pdf', - mtime: 234560000, - size: 58009, - quotaAvailableBytes: '-1', - etag: '123', - permissions: OC.PERMISSION_ALL, - hasPreview: true, - isEncrypted: false - }); - expect(files[2]).toEqual({ - id: 4, - type: 'dir', - name: 'somedir', - mimetype: 'httpd/unix-directory', - mtime: 134560000, - size: 250, - quotaAvailableBytes: '-1', - etag: '456', - permissions: OC.PERMISSION_ALL, - hasPreview: true, - isEncrypted: false - }); - expect(files[0].id).toEqual(1); - expect(files[0].name).toEqual('One.txt'); - expect(files[1].id).toEqual(3); - expect(files[1].name).toEqual('Three.pdf'); - expect(files[2].id).toEqual(4); - expect(files[2].name).toEqual('somedir'); - }); - it('Removing a file removes it from the selection', function() { - fileList.remove('Three.pdf'); - var files = fileList.getSelectedFiles(); - expect(files.length).toEqual(2); - expect(files[0]).toEqual({ - id: 1, - name: 'One.txt', - mimetype: 'text/plain', - mtime: 123456789, - type: 'file', - size: 12, - quotaAvailableBytes: '-1', - etag: 'abc', - permissions: OC.PERMISSION_ALL, - hasPreview: true, - isEncrypted: false - }); - expect(files[1]).toEqual({ - id: 4, - type: 'dir', - name: 'somedir', - mimetype: 'httpd/unix-directory', - mtime: 134560000, - size: 250, - quotaAvailableBytes: '-1', - etag: '456', - permissions: OC.PERMISSION_ALL, - hasPreview: true, - isEncrypted: false - }); - }); - describe('Download', function() { - beforeEach(function() { - fileList.$el.find('.actions-selected').click(); - }); - - it('Opens download URL when clicking "Download"', function() { - $('.selectedActions .filesSelectMenu .download').click(); - expect(redirectStub.calledOnce).toEqual(true); - expect(redirectStub.getCall(0).args[0]).toContain(OC.getRootPath() + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22One.txt%22%2C%22Three.pdf%22%2C%22somedir%22%5D'); - redirectStub.restore(); - }); - it('Downloads root folder when all selected in root folder', function() { - fileList.changeDirectory('/', false, true); - $('.select-all').click(); - $('.selectedActions .filesSelectMenu .download').click(); - expect(redirectStub.calledOnce).toEqual(true); - expect(redirectStub.getCall(0).args[0]).toContain(OC.getRootPath() + '/index.php/apps/files/ajax/download.php?dir=%2F&files='); - }); - it('Downloads parent folder when all selected in subfolder', function() { - $('.select-all').click(); - $('.selectedActions .filesSelectMenu .download').click(); - expect(redirectStub.calledOnce).toEqual(true); - expect(redirectStub.getCall(0).args[0]).toContain(OC.getRootPath() + '/index.php/apps/files/ajax/download.php?dir=%2F&files=subdir'); - }); - - afterEach(function() { - fileList.$el.find('.actions-selected').click(); - }); - }); - - describe('Delete', function() { - var deleteStub, deferredDelete; - beforeEach(function() { - deferredDelete = $.Deferred(); - deleteStub = sinon.stub(filesClient, 'remove'); - fileList.$el.find('.actions-selected').click(); - }); - - afterEach(function() { - fileList.$el.find('.actions-selected').click(); - deleteStub.restore(); - }); - - it('Deletes selected files when "Delete" clicked', function(done) { - var deferred = $.Deferred(); - - deleteStub.returns(deferredDelete.promise()); - deleteStub.onCall(2).callsFake(function(){ - expect(deleteStub.callCount).toEqual(3); - expect(deleteStub.getCall(0).args[0]).toEqual('/subdir/One.txt'); - expect(deleteStub.getCall(1).args[0]).toEqual('/subdir/Three.pdf'); - expect(deleteStub.getCall(2).args[0]).toEqual('/subdir/somedir'); - return deferredDelete.promise(); - }); - - stub = sinon.stub(fileList._operationProgressBar, 'hideProgressBar').callsFake(function(){ - expect(fileList.findFileEl('One.txt').length).toEqual(0); - expect(fileList.findFileEl('Three.pdf').length).toEqual(0); - expect(fileList.findFileEl('somedir').length).toEqual(0); - expect(fileList.findFileEl('Two.jpg').length).toEqual(1); - done(); - deferred.resolve(); - }); - $('.selectedActions .filesSelectMenu .delete').click(); - deferredDelete.resolve(204); - return deferred.promise(); - }); - it('Deletes all files when all selected when "Delete" clicked', function(done) { - var deferred = $.Deferred(); - - deleteStub.returns(deferredDelete.promise()); - deleteStub.onCall(3).callsFake(function(){ - expect(deleteStub.getCall(0).args[0]).toEqual('/subdir/One.txt'); - expect(deleteStub.getCall(1).args[0]).toEqual('/subdir/Two.jpg'); - expect(deleteStub.getCall(2).args[0]).toEqual('/subdir/Three.pdf'); - expect(deleteStub.getCall(3).args[0]).toEqual('/subdir/somedir'); - return deferredDelete.promise(); - }); - - stub = sinon.stub(fileList._operationProgressBar, 'hideProgressBar').callsFake(function(){ - expect(fileList.isEmpty).toEqual(true); - expect(deleteStub.callCount).toEqual(4); - done(); - deferred.resolve(); - }); - $('.select-all').click(); - $('.selectedActions .filesSelectMenu .delete').click(); - deferredDelete.resolve(204); - - return deferred.promise(); - }); - }); - }); - it('resets the file selection on reload', function() { - fileList.$el.find('.select-all').click(); - fileList.reload(); - expect(fileList.$el.find('.select-all').prop('checked')).toEqual(false); - expect(fileList.getSelectedFiles()).toEqual([]); - }); - describe('Disabled selection', function() { - beforeEach(function() { - fileList._allowSelection = false; - fileList.setFiles(testFiles); - }); - it('Does not render checkboxes', function() { - expect(fileList.$fileList.find('.selectCheckBox').length).toEqual(0); - }); - it('Does not select a file with Ctrl or Shift if selection is not allowed', function() { - var $tr = fileList.findFileEl('One.txt'); - var $tr2 = fileList.findFileEl('Three.pdf'); - var e; - e = new $.Event('click'); - e.ctrlKey = true; - $tr.find('td.filename .name').trigger(e); - - // click on second entry, does not clear the selection - e = new $.Event('click'); - e.ctrlKey = true; - $tr2.find('td.filename .name').trigger(e); - - expect(fileList.getSelectedFiles().length).toEqual(0); - - // deselect now - e = new $.Event('click'); - e.shiftKey = true; - $tr2.find('td.filename .name').trigger(e); - expect(fileList.getSelectedFiles().length).toEqual(0); - }); - }); - }); - describe('File actions', function() { - it('Clicking on a file name will trigger default action', function() { - var actionStub = sinon.stub(); - fileList.setFiles(testFiles); - fileList.fileActions.registerAction({ - mime: 'text/plain', - name: 'Test', - type: OCA.Files.FileActions.TYPE_INLINE, - permissions: OC.PERMISSION_ALL, - icon: function() { - // Specify icon for history button - return OC.imagePath('core','actions/history'); - }, - actionHandler: actionStub - }); - fileList.fileActions.setDefault('text/plain', 'Test'); - var $tr = fileList.findFileEl('One.txt'); - $tr.find('td.filename .nametext').click(); - expect(actionStub.calledOnce).toEqual(true); - expect(actionStub.getCall(0).args[0]).toEqual('One.txt'); - var context = actionStub.getCall(0).args[1]; - expect(context.$file.is($tr)).toEqual(true); - expect(context.fileList).toBeDefined(); - expect(context.fileActions).toBeDefined(); - expect(context.dir).toEqual('/subdir'); - }); - it('Clicking on an empty space of the file row will trigger the "Details" action', function() { - var detailsActionStub = sinon.stub(); - fileList.setFiles(testFiles); - // Override the "Details" action set internally by the FileList for - // easier testing. - fileList.fileActions.registerAction({ - mime: 'all', - name: 'Details', - permissions: OC.PERMISSION_NONE, - actionHandler: detailsActionStub - }); - // Ensure that the action works even if fileActions.currentFile is - // not set. - fileList.fileActions.currentFile = null; - var $tr = fileList.findFileEl('One.txt'); - $tr.find('td.filesize').click(); - expect(detailsActionStub.calledOnce).toEqual(true); - expect(detailsActionStub.getCall(0).args[0]).toEqual('One.txt'); - var context = detailsActionStub.getCall(0).args[1]; - expect(context.$file.is($tr)).toEqual(true); - expect(context.fileList).toBe(fileList); - expect(context.fileActions).toBe(fileList.fileActions); - expect(context.dir).toEqual('/subdir'); - }); - it('redisplays actions when new actions have been registered', function() { - var actionStub = sinon.stub(); - var readyHandler = sinon.stub(); - var clock = sinon.useFakeTimers(); - var debounceStub = sinon.stub(_, 'debounce').callsFake(function(callback) { - return function() { - // defer instead of debounce, to make it work with clock - _.defer(callback); - }; - }); - - // need to reinit the list to make the debounce call - fileList.destroy(); - fileList = new OCA.Files.FileList($('#app-content-files')); - - fileList.setFiles(testFiles); - - fileList.$fileList.on('fileActionsReady', readyHandler); - - fileList.fileActions.registerAction({ - mime: 'text/plain', - name: 'Test', - type: OCA.Files.FileActions.TYPE_INLINE, - permissions: OC.PERMISSION_ALL, - icon: function() { - // Specify icon for history button - return OC.imagePath('core','actions/history'); - }, - actionHandler: actionStub - }); - var $tr = fileList.findFileEl('One.txt'); - expect($tr.find('.action-test').length).toEqual(0); - expect(readyHandler.notCalled).toEqual(true); - - // update is delayed - clock.tick(100); - expect($tr.find('.action-test').length).toEqual(1); - expect(readyHandler.calledOnce).toEqual(true); - - clock.restore(); - debounceStub.restore(); - }); - }); - describe('Sorting files', function() { - - var getCurrentUserStub; - - beforeEach(function() { - getCurrentUserStub = sinon.stub(OC, 'getCurrentUser').returns({ - uid: 1, - displayName: 'user1' - }); - }); - - afterEach(function() { - getCurrentUserStub.restore(); - }); - - it('Toggles the sort indicator when clicking on a column header', function() { - var ASC_CLASS = fileList.SORT_INDICATOR_ASC_CLASS; - var DESC_CLASS = fileList.SORT_INDICATOR_DESC_CLASS; - var request; - var sortingUrl = OC.generateUrl('/apps/files/api/v1/sorting'); - fileList.$el.find('.column-size .columntitle').click(); - // moves triangle to size column, check indicator on name is hidden - expect( - fileList.$el.find('.column-name .sort-indicator').hasClass('hidden') - ).toEqual(true); - // check indicator on size is visible and defaults to descending - expect( - fileList.$el.find('.column-size .sort-indicator').hasClass('hidden') - ).toEqual(false); - expect( - fileList.$el.find('.column-size .sort-indicator').hasClass(DESC_CLASS) - ).toEqual(true); - // check if changes are persisted - expect(fakeServer.requests.length).toEqual(1); - request = fakeServer.requests[0]; - expect(request.url).toEqual(sortingUrl); - - // click again on size column, reverses direction - fileList.$el.find('.column-size .columntitle').click(); - expect( - fileList.$el.find('.column-size .sort-indicator').hasClass('hidden') - ).toEqual(false); - expect( - fileList.$el.find('.column-size .sort-indicator').hasClass(ASC_CLASS) - ).toEqual(true); - // check if changes are persisted - expect(fakeServer.requests.length).toEqual(2); - request = fakeServer.requests[1]; - expect(request.url).toEqual(sortingUrl); - - // click again on size column, reverses direction - fileList.$el.find('.column-size .columntitle').click(); - expect( - fileList.$el.find('.column-size .sort-indicator').hasClass('hidden') - ).toEqual(false); - expect( - fileList.$el.find('.column-size .sort-indicator').hasClass(DESC_CLASS) - ).toEqual(true); - expect(fakeServer.requests.length).toEqual(3); - request = fakeServer.requests[2]; - expect(request.url).toEqual(sortingUrl); - - // click on mtime column, moves indicator there - fileList.$el.find('.column-mtime .columntitle').click(); - expect( - fileList.$el.find('.column-size .sort-indicator').hasClass('hidden') - ).toEqual(true); - expect( - fileList.$el.find('.column-mtime .sort-indicator').hasClass('hidden') - ).toEqual(false); - expect( - fileList.$el.find('.column-mtime .sort-indicator').hasClass(DESC_CLASS) - ).toEqual(true); - expect(fakeServer.requests.length).toEqual(4); - request = fakeServer.requests[3]; - expect(request.url).toEqual(sortingUrl); - }); - it('Uses correct sort comparator when inserting files', function() { - testFiles.sort(OCA.Files.FileList.Comparators.size); - testFiles.reverse(); //default is descending - fileList.setFiles(testFiles); - fileList.$el.find('.column-size .columntitle').click(); - var newFileData = new FileInfo({ - id: 999, - name: 'new file.txt', - mimetype: 'text/plain', - size: 40001, - etag: '999' - }); - fileList.add(newFileData); - expect(fileList.findFileEl('Three.pdf').index()).toEqual(0); - expect(fileList.findFileEl('new file.txt').index()).toEqual(1); - expect(fileList.findFileEl('Two.jpg').index()).toEqual(2); - expect(fileList.findFileEl('somedir').index()).toEqual(3); - expect(fileList.findFileEl('One.txt').index()).toEqual(4); - expect(fileList.files.length).toEqual(5); - expect(fileList.$fileList.find('tr').length).toEqual(5); - }); - it('Uses correct reversed sort comparator when inserting files', function() { - testFiles.sort(OCA.Files.FileList.Comparators.size); - fileList.setFiles(testFiles); - fileList.$el.find('.column-size .columntitle').click(); - - // reverse sort - fileList.$el.find('.column-size .columntitle').click(); - var newFileData = new FileInfo({ - id: 999, - name: 'new file.txt', - mimetype: 'text/plain', - size: 40001, - etag: '999' - }); - fileList.add(newFileData); - expect(fileList.findFileEl('One.txt').index()).toEqual(0); - expect(fileList.findFileEl('somedir').index()).toEqual(1); - expect(fileList.findFileEl('Two.jpg').index()).toEqual(2); - expect(fileList.findFileEl('new file.txt').index()).toEqual(3); - expect(fileList.findFileEl('Three.pdf').index()).toEqual(4); - expect(fileList.files.length).toEqual(5); - expect(fileList.$fileList.find('tr').length).toEqual(5); - }); - it('does not sort when clicking on header whenever multiselect is enabled', function() { - var sortStub = sinon.stub(OCA.Files.FileList.prototype, 'setSort'); - - fileList.setFiles(testFiles); - fileList.findFileEl('One.txt').find('input:checkbox:first').click(); - - fileList.$el.find('.column-size .columntitle').click(); - - expect(sortStub.notCalled).toEqual(true); - - // can sort again after deselecting - fileList.findFileEl('One.txt').find('input:checkbox:first').click(); - - fileList.$el.find('.column-size .columntitle').click(); - - expect(sortStub.calledOnce).toEqual(true); - - sortStub.restore(); - }); - - describe('if no user logged in', function() { - beforeEach(function() { - getCurrentUserStub.returns({ - uid: null, - displayName: 'Guest' - }); - }); - - it('shouldn\'t send an update sort order request', function() { - OC.currentUser = false; - fileList.$el.find('.column-size .columntitle').click(); - // check if there was no request - expect(fakeServer.requests.length).toEqual(0); - }); - }); - - describe('with favorites', function() { - it('shows favorite files on top', function() { - testFiles.push(new FileInfo({ - id: 5, - type: 'file', - name: 'ZZY Before last file in ascending order', - mimetype: 'text/plain', - mtime: 999999998, - size: 9999998, - // Tags would be added by TagsPlugin - tags: [OC.TAG_FAVORITE], - }), new FileInfo({ - id: 6, - type: 'file', - name: 'ZZZ Last file in ascending order', - mimetype: 'text/plain', - mtime: 999999999, - size: 9999999, - // Tags would be added by TagsPlugin - tags: [OC.TAG_FAVORITE], - })); - - fileList.setFiles(testFiles); - - // Sort by name in ascending order (default sorting is by name - // in ascending order, but setFiles does not trigger a sort, so - // the files must be sorted before being set or a sort must be - // triggered afterwards by clicking on the header). - fileList.$el.find('.column-name .columntitle').click(); - fileList.$el.find('.column-name .columntitle').click(); - - expect(fileList.findFileEl('ZZY Before last file in ascending order').index()).toEqual(0); - expect(fileList.findFileEl('ZZZ Last file in ascending order').index()).toEqual(1); - expect(fileList.findFileEl('somedir').index()).toEqual(2); - expect(fileList.findFileEl('One.txt').index()).toEqual(3); - expect(fileList.findFileEl('Three.pdf').index()).toEqual(4); - expect(fileList.findFileEl('Two.jpg').index()).toEqual(5); - - // Sort by size in ascending order - fileList.$el.find('.column-size .columntitle').click(); - fileList.$el.find('.column-size .columntitle').click(); - - expect(fileList.findFileEl('ZZY Before last file in ascending order').index()).toEqual(0); - expect(fileList.findFileEl('ZZZ Last file in ascending order').index()).toEqual(1); - expect(fileList.findFileEl('One.txt').index()).toEqual(2); - expect(fileList.findFileEl('somedir').index()).toEqual(3); - expect(fileList.findFileEl('Two.jpg').index()).toEqual(4); - expect(fileList.findFileEl('Three.pdf').index()).toEqual(5); - - // Sort by modification time in ascending order - fileList.$el.find('.column-mtime .columntitle').click(); - fileList.$el.find('.column-mtime .columntitle').click(); - - expect(fileList.findFileEl('ZZY Before last file in ascending order').index()).toEqual(0); - expect(fileList.findFileEl('ZZZ Last file in ascending order').index()).toEqual(1); - expect(fileList.findFileEl('One.txt').index()).toEqual(2); - expect(fileList.findFileEl('somedir').index()).toEqual(3); - expect(fileList.findFileEl('Three.pdf').index()).toEqual(4); - expect(fileList.findFileEl('Two.jpg').index()).toEqual(5); - }); - it('shows favorite files on top also when using descending order', function() { - testFiles.push(new FileInfo({ - id: 5, - type: 'file', - name: 'AAB Before last file in descending order', - mimetype: 'text/plain', - mtime: 2, - size: 2, - // Tags would be added by TagsPlugin - tags: [OC.TAG_FAVORITE], - }), new FileInfo({ - id: 6, - type: 'file', - name: 'AAA Last file in descending order', - mimetype: 'text/plain', - mtime: 1, - size: 1, - // Tags would be added by TagsPlugin - tags: [OC.TAG_FAVORITE], - })); - - fileList.setFiles(testFiles); - - // Sort by name in descending order - fileList.$el.find('.column-name .columntitle').click(); - - expect(fileList.findFileEl('AAB Before last file in descending order').index()).toEqual(0); - expect(fileList.findFileEl('AAA Last file in descending order').index()).toEqual(1); - expect(fileList.findFileEl('Two.jpg').index()).toEqual(2); - expect(fileList.findFileEl('Three.pdf').index()).toEqual(3); - expect(fileList.findFileEl('One.txt').index()).toEqual(4); - expect(fileList.findFileEl('somedir').index()).toEqual(5); - - // Sort by size in descending order - fileList.$el.find('.column-size .columntitle').click(); - - expect(fileList.findFileEl('AAB Before last file in descending order').index()).toEqual(0); - expect(fileList.findFileEl('AAA Last file in descending order').index()).toEqual(1); - expect(fileList.findFileEl('Three.pdf').index()).toEqual(2); - expect(fileList.findFileEl('Two.jpg').index()).toEqual(3); - expect(fileList.findFileEl('somedir').index()).toEqual(4); - expect(fileList.findFileEl('One.txt').index()).toEqual(5); - - // Sort by modification time in descending order - fileList.$el.find('.column-mtime .columntitle').click(); - - expect(fileList.findFileEl('AAB Before last file in descending order').index()).toEqual(0); - expect(fileList.findFileEl('AAA Last file in descending order').index()).toEqual(1); - expect(fileList.findFileEl('Two.jpg').index()).toEqual(2); - expect(fileList.findFileEl('Three.pdf').index()).toEqual(3); - expect(fileList.findFileEl('somedir').index()).toEqual(4); - expect(fileList.findFileEl('One.txt').index()).toEqual(5); - }); - }); - }); - describe('create file', function() { - var deferredCreate; - var deferredInfo; - var createStub; - var getFileInfoStub; - - beforeEach(function() { - deferredCreate = $.Deferred(); - deferredInfo = $.Deferred(); - createStub = sinon.stub(filesClient, 'putFileContents') - .returns(deferredCreate.promise()); - getFileInfoStub = sinon.stub(filesClient, 'getFileInfo') - .returns(deferredInfo.promise()); - }); - afterEach(function() { - createStub.restore(); - getFileInfoStub.restore(); - }); - - it('creates file with given name and adds it to the list', function(done) { - var creating = fileList.createFile('test.txt'); - - expect(createStub.calledOnce).toEqual(true); - expect(createStub.getCall(0).args[0]).toEqual('/subdir/test.txt'); - expect(createStub.getCall(0).args[2]).toEqual({ - contentType: 'text/plain', - overwrite: true - }); - - deferredCreate.resolve(200); - - expect(getFileInfoStub.calledOnce).toEqual(true); - expect(getFileInfoStub.getCall(0).args[0]).toEqual('/subdir/test.txt'); - - deferredInfo.resolve( - 200, - new FileInfo({ - path: '/subdir', - name: 'test.txt', - mimetype: 'text/plain' - }) - ); - - return creating.then(function() { - var $tr = fileList.findFileEl('test.txt'); - expect($tr.length).toEqual(1); - expect($tr.attr('data-mime')).toEqual('text/plain'); - }).then(done, done); - }); - // TODO: error cases - // TODO: unique name cases - }); - describe('create folder', function() { - var deferredCreate; - var deferredInfo; - var createStub; - var getFileInfoStub; - - beforeEach(function() { - deferredCreate = $.Deferred(); - deferredInfo = $.Deferred(); - createStub = sinon.stub(filesClient, 'createDirectory') - .returns(deferredCreate.promise()); - getFileInfoStub = sinon.stub(filesClient, 'getFileInfo') - .returns(deferredInfo.promise()); - }); - afterEach(function() { - createStub.restore(); - getFileInfoStub.restore(); - }); - - it('creates folder with given name and adds it to the list', function(done) { - var creating = fileList.createDirectory('sub dir'); - - expect(createStub.calledOnce).toEqual(true); - expect(createStub.getCall(0).args[0]).toEqual('/subdir/sub dir'); - - deferredCreate.resolve(200); - - expect(getFileInfoStub.calledOnce).toEqual(true); - expect(getFileInfoStub.getCall(0).args[0]).toEqual('/subdir/sub dir'); - - deferredInfo.resolve( - 200, - new FileInfo({ - path: '/subdir', - name: 'sub dir', - mimetype: 'httpd/unix-directory' - }) - ); - - return creating.then(function() { - var $tr = fileList.findFileEl('sub dir'); - expect($tr.length).toEqual(1); - expect($tr.attr('data-mime')).toEqual('httpd/unix-directory'); - }).then(done, done); - }); - // TODO: error cases - // TODO: unique name cases - }); - describe('addAndFetchFileInfo', function() { - var getFileInfoStub; - var getFileInfoDeferred; - - beforeEach(function() { - getFileInfoDeferred = $.Deferred(); - getFileInfoStub = sinon.stub(OC.Files.Client.prototype, 'getFileInfo'); - getFileInfoStub.returns(getFileInfoDeferred.promise()); - }); - afterEach(function() { - getFileInfoStub.restore(); - }); - it('does not fetch if the given folder is not the current one', function() { - var promise = fileList.addAndFetchFileInfo('testfile.txt', '/another'); - expect(getFileInfoStub.notCalled).toEqual(true); - - expect(promise.state()).toEqual('resolved'); - }); - it('fetches info when folder is the current one', function(done) { - fileList.addAndFetchFileInfo('testfile.txt', '/subdir'); - - return Promise.resolve().then(function() { - expect(getFileInfoStub.calledOnce).toEqual(true); - expect(getFileInfoStub.getCall(0).args[0]).toEqual('/subdir/testfile.txt'); - }).then(done, done); - }); - it('adds file data to list when fetching is done', function(done) { - var adding = fileList.addAndFetchFileInfo('testfile.txt', '/subdir'); - getFileInfoDeferred.resolve(200, { - name: 'testfile.txt', - size: 100 - }); - - return adding.then(function() { - expect(fileList.findFileEl('testfile.txt').attr('data-size')).toEqual('100'); - }).then(done, done); - }); - it('replaces file data to list when fetching is done', function(done) { - var adding = fileList.addAndFetchFileInfo('testfile.txt', '/subdir', {replace: true}); - fileList.add({ - name: 'testfile.txt', - size: 95 - }); - getFileInfoDeferred.resolve(200, { - name: 'testfile.txt', - size: 100 - }); - expect(fileList.findFileEl('testfile.txt').attr('data-size')).toEqual('95'); - return adding.then(function() { - expect(fileList.findFileEl('testfile.txt').attr('data-size')).toEqual('100'); - }).then(done, done); - }); - it('resolves promise with file data when fetching is done', function(done) { - var promise = fileList.addAndFetchFileInfo('testfile.txt', '/subdir', {replace: true}); - getFileInfoDeferred.resolve(200, { - name: 'testfile.txt', - size: 100 - }); - expect(promise.state()).toEqual('pending'); - return promise.then(function(status, data) { - expect(promise.state()).toEqual('resolved'); - expect(status).toEqual(200); - expect(data.name).toEqual('testfile.txt'); - expect(data.size).toEqual(100); - }).then(done, done); - }); - }); - /** - * Test upload mostly by testing the code inside the event handlers - * that were registered on the magic upload object - */ - describe('file upload', function() { - var uploadData; - var uploader; - - beforeEach(function() { - fileList.setFiles(testFiles); - uploader = fileList._uploader; - // simulate data structure from jquery.upload - uploadData = { - files: [{ - name: 'upload.txt' - }] - }; - }); - - afterEach(function() { - uploader = null; - uploadData = null; - }); - - describe('enableupload', function() { - it('sets up uploader when enableUpload is true', function() { - expect(fileList._uploader).toBeDefined(); - }); - it('does not sets up uploader when enableUpload is false', function() { - fileList.destroy(); - fileList = new OCA.Files.FileList($('#app-content-files'), { - filesClient: filesClient - }); - expect(fileList._uploader).toBeFalsy(); - }); - }); - - describe('adding files for upload', function() { - /** - * Simulate add event on the given target - * - * @return event object including the result - */ - function addFile(data) { - uploader.trigger('add', {}, data || {}); - } - - it('sets target dir to the current directory', function() { - addFile(uploadData); - expect(uploadData.targetDir).toEqual('/subdir'); - }); - }); - describe('dropping external files', function() { - - /** - * Simulate drop event on the given target - * - * @param $target target element to drop on - * @return event object including the result - */ - function dropOn($target, data) { - var eventData = { - delegatedEvent: { - target: $target - }, - preventDefault: function () { - }, - stopPropagation: function() { - } - }; - uploader.trigger('drop', eventData, data || {}); - return !!data.targetDir; - } - it('drop on a tr or crumb outside file list does not trigger upload', function() { - var $anotherTable = $('<table><tbody><tr><td>outside<div class="crumb">crumb</div></td></tr></table>'); - var ev; - $('#testArea').append($anotherTable); - ev = dropOn($anotherTable.find('tr'), uploadData); - expect(ev).toEqual(false); - - ev = dropOn($anotherTable.find('.crumb'), uploadData); - expect(ev).toEqual(false); - }); - it('drop on an element outside file list container does not trigger upload', function() { - var $anotherEl = $('<div>outside</div>'); - var ev; - $('#testArea').append($anotherEl); - ev = dropOn($anotherEl, uploadData); - - expect(ev).toEqual(false); - }); - it('drop on an element inside the table triggers upload', function() { - var ev; - ev = dropOn(fileList.$fileList.find('th:first'), uploadData); - - expect(ev).not.toEqual(false); - expect(uploadData.targetDir).toEqual('/subdir'); - }); - it('drop on an element on the table container triggers upload', function() { - var ev; - ev = dropOn($('#app-content-files'), uploadData); - - expect(ev).not.toEqual(false); - expect(uploadData.targetDir).toEqual('/subdir'); - }); - it('drop on an element inside the table does not trigger upload if no upload permission', function() { - $('#permissions').val(0); - var ev; - ev = dropOn(fileList.$fileList.find('th:first'), uploadData); - - expect(ev).toEqual(false); - expect(notificationStub.calledOnce).toEqual(true); - }); - it('drop on an folder does not trigger upload if no upload permission on that folder', function() { - var $tr = fileList.findFileEl('somedir'); - var ev; - $tr.data('permissions', OC.PERMISSION_READ); - ev = dropOn($tr, uploadData); - - expect(ev).toEqual(false); - expect(notificationStub.calledOnce).toEqual(true); - }); - it('drop on a file row inside the table triggers upload to current folder', function() { - var ev; - ev = dropOn(fileList.findFileEl('One.txt').find('td:first'), uploadData); - - expect(ev).not.toEqual(false); - expect(uploadData.targetDir).toEqual('/subdir'); - }); - it('drop on a folder row inside the table triggers upload to target folder', function() { - var ev; - ev = dropOn(fileList.findFileEl('somedir').find('td:eq(2)'), uploadData); - - expect(ev).not.toEqual(false); - expect(uploadData.targetDir).toEqual('/subdir/somedir'); - }); - it('drop on a breadcrumb inside the table triggers upload to target folder', function() { - var ev; - fileList.changeDirectory('a/b/c/d'); - ev = dropOn(fileList.$el.find('.crumb:eq(3)'), uploadData); - - expect(ev).not.toEqual(false); - expect(uploadData.targetDir).toEqual('/a/b'); - }); - it('renders upload indicator element for folders only', function() { - fileList.add({ - name: 'afolder', - type: 'dir', - mime: 'httpd/unix-directory' - }); - fileList.add({ - name: 'afile.txt', - type: 'file', - mime: 'text/plain' - }); - - expect(fileList.findFileEl('afolder').find('.uploadtext').length).toEqual(1); - expect(fileList.findFileEl('afile.txt').find('.uploadtext').length).toEqual(0); - }); - }); - - describe('after folder creation due to folder upload', function() { - it('fetches folder info', function() { - var fetchInfoStub = sinon.stub(fileList, 'addAndFetchFileInfo'); - - uploader.trigger('createdfolder', '/subdir/newfolder'); - - expect(fetchInfoStub.calledOnce).toEqual(true); - expect(fetchInfoStub.getCall(0).args[0]).toEqual('newfolder'); - expect(fetchInfoStub.getCall(0).args[1]).toEqual('/subdir'); - - fetchInfoStub.restore(); - }); - }); - - describe('after upload', function() { - var fetchInfoStub; - - beforeEach(function() { - fetchInfoStub = sinon.stub(fileList, 'addAndFetchFileInfo'); - - }); - afterEach(function() { - fetchInfoStub.restore(); - }); - - - function createUpload(name, dir) { - var jqXHR = { - status: 200 - }; - return { - getFileName: sinon.stub().returns(name), - getFullPath: sinon.stub().returns(dir), - data: { - jqXHR: jqXHR - } - }; - } - - /** - * Simulate add event on the given target - * - * @return event object including the result - */ - function addFile(data) { - var ev = new $.Event('done', { - jqXHR: {status: 200} - }); - var deferred = $.Deferred(); - fetchInfoStub.returns(deferred.promise()); - uploader.trigger('done', ev, data || {}); - return deferred; - } - - it('fetches file info', function() { - addFile(createUpload('upload.txt', '/subdir')); - expect(fetchInfoStub.calledOnce).toEqual(true); - expect(fetchInfoStub.getCall(0).args[0]).toEqual('upload.txt'); - expect(fetchInfoStub.getCall(0).args[1]).toEqual('/subdir'); - }); - it('highlights all uploaded files after all fetches are done', function(done) { - var highlightStub = sinon.stub(fileList, 'highlightFiles'); - var def1 = addFile(createUpload('upload.txt', '/subdir')); - var def2 = addFile(createUpload('upload2.txt', '/subdir')); - var def3 = addFile(createUpload('upload3.txt', '/another')); - uploader.trigger('stop', {}); - - expect(highlightStub.notCalled).toEqual(true); - def1.resolve(); - expect(highlightStub.notCalled).toEqual(true); - def2.resolve(); - def3.resolve(); - setTimeout(function() { - expect(highlightStub.callCount).toEqual(1); - expect(highlightStub.getCall(0).args[0]).toEqual(['upload.txt', 'upload2.txt']); - - highlightStub.restore(); - - done(); - }, 5); - }); - it('queries storage stats after all fetches are done', function(done) { - var statStub = sinon.stub(fileList, 'updateStorageStatistics'); - var highlightStub = sinon.stub(fileList, 'highlightFiles'); - var def1 = addFile(createUpload('upload.txt', '/subdir')); - var def2 = addFile(createUpload('upload2.txt', '/subdir')); - var def3 = addFile(createUpload('upload3.txt', '/another')); - uploader.trigger('stop', {}); - - expect(statStub.notCalled).toEqual(true); - def1.resolve(); - expect(statStub.notCalled).toEqual(true); - def2.resolve(); - def3.resolve(); - setTimeout(function() { - expect(statStub.calledOnce).toEqual(true); - - highlightStub.restore(); - - done(); - }, 3); - }); - }); - }); - describe('Handling errors', function () { - var deferredList; - var getFolderContentsStub; - var reloading; - - beforeEach(function() { - deferredList = $.Deferred(); - getFolderContentsStub = - sinon.stub(filesClient, 'getFolderContents'); - getFolderContentsStub.onCall(0).returns(deferredList.promise()); - getFolderContentsStub.onCall(1).returns($.Deferred().promise()); - reloading = fileList.reload(); - }); - afterEach(function() { - getFolderContentsStub.restore(); - fileList = undefined; - }); - it('redirects to root folder in case of forbidden access', function (done) { - deferredList.reject(403); - - return reloading.then(function() { - expect(fileList.getCurrentDirectory()).toEqual('/'); - expect(getFolderContentsStub.calledTwice).toEqual(true); - }).then(done, done); - }); - it('redirects to root folder and shows notification in case of internal server error', function (done) { - expect(notificationStub.notCalled).toEqual(true); - deferredList.reject(500); - - return reloading.then(function() { - expect(fileList.getCurrentDirectory()).toEqual('/'); - expect(getFolderContentsStub.calledTwice).toEqual(true); - expect(notificationStub.calledOnce).toEqual(true); - }).then(done, done); - }); - it('redirects to root folder and shows notification in case of storage not available', function (done) { - expect(notificationStub.notCalled).toEqual(true); - deferredList.reject(503, 'Storage is temporarily not available'); - - return reloading.then(function() { - expect(fileList.getCurrentDirectory()).toEqual('/'); - expect(getFolderContentsStub.calledTwice).toEqual(true); - expect(notificationStub.calledOnce).toEqual(true); - }).then(done, done); - }); - }); - describe('showFileBusyState', function() { - var $tr; - - beforeEach(function() { - fileList.setFiles(testFiles); - $tr = fileList.findFileEl('Two.jpg'); - }); - it('shows spinner on busy rows', function() { - fileList.showFileBusyState('Two.jpg', true); - expect($tr.hasClass('busy')).toEqual(true); - expect($tr.find('.thumbnail').parent().attr('class')) - .toContain('icon-loading-small'); - - fileList.showFileBusyState('Two.jpg', false); - expect($tr.hasClass('busy')).toEqual(false); - expect(OC.TestUtil.getImageUrl($tr.find('.thumbnail'))) - .toEqual(OC.imagePath('core', 'filetypes/image.svg')); - }); - it('accepts multiple input formats', function() { - _.each([ - 'Two.jpg', - ['Two.jpg'], - $tr, - [$tr] - ], function(testCase) { - fileList.showFileBusyState(testCase, true); - expect($tr.hasClass('busy')).toEqual(true); - fileList.showFileBusyState(testCase, false); - expect($tr.hasClass('busy')).toEqual(false); - }); - }); - }); - describe('elementToFile', function() { - var $tr; - - beforeEach(function() { - fileList.setFiles(testFiles); - $tr = fileList.findFileEl('One.txt'); - }); - - it('converts data attributes to file info structure', function() { - var fileInfo = fileList.elementToFile($tr); - expect(fileInfo.id).toEqual(1); - expect(fileInfo.name).toEqual('One.txt'); - expect(fileInfo.mtime).toEqual(123456789); - expect(fileInfo.etag).toEqual('abc'); - expect(fileInfo.permissions).toEqual(OC.PERMISSION_ALL); - expect(fileInfo.size).toEqual(12); - expect(fileInfo.mimetype).toEqual('text/plain'); - expect(fileInfo.type).toEqual('file'); - expect(fileInfo.path).not.toBeDefined(); - expect(fileInfo.isEncrypted).toEqual(false); - }); - it('sets isEncrypted attribute if data includes true e2eencrypted', function() { - testFiles[3].isEncrypted = true; - - fileList.setFiles(testFiles); - $tr = fileList.findFileEl('somedir'); - - var fileInfo = fileList.elementToFile($tr); - expect(fileInfo.isEncrypted).toEqual(true); - }); - it('adds path attribute if available', function() { - $tr.attr('data-path', '/subdir'); - var fileInfo = fileList.elementToFile($tr); - expect(fileInfo.path).toEqual('/subdir'); - }); - }); - describe('new file menu', function() { - var newFileMenuStub; - - beforeEach(function() { - newFileMenuStub = sinon.stub(OCA.Files.NewFileMenu.prototype, 'showAt'); - }); - afterEach(function() { - newFileMenuStub.restore(); - }) - it('renders new button when no legacy upload button exists', function() { - expect(fileList.$el.find('.button.upload').length).toEqual(0); - expect(fileList.$el.find('.button.new').length).toEqual(1); - }); - it('does not render new button when no legacy upload button exists (public page)', function() { - fileList.destroy(); - $('.files-controls').append('<input type="button" class="button upload" />'); - fileList = new OCA.Files.FileList($('#app-content-files')); - expect(fileList.$el.find('.button.upload').length).toEqual(1); - expect(fileList.$el.find('.button.new').length).toEqual(0); - }); - it('opens the new file menu when clicking on the "New" button', function() { - var $button = fileList.$el.find('.button.new'); - $button.click(); - expect(newFileMenuStub.calledOnce).toEqual(true); - }); - it('does not open the new file menu when button is disabled', function() { - var $button = fileList.$el.find('.button.new'); - $button.addClass('disabled'); - $button.click(); - expect(newFileMenuStub.notCalled).toEqual(true); - }); - }); - describe('mount type detection', function() { - function testMountType(dirInfoId, dirInfoMountType, inputMountType, expectedMountType) { - var $tr; - fileList.dirInfo.id = dirInfoId; - fileList.dirInfo.mountType = dirInfoMountType; - $tr = fileList.add({ - type: 'dir', - mimetype: 'httpd/unix-directory', - name: 'test dir', - mountType: inputMountType - }); - - expect($tr.attr('data-mounttype')).toEqual(expectedMountType); - } - - it('leaves mount type as is if no parent exists', function() { - testMountType(null, null, 'external', 'external'); - testMountType(null, null, 'shared', 'shared'); - }); - it('detects share root if parent exists', function() { - testMountType(123, null, 'shared', 'shared-root'); - testMountType(123, 'shared', 'shared', 'shared'); - testMountType(123, 'shared-root', 'shared', 'shared'); - }); - it('detects external storage root if parent exists', function() { - testMountType(123, null, 'external', 'external-root'); - testMountType(123, 'external', 'external', 'external'); - testMountType(123, 'external-root', 'external', 'external'); - }); - }); - describe('file list should not refresh if url does not change', function() { - var fileListStub; - - beforeEach(function() { - fileListStub = sinon.stub(OCA.Files.FileList.prototype, 'changeDirectory'); - fileList._currentDirectory = '/subdir'; - }); - afterEach(function() { - fileListStub.restore(); - }); - it('File list must not be refreshed', function() { - $('#app-content-files').trigger(new $.Event('urlChanged', {dir: '/subdir'})); - expect(fileListStub.notCalled).toEqual(true); - }); - it('File list must be refreshed', function() { - $('#app-content-files').trigger(new $.Event('urlChanged', {dir: '/'})); - expect(fileListStub.notCalled).toEqual(false); - }); - }); -}); diff --git a/apps/files/tests/js/filesSpec.js b/apps/files/tests/js/filesSpec.js deleted file mode 100644 index cb215397420..00000000000 --- a/apps/files/tests/js/filesSpec.js +++ /dev/null @@ -1,147 +0,0 @@ -/** -* @copyright 2014 Vincent Petry <pvince81@owncloud.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Felix Heidecke <felix@heidecke.me> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0-or-later - * - * 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/>. - * - */ - -describe('OCA.Files.Files tests', function() { - var Files = OCA.Files.Files; - - describe('File name validation', function() { - it('Validates correct file names', function() { - var fileNames = [ - 'boringname', - 'something.with.extension', - 'now with spaces', - '.a', - '..a', - '.dotfile', - 'single\'quote', - ' spaces before', - 'spaces after ', - 'allowed chars including the crazy ones $%&_-^@!,()[]{}=;#', - '汉字也能用', - 'und Ümläüte sind auch willkommen' - ]; - for ( var i = 0; i < fileNames.length; i++ ) { - var error = false; - try { - expect(Files.isFileNameValid(fileNames[i])).toEqual(true); - } - catch (e) { - error = e; - } - expect(error).toEqual(false); - } - }); - it('Detects invalid file names', function() { - var fileNames = [ - '', - ' ', - '.', - '..', - ' ..', - '.. ', - '. ', - ' .', - 'foo.part', - 'bar.filepart' - ]; - for ( var i = 0; i < fileNames.length; i++ ) { - var threwException = false; - try { - Files.isFileNameValid(fileNames[i]); - console.error('Invalid file name not detected:', fileNames[i]); - } - catch (e) { - threwException = true; - } - expect(threwException).toEqual(true); - } - }); - }); - describe('getDownloadUrl', function() { - it('returns the ajax download URL when filename and dir specified', function() { - var url = Files.getDownloadUrl('test file.txt', '/subdir'); - expect(url).toEqual(OC.getRootPath() + '/remote.php/webdav/subdir/test%20file.txt'); - }); - it('returns the webdav download URL when filename and root dir specified', function() { - var url = Files.getDownloadUrl('test file.txt', '/'); - expect(url).toEqual(OC.getRootPath() + '/remote.php/webdav/test%20file.txt'); - }); - it('returns the ajax download URL when multiple files specified', function() { - var url = Files.getDownloadUrl(['test file.txt', 'abc.txt'], '/subdir'); - expect(url).toEqual(OC.getRootPath() + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22test%20file.txt%22%2C%22abc.txt%22%5D'); - }); - }); - describe('handleDownload', function() { - var redirectStub; - var cookieStub; - var clock; - var testUrl; - - beforeEach(function() { - testUrl = 'http://example.com/owncloud/path/download.php'; - redirectStub = sinon.stub(OC, 'redirect'); - cookieStub = sinon.stub(OC.Util, 'isCookieSetToValue'); - clock = sinon.useFakeTimers(); - }); - afterEach(function() { - redirectStub.restore(); - cookieStub.restore(); - clock.restore(); - }); - - it('appends secret to url when no existing parameters', function() { - Files.handleDownload(testUrl); - expect(redirectStub.calledOnce).toEqual(true); - expect(redirectStub.getCall(0).args[0]).toContain(testUrl + '?downloadStartSecret='); - }); - it('appends secret to url with existing parameters', function() { - Files.handleDownload(testUrl + '?test=1'); - expect(redirectStub.calledOnce).toEqual(true); - expect(redirectStub.getCall(0).args[0]).toContain(testUrl + '?test=1&downloadStartSecret='); - }); - it('sets cookie and calls callback when cookie appears', function() { - var callbackStub = sinon.stub(); - var token; - Files.handleDownload(testUrl, callbackStub); - expect(redirectStub.calledOnce).toEqual(true); - token = OC.parseQueryString(redirectStub.getCall(0).args[0]).downloadStartSecret; - expect(token).toBeDefined(); - - expect(cookieStub.calledOnce).toEqual(true); - cookieStub.returns(false); - clock.tick(600); - - expect(cookieStub.calledTwice).toEqual(true); - expect(cookieStub.getCall(1).args[0]).toEqual('ocDownloadStarted'); - expect(cookieStub.getCall(1).args[1]).toEqual(token); - expect(callbackStub.notCalled).toEqual(true); - - cookieStub.returns(true); - clock.tick(2000); - - expect(cookieStub.callCount).toEqual(3); - expect(callbackStub.calledOnce).toEqual(true); - }); - }); -}); diff --git a/apps/files/tests/js/filesummarySpec.js b/apps/files/tests/js/filesummarySpec.js deleted file mode 100644 index 8bc7bd8f995..00000000000 --- a/apps/files/tests/js/filesummarySpec.js +++ /dev/null @@ -1,246 +0,0 @@ -/** -* @copyright 2014 Vincent Petry <pvince81@owncloud.com> - * - * @author Jörn Friedrich Dreyer <jfd@butonic.de> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0-or-later - * - * 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/>. - * - */ - -describe('OCA.Files.FileSummary tests', function() { - var FileSummary = OCA.Files.FileSummary; - var $container; - - beforeEach(function() { - $container = $('<table><tr></tr></table>').find('tr'); - }); - afterEach(function() { - $container = null; - }); - - it('renders summary as text', function() { - var s = new FileSummary($container); - s.setSummary({ - totalDirs: 5, - totalFiles: 2, - totalSize: 256000 - }); - expect($container.hasClass('hidden')).toEqual(false); - expect($container.find('.dirinfo').text()).toEqual('5 folders'); - expect($container.find('.fileinfo').text()).toEqual('2 files'); - expect($container.find('.filesize').text()).toEqual('250 KB'); - }); - it('hides summary when no files or folders', function() { - var s = new FileSummary($container); - s.setSummary({ - totalDirs: 0, - totalFiles: 0, - totalSize: 0 - }); - expect($container.hasClass('hidden')).toEqual(true); - }); - it('increases summary when adding files', function() { - var s = new FileSummary($container); - s.setSummary({ - totalDirs: 5, - totalFiles: 2, - totalSize: 256000 - }); - s.add({type: 'file', size: 256000}); - s.add({type: 'dir', size: 100}); - s.update(); - expect($container.hasClass('hidden')).toEqual(false); - expect($container.find('.dirinfo').text()).toEqual('6 folders'); - expect($container.find('.fileinfo').text()).toEqual('3 files'); - expect($container.find('.filesize').text()).toEqual('500 KB'); - expect(s.summary.totalDirs).toEqual(6); - expect(s.summary.totalFiles).toEqual(3); - expect(s.summary.totalSize).toEqual(512100); - }); - it('decreases summary when removing files', function() { - var s = new FileSummary($container); - s.setSummary({ - totalDirs: 5, - totalFiles: 2, - totalSize: 256000 - }); - s.remove({type: 'file', size: 128000}); - s.remove({type: 'dir', size: 100}); - s.update(); - expect($container.hasClass('hidden')).toEqual(false); - expect($container.find('.dirinfo').text()).toEqual('4 folders'); - expect($container.find('.fileinfo').text()).toEqual('1 file'); - expect($container.find('.filesize').text()).toEqual('125 KB'); - expect(s.summary.totalDirs).toEqual(4); - expect(s.summary.totalFiles).toEqual(1); - expect(s.summary.totalSize).toEqual(127900); - }); - - it('renders filtered summary as text', function() { - var s = new FileSummary($container); - s.setSummary({ - totalDirs: 5, - totalFiles: 2, - totalSize: 256000, - filter: 'foo' - }); - expect($container.hasClass('hidden')).toEqual(false); - expect($container.find('.dirinfo').text()).toEqual('5 folders'); - expect($container.find('.fileinfo').text()).toEqual('2 files'); - expect($container.find('.filter').text()).toEqual(' match "foo"'); - expect($container.find('.filesize').text()).toEqual('250 KB'); - }); - it('hides filtered summary when no files or folders', function() { - var s = new FileSummary($container); - s.setSummary({ - totalDirs: 0, - totalFiles: 0, - totalSize: 0, - filter: 'foo' - }); - expect($container.hasClass('hidden')).toEqual(true); - }); - it('increases filtered summary when adding files', function() { - var s = new FileSummary($container); - s.setSummary({ - totalDirs: 5, - totalFiles: 2, - totalSize: 256000, - filter: 'foo' - }); - s.add({name: 'bar.txt', type: 'file', size: 256000}); - s.add({name: 'foo.txt', type: 'file', size: 256001}); - s.add({name: 'bar', type: 'dir', size: 100}); - s.add({name: 'foo', type: 'dir', size: 102}); - s.update(); - expect($container.hasClass('hidden')).toEqual(false); - expect($container.find('.dirinfo').text()).toEqual('6 folders'); - expect($container.find('.fileinfo').text()).toEqual('3 files'); - expect($container.find('.filter').text()).toEqual(' match "foo"'); - expect($container.find('.filesize').text()).toEqual('500 KB'); - expect(s.summary.totalDirs).toEqual(6); - expect(s.summary.totalFiles).toEqual(3); - expect(s.summary.totalSize).toEqual(512103); - }); - it('decreases filtered summary when removing files', function() { - var s = new FileSummary($container); - s.setSummary({ - totalDirs: 5, - totalFiles: 2, - totalSize: 256000, - filter: 'foo' - }); - s.remove({name: 'bar.txt', type: 'file', size: 128000}); - s.remove({name: 'foo.txt', type: 'file', size: 127999}); - s.remove({name: 'bar', type: 'dir', size: 100}); - s.remove({name: 'foo', type: 'dir', size: 98}); - s.update(); - expect($container.hasClass('hidden')).toEqual(false); - expect($container.find('.dirinfo').text()).toEqual('4 folders'); - expect($container.find('.fileinfo').text()).toEqual('1 file'); - expect($container.find('.filter').text()).toEqual(' match "foo"'); - expect($container.find('.filesize').text()).toEqual('125 KB'); - expect(s.summary.totalDirs).toEqual(4); - expect(s.summary.totalFiles).toEqual(1); - expect(s.summary.totalSize).toEqual(127903); - }); - it('properly sum up pending folder sizes after adding', function() { - var s = new FileSummary($container); - s.setSummary({ - totalDirs: 0, - totalFiles: 0, - totalSize: 0 - }); - s.add({type: 'dir', size: -1}); - s.update(); - expect($container.hasClass('hidden')).toEqual(false); - expect($container.find('.dirinfo').text()).toEqual('1 folder'); - expect($container.find('.fileinfo').hasClass('hidden')).toEqual(true); - expect($container.find('.filesize').text()).toEqual('Pending'); - expect(s.summary.totalDirs).toEqual(1); - expect(s.summary.totalFiles).toEqual(0); - expect(s.summary.totalSize).toEqual(0); - }); - it('properly sum up pending folder sizes after remove', function() { - var s = new FileSummary($container); - s.setSummary({ - totalDirs: 0, - totalFiles: 0, - totalSize: 0 - }); - s.add({type: 'dir', size: -1}); - s.remove({type: 'dir', size: -1}); - s.update(); - expect($container.hasClass('hidden')).toEqual(true); - expect(s.summary.totalDirs).toEqual(0); - expect(s.summary.totalFiles).toEqual(0); - expect(s.summary.totalSize).toEqual(0); - }); - describe('hidden files', function() { - var config; - var summary; - - beforeEach(function() { - config = new OC.Backbone.Model(); - summary = new FileSummary($container, { - config: config - }); - }); - - it('renders hidden count section when hidden files are hidden', function() { - window._nc_event_bus.emit('files:config:updated', { key: 'show_hidden', value: false }); - - summary.add({name: 'abc', type: 'file', size: 256000}); - summary.add({name: 'def', type: 'dir', size: 100}); - summary.add({name: '.hidden', type: 'dir', size: 512000}); - summary.update(); - expect($container.hasClass('hidden')).toEqual(false); - expect($container.find('.dirinfo').text()).toEqual('2 folders'); - expect($container.find('.fileinfo').text()).toEqual('1 file'); - expect($container.find('.hiddeninfo').hasClass('hidden')).toEqual(false); - expect($container.find('.hiddeninfo').text()).toEqual(' (including 1 hidden)'); - expect($container.find('.filesize').text()).toEqual('750 KB'); - }); - it('does not render hidden count section when hidden files exist but are visible', function() { - window._nc_event_bus.emit('files:config:updated', { key: 'show_hidden', value: true }); - - summary.add({name: 'abc', type: 'file', size: 256000}); - summary.add({name: 'def', type: 'dir', size: 100}); - summary.add({name: '.hidden', type: 'dir', size: 512000}); - summary.update(); - expect($container.hasClass('hidden')).toEqual(false); - expect($container.find('.dirinfo').text()).toEqual('2 folders'); - expect($container.find('.fileinfo').text()).toEqual('1 file'); - expect($container.find('.hiddeninfo').hasClass('hidden')).toEqual(true); - expect($container.find('.filesize').text()).toEqual('750 KB'); - }); - it('does not render hidden count section when no hidden files exist', function() { - window._nc_event_bus.emit('files:config:updated', { key: 'show_hidden', value: false }); - - summary.add({name: 'abc', type: 'file', size: 256000}); - summary.add({name: 'def', type: 'dir', size: 100}); - summary.update(); - expect($container.hasClass('hidden')).toEqual(false); - expect($container.find('.dirinfo').text()).toEqual('1 folder'); - expect($container.find('.fileinfo').text()).toEqual('1 file'); - expect($container.find('.hiddeninfo').hasClass('hidden')).toEqual(true); - expect($container.find('.filesize').text()).toEqual('250 KB'); - }); - }); -}); diff --git a/apps/files/tests/js/mainfileinfodetailviewSpec.js b/apps/files/tests/js/mainfileinfodetailviewSpec.js deleted file mode 100644 index 5793db8fb98..00000000000 --- a/apps/files/tests/js/mainfileinfodetailviewSpec.js +++ /dev/null @@ -1,292 +0,0 @@ -/** -* @copyright 2015 Vincent Petry <pvince81@owncloud.com> - * - * @author Arthur Schiwon <blizzz@arthur-schiwon.de> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Michael Jobst <mjobst+github@tecratech.de> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Raghu Nayyar <hey@raghunayyar.com> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0-or-later - * - * 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/>. - * - */ - -describe('OCA.Files.MainFileInfoDetailView tests', function() { - var view, tooltipStub, fileActions, fileList, testFileInfo; - - beforeEach(function() { - tooltipStub = sinon.stub($.fn, 'tooltip'); - fileActions = new OCA.Files.FileActions(); - fileList = new OCA.Files.FileList($('<table></table>'), { - fileActions: fileActions - }); - view = new OCA.Files.MainFileInfoDetailView({ - fileList: fileList, - fileActions: fileActions - }); - testFileInfo = new OCA.Files.FileInfoModel({ - id: 5, - name: 'One.txt', - mimetype: 'text/plain', - permissions: 31, - path: '/subdir', - size: 123456789, - etag: 'abcdefg', - mtime: Date.UTC(2015, 6, 17, 1, 2, 0, 0) - }); - }); - afterEach(function() { - view.remove(); - view = undefined; - tooltipStub.restore(); - - }); - describe('rendering', function() { - it('displays basic info', function() { - var clock = sinon.useFakeTimers(Date.UTC(2015, 6, 17, 1, 2, 0, 3)); - var dateExpected = OC.Util.formatDate(Date(Date.UTC(2015, 6, 17, 1, 2, 0, 0))); - view.setFileInfo(testFileInfo); - expect(view.$el.find('.fileName h3').text()).toEqual('One.txt'); - expect(view.$el.find('.fileName h3').attr('title')).toEqual('One.txt'); - expect(view.$el.find('.size').text()).toEqual('117.7 MB'); - expect(view.$el.find('.size').attr('title')).toEqual('123456789 bytes'); - expect(view.$el.find('.date').text()).toEqual('seconds ago'); - expect(view.$el.find('.date').attr('title')).toEqual(dateExpected); - clock.restore(); - }); - it('displays permalink', function() { - view.setFileInfo(testFileInfo); - expect(view.$el.find('.permalink').attr('href')) - .toEqual(OC.getProtocol() + '://' + OC.getHost() + OC.generateUrl('/f/5')); - }); - it('displays favorite icon', function() { - fileActions.registerAction({ - name: 'Favorite', - mime: 'all', - permissions: OC.PERMISSION_NONE - }); - - testFileInfo.set('tags', [OC.TAG_FAVORITE]); - view.setFileInfo(testFileInfo); - expect(view.$el.find('.action-favorite > span').hasClass('icon-starred')).toEqual(true); - expect(view.$el.find('.action-favorite > span').hasClass('icon-star')).toEqual(false); - - testFileInfo.set('tags', []); - view.setFileInfo(testFileInfo); - expect(view.$el.find('.action-favorite > span').hasClass('icon-starred')).toEqual(false); - expect(view.$el.find('.action-favorite > span').hasClass('icon-star')).toEqual(true); - }); - it('does not display favorite icon if favorite action is not available', function() { - testFileInfo.set('tags', [OC.TAG_FAVORITE]); - view.setFileInfo(testFileInfo); - expect(view.$el.find('.action-favorite').length).toEqual(0); - - testFileInfo.set('tags', []); - view.setFileInfo(testFileInfo); - expect(view.$el.find('.action-favorite').length).toEqual(0); - }); - it('displays mime icon', function() { - // File - var lazyLoadPreviewStub = sinon.stub(fileList, 'lazyLoadPreview'); - testFileInfo.set('mimetype', 'text/calendar'); - view.setFileInfo(testFileInfo); - - expect(lazyLoadPreviewStub.calledOnce).toEqual(true); - var previewArgs = lazyLoadPreviewStub.getCall(0).args; - expect(previewArgs[0].mime).toEqual('text/calendar'); - expect(previewArgs[0].path).toEqual('/subdir/One.txt'); - expect(previewArgs[0].etag).toEqual('abcdefg'); - - expect(view.$el.find('.thumbnail').hasClass('icon-loading')).toEqual(true); - - // returns mime icon first without img parameter - previewArgs[0].callback( - OC.imagePath('core', 'filetypes/text-calendar.svg') - ); - - // still loading - expect(view.$el.find('.thumbnail').hasClass('icon-loading')).toEqual(true); - - // preview loading failed, no prview - previewArgs[0].error(); - - // loading stopped, the mimetype icon gets displayed - expect(view.$el.find('.thumbnail').hasClass('icon-loading')).toEqual(false); - expect(view.$el.find('.thumbnail').css('background-image')) - .toContain('filetypes/text-calendar.svg'); - - // Folder - testFileInfo.set('mimetype', 'httpd/unix-directory'); - view.setFileInfo(testFileInfo); - - expect(view.$el.find('.thumbnail').css('background-image')) - .toContain('filetypes/folder.svg'); - - lazyLoadPreviewStub.restore(); - }); - it('uses icon from model if present in model', function() { - var lazyLoadPreviewStub = sinon.stub(fileList, 'lazyLoadPreview'); - testFileInfo.set('mimetype', 'httpd/unix-directory'); - testFileInfo.set('icon', OC.MimeType.getIconUrl('dir-external')); - view.setFileInfo(testFileInfo); - - expect(lazyLoadPreviewStub.notCalled).toEqual(true); - - expect(view.$el.find('.thumbnail').hasClass('icon-loading')).toEqual(false); - expect(view.$el.find('.thumbnail').css('background-image')) - .toContain('filetypes/folder-external.svg'); - - lazyLoadPreviewStub.restore(); - }); - it('displays thumbnail', function() { - var lazyLoadPreviewStub = sinon.stub(fileList, 'lazyLoadPreview'); - - testFileInfo.set('mimetype', 'text/plain'); - view.setFileInfo(testFileInfo); - - expect(lazyLoadPreviewStub.calledOnce).toEqual(true); - var previewArgs = lazyLoadPreviewStub.getCall(0).args; - expect(previewArgs[0].mime).toEqual('text/plain'); - expect(previewArgs[0].path).toEqual('/subdir/One.txt'); - expect(previewArgs[0].etag).toEqual('abcdefg'); - - expect(view.$el.find('.thumbnail').hasClass('icon-loading')).toEqual(true); - - // returns mime icon first without img parameter - previewArgs[0].callback( - OC.imagePath('core', 'filetypes/text-plain.svg') - ); - - // still loading - expect(view.$el.find('.thumbnail').hasClass('icon-loading')).toEqual(true); - - // return an actual (simulated) image - previewArgs[0].callback( - 'testimage', { - width: 100, - height: 200 - } - ); - - // loading stopped, image got displayed - expect(view.$el.find('.thumbnail').css('background-image')) - .toContain('testimage'); - - expect(view.$el.find('.thumbnail').hasClass('icon-loading')).toEqual(false); - - lazyLoadPreviewStub.restore(); - }); - it('does not show size if no size available', function() { - testFileInfo.unset('size'); - view.setFileInfo(testFileInfo); - - expect(view.$el.find('.size').length).toEqual(0); - }); - it('renders displayName instead of name if available', function() { - testFileInfo.set('displayName', 'hello.txt'); - view.setFileInfo(testFileInfo); - - expect(view.$el.find('.fileName h3').text()).toEqual('hello.txt'); - expect(view.$el.find('.fileName h3').attr('title')).toEqual('hello.txt'); - }); - it('rerenders when changes are made on the model', function() { - // Show the "Favorite" icon - fileActions.registerAction({ - name: 'Favorite', - mime: 'all', - permissions: OC.PERMISSION_NONE - }); - - view.setFileInfo(testFileInfo); - - testFileInfo.set('tags', [OC.TAG_FAVORITE]); - - expect(view.$el.find('.action-favorite > span').hasClass('icon-starred')).toEqual(true); - expect(view.$el.find('.action-favorite > span').hasClass('icon-star')).toEqual(false); - - testFileInfo.set('tags', []); - - expect(view.$el.find('.action-favorite > span').hasClass('icon-starred')).toEqual(false); - expect(view.$el.find('.action-favorite > span').hasClass('icon-star')).toEqual(true); - }); - it('unbinds change listener from model', function() { - // Show the "Favorite" icon - fileActions.registerAction({ - name: 'Favorite', - mime: 'all', - permissions: OC.PERMISSION_NONE - }); - - view.setFileInfo(testFileInfo); - view.setFileInfo(new OCA.Files.FileInfoModel({ - id: 999, - name: 'test.txt', - path: '/' - })); - - // set value on old model - testFileInfo.set('tags', [OC.TAG_FAVORITE]); - - // no change - expect(view.$el.find('.action-favorite > span').hasClass('icon-starred')).toEqual(false); - expect(view.$el.find('.action-favorite > span').hasClass('icon-star')).toEqual(true); - }); - }); - describe('events', function() { - it('triggers default action when clicking on the thumbnail', function() { - var actionHandler = sinon.stub(); - - fileActions.registerAction({ - name: 'Something', - mime: 'all', - permissions: OC.PERMISSION_READ, - actionHandler: actionHandler - }); - fileActions.setDefault('text/plain', 'Something'); - - view.setFileInfo(testFileInfo); - - view.$el.find('.thumbnail').click(); - - expect(actionHandler.calledOnce).toEqual(true); - expect(actionHandler.getCall(0).args[0]).toEqual('One.txt'); - expect(actionHandler.getCall(0).args[1].fileList).toEqual(fileList); - expect(actionHandler.getCall(0).args[1].fileActions).toEqual(fileActions); - expect(actionHandler.getCall(0).args[1].fileInfoModel).toEqual(testFileInfo); - }); - it('triggers "Favorite" action when clicking on the star', function() { - var actionHandler = sinon.stub(); - - fileActions.registerAction({ - name: 'Favorite', - mime: 'all', - permissions: OC.PERMISSION_READ, - actionHandler: actionHandler - }); - - view.setFileInfo(testFileInfo); - - view.$el.find('.action-favorite').click(); - - expect(actionHandler.calledOnce).toEqual(true); - expect(actionHandler.getCall(0).args[0]).toEqual('One.txt'); - expect(actionHandler.getCall(0).args[1].fileList).toEqual(fileList); - expect(actionHandler.getCall(0).args[1].fileActions).toEqual(fileActions); - expect(actionHandler.getCall(0).args[1].fileInfoModel).toEqual(testFileInfo); - }); - }); -}); diff --git a/apps/files/tests/js/newfilemenuSpec.js b/apps/files/tests/js/newfilemenuSpec.js deleted file mode 100644 index db85d105709..00000000000 --- a/apps/files/tests/js/newfilemenuSpec.js +++ /dev/null @@ -1,151 +0,0 @@ -/** -* @copyright 2015 Vincent Petry <pvince81@owncloud.com> - * - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0-or-later - * - * 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/>. - * - */ - -describe('OCA.Files.NewFileMenu', function() { - var FileList = OCA.Files.FileList; - var menu, fileList, $uploadField, $trigger; - - beforeEach(function() { - // dummy upload button - var $container = $('<div id="app-content-files"></div>'); - $uploadField = $('<input id="file_upload_start"></input>'); - $trigger = $('<a href="#">Menu</a>'); - $container.append($uploadField).append($trigger); - $('#testArea').append($container); - - fileList = new FileList($container); - menu = new OCA.Files.NewFileMenu({ - fileList: fileList - }); - menu.showAt($trigger); - }); - afterEach(function() { - OC.hideMenus(); - fileList = null; - menu = null; - }); - - describe('rendering', function() { - it('renders menu items', function() { - var $items = menu.$el.find('.menuitem'); - expect($items.length).toEqual(2); - // label points to the file_upload_start item - var $item = $items.eq(0); - expect($item.is('label')).toEqual(true); - expect($item.attr('for')).toEqual('file_upload_start'); - }); - }); - describe('New file/folder', function() { - var $input; - var createDirectoryStub; - - beforeEach(function() { - createDirectoryStub = sinon.stub(FileList.prototype, 'createDirectory'); - menu.$el.find('.menuitem').eq(1).click(); - $input = menu.$el.find('form.filenameform input'); - }); - afterEach(function() { - createDirectoryStub.restore(); - }); - - it('sets default text in field', function() { - // text + submit - expect($input.length).toEqual(2); - expect($input.val()).toEqual('New folder'); - }); - it('prevents entering invalid file names', function() { - $input.val('..'); - $input.trigger(new $.Event('keyup', {keyCode: 13})); - $input.closest('form').submit(); - - expect(createDirectoryStub.notCalled).toEqual(true); - }); - it('prevents entering file names that already exist', function() { - var inListStub = sinon.stub(fileList, 'inList').returns(true); - $input.val('existing.txt'); - $input.trigger(new $.Event('keyup', {keyCode: 13})); - $input.closest('form').submit(); - - expect(createDirectoryStub.notCalled).toEqual(true); - inListStub.restore(); - }); - it('creates directory when clicking on create directory field', function() { - $input = menu.$el.find('form.filenameform input'); - $input.val('some folder'); - $input.trigger(new $.Event('keyup', {keyCode: 13})); - $input.closest('form').submit(); - - expect(createDirectoryStub.calledOnce).toEqual(true); - expect(createDirectoryStub.getCall(0).args[0]).toEqual('some folder'); - }); - }); - describe('custom entries', function() { - var oldPlugins; - var plugin; - var actionStub; - - beforeEach(function() { - oldPlugins = _.extend({}, OC.Plugins._plugins); - actionStub = sinon.stub(); - plugin = { - attach: function(menu) { - menu.addMenuEntry({ - id: 'file', - displayName: t('files_texteditor', 'Text file'), - templateName: t('files_texteditor', 'New text file.txt'), - iconClass: 'icon-filetype-text', - fileType: 'file', - actionHandler: actionStub - }); - } - }; - - OC.Plugins.register('OCA.Files.NewFileMenu', plugin); - menu = new OCA.Files.NewFileMenu({ - fileList: fileList - }); - menu.showAt($trigger); - }); - afterEach(function() { - OC.Plugins._plugins = oldPlugins; - }); - it('renders custom menu items', function() { - expect(menu.$el.find('.menuitem').length).toEqual(3); - expect(menu.$el.find('.menuitem[data-action=file]').length).toEqual(1); - }); - it('calls action handler when clicking on custom item', function() { - menu.$el.find('.menuitem').eq(2).click(); - var $input = menu.$el.find('form.filenameform input'); - $input.val('some name'); - $input.trigger(new $.Event('keyup', {keyCode: 13})); - $input.closest('form').submit(); - - expect(actionStub.calledOnce).toEqual(true); - expect(actionStub.getCall(0).args[0]).toEqual('some name'); - }); - it('switching fields removes the previous form', function() { - menu.$el.find('.menuitem').eq(2).click(); - expect(menu.$el.find('form').length).toEqual(1); - }); - }); -}); diff --git a/apps/files/tests/js/tagspluginspec.js b/apps/files/tests/js/tagspluginspec.js deleted file mode 100644 index 864e3cffca5..00000000000 --- a/apps/files/tests/js/tagspluginspec.js +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com> - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0-or-later - * - * 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/>. - * - */ - -describe('OCA.Files.TagsPlugin tests', function() { - var fileList; - var testFiles; - - beforeEach(function() { - var $content = $('<div id="app-content"></div>'); - $('#testArea').append($content); - // dummy file list - var $div = $( - '<div>' + - '<table class="files-filestable">' + - '<thead></thead>' + - '<tbody class="files-fileList"></tbody>' + - '</table>' + - '</div>'); - $('#app-content').append($div); - - fileList = new OCA.Files.FileList($div); - OCA.Files.TagsPlugin.attach(fileList); - - testFiles = [{ - id: 1, - type: 'file', - name: 'One.txt', - path: '/subdir', - mimetype: 'text/plain', - size: 12, - permissions: OC.PERMISSION_ALL, - etag: 'abc', - shareOwner: 'User One', - isShareMountPoint: false, - tags: ['tag1', 'tag2'] - }]; - }); - afterEach(function() { - fileList.destroy(); - fileList = null; - }); - - describe('Favorites icon', function() { - it('renders favorite icon and extra data', function() { - var $favoriteMark, $tr; - fileList.setFiles(testFiles); - $tr = fileList.$el.find('tbody tr:first'); - $favoriteMark = $tr.find('.favorite-mark'); - expect($favoriteMark.length).toEqual(1); - expect($favoriteMark.hasClass('permanent')).toEqual(false); - - expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2']); - expect($tr.attr('data-favorite')).not.toBeDefined(); - }); - it('renders permanent favorite icon and extra data', function() { - var $favoriteMark, $tr; - testFiles[0].tags.push(OC.TAG_FAVORITE); - fileList.setFiles(testFiles); - $tr = fileList.$el.find('tbody tr:first'); - $favoriteMark = $tr.find('.favorite-mark'); - expect($favoriteMark.length).toEqual(1); - expect($favoriteMark.hasClass('permanent')).toEqual(true); - - expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2', OC.TAG_FAVORITE]); - expect($tr.attr('data-favorite')).toEqual('true'); - }); - }); - describe('Applying tags', function() { - it('through FileActionsMenu sends request to server and updates icon', function(done) { - var request; - fileList.setFiles(testFiles); - var $tr = fileList.findFileEl('One.txt'); - var $favoriteMark = $tr.find('.favorite-mark'); - var $showMenuAction = $tr.find('.action-menu'); - $showMenuAction.click(); - var $favoriteActionInMenu = $tr.find('.fileActionsMenu .action-favorite'); - $favoriteActionInMenu.click(); - - expect(fakeServer.requests.length).toEqual(1); - request = fakeServer.requests[0]; - expect(JSON.parse(request.requestBody)).toEqual({ - tags: ['tag1', 'tag2', OC.TAG_FAVORITE] - }); - request.respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - tags: ['tag1', 'tag2', 'tag3', OC.TAG_FAVORITE] - })); - - setTimeout(function () { - // re-read the element as it was re-inserted - $tr = fileList.findFileEl('One.txt'); - $favoriteMark = $tr.find('.favorite-mark'); - $showMenuAction = $tr.find('.action-menu'); - - expect($tr.attr('data-favorite')).toEqual('true'); - expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2', 'tag3', OC.TAG_FAVORITE]); - expect(fileList.files[0].tags).toEqual(['tag1', 'tag2', 'tag3', OC.TAG_FAVORITE]); - expect($favoriteMark.find('.icon').hasClass('icon-star')).toEqual(false); - expect($favoriteMark.find('.icon').hasClass('icon-starred')).toEqual(true); - - // show again the menu and get the new action, as the menu was - // closed and removed (and with it, the previous action) when that - // action was clicked - $showMenuAction.click(); - $favoriteActionInMenu = $tr.find('.fileActionsMenu .action-favorite'); - $favoriteActionInMenu.click(); - - setTimeout(function() { - expect(fakeServer.requests.length).toEqual(2); - request = fakeServer.requests[1]; - expect(JSON.parse(request.requestBody)).toEqual({ - tags: ['tag1', 'tag2', 'tag3'] - }); - - request.respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ - tags: ['tag1', 'tag2', 'tag3'] - })); - - setTimeout(function() { - // re-read the element as it was re-inserted - $tr = fileList.findFileEl('One.txt'); - $favoriteMark = $tr.find('.favorite-mark'); - - expect($tr.attr('data-favorite')).toBeFalsy(); - expect($tr.attr('data-tags').split('|')).toEqual(['tag1', 'tag2', 'tag3']); - expect(fileList.files[0].tags).toEqual(['tag1', 'tag2', 'tag3']); - expect($favoriteMark.find('.icon').hasClass('icon-star')).toEqual(true); - expect($favoriteMark.find('.icon').hasClass('icon-starred')).toEqual(false); - - done(); - }, 1); - }, 1); - }, 1); - }); - }); - describe('elementToFile', function() { - it('returns tags', function() { - fileList.setFiles(testFiles); - var $tr = fileList.findFileEl('One.txt'); - var data = fileList.elementToFile($tr); - expect(data.tags).toEqual(['tag1', 'tag2']); - }); - it('returns empty array when no tags present', function() { - delete testFiles[0].tags; - fileList.setFiles(testFiles); - var $tr = fileList.findFileEl('One.txt'); - var data = fileList.elementToFile($tr); - expect(data.tags).toEqual([]); - }); - }); -}); |