diff options
author | Daniel Calviño Sánchez <danxuliu@gmail.com> | 2020-12-03 14:19:43 +0100 |
---|---|---|
committer | Daniel Calviño Sánchez <danxuliu@gmail.com> | 2020-12-07 04:47:56 +0100 |
commit | 2cc22a06b4d56e1d46d1de45993b3149455c3bb4 (patch) | |
tree | 5a9b33f4a204299a39e5c57999dc636210c12fb8 /build | |
parent | 184742e6ff1fe27ebc663dd1adff9ae87408d87d (diff) | |
download | nextcloud-server-2cc22a06b4d56e1d46d1de45993b3149455c3bb4.tar.gz nextcloud-server-2cc22a06b4d56e1d46d1de45993b3149455c3bb4.zip |
Add integration tests for user avatars
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Diffstat (limited to 'build')
-rw-r--r-- | build/integration/data/coloured-pattern.png | bin | 0 -> 2447 bytes | |||
-rw-r--r-- | build/integration/data/green-square-256.png | bin | 0 -> 645 bytes | |||
-rw-r--r-- | build/integration/features/avatar.feature | 135 | ||||
-rw-r--r-- | build/integration/features/bootstrap/Avatar.php | 208 | ||||
-rw-r--r-- | build/integration/features/bootstrap/BasicStructure.php | 1 |
5 files changed, 344 insertions, 0 deletions
diff --git a/build/integration/data/coloured-pattern.png b/build/integration/data/coloured-pattern.png Binary files differnew file mode 100644 index 00000000000..cf43787f3fd --- /dev/null +++ b/build/integration/data/coloured-pattern.png diff --git a/build/integration/data/green-square-256.png b/build/integration/data/green-square-256.png Binary files differnew file mode 100644 index 00000000000..9f14b707ca3 --- /dev/null +++ b/build/integration/data/green-square-256.png diff --git a/build/integration/features/avatar.feature b/build/integration/features/avatar.feature new file mode 100644 index 00000000000..8580471ef55 --- /dev/null +++ b/build/integration/features/avatar.feature @@ -0,0 +1,135 @@ +Feature: avatar + + Background: + Given user "user0" exists + + Scenario: get default user avatar + When user "user0" gets avatar for user "user0" + Then The following headers should be set + | Content-Type | image/png | + | X-NC-IsCustomAvatar | 0 | + And last avatar is a square of size 128 + And last avatar is not a single color + + Scenario: get default user avatar as an anonymous user + When user "anonymous" gets avatar for user "user0" + Then The following headers should be set + | Content-Type | image/png | + | X-NC-IsCustomAvatar | 0 | + And last avatar is a square of size 128 + And last avatar is not a single color + + + + Scenario: get temporary user avatar before cropping it + Given Logging in using web as "user0" + And logged in user posts temporary avatar from file "data/green-square-256.png" + When logged in user gets temporary avatar + Then The following headers should be set + | Content-Type | image/png | + # "last avatar" also includes the last temporary avatar + And last avatar is a square of size 256 + And last avatar is a single "#00FF00" color + + Scenario: get user avatar before cropping it + Given Logging in using web as "user0" + And logged in user posts temporary avatar from file "data/green-square-256.png" + # Avatar needs to be cropped to finish setting it even if it is squared + When user "user0" gets avatar for user "user0" + Then The following headers should be set + | Content-Type | image/png | + | X-NC-IsCustomAvatar | 0 | + And last avatar is a square of size 128 + And last avatar is not a single color + + + + Scenario: set user avatar from file + Given Logging in using web as "user0" + When logged in user posts temporary avatar from file "data/coloured-pattern.png" + And logged in user crops temporary avatar + | x | 384 | + | y | 256 | + | w | 128 | + | h | 128 | + Then logged in user gets temporary avatar with 404 + And user "user0" gets avatar for user "user0" + And The following headers should be set + | Content-Type | image/png | + | X-NC-IsCustomAvatar | 1 | + And last avatar is a square of size 128 + And last avatar is a single "#FF0000" color + And user "anonymous" gets avatar for user "user0" + And The following headers should be set + | Content-Type | image/png | + | X-NC-IsCustomAvatar | 1 | + And last avatar is a square of size 128 + And last avatar is a single "#FF0000" color + + Scenario: set user avatar from internal path + Given user "user0" uploads file "data/coloured-pattern.png" to "/internal-coloured-pattern.png" + And Logging in using web as "user0" + When logged in user posts temporary avatar from internal path "internal-coloured-pattern.png" + And logged in user crops temporary avatar + | x | 704 | + | y | 320 | + | w | 64 | + | h | 64 | + Then logged in user gets temporary avatar with 404 + And user "user0" gets avatar for user "user0" with size "64" + And The following headers should be set + | Content-Type | image/png | + | X-NC-IsCustomAvatar | 1 | + And last avatar is a square of size 64 + And last avatar is a single "#00FF00" color + And user "anonymous" gets avatar for user "user0" with size "64" + And The following headers should be set + | Content-Type | image/png | + | X-NC-IsCustomAvatar | 1 | + And last avatar is a square of size 64 + And last avatar is a single "#00FF00" color + + Scenario: cropped user avatar needs to be squared + Given Logging in using web as "user0" + And logged in user posts temporary avatar from file "data/coloured-pattern.png" + When logged in user crops temporary avatar with 400 + | x | 384 | + | y | 256 | + | w | 192 | + | h | 128 | + + + + Scenario: delete user avatar + Given Logging in using web as "user0" + And logged in user posts temporary avatar from file "data/coloured-pattern.png" + And logged in user crops temporary avatar + | x | 384 | + | y | 256 | + | w | 128 | + | h | 128 | + And user "user0" gets avatar for user "user0" + And The following headers should be set + | Content-Type | image/png | + | X-NC-IsCustomAvatar | 1 | + And last avatar is a square of size 128 + And last avatar is a single "#FF0000" color + And user "anonymous" gets avatar for user "user0" + And The following headers should be set + | Content-Type | image/png | + | X-NC-IsCustomAvatar | 1 | + And last avatar is a square of size 128 + And last avatar is a single "#FF0000" color + When logged in user deletes the user avatar + Then user "user0" gets avatar for user "user0" + And The following headers should be set + | Content-Type | image/png | + | X-NC-IsCustomAvatar | 0 | + And last avatar is a square of size 128 + And last avatar is not a single color + And user "anonymous" gets avatar for user "user0" + And The following headers should be set + | Content-Type | image/png | + | X-NC-IsCustomAvatar | 0 | + And last avatar is a square of size 128 + And last avatar is not a single color diff --git a/build/integration/features/bootstrap/Avatar.php b/build/integration/features/bootstrap/Avatar.php new file mode 100644 index 00000000000..215a3386ab8 --- /dev/null +++ b/build/integration/features/bootstrap/Avatar.php @@ -0,0 +1,208 @@ +<?php +/** + * @copyright Copyright (c) 2020, Daniel Calviño Sánchez (danxuliu@gmail.com) + * + * @author Daniel Calviño Sánchez <danxuliu@gmail.com> + * + * @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/>. + * + */ + +use Behat\Gherkin\Node\TableNode; +use PHPUnit\Framework\Assert; + +require __DIR__ . '/../../vendor/autoload.php'; + +trait Avatar { + + /** @var string **/ + private $lastAvatar; + + /** @AfterScenario **/ + public function cleanupLastAvatar() { + $this->lastAvatar = null; + } + + private function getLastAvatar() { + $this->lastAvatar = ''; + + $body = $this->response->getBody(); + while (!$body->eof()) { + $this->lastAvatar .= $body->read(8192); + } + $body->close(); + } + + /** + * @When user :user gets avatar for user :userAvatar + * + * @param string $user + * @param string $userAvatar + */ + public function userGetsAvatarForUser(string $user, string $userAvatar) { + $this->userGetsAvatarForUserWithSize($user, $userAvatar, '128'); + } + + /** + * @When user :user gets avatar for user :userAvatar with size :size + * + * @param string $user + * @param string $userAvatar + * @param string $size + */ + public function userGetsAvatarForUserWithSize(string $user, string $userAvatar, string $size) { + $this->asAn($user); + $this->sendingToDirectUrl('GET', '/index.php/avatar/' . $userAvatar . '/' . $size); + $this->theHTTPStatusCodeShouldBe('200'); + + $this->getLastAvatar(); + } + + /** + * @When logged in user gets temporary avatar + */ + public function loggedInUserGetsTemporaryAvatar() { + $this->loggedInUserGetsTemporaryAvatarWith('200'); + } + + /** + * @When logged in user gets temporary avatar with :statusCode + * + * @param string $statusCode + */ + public function loggedInUserGetsTemporaryAvatarWith(string $statusCode) { + $this->sendingAToWithRequesttoken('GET', '/index.php/avatar/tmp'); + $this->theHTTPStatusCodeShouldBe($statusCode); + + $this->getLastAvatar(); + } + + /** + * @When logged in user posts temporary avatar from file :source + * + * @param string $source + */ + public function loggedInUserPostsTemporaryAvatarFromFile(string $source) { + $file = \GuzzleHttp\Psr7\stream_for(fopen($source, 'r')); + + $this->sendingAToWithRequesttoken('POST', '/index.php/avatar', + [ + 'multipart' => [ + [ + 'name' => 'files[]', + 'contents' => $file + ] + ] + ]); + $this->theHTTPStatusCodeShouldBe('200'); + } + + /** + * @When logged in user posts temporary avatar from internal path :path + * + * @param string $path + */ + public function loggedInUserPostsTemporaryAvatarFromInternalPath(string $path) { + $this->sendingAToWithRequesttoken('POST', '/index.php/avatar?path=' . $path); + $this->theHTTPStatusCodeShouldBe('200'); + } + + /** + * @When logged in user crops temporary avatar + * + * @param TableNode $crop + */ + public function loggedInUserCropsTemporaryAvatar(TableNode $crop) { + $this->loggedInUserCropsTemporaryAvatarWith('200', $crop); + } + + /** + * @When logged in user crops temporary avatar with :statusCode + * + * @param string $statusCode + * @param TableNode $crop + */ + public function loggedInUserCropsTemporaryAvatarWith(string $statusCode, TableNode $crop) { + $parameters = []; + foreach ($crop->getRowsHash() as $key => $value) { + $parameters[] = 'crop[' . $key . ']=' . $value; + } + + $this->sendingAToWithRequesttoken('POST', '/index.php/avatar/cropped?' . implode('&', $parameters)); + $this->theHTTPStatusCodeShouldBe($statusCode); + } + + /** + * @When logged in user deletes the user avatar + */ + public function loggedInUserDeletesTheUserAvatar() { + $this->sendingAToWithRequesttoken('DELETE', '/index.php/avatar'); + $this->theHTTPStatusCodeShouldBe('200'); + } + + /** + * @Then last avatar is a square of size :size + * + * @param string size + */ + public function lastAvatarIsASquareOfSize(string $size) { + list($width, $height) = getimagesizefromstring($this->lastAvatar); + + Assert::assertEquals($width, $height, 'Avatar is not a square'); + Assert::assertEquals($size, $width); + } + + /** + * @Then last avatar is not a single color + */ + public function lastAvatarIsNotASingleColor() { + Assert::assertEquals(null, $this->getColorFromLastAvatar()); + } + + /** + * @Then last avatar is a single :color color + * + * @param string $color + * @param string $size + */ + public function lastAvatarIsASingleColor(string $color) { + Assert::assertEquals($color, $this->getColorFromLastAvatar()); + } + + private function getColorFromLastAvatar() { + $image = imagecreatefromstring($this->lastAvatar); + + $firstPixelColor = imagecolorat($image, 0, 0); + + for ($i = 0; $i < imagesx($image); $i++) { + for ($j = 0; $j < imagesx($image); $j++) { + $currentPixelColor = imagecolorat($image, $i, $j); + + if ($firstPixelColor !== $currentPixelColor) { + imagedestroy($image); + + return null; + } + } + } + + imagedestroy($image); + + // Assume that the image is a truecolor image and thus the index is the + // RGB value of the pixel as an integer. + return '#' . str_pad(strtoupper(dechex($firstPixelColor)), 6, '0', STR_PAD_LEFT); + } +} diff --git a/build/integration/features/bootstrap/BasicStructure.php b/build/integration/features/bootstrap/BasicStructure.php index 4775a23b902..ac5530be5a5 100644 --- a/build/integration/features/bootstrap/BasicStructure.php +++ b/build/integration/features/bootstrap/BasicStructure.php @@ -44,6 +44,7 @@ require __DIR__ . '/../../vendor/autoload.php'; trait BasicStructure { use Auth; + use Avatar; use Download; use Mail; use Trashbin; |