Skip to content

Commit 565c5dd

Browse files
committed
Add integration tests for nests
1 parent 6eaab29 commit 565c5dd

File tree

5 files changed

+320
-3
lines changed

5 files changed

+320
-3
lines changed

app/Transformers/Api/Application/EggTransformer.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ public function transform(Egg $model)
4646
'description' => $model->description,
4747
'docker_image' => $model->docker_image,
4848
'config' => [
49-
'files' => json_decode($model->config_files),
50-
'startup' => json_decode($model->config_startup),
49+
'files' => json_decode($model->config_files, true),
50+
'startup' => json_decode($model->config_startup, true),
5151
'stop' => $model->config_stop,
52-
'logs' => json_decode($model->config_logs),
52+
'logs' => json_decode($model->config_logs, true),
5353
'extends' => $model->config_from,
5454
],
5555
'startup' => $model->startup,

app/Transformers/Api/Application/NestTransformer.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Pterodactyl\Models\Egg;
66
use Pterodactyl\Models\Nest;
7+
use Pterodactyl\Models\Server;
78
use Pterodactyl\Services\Acl\Api\AdminAcl;
89

910
class NestTransformer extends BaseTransformer
@@ -49,6 +50,8 @@ public function transform(Nest $model)
4950
*
5051
* @param \Pterodactyl\Models\Nest $model
5152
* @return \League\Fractal\Resource\Collection|\League\Fractal\Resource\NullResource
53+
*
54+
* @throws \Pterodactyl\Exceptions\Transformer\InvalidTransformerLevelException
5255
*/
5356
public function includeEggs(Nest $model)
5457
{
@@ -60,4 +63,23 @@ public function includeEggs(Nest $model)
6063

6164
return $this->collection($model->getRelation('eggs'), $this->makeTransformer(EggTransformer::class), Egg::RESOURCE_NAME);
6265
}
66+
67+
/**
68+
* Include the servers relationship on the given Nest model.
69+
*
70+
* @param \Pterodactyl\Models\Nest $model
71+
* @return \League\Fractal\Resource\Collection|\League\Fractal\Resource\NullResource
72+
*
73+
* @throws \Pterodactyl\Exceptions\Transformer\InvalidTransformerLevelException
74+
*/
75+
public function includeServers(Nest $model)
76+
{
77+
if (! $this->authorize(AdminAcl::RESOURCE_SERVERS)) {
78+
return $this->null();
79+
}
80+
81+
$model->loadMissing('servers');
82+
83+
return $this->collection($model->getRelation('servers'), $this->makeTransformer(ServerTransformer::class), Server::RESOURCE_NAME);
84+
}
6385
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
<?php
2+
3+
namespace Pterodactyl\Tests\Integration\Api\Application\Nests;
4+
5+
use Illuminate\Support\Arr;
6+
use Illuminate\Http\Response;
7+
use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
8+
use Pterodactyl\Transformers\Api\Application\EggTransformer;
9+
use Pterodactyl\Tests\Integration\Api\Application\ApplicationApiIntegrationTestCase;
10+
11+
class EggControllerTest extends ApplicationApiIntegrationTestCase
12+
{
13+
/**
14+
* @var \Pterodactyl\Contracts\Repository\EggRepositoryInterface
15+
*/
16+
private $repository;
17+
18+
/**
19+
* Setup tests.
20+
*/
21+
public function setUp()
22+
{
23+
parent::setUp();
24+
25+
$this->repository = $this->app->make(EggRepositoryInterface::class);
26+
}
27+
28+
/**
29+
* Test that all of the eggs belonging to a given nest can be returned.
30+
*/
31+
public function testListAllEggsInNest()
32+
{
33+
$eggs = $this->repository->findWhere([['nest_id', '=', 1]]);
34+
35+
$response = $this->getJson('/api/application/nests/' . $eggs->first()->nest_id . '/eggs');
36+
$response->assertStatus(Response::HTTP_OK);
37+
$response->assertJsonCount(count($eggs), 'data');
38+
$response->assertJsonStructure([
39+
'object',
40+
'data' => [
41+
[
42+
'object',
43+
'attributes' => [
44+
'id', 'uuid', 'nest', 'author', 'description', 'docker_image', 'startup', 'created_at', 'updated_at',
45+
'script' => ['privileged', 'install', 'entry', 'container', 'extends'],
46+
'config' => [
47+
'files' => [],
48+
'startup' => ['done', 'userInteraction' => []],
49+
'stop',
50+
'logs' => ['custom', 'location'],
51+
'extends',
52+
],
53+
],
54+
],
55+
],
56+
]);
57+
58+
foreach (array_get($response->json(), 'data') as $datum) {
59+
$egg = $eggs->where('id', '=', $datum['attributes']['id'])->first();
60+
61+
$expected = json_encode(Arr::sortRecursive($datum['attributes']));
62+
$actual = json_encode(Arr::sortRecursive($this->getTransformer(EggTransformer::class)->transform($egg)));
63+
64+
$this->assertSame($expected, $actual,
65+
'Unable to find JSON fragment: ' . PHP_EOL . PHP_EOL . "[{$expected}]" . PHP_EOL . PHP_EOL . 'within' . PHP_EOL . PHP_EOL . "[{$actual}]."
66+
);
67+
}
68+
}
69+
70+
/**
71+
* Test that a single egg can be returned.
72+
*/
73+
public function testReturnSingleEgg()
74+
{
75+
$egg = $this->repository->find(1);
76+
77+
$response = $this->getJson('/api/application/nests/' . $egg->nest_id . '/eggs/' . $egg->id);
78+
$response->assertStatus(Response::HTTP_OK);
79+
$response->assertJsonStructure([
80+
'object',
81+
'attributes' => [
82+
'id', 'uuid', 'nest', 'author', 'description', 'docker_image', 'startup', 'script' => [], 'config' => [], 'created_at', 'updated_at',
83+
],
84+
]);
85+
86+
$response->assertJson([
87+
'object' => 'egg',
88+
'attributes' => $this->getTransformer(EggTransformer::class)->transform($egg),
89+
], true);
90+
}
91+
92+
/**
93+
* Test that a single egg and all of the defined relationships can be returned.
94+
*/
95+
public function testReturnSingleEggWithRelationships()
96+
{
97+
$egg = $this->repository->find(1);
98+
99+
$response = $this->getJson('/api/application/nests/' . $egg->nest_id . '/eggs/' . $egg->id . '?include=servers,variables,nest');
100+
$response->assertStatus(Response::HTTP_OK);
101+
$response->assertJsonStructure([
102+
'object',
103+
'attributes' => [
104+
'relationships' => [
105+
'nest' => ['object', 'attributes'],
106+
'servers' => ['object', 'data' => []],
107+
'variables' => ['object', 'data' => []],
108+
],
109+
],
110+
]);
111+
}
112+
113+
/**
114+
* Test that a missing egg returns a 404 error.
115+
*/
116+
public function testGetMissingEgg()
117+
{
118+
$egg = $this->repository->find(1);
119+
120+
$response = $this->getJson('/api/application/nests/' . $egg->nest_id . '/eggs/nil');
121+
$this->assertNotFoundJson($response);
122+
}
123+
124+
/**
125+
* Test that an authentication error occurs if a key does not have permission
126+
* to access a resource.
127+
*/
128+
public function testErrorReturnedIfNoPermission()
129+
{
130+
$egg = $this->repository->find(1);
131+
$this->createNewDefaultApiKey($this->getApiUser(), ['r_eggs' => 0]);
132+
133+
$response = $this->getJson('/api/application/nests/' . $egg->nest_id . '/eggs');
134+
$this->assertAccessDeniedJson($response);
135+
}
136+
137+
/**
138+
* Test that a nests's existence is not exposed unless an API key has permission
139+
* to access the resource.
140+
*/
141+
public function testResourceIsNotExposedWithoutPermissions()
142+
{
143+
$egg = $this->repository->find(1);
144+
$this->createNewDefaultApiKey($this->getApiUser(), ['r_eggs' => 0]);
145+
146+
$response = $this->getJson('/api/application/nests/' . $egg->nest_id . '/eggs/nil');
147+
$this->assertAccessDeniedJson($response);
148+
}
149+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php
2+
3+
namespace Pterodactyl\Tests\Integration\Api\Application\Nests;
4+
5+
use Illuminate\Http\Response;
6+
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
7+
use Pterodactyl\Transformers\Api\Application\NestTransformer;
8+
use Pterodactyl\Tests\Integration\Api\Application\ApplicationApiIntegrationTestCase;
9+
10+
class NestControllerTest extends ApplicationApiIntegrationTestCase
11+
{
12+
/**
13+
* @var \Pterodactyl\Contracts\Repository\NestRepositoryInterface
14+
*/
15+
private $repository;
16+
17+
/**
18+
* Setup tests.
19+
*/
20+
public function setUp()
21+
{
22+
parent::setUp();
23+
24+
$this->repository = $this->app->make(NestRepositoryInterface::class);
25+
}
26+
27+
/**
28+
* Test that the expected nests are returned in the request.
29+
*/
30+
public function testNestResponse()
31+
{
32+
/** @var \Pterodactyl\Models\Nest[] $nests */
33+
$nests = $this->repository->all();
34+
35+
$response = $this->getJson('/api/application/nests');
36+
$response->assertStatus(Response::HTTP_OK);
37+
$response->assertJsonCount(count($nests), 'data');
38+
$response->assertJsonStructure([
39+
'object',
40+
'data' => [['object', 'attributes' => ['id', 'uuid', 'author', 'name', 'description', 'created_at', 'updated_at']]],
41+
'meta' => ['pagination' => ['total', 'count', 'per_page', 'current_page', 'total_pages']],
42+
]);
43+
44+
$response->assertJson([
45+
'object' => 'list',
46+
'data' => [],
47+
'meta' => [
48+
'pagination' => [
49+
'total' => 4,
50+
'count' => 4,
51+
'per_page' => 50,
52+
'current_page' => 1,
53+
'total_pages' => 1,
54+
],
55+
],
56+
]);
57+
58+
foreach ($nests as $nest) {
59+
$response->assertJsonFragment([
60+
'object' => 'nest',
61+
'attributes' => $this->getTransformer(NestTransformer::class)->transform($nest),
62+
]);
63+
}
64+
}
65+
66+
/**
67+
* Test that getting a single nest returns the expected result.
68+
*/
69+
public function testSingleNestResponse()
70+
{
71+
$nest = $this->repository->find(1);
72+
73+
$response = $this->getJson('/api/application/nests/' . $nest->id);
74+
$response->assertStatus(Response::HTTP_OK);
75+
$response->assertJsonStructure([
76+
'object',
77+
'attributes' => ['id', 'uuid', 'author', 'name', 'description', 'created_at', 'updated_at'],
78+
]);
79+
80+
$response->assertJson([
81+
'object' => 'nest',
82+
'attributes' => $this->getTransformer(NestTransformer::class)->transform($nest),
83+
]);
84+
}
85+
86+
/**
87+
* Test that including eggs in the response works as expected.
88+
*/
89+
public function testSingleNestWithEggsIncluded()
90+
{
91+
$nest = $this->repository->find(1);
92+
$nest->loadMissing('eggs');
93+
94+
$response = $this->getJson('/api/application/nests/' . $nest->id . '?include=servers,eggs');
95+
$response->assertStatus(Response::HTTP_OK);
96+
$response->assertJsonStructure([
97+
'object',
98+
'attributes' => [
99+
'relationships' => [
100+
'eggs' => ['object', 'data' => []],
101+
'servers' => ['object', 'data' => []],
102+
],
103+
],
104+
]);
105+
106+
$response->assertJsonCount(count($nest->getRelation('eggs')), 'attributes.relationships.eggs.data');
107+
}
108+
109+
/**
110+
* Test that a missing nest returns a 404 error.
111+
*/
112+
public function testGetMissingNest()
113+
{
114+
$response = $this->getJson('/api/application/nests/nil');
115+
$this->assertNotFoundJson($response);
116+
}
117+
118+
/**
119+
* Test that an authentication error occurs if a key does not have permission
120+
* to access a resource.
121+
*/
122+
public function testErrorReturnedIfNoPermission()
123+
{
124+
$nest = $this->repository->find(1);
125+
$this->createNewDefaultApiKey($this->getApiUser(), ['r_nests' => 0]);
126+
127+
$response = $this->getJson('/api/application/nests/' . $nest->id);
128+
$this->assertAccessDeniedJson($response);
129+
}
130+
131+
/**
132+
* Test that a nest's existence is not exposed unless an API key has permission
133+
* to access the resource.
134+
*/
135+
public function testResourceIsNotExposedWithoutPermissions()
136+
{
137+
$nest = $this->repository->find(1);
138+
$this->createNewDefaultApiKey($this->getApiUser(), ['r_nests' => 0]);
139+
140+
$response = $this->getJson('/api/application/nests/' . $nest->id);
141+
$this->assertAccessDeniedJson($response);
142+
}
143+
}

tests/Integration/IntegrationTestCase.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ public function setUp()
2323
Model::unsetEventDispatcher();
2424
}
2525

26+
/**
27+
* @return array
28+
*/
2629
protected function connectionsToTransact()
2730
{
2831
return ['testing'];

0 commit comments

Comments
 (0)