Browse Source
Add integration tests for user avatars
Add integration tests for user avatars
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>pull/24578/head
6 changed files with 369 additions and 0 deletions
-
25.drone.yml
-
BINbuild/integration/data/coloured-pattern.png
-
BINbuild/integration/data/green-square-256.png
-
135build/integration/features/avatar.feature
-
208build/integration/features/bootstrap/Avatar.php
-
1build/integration/features/bootstrap/BasicStructure.php
|
After Width: 1024 | Height: 512 | Size: 2.4 KiB |
|
After Width: 256 | Height: 256 | Size: 645 B |
@ -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 |
|||
@ -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); |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue