Update tests for SkinlibController
This commit is contained in:
parent
55c2fb38ac
commit
157c9e8b22
|
|
@ -38,7 +38,7 @@ class SkinlibController extends Controller
|
|||
* Available Query String: filter, uploader, page, sort, keyword, items_per_page.
|
||||
*
|
||||
* @param Request $request [description]
|
||||
* @return [type] [description]
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function getSkinlibFiltered(Request $request)
|
||||
{
|
||||
|
|
@ -59,6 +59,7 @@ class SkinlibController extends Controller
|
|||
|
||||
// How many items to show in one page
|
||||
$itemsPerPage = $request->input('items_per_page', 20);
|
||||
$itemsPerPage = $itemsPerPage <= 0 ? 20 : $itemsPerPage;
|
||||
|
||||
// Keyword to search
|
||||
$keyword = $request->input('keyword', '');
|
||||
|
|
@ -95,7 +96,7 @@ class SkinlibController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
$totalPages = ceil($query->count() / 20);
|
||||
$totalPages = ceil($query->count() / $itemsPerPage);
|
||||
|
||||
$textures = $query->orderBy($sortBy, 'desc')
|
||||
->skip(($currentPage - 1) * $itemsPerPage)
|
||||
|
|
@ -161,8 +162,8 @@ class SkinlibController extends Controller
|
|||
$t->name = $request->input('name');
|
||||
$t->type = $request->input('type');
|
||||
$t->likes = 1;
|
||||
$t->hash = Utils::upload($_FILES['file']);
|
||||
$t->size = ceil($_FILES['file']['size'] / 1024);
|
||||
$t->hash = Utils::upload($request->file('file'));
|
||||
$t->size = ceil($request->file('file')->getSize() / 1024);
|
||||
$t->public = ($request->input('public') == 'true') ? "1" : "0";
|
||||
$t->uploader = $this->user->uid;
|
||||
$t->upload_at = Utils::getTimeFormatted();
|
||||
|
|
@ -177,7 +178,7 @@ class SkinlibController extends Controller
|
|||
|
||||
if (!$results->isEmpty()) {
|
||||
foreach ($results as $result) {
|
||||
// if the texture already uploaded was setted to private,
|
||||
// if the texture already uploaded was set to private,
|
||||
// then allow to re-upload it.
|
||||
if ($result->type == $t->type && $result->public == "1") {
|
||||
return json(trans('skinlib.upload.repeated'), 0, [
|
||||
|
|
@ -196,7 +197,7 @@ class SkinlibController extends Controller
|
|||
'tid' => $t->tid
|
||||
]);
|
||||
}
|
||||
}
|
||||
} // @codeCoverageIgnore
|
||||
|
||||
public function delete(Request $request, UserRepository $users)
|
||||
{
|
||||
|
|
@ -211,8 +212,8 @@ class SkinlibController extends Controller
|
|||
}
|
||||
|
||||
// check if file occupied
|
||||
if (Texture::where('hash', $result['hash'])->count() == 1) {
|
||||
Storage::delete($result['hash']);
|
||||
if (Texture::where('hash', $result->hash)->count() == 1) {
|
||||
Storage::disk('textures')->delete($result->hash);
|
||||
}
|
||||
|
||||
if (option('return_score')) {
|
||||
|
|
@ -232,13 +233,11 @@ class SkinlibController extends Controller
|
|||
if ($result->delete()) {
|
||||
return json(trans('skinlib.delete.success'), 0);
|
||||
}
|
||||
}
|
||||
} // @codeCoverageIgnore
|
||||
|
||||
public function privacy(Request $request, UserRepository $users)
|
||||
{
|
||||
$t = Texture::find($request->input('tid'));
|
||||
$type = $t->type;
|
||||
$uid = session('uid');
|
||||
|
||||
if (!$t)
|
||||
return json(trans('skinlib.non-existent'), 1);
|
||||
|
|
@ -251,9 +250,13 @@ class SkinlibController extends Controller
|
|||
return json(trans('skinlib.upload.lack-score'), 1);
|
||||
}
|
||||
|
||||
foreach (Player::where("tid_$type", $t->tid)->where('uid', '<>', $uid)->get() as $player) {
|
||||
$player->setTexture(["tid_$type" => 0]);
|
||||
}
|
||||
$type = $t->type;
|
||||
Player::where("tid_$type", $t->tid)
|
||||
->where('uid', '<>', session('uid'))
|
||||
->get()
|
||||
->each(function ($player) use ($type) {
|
||||
$player->setTexture(["tid_$type" => 0]);
|
||||
});
|
||||
|
||||
@$users->get($t->uploader)->setScore($score_diff, 'plus');
|
||||
|
||||
|
|
@ -264,7 +267,7 @@ class SkinlibController extends Controller
|
|||
'public' => $t->public
|
||||
]);
|
||||
}
|
||||
}
|
||||
} // @codeCoverageIgnore
|
||||
|
||||
public function rename(Request $request) {
|
||||
$this->validate($request, [
|
||||
|
|
@ -285,13 +288,13 @@ class SkinlibController extends Controller
|
|||
if ($t->save()) {
|
||||
return json(trans('skinlib.rename.success', ['name' => $request->input('new_name')]), 0);
|
||||
}
|
||||
}
|
||||
} // @codeCoverageIgnore
|
||||
|
||||
/**
|
||||
* Check Uploaded Files
|
||||
*
|
||||
* @param Request $request
|
||||
* @return void
|
||||
* @return JsonResponse
|
||||
*/
|
||||
private function checkUpload(Request $request)
|
||||
{
|
||||
|
|
@ -307,16 +310,13 @@ class SkinlibController extends Controller
|
|||
'public' => 'required'
|
||||
]);
|
||||
|
||||
if ($_FILES['file']['type'] != "image/png" && $_FILES['file']['type'] != "image/x-png") {
|
||||
$mime = $request->file('file')->getMimeType();
|
||||
if ($mime != "image/png" && $mime != "image/x-png") {
|
||||
return json(trans('skinlib.upload.type-error'), 1);
|
||||
}
|
||||
|
||||
// if error occured while uploading file
|
||||
if ($_FILES['file']["error"] > 0)
|
||||
return json($_FILES['file']["error"], 1);
|
||||
|
||||
$type = $request->input('type');
|
||||
$size = getimagesize($_FILES['file']["tmp_name"]);
|
||||
$size = getimagesize($request->file('file'));
|
||||
$ratio = $size[0] / $size[1];
|
||||
|
||||
if ($type == "steve" || $type == "alex") {
|
||||
|
|
@ -330,6 +330,6 @@ class SkinlibController extends Controller
|
|||
} else {
|
||||
return json(trans('general.illegal-parameters'), 1);
|
||||
}
|
||||
}
|
||||
} // @codeCoverageIgnore
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,36 +120,23 @@ class Utils
|
|||
/**
|
||||
* Rename uploaded file
|
||||
*
|
||||
* @param array $file files uploaded via HTTP POST
|
||||
* @param \Illuminate\Http\UploadedFile $file files uploaded via HTTP POST
|
||||
* @return string $hash sha256 hash of file
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function upload($file)
|
||||
{
|
||||
$path = 'tmp'.time();
|
||||
$absolute_path = storage_path("textures/$path");
|
||||
|
||||
$hash = hash_file('sha256', $file);
|
||||
try {
|
||||
if (false === move_uploaded_file($file['tmp_name'], $absolute_path)) {
|
||||
throw new \Exception('Failed to remove uploaded files, please check the permission', 1);
|
||||
$storage = Storage::disk('textures');
|
||||
if (!$storage->exists($hash)) {
|
||||
$storage->put($hash, file_get_contents($file));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::warning("Failed to move uploaded file, $e");
|
||||
} finally {
|
||||
if (file_exists($absolute_path)) {
|
||||
$hash = hash_file('sha256', $absolute_path);
|
||||
|
||||
if (! Storage::disk('textures')->has($hash)) {
|
||||
Storage::disk('textures')->move($path, $hash);
|
||||
} else {
|
||||
// delete the temp file
|
||||
unlink($absolute_path);
|
||||
}
|
||||
|
||||
return $hash;
|
||||
} else {
|
||||
Log::warning("Failed to upload file $path");
|
||||
}
|
||||
Log::warning("Failed to upload file {$file->getFilename()}");
|
||||
throw new \Exception("Failed to upload file {$file->getFilename()}");
|
||||
}
|
||||
return $hash;
|
||||
}
|
||||
|
||||
public static function download($url, $path)
|
||||
|
|
|
|||
936
tests/SkinlibControllerTest.php
Normal file
936
tests/SkinlibControllerTest.php
Normal file
|
|
@ -0,0 +1,936 @@
|
|||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\Closet;
|
||||
use App\Models\Player;
|
||||
use App\Models\Texture;
|
||||
use App\Services\Utils;
|
||||
use org\bovigo\vfs\vfsStream;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
class SkinlibControllerTest extends TestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* @var \org\bovigo\vfs\vfsStreamDirectory
|
||||
*/
|
||||
private $vfs_root;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->vfs_root = vfsStream::setup();
|
||||
}
|
||||
|
||||
protected function serializeTextures($textures) {
|
||||
return $textures
|
||||
->map(function ($texture) {
|
||||
return [
|
||||
'tid' => $texture->tid,
|
||||
'name' => $texture->name,
|
||||
'type' => $texture->type,
|
||||
'likes' => $texture->likes,
|
||||
'hash' => $texture->hash,
|
||||
'size' => $texture->size,
|
||||
'uploader' => $texture->uploader,
|
||||
'public' => $texture->public ? 1 : 0,
|
||||
'upload_at' => $texture->upload_at->format('Y-m-d H:i:s')
|
||||
];
|
||||
})
|
||||
->all();
|
||||
}
|
||||
|
||||
public function testIndex()
|
||||
{
|
||||
$this->visit('/skinlib')
|
||||
->seePageIs('/skinlib')
|
||||
->assertViewHas('user');
|
||||
}
|
||||
|
||||
public function testGetSkinlibFiltered()
|
||||
{
|
||||
$this->get('/skinlib/data')
|
||||
->seeJson([
|
||||
'items' => [],
|
||||
'anonymous' => true,
|
||||
'total_pages' => 0
|
||||
]);
|
||||
|
||||
$steves = factory(Texture::class)->times(5)->create();
|
||||
$alexs = factory(Texture::class, 'alex')->times(5)->create();
|
||||
$skins = $steves->merge($alexs);
|
||||
$capes = factory(Texture::class, 'cape')->times(5)->create();
|
||||
|
||||
// Default arguments
|
||||
$expected = $skins
|
||||
->sortByDesc('upload_at')
|
||||
->values(); // WTF! DO NOT FORGET IT!!
|
||||
$this->get('/skinlib/data')
|
||||
->seeJson([
|
||||
'items' => $this->serializeTextures($expected),
|
||||
'anonymous' => true,
|
||||
'total_pages' => 1
|
||||
]);
|
||||
|
||||
// Only steve
|
||||
$expected = $steves
|
||||
->sortByDesc('upload_at')
|
||||
->values();
|
||||
$this->get('/skinlib/data?filter=steve')
|
||||
->seeJson([
|
||||
'items' => $this->serializeTextures($expected),
|
||||
'anonymous' => true,
|
||||
'total_pages' => 1
|
||||
]);
|
||||
|
||||
// Invalid type
|
||||
$this->get('/skinlib/data?filter=what')
|
||||
->seeJson([
|
||||
'items' => [],
|
||||
'anonymous' => true,
|
||||
'total_pages' => 0
|
||||
]);
|
||||
|
||||
// Only capes
|
||||
$expected = $capes
|
||||
->sortByDesc('upload_at')
|
||||
->values();
|
||||
$this->get('/skinlib/data?filter=cape')
|
||||
->seeJson([
|
||||
'items' => $this->serializeTextures($expected),
|
||||
'anonymous' => true,
|
||||
'total_pages' => 1
|
||||
]);
|
||||
|
||||
// Only specified uploader
|
||||
$uid = $skins->random()->uploader;
|
||||
$expected = $skins
|
||||
->filter(function ($texture) use ($uid) {
|
||||
return $texture->uploader == $uid;
|
||||
})
|
||||
->sortByDesc('upload_at')
|
||||
->values();
|
||||
$this->get('/skinlib/data?uploader='.$uid)
|
||||
->seeJson([
|
||||
'items' => $this->serializeTextures($expected),
|
||||
'anonymous' => true,
|
||||
'total_pages' => 1
|
||||
]);
|
||||
|
||||
// Sort by `likes`
|
||||
$expected = $skins
|
||||
->sortByDesc('likes')
|
||||
->values();
|
||||
$this->get('/skinlib/data?sort=likes')
|
||||
->seeJson([
|
||||
'items' => $this->serializeTextures($expected),
|
||||
'anonymous' => true,
|
||||
'total_pages' => 1
|
||||
]);
|
||||
|
||||
// Search
|
||||
$keyword = str_limit($skins->random()->name, 1, '');
|
||||
$expected = $skins
|
||||
->filter(function ($texture) use ($keyword) {
|
||||
return str_contains($texture->name, $keyword) ||
|
||||
str_contains($texture->name, strtolower($keyword));
|
||||
})
|
||||
->sortByDesc('upload_at')
|
||||
->values();
|
||||
$this->get('/skinlib/data?keyword='.$keyword)
|
||||
->seeJson([
|
||||
'items' => $this->serializeTextures($expected),
|
||||
'anonymous' => true,
|
||||
'total_pages' => 1
|
||||
]);
|
||||
|
||||
// More than one argument
|
||||
$keyword = str_limit($skins->random()->name, 1, '');
|
||||
$expected = $skins
|
||||
->filter(function ($texture) use ($keyword) {
|
||||
return str_contains($texture->name, $keyword) ||
|
||||
str_contains($texture->name, strtolower($keyword));
|
||||
})
|
||||
->sortByDesc('likes')
|
||||
->values();
|
||||
$this->get('/skinlib/data?sort=likes&keyword='.$keyword)
|
||||
->seeJson([
|
||||
'items' => $this->serializeTextures($expected),
|
||||
'anonymous' => true,
|
||||
'total_pages' => 1
|
||||
]);
|
||||
|
||||
// Pagination
|
||||
$steves = factory(Texture::class)
|
||||
->times(15)
|
||||
->create()
|
||||
->merge($steves);
|
||||
$skins = $steves->merge($alexs);
|
||||
$expected = $skins
|
||||
->sortByDesc('upload_at')
|
||||
->values()
|
||||
->forPage(1, 20);
|
||||
$expected = $this->serializeTextures($expected);
|
||||
$this->get('/skinlib/data')
|
||||
->seeJson([
|
||||
'items' => $expected,
|
||||
'anonymous' => true,
|
||||
'total_pages' => 2
|
||||
]);
|
||||
$this->get('/skinlib/data?page=-5')
|
||||
->seeJson([
|
||||
'items' => $expected,
|
||||
'anonymous' => true,
|
||||
'total_pages' => 2
|
||||
]);
|
||||
$expected = $skins
|
||||
->sortByDesc('upload_at')
|
||||
->values()
|
||||
->forPage(2, 20)
|
||||
->values();
|
||||
$expected = $this->serializeTextures($expected);
|
||||
$this->get('/skinlib/data?page=2')
|
||||
->seeJson([
|
||||
'items' => $expected,
|
||||
'anonymous' => true,
|
||||
'total_pages' => 2
|
||||
]);
|
||||
$this->get('/skinlib/data?page=8')
|
||||
->seeJson([
|
||||
'items' => [],
|
||||
'anonymous' => true,
|
||||
'total_pages' => 2
|
||||
]);
|
||||
$this->get('/skinlib/data?items_per_page=-6&page=2')
|
||||
->seeJson([
|
||||
'items' => $expected,
|
||||
'anonymous' => true,
|
||||
'total_pages' => 2
|
||||
]);
|
||||
$expected = $skins
|
||||
->sortByDesc('upload_at')
|
||||
->values()
|
||||
->forPage(3, 8)
|
||||
->values();
|
||||
$this->get('/skinlib/data?page=3&items_per_page=8')
|
||||
->seeJson([
|
||||
'items' => $this->serializeTextures($expected),
|
||||
'anonymous' => true,
|
||||
'total_pages' => 4
|
||||
]);
|
||||
|
||||
// Add some private textures
|
||||
$uploader = factory(User::class)->create();
|
||||
$otherUser = factory(User::class)->create();
|
||||
$private = factory(Texture::class)
|
||||
->times(5)
|
||||
->create(['public' => false, 'uploader' => $uploader->uid]);
|
||||
|
||||
// If not logged in, private textures should not be shown
|
||||
$expected = $skins
|
||||
->sortByDesc('upload_at')
|
||||
->values()
|
||||
->forPage(1, 20);
|
||||
$expected = $this->serializeTextures($expected);
|
||||
$this->get('/skinlib/data')
|
||||
->seeJson([
|
||||
'items' => $expected,
|
||||
'anonymous' => true,
|
||||
'total_pages' => 2
|
||||
]);
|
||||
|
||||
// Other users should not see someone's private textures
|
||||
for ($i = 0; $i < count($expected); $i++) {
|
||||
$expected[$i]['liked'] = false;
|
||||
}
|
||||
$this->actAs($otherUser)
|
||||
->get('/skinlib/data')
|
||||
->seeJson([
|
||||
'items' => $expected,
|
||||
'anonymous' => false,
|
||||
'total_pages' => 2
|
||||
]);
|
||||
|
||||
// A user has added a texture from skin library to his closet
|
||||
$texture = $skins
|
||||
->sortByDesc('upload_at')
|
||||
->values()
|
||||
->first();
|
||||
$closet = new Closet($otherUser->uid);
|
||||
$closet->add($texture->tid, $texture->name);
|
||||
$closet->save();
|
||||
for ($i = 0; $i < count($expected); $i++) {
|
||||
if ($expected[$i]['tid'] == $texture->tid) {
|
||||
$expected[$i]['liked'] = true;
|
||||
} else {
|
||||
$expected[$i]['liked'] = false;
|
||||
}
|
||||
}
|
||||
$this->get('/skinlib/data')
|
||||
->seeJson([
|
||||
'items' => $expected,
|
||||
'anonymous' => false,
|
||||
'total_pages' => 2
|
||||
]);
|
||||
|
||||
// Uploader can see his private textures
|
||||
$expected = $skins
|
||||
->merge($private)
|
||||
->sortByDesc('upload_at')
|
||||
->values()
|
||||
->forPage(1, 20);
|
||||
$expected = $this->serializeTextures($expected);
|
||||
for ($i = 0; $i < count($expected); $i++) {
|
||||
// The reason we use `false` here is that some textures just were
|
||||
// uploaded by this user, but these textures are not in his closet.
|
||||
// By default(not in testing like now), when you uploaded a texture,
|
||||
// that texture will be added to your closet.
|
||||
// So here, we can assume that a user upload some textures, but he
|
||||
// has deleted them from his closet.
|
||||
$expected[$i]['liked'] = false;
|
||||
}
|
||||
$this->actAs($uploader)
|
||||
->get('/skinlib/data')
|
||||
->seeJson([
|
||||
'items' => $expected,
|
||||
'anonymous' => false,
|
||||
'total_pages' => 2
|
||||
]);
|
||||
|
||||
// Administrators can see private textures
|
||||
$admin = factory(User::class, 'admin')->create();
|
||||
$this->actAs($admin)
|
||||
->get('/skinlib/data')
|
||||
->seeJson([
|
||||
'items' => $expected,
|
||||
'anonymous' => false,
|
||||
'total_pages' => 2
|
||||
]);
|
||||
}
|
||||
|
||||
public function testShow()
|
||||
{
|
||||
// Cannot find texture
|
||||
$this->get('/skinlib/show/1')
|
||||
->see(trans('skinlib.show.deleted'));
|
||||
|
||||
// Invalid texture
|
||||
option(['auto_del_invalid_texture' => false]);
|
||||
$texture = factory(Texture::class)->create();
|
||||
$this->get('/skinlib/show/'.$texture->tid)
|
||||
->see(trans('skinlib.show.deleted').trans('skinlib.show.contact-admin'));
|
||||
$this->assertNotNull(Texture::find($texture->tid));
|
||||
|
||||
option(['auto_del_invalid_texture' => true]);
|
||||
$this->get('/skinlib/show/'.$texture->tid)
|
||||
->see(trans('skinlib.show.deleted'));
|
||||
$this->assertNull(Texture::find($texture->tid));
|
||||
|
||||
// Show a texture
|
||||
$texture = factory(Texture::class)->create();
|
||||
Storage::disk('textures')->put($texture->hash, '');
|
||||
$this->get('/skinlib/show/'.$texture->tid)
|
||||
->assertViewHas('texture')
|
||||
->assertViewHas('with_out_filter', true)
|
||||
->assertViewHas('user');
|
||||
|
||||
// Guest should not see private texture
|
||||
$uploader = factory(User::class)->create();
|
||||
$texture = factory(Texture::class)->create([
|
||||
'uploader' => $uploader->uid,
|
||||
'public' => false
|
||||
]);
|
||||
Storage::disk('textures')->put($texture->hash, '');
|
||||
$this->get('/skinlib/show/'.$texture->tid)
|
||||
->see(trans('skinlib.show.private'));
|
||||
|
||||
// Other user should not see private texture
|
||||
$this->actAs('normal')
|
||||
->get('/skinlib/show/'.$texture->tid)
|
||||
->see(trans('skinlib.show.private'));
|
||||
|
||||
// Administrators should be able to see private textures
|
||||
$this->actAs('admin')
|
||||
->get('/skinlib/show/'.$texture->tid)
|
||||
->assertViewHas('texture');
|
||||
|
||||
// Uploader should be able to see private textures
|
||||
$this->actAs($uploader)
|
||||
->get('/skinlib/show/'.$texture->tid)
|
||||
->assertViewHas('texture');
|
||||
}
|
||||
|
||||
public function testInfo()
|
||||
{
|
||||
// Non-existed texture
|
||||
$this->get('/skinlib/info/1')
|
||||
->seeJson([]);
|
||||
|
||||
$texture = factory(Texture::class)->create();
|
||||
$this->get('/skinlib/info/'.$texture->tid)
|
||||
->seeJson([
|
||||
'tid' => $texture->tid,
|
||||
'name' => $texture->name,
|
||||
'type' => $texture->type,
|
||||
'likes' => $texture->likes,
|
||||
'hash' => $texture->hash,
|
||||
'size' => $texture->size,
|
||||
'uploader' => $texture->uploader,
|
||||
'public' => $texture->public ? 1 : 0,
|
||||
'upload_at' => $texture->upload_at->format('Y-m-d H:i:s')
|
||||
]);
|
||||
}
|
||||
|
||||
public function testUpload()
|
||||
{
|
||||
$this->actAs('normal')
|
||||
->visit('/skinlib/upload')
|
||||
->seePageIs('/skinlib/upload')
|
||||
->assertViewHas('user')
|
||||
->assertViewHas('with_out_filter', true);
|
||||
}
|
||||
|
||||
public function testHandleUpload()
|
||||
{
|
||||
// Some error occurred when uploading file
|
||||
$file = vfsStream::newFile('test.png')
|
||||
->at($this->vfs_root);
|
||||
$upload = new UploadedFile(
|
||||
$file->url(),
|
||||
$file->getName(),
|
||||
'image/png',
|
||||
50,
|
||||
UPLOAD_ERR_NO_TMP_DIR,
|
||||
true
|
||||
);
|
||||
$this->actAs('normal')
|
||||
->call(
|
||||
'POST',
|
||||
'/skinlib/upload',
|
||||
[],
|
||||
[],
|
||||
['file' => $upload]
|
||||
)
|
||||
->getContent();
|
||||
$this->seeJson([
|
||||
'errno' => UPLOAD_ERR_NO_TMP_DIR,
|
||||
'msg' => Utils::convertUploadFileError(UPLOAD_ERR_NO_TMP_DIR)
|
||||
]);
|
||||
|
||||
// Without `name` field
|
||||
$this->post('/skinlib/upload', [], [
|
||||
'X-Requested-With' => 'XMLHttpRequest'
|
||||
])->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('validation.required', ['attribute' => 'Name'])
|
||||
]);
|
||||
|
||||
// With some special chars
|
||||
$this->post('/skinlib/upload', [
|
||||
'name' => '\\'
|
||||
], [
|
||||
'X-Requested-With' => 'XMLHttpRequest'
|
||||
])->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('validation.no_special_chars', ['attribute' => 'Name'])
|
||||
]);
|
||||
|
||||
// Without file
|
||||
$this->post('/skinlib/upload', [
|
||||
'name' => 'texture'
|
||||
], [
|
||||
'X-Requested-With' => 'XMLHttpRequest'
|
||||
])->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('validation.required', ['attribute' => 'File'])
|
||||
]);
|
||||
|
||||
// Too large file
|
||||
option(['max_upload_file_size' => 2]);
|
||||
$this->post('/skinlib/upload', [
|
||||
'name' => 'texture',
|
||||
'file' => $upload
|
||||
], [
|
||||
'X-Requested-With' => 'XMLHttpRequest'
|
||||
])->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('validation.max.file', ['attribute' => 'File', 'max' => '2'])
|
||||
]);
|
||||
option(['max_upload_file_size' => 1024]);
|
||||
|
||||
// Without `public` field
|
||||
$this->post('/skinlib/upload', [
|
||||
'name' => 'texture',
|
||||
'file' => 'content' // Though it is not a file, it is OK
|
||||
], [
|
||||
'X-Requested-With' => 'XMLHttpRequest'
|
||||
])->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('validation.required', ['attribute' => 'public'])
|
||||
]);
|
||||
|
||||
// Not a PNG image
|
||||
$upload = new UploadedFile(
|
||||
$file->url(),
|
||||
$file->getName(),
|
||||
'image/jpeg',
|
||||
2,
|
||||
null,
|
||||
true
|
||||
);
|
||||
$this->call(
|
||||
'POST',
|
||||
'/skinlib/upload',
|
||||
[
|
||||
'name' => 'texture',
|
||||
'public' => 'true'
|
||||
],
|
||||
[],
|
||||
['file' => $upload]
|
||||
);
|
||||
$this->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('skinlib.upload.type-error')
|
||||
]);
|
||||
|
||||
// No texture type is specified
|
||||
$file = vfsStream::newFile('test.png')
|
||||
->at($this->vfs_root);
|
||||
imagepng(imagecreatetruecolor(64, 32), $file->url());
|
||||
$upload = new UploadedFile($file->url(), $file->getName(), 'image/x-png', 2, null, true);
|
||||
$this->call(
|
||||
'POST',
|
||||
'/skinlib/upload',
|
||||
[
|
||||
'name' => 'texture',
|
||||
'public' => 'true'
|
||||
],
|
||||
[],
|
||||
['file' => $upload]
|
||||
);
|
||||
$this->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('general.illegal-parameters')
|
||||
]);
|
||||
|
||||
// Invalid skin size
|
||||
imagepng(imagecreatetruecolor(64, 30), $file->url());
|
||||
$this->call(
|
||||
'POST',
|
||||
'/skinlib/upload',
|
||||
[
|
||||
'name' => 'texture',
|
||||
'public' => 'true',
|
||||
'type' => 'steve'
|
||||
],
|
||||
[],
|
||||
['file' => $upload]
|
||||
);
|
||||
$this->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans(
|
||||
'skinlib.upload.invalid-size',
|
||||
[
|
||||
'type' => trans('general.skin'),
|
||||
'width' => 64,
|
||||
'height' => 30
|
||||
]
|
||||
)
|
||||
]);
|
||||
imagepng(imagecreatetruecolor(100, 50), $file->url());
|
||||
$this->call(
|
||||
'POST',
|
||||
'/skinlib/upload',
|
||||
[
|
||||
'name' => 'texture',
|
||||
'public' => 'true',
|
||||
'type' => 'alex'
|
||||
],
|
||||
[],
|
||||
['file' => $upload]
|
||||
);
|
||||
$this->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans(
|
||||
'skinlib.upload.invalid-hd-skin',
|
||||
[
|
||||
'type' => trans('general.skin'),
|
||||
'width' => 100,
|
||||
'height' => 50
|
||||
]
|
||||
)
|
||||
]);
|
||||
imagepng(imagecreatetruecolor(64, 30), $file->url());
|
||||
$this->call(
|
||||
'POST',
|
||||
'/skinlib/upload',
|
||||
[
|
||||
'name' => 'texture',
|
||||
'public' => 'true',
|
||||
'type' => 'cape'
|
||||
],
|
||||
[],
|
||||
['file' => $upload]
|
||||
);
|
||||
$this->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans(
|
||||
'skinlib.upload.invalid-size',
|
||||
[
|
||||
'type' => trans('general.cape'),
|
||||
'width' => 64,
|
||||
'height' => 30
|
||||
]
|
||||
)
|
||||
]);
|
||||
|
||||
imagepng(imagecreatetruecolor(64, 32), $file->url());
|
||||
$upload = new UploadedFile($file->url(), $file->getName(), 'image/png', 1, null, true);
|
||||
|
||||
// Score is not enough
|
||||
$user = factory(User::class)->create(['score' => 0]);
|
||||
$this->actAs($user)
|
||||
->call(
|
||||
'POST',
|
||||
'/skinlib/upload',
|
||||
[
|
||||
'name' => 'texture',
|
||||
'public' => 'true',
|
||||
'type' => 'steve'
|
||||
],
|
||||
[],
|
||||
['file' => $upload]
|
||||
);
|
||||
$this->seeJson([
|
||||
'errno' => 7,
|
||||
'msg' => trans('skinlib.upload.lack-score')
|
||||
]);
|
||||
|
||||
$user->score =
|
||||
(int) option('score_per_closet_item') +
|
||||
(int) option('score_per_storage');
|
||||
$user->save();
|
||||
$this->call(
|
||||
'POST',
|
||||
'/skinlib/upload',
|
||||
[
|
||||
'name' => 'texture',
|
||||
'public' => 'false', // Private texture cost more scores
|
||||
'type' => 'steve'
|
||||
],
|
||||
[],
|
||||
['file' => $upload]
|
||||
);
|
||||
$this->seeJson([
|
||||
'errno' => 7,
|
||||
'msg' => trans('skinlib.upload.lack-score')
|
||||
]);
|
||||
$this->call(
|
||||
'POST',
|
||||
'/skinlib/upload',
|
||||
[
|
||||
'name' => 'texture',
|
||||
'public' => 'true', // Public texture
|
||||
'type' => 'steve'
|
||||
],
|
||||
[],
|
||||
['file' => $upload]
|
||||
);
|
||||
$uploaded = Texture::where('name', 'texture')->first();
|
||||
$this->seeJson([
|
||||
'errno' => 0,
|
||||
'msg' => trans('skinlib.upload.success', ['name' => 'texture']),
|
||||
'tid' => $uploaded->tid
|
||||
]);
|
||||
$this->assertEquals(0, User::find($user->uid)->score);
|
||||
$this->assertTrue(Storage::disk('textures')->exists($uploaded->hash));
|
||||
$this->assertEquals('texture', $user->getCloset()->get($uploaded->tid)['name']);
|
||||
$this->assertEquals('texture', $uploaded->name);
|
||||
$this->assertEquals('steve', $uploaded->type);
|
||||
$this->assertEquals(1, $uploaded->likes);
|
||||
$this->assertEquals(1, $uploaded->size);
|
||||
$this->assertEquals('1', $uploaded->public);
|
||||
$this->assertEquals($user->uid, $uploaded->uploader);
|
||||
|
||||
// Upload a duplicated texture
|
||||
$user->score = 1000;
|
||||
$user->save();
|
||||
$this->call(
|
||||
'POST',
|
||||
'/skinlib/upload',
|
||||
[
|
||||
'name' => 'texture',
|
||||
'public' => 'true',
|
||||
'type' => 'steve'
|
||||
],
|
||||
[],
|
||||
['file' => $upload]
|
||||
);
|
||||
$this->seeJson([
|
||||
'errno' => 0,
|
||||
'msg' => trans('skinlib.upload.repeated'),
|
||||
'tid' => $uploaded->tid
|
||||
]);
|
||||
}
|
||||
|
||||
public function testDelete()
|
||||
{
|
||||
$uploader = factory(User::class)->create();
|
||||
$other = factory(User::class)->create();
|
||||
$texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
|
||||
option(['return_score' => false]);
|
||||
|
||||
// Non-existed texture
|
||||
$this->actAs($uploader)
|
||||
->post('/skinlib/delete', ['tid' => -1])
|
||||
->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('skinlib.non-existent')
|
||||
]);
|
||||
|
||||
// Other user should not be able to delete
|
||||
$this->actAs($other)
|
||||
->post('/skinlib/delete', ['tid' => $texture->tid])
|
||||
->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('skinlib.no-permission')
|
||||
]);
|
||||
|
||||
// Administrators can delete it
|
||||
$this->actAs('admin')
|
||||
->post('/skinlib/delete', ['tid' => $texture->tid])
|
||||
->seeJson([
|
||||
'errno' => 0,
|
||||
'msg' => trans('skinlib.delete.success')
|
||||
]);
|
||||
$this->assertNull(Texture::find($texture->tid));
|
||||
|
||||
$texture = factory(Texture::class)->create();
|
||||
factory(Texture::class)->create(['hash' => $texture->hash]);
|
||||
Storage::disk('textures')->put($texture->hash, '');
|
||||
|
||||
// When file is occupied, the file should not be deleted
|
||||
$this->post('/skinlib/delete', ['tid' => $texture->tid])
|
||||
->seeJson([
|
||||
'errno' => 0,
|
||||
'msg' => trans('skinlib.delete.success')
|
||||
]);
|
||||
$this->assertNull(Texture::find($texture->tid));
|
||||
$this->assertTrue(Storage::disk('textures')->exists($texture->hash));
|
||||
|
||||
$texture = factory(Texture::class)->create();
|
||||
factory(Texture::class)->create(['hash' => $texture->hash]);
|
||||
$this->post('/skinlib/delete', ['tid' => $texture->tid])
|
||||
->seeJson([
|
||||
'errno' => 0,
|
||||
'msg' => trans('skinlib.delete.success')
|
||||
]);
|
||||
$this->assertNull(Texture::find($texture->tid));
|
||||
$this->assertFalse(Storage::disk('textures')->exists($texture->hash));
|
||||
|
||||
// Return score
|
||||
option(['return_score' => true]);
|
||||
$texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
|
||||
$this->actAs($uploader)
|
||||
->post('/skinlib/delete', ['tid' => $texture->tid])
|
||||
->seeJson([
|
||||
'errno' => 0,
|
||||
'msg' => trans('skinlib.delete.success')
|
||||
]);
|
||||
$this->assertEquals(
|
||||
$uploader->score + $texture->size * option('score_per_storage'),
|
||||
User::find($uploader->uid)->score
|
||||
);
|
||||
|
||||
$uploader = User::find($uploader->uid);
|
||||
$texture = factory(Texture::class)->create([
|
||||
'uploader' => $uploader->uid,
|
||||
'public' => false
|
||||
]);
|
||||
$this->actAs($uploader)
|
||||
->post('/skinlib/delete', ['tid' => $texture->tid])
|
||||
->seeJson([
|
||||
'errno' => 0,
|
||||
'msg' => trans('skinlib.delete.success')
|
||||
]);
|
||||
$this->assertEquals(
|
||||
$uploader->score + $texture->size * option('private_score_per_storage'),
|
||||
User::find($uploader->uid)->score
|
||||
);
|
||||
}
|
||||
|
||||
public function testPrivacy()
|
||||
{
|
||||
$uploader = factory(User::class)->create();
|
||||
$other = factory(User::class)->create();
|
||||
$texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
|
||||
|
||||
// Non-existed texture
|
||||
$this->actAs($uploader)
|
||||
->post('/skinlib/privacy', ['tid' => -1])
|
||||
->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('skinlib.non-existent')
|
||||
]);
|
||||
|
||||
// Other user should not be able to set privacy
|
||||
$this->actAs($other)
|
||||
->post('/skinlib/privacy', ['tid' => $texture->tid])
|
||||
->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('skinlib.no-permission')
|
||||
]);
|
||||
|
||||
// Administrators can change it
|
||||
$uploader->score += $texture->size * option('private_score_per_storage');
|
||||
$uploader->save();
|
||||
$this->actAs('admin')
|
||||
->post('/skinlib/privacy', ['tid' => $texture->tid])
|
||||
->seeJson([
|
||||
'errno' => 0,
|
||||
'msg' => trans('skinlib.privacy.success', ['privacy' => trans('general.private')]),
|
||||
'public' => '0'
|
||||
]);
|
||||
$this->assertEquals(0, Texture::find($texture->tid)->public);
|
||||
|
||||
// Setting a texture to be private needs more scores
|
||||
$texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
|
||||
$uploader->score = 0;
|
||||
$uploader->save();
|
||||
$this->actAs($uploader)
|
||||
->post('/skinlib/privacy', ['tid' => $texture->tid])
|
||||
->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('skinlib.upload.lack-score')
|
||||
]);
|
||||
$this->assertEquals(1, Texture::find($texture->tid)->public);
|
||||
|
||||
$texture->public = true;
|
||||
$texture->save();
|
||||
$uploader->score = $texture->size *
|
||||
(option('private_score_per_storage') - option('score_per_storage'));
|
||||
$uploader->save();
|
||||
$this->post('/skinlib/privacy', ['tid' => $texture->tid])
|
||||
->seeJson([
|
||||
'errno' => 0,
|
||||
'msg' => trans('skinlib.privacy.success', ['privacy' => trans('general.private')]),
|
||||
'public' => '0'
|
||||
]);
|
||||
$this->assertEquals(0, User::find($uploader->uid)->score);
|
||||
|
||||
// When setting a texture to be private,
|
||||
// other players should not be able to use it.
|
||||
$texture->public = '1';
|
||||
$texture->save();
|
||||
$uploader->score += $texture->size * option('private_score_per_storage');
|
||||
$uploader->save();
|
||||
$player = factory(Player::class)->create(['tid_steve' => $texture->tid]);
|
||||
$this->post('/skinlib/privacy', ['tid' => $texture->tid])
|
||||
->seeJson([
|
||||
'errno' => 0,
|
||||
'msg' => trans('skinlib.privacy.success', ['privacy' => trans('general.private')]),
|
||||
'public' => '0'
|
||||
]);
|
||||
$this->assertEquals(0, Player::find($player->pid)->tid_steve);
|
||||
}
|
||||
|
||||
public function testRename()
|
||||
{
|
||||
$uploader = factory(User::class)->create();
|
||||
$other = factory(User::class)->create();
|
||||
$texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
|
||||
|
||||
// Without `tid` field
|
||||
$this->actAs($uploader)
|
||||
->post('/skinlib/rename', [], [
|
||||
'X-Requested-With' => 'XMLHttpRequest'
|
||||
])
|
||||
->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('validation.required', ['attribute' => 'tid'])
|
||||
]);
|
||||
|
||||
// `tid` is not a integer
|
||||
$this->post('/skinlib/rename', [
|
||||
'tid' => 'str'
|
||||
], [
|
||||
'X-Requested-With' => 'XMLHttpRequest'
|
||||
])
|
||||
->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('validation.integer', ['attribute' => 'tid'])
|
||||
]);
|
||||
|
||||
// Without `new_name` field
|
||||
$this->post('/skinlib/rename', [
|
||||
'tid' => $texture->tid
|
||||
], [
|
||||
'X-Requested-With' => 'XMLHttpRequest'
|
||||
])
|
||||
->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('validation.required', ['attribute' => 'new name'])
|
||||
]);
|
||||
|
||||
// `new_name` has special chars
|
||||
$this->post('/skinlib/rename', [
|
||||
'tid' => $texture->tid,
|
||||
'new_name' => '\\'
|
||||
], [
|
||||
'X-Requested-With' => 'XMLHttpRequest'
|
||||
])
|
||||
->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('validation.no_special_chars', ['attribute' => 'new name'])
|
||||
]);
|
||||
|
||||
// Non-existed texture
|
||||
$this->post('/skinlib/rename', [
|
||||
'tid' => -1,
|
||||
'new_name' => 'name'
|
||||
])
|
||||
->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('skinlib.non-existent')
|
||||
]);
|
||||
|
||||
// Other user should not be able to rename
|
||||
$this->actAs($other)
|
||||
->post('/skinlib/rename', [
|
||||
'tid' => $texture->tid,
|
||||
'new_name' => 'name'
|
||||
])
|
||||
->seeJson([
|
||||
'errno' => 1,
|
||||
'msg' => trans('skinlib.no-permission')
|
||||
]);
|
||||
|
||||
// Administrators should be able to rename
|
||||
$this->actAs('admin')
|
||||
->post('/skinlib/rename', [
|
||||
'tid' => $texture->tid,
|
||||
'new_name' => 'name'
|
||||
])
|
||||
->seeJson([
|
||||
'errno' => 0,
|
||||
'msg' => trans('skinlib.rename.success', ['name' => 'name'])
|
||||
]);
|
||||
$this->assertEquals('name', Texture::find($texture->tid)->name);
|
||||
|
||||
// Uploader should be able to rename
|
||||
$this->actAs($uploader)
|
||||
->post('/skinlib/rename', [
|
||||
'tid' => $texture->tid,
|
||||
'new_name' => 'new_name'
|
||||
])
|
||||
->seeJson([
|
||||
'errno' => 0,
|
||||
'msg' => trans('skinlib.rename.success', ['name' => 'new_name'])
|
||||
]);
|
||||
$this->assertEquals('new_name', Texture::find($texture->tid)->name);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user