model = factory(EggVariable::class)->make(); $this->repository = m::mock(EggVariableRepositoryInterface::class); $this->validator = m::mock(Factory::class); } /** * Test the function when no env_variable key is passed into the function. */ public function testVariableIsUpdatedWhenNoEnvironmentVariableIsPassed() { $this->repository->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf() ->shouldReceive('update')->with($this->model->id, m::subset([ 'user_viewable' => false, 'user_editable' => false, ]))->once()->andReturn(true); $this->assertTrue($this->getService()->handle($this->model, [])); } /** * Test that a null value passed in for the default is converted to a string. * * @see https://github.com/Pterodactyl/Panel/issues/934 */ public function testNullDefaultValue() { $this->repository->shouldReceive('withoutFreshModel->update')->with($this->model->id, m::subset([ 'user_viewable' => false, 'user_editable' => false, 'default_value' => '', ]))->once()->andReturn(true); $this->assertTrue($this->getService()->handle($this->model, ['default_value' => null])); } /** * Test the function when a valid env_variable key is passed into the function. */ public function testVariableIsUpdatedWhenValidEnvironmentVariableIsPassed() { $this->repository->shouldReceive('setColumns')->with('id')->once()->andReturnSelf() ->shouldReceive('findCountWhere')->with([ ['env_variable', '=', 'TEST_VAR_123'], ['egg_id', '=', $this->model->option_id], ['id', '!=', $this->model->id], ])->once()->andReturn(0); $this->repository->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf() ->shouldReceive('update')->with($this->model->id, m::subset([ 'user_viewable' => false, 'user_editable' => false, 'env_variable' => 'TEST_VAR_123', ]))->once()->andReturn(true); $this->assertTrue($this->getService()->handle($this->model, ['env_variable' => 'TEST_VAR_123'])); } /** * Test that an empty (null) value passed in the option key is handled * properly as an array. Also tests that a null description is handled. * * @see https://github.com/Pterodactyl/Panel/issues/841 */ public function testNullOptionValueIsPassedAsArray() { $this->repository->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf() ->shouldReceive('update')->with($this->model->id, m::subset([ 'user_viewable' => false, 'user_editable' => false, 'description' => '', ]))->once()->andReturn(true); $this->assertTrue($this->getService()->handle($this->model, ['options' => null, 'description' => null])); } /** * Test that data passed into the handler is overwritten inside the handler. */ public function testDataPassedIntoHandlerTakesLowerPriorityThanDataSet() { $this->repository->shouldReceive('setColumns')->with('id')->once()->andReturnSelf() ->shouldReceive('findCountWhere')->with([ ['env_variable', '=', 'TEST_VAR_123'], ['egg_id', '=', $this->model->option_id], ['id', '!=', $this->model->id], ])->once()->andReturn(0); $this->repository->shouldReceive('withoutFreshModel')->withNoArgs()->once()->andReturnSelf() ->shouldReceive('update')->with($this->model->id, m::subset([ 'user_viewable' => false, 'user_editable' => false, 'env_variable' => 'TEST_VAR_123', ]))->once()->andReturn(true); $this->assertTrue($this->getService()->handle($this->model, ['user_viewable' => 123456, 'env_variable' => 'TEST_VAR_123'])); } /** * Test that a non-unique environment variable triggers an exception. */ public function testExceptionIsThrownIfEnvironmentVariableIsNotUnique() { $this->repository->shouldReceive('setColumns')->with('id')->once()->andReturnSelf() ->shouldReceive('findCountWhere')->with([ ['env_variable', '=', 'TEST_VAR_123'], ['egg_id', '=', $this->model->option_id], ['id', '!=', $this->model->id], ])->once()->andReturn(1); try { $this->getService()->handle($this->model, ['env_variable' => 'TEST_VAR_123']); } catch (Exception $exception) { $this->assertInstanceOf(DisplayException::class, $exception); $this->assertEquals(trans('exceptions.service.variables.env_not_unique', [ 'name' => 'TEST_VAR_123', ]), $exception->getMessage()); } } /** * Test that all of the reserved variables defined in the model trigger an exception. * * @dataProvider reservedNamesProvider */ public function testExceptionIsThrownIfEnvironmentVariableIsInListOfReservedNames(string $variable) { $this->expectException(ReservedVariableNameException::class); $this->getService()->handle($this->model, ['env_variable' => $variable]); } /** * Test that validation errors due to invalid rules are caught and handled properly. */ public function testInvalidValidationRulesResultInException() { $this->expectException(BadValidationRuleException::class); $this->expectExceptionMessage('The validation rule "hodor_door" is not a valid rule for this application.'); $data = ['env_variable' => 'TEST_VAR_123', 'rules' => 'string|hodorDoor']; $this->repository->shouldReceive('setColumns->findCountWhere')->once()->andReturn(0); $this->validator->shouldReceive('make')->once() ->with(['__TEST' => 'test'], ['__TEST' => 'string|hodorDoor']) ->andReturnSelf(); $this->validator->shouldReceive('fails')->once() ->withNoArgs() ->andThrow(new BadMethodCallException('Method [validateHodorDoor] does not exist.')); $this->getService()->handle($this->model, $data); } /** * Test that an exception not stemming from a bad rule is not caught. */ public function testExceptionNotCausedByBadRuleIsNotCaught() { $this->expectException(BadMethodCallException::class); $this->expectExceptionMessage('Received something, but no expectations were specified.'); $data = ['rules' => 'string']; $this->validator->shouldReceive('make')->once() ->with(['__TEST' => 'test'], ['__TEST' => 'string']) ->andReturnSelf(); $this->validator->shouldReceive('fails')->once() ->withNoArgs() ->andThrow(new BadMethodCallException('Received something, but no expectations were specified.')); $this->getService()->handle($this->model, $data); } /** * Provides the data to be used in the tests. * * @return array */ public function reservedNamesProvider() { $data = []; $exploded = explode(',', EggVariable::RESERVED_ENV_NAMES); foreach ($exploded as $e) { $data[] = [$e]; } return $data; } /** * Return an instance of the service with mocked dependencies for testing. * * @return \Pterodactyl\Services\Eggs\Variables\VariableUpdateService */ private function getService(): VariableUpdateService { return new VariableUpdateService($this->repository, $this->validator); } }