Skip to content

Commit d95a63c

Browse files
committed
Today Dane learned about Mockery::subset, tomorrow we take over Canada.
In other news, why could no one have mentioned this a few months ago. Would have been nice.
1 parent 3e689cf commit d95a63c

File tree

2 files changed

+204
-3
lines changed

2 files changed

+204
-3
lines changed

database/factories/ModelFactory.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,11 @@
103103
$factory->define(Pterodactyl\Models\ServiceOption::class, function (Faker\Generator $faker) {
104104
return [
105105
'id' => $faker->unique()->randomNumber(),
106+
'uuid' => $faker->unique()->uuid,
106107
'service_id' => $faker->unique()->randomNumber(),
107108
'name' => $faker->name,
108109
'description' => implode(' ', $faker->sentences(3)),
109-
'tag' => $faker->unique()->randomNumber(5),
110+
'tag' => 'test@testfactory.com:' . $faker->unique()->randomNumber(8),
110111
];
111112
});
112113

@@ -120,8 +121,6 @@
120121
'user_viewable' => 0,
121122
'user_editable' => 0,
122123
'rules' => 'required|string',
123-
'created_at' => \Carbon\Carbon::now(),
124-
'updated_at' => \Carbon\Carbon::now(),
125124
];
126125
});
127126

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
<?php
2+
/**
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
5+
*
6+
* This software is licensed under the terms of the MIT license.
7+
* https://opensource.org/licenses/MIT
8+
*/
9+
10+
namespace Tests\Unit\Services\Services\Sharing;
11+
12+
use Mockery as m;
13+
use Tests\TestCase;
14+
use Ramsey\Uuid\Uuid;
15+
use Pterodactyl\Models\Service;
16+
use Illuminate\Http\UploadedFile;
17+
use Pterodactyl\Models\ServiceOption;
18+
use Pterodactyl\Models\ServiceVariable;
19+
use Illuminate\Database\ConnectionInterface;
20+
use Pterodactyl\Exceptions\PterodactylException;
21+
use Pterodactyl\Contracts\Repository\ServiceRepositoryInterface;
22+
use Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException;
23+
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
24+
use Pterodactyl\Services\Services\Sharing\ServiceOptionImporterService;
25+
use Pterodactyl\Contracts\Repository\ServiceVariableRepositoryInterface;
26+
use Pterodactyl\Exceptions\Service\ServiceOption\DuplicateOptionTagException;
27+
28+
class ServiceOptionImporterServiceTest extends TestCase
29+
{
30+
/**
31+
* @var \Illuminate\Database\ConnectionInterface|\Mockery\Mock
32+
*/
33+
protected $connection;
34+
35+
/**
36+
* @var \Illuminate\Http\UploadedFile|\Mockery\Mock
37+
*/
38+
protected $file;
39+
40+
/**
41+
* @var \Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface|\Mockery\Mock
42+
*/
43+
protected $repository;
44+
45+
/**
46+
* @var \Pterodactyl\Services\Services\Sharing\ServiceOptionImporterService
47+
*/
48+
protected $service;
49+
50+
/**
51+
* @var \Pterodactyl\Contracts\Repository\ServiceRepositoryInterface|\Mockery\Mock
52+
*/
53+
protected $serviceRepository;
54+
55+
/**
56+
* @var \Pterodactyl\Contracts\Repository\ServiceVariableRepositoryInterface|\Mockery\Mock
57+
*/
58+
protected $serviceVariableRepository;
59+
60+
/**
61+
* @var \Ramsey\Uuid\Uuid|\Mockery\Mock
62+
*/
63+
protected $uuid;
64+
65+
/**
66+
* Setup tests.
67+
*/
68+
public function setUp()
69+
{
70+
parent::setUp();
71+
72+
$this->connection = m::mock(ConnectionInterface::class);
73+
$this->file = m::mock(UploadedFile::class);
74+
$this->repository = m::mock(ServiceOptionRepositoryInterface::class);
75+
$this->serviceRepository = m::mock(ServiceRepositoryInterface::class);
76+
$this->serviceVariableRepository = m::mock(ServiceVariableRepositoryInterface::class);
77+
$this->uuid = m::mock('overload:' . Uuid::class);
78+
79+
$this->service = new ServiceOptionImporterService(
80+
$this->connection, $this->serviceRepository, $this->repository, $this->serviceVariableRepository
81+
);
82+
}
83+
84+
/**
85+
* Test that a service option can be successfully imported.
86+
*/
87+
public function testServiceOptionIsImported()
88+
{
89+
$option = factory(ServiceOption::class)->make();
90+
$service = factory(Service::class)->make();
91+
$service->options = collect([factory(ServiceOption::class)->make()]);
92+
93+
$this->file->shouldReceive('isValid')->withNoArgs()->once()->andReturn(true);
94+
$this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(true);
95+
$this->file->shouldReceive('getSize')->withNoArgs()->once()->andReturn(100);
96+
$this->file->shouldReceive('openFile->fread')->with(100)->once()->andReturn(json_encode([
97+
'meta' => ['version' => 'PTDL_v1'],
98+
'name' => $option->name,
99+
'tag' => $option->tag,
100+
'variables' => [
101+
$variable = factory(ServiceVariable::class)->make(),
102+
],
103+
]));
104+
$this->serviceRepository->shouldReceive('getWithOptions')->with($service->id)->once()->andReturn($service);
105+
106+
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
107+
$this->uuid->shouldReceive('uuid4->toString')->withNoArgs()->once()->andReturn($option->uuid);
108+
$this->repository->shouldReceive('create')->with(m::subset([
109+
'uuid' => $option->uuid,
110+
'service_id' => $service->id,
111+
'name' => $option->name,
112+
'tag' => $option->tag,
113+
]), true, true)->once()->andReturn($option);
114+
115+
$this->serviceVariableRepository->shouldReceive('create')->with(m::subset([
116+
'option_id' => $option->id,
117+
'env_variable' => $variable->env_variable,
118+
]))->once()->andReturnNull();
119+
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
120+
121+
$response = $this->service->handle($this->file, $service->id);
122+
$this->assertNotEmpty($response);
123+
$this->assertInstanceOf(ServiceOption::class, $response);
124+
$this->assertSame($option, $response);
125+
}
126+
127+
/**
128+
* Test that an exception is thrown if the file is invalid.
129+
*/
130+
public function testExceptionIsThrownIfFileIsInvalid()
131+
{
132+
$this->file->shouldReceive('isValid')->withNoArgs()->once()->andReturn(false);
133+
try {
134+
$this->service->handle($this->file, 1234);
135+
} catch (PterodactylException $exception) {
136+
$this->assertInstanceOf(InvalidFileUploadException::class, $exception);
137+
$this->assertEquals(trans('exceptions.service.exporter.import_file_error'), $exception->getMessage());
138+
}
139+
}
140+
141+
/**
142+
* Test that an exception is thrown if the file is not a file.
143+
*/
144+
public function testExceptionIsThrownIfFileIsNotAFile()
145+
{
146+
$this->file->shouldReceive('isValid')->withNoArgs()->once()->andReturn(true);
147+
$this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(false);
148+
149+
try {
150+
$this->service->handle($this->file, 1234);
151+
} catch (PterodactylException $exception) {
152+
$this->assertInstanceOf(InvalidFileUploadException::class, $exception);
153+
$this->assertEquals(trans('exceptions.service.exporter.import_file_error'), $exception->getMessage());
154+
}
155+
}
156+
157+
/**
158+
* Test that an exception is thrown if the JSON metadata is invalid.
159+
*/
160+
public function testExceptionIsThrownIfJsonMetaDataIsInvalid()
161+
{
162+
$this->file->shouldReceive('isValid')->withNoArgs()->once()->andReturn(true);
163+
$this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(true);
164+
$this->file->shouldReceive('getSize')->withNoArgs()->once()->andReturn(100);
165+
$this->file->shouldReceive('openFile->fread')->with(100)->once()->andReturn(json_encode([
166+
'meta' => ['version' => 'hodor'],
167+
]));
168+
169+
try {
170+
$this->service->handle($this->file, 1234);
171+
} catch (PterodactylException $exception) {
172+
$this->assertInstanceOf(InvalidFileUploadException::class, $exception);
173+
$this->assertEquals(trans('exceptions.service.exporter.invalid_json_provided'), $exception->getMessage());
174+
}
175+
}
176+
177+
/**
178+
* Test that an exception is thrown if a duplicate tag exists.
179+
*/
180+
public function testExceptionIsThrownIfDuplicateTagExists()
181+
{
182+
$option = factory(ServiceOption::class)->make();
183+
$service = factory(Service::class)->make();
184+
$service->options = collect([factory(ServiceOption::class)->make(['tag' => $option->tag])]);
185+
186+
$this->file->shouldReceive('isValid')->withNoArgs()->once()->andReturn(true);
187+
$this->file->shouldReceive('isFile')->withNoArgs()->once()->andReturn(true);
188+
$this->file->shouldReceive('getSize')->withNoArgs()->once()->andReturn(100);
189+
$this->file->shouldReceive('openFile->fread')->with(100)->once()->andReturn(json_encode([
190+
'meta' => ['version' => 'PTDL_v1'],
191+
'tag' => $option->tag,
192+
]));
193+
$this->serviceRepository->shouldReceive('getWithOptions')->with($service->id)->once()->andReturn($service);
194+
195+
try {
196+
$this->service->handle($this->file, $service->id);
197+
} catch (PterodactylException $exception) {
198+
$this->assertInstanceOf(DuplicateOptionTagException::class, $exception);
199+
$this->assertEquals(trans('exceptions.service.options.duplicate_tag'), $exception->getMessage());
200+
}
201+
}
202+
}

0 commit comments

Comments
 (0)