strategy = new class {
use ParsesValidationRules;
public function parse($validationRules, $customParameterData = []): array
{
$this->config = new DocumentationConfig([]);
$bodyParametersFromValidationRules = $this->getBodyParametersFromValidationRules($validationRules, $customParameterData);
return $this->normaliseArrayAndObjectParameters($bodyParametersFromValidationRules);
}
};
}
/**
* @test
* @dataProvider supportedRules
*/
public function can_parse_supported_rules(array $ruleset, array $customInfo, array $expected)
{
$results = $this->strategy->parse($ruleset, $customInfo);
$parameterName = array_keys($ruleset)[0];
ray($parameterName, $results[$parameterName]);
$this->assertEquals($expected['type'], $results[$parameterName]['type']);
$this->assertStringEndsWith($expected['description'], $results[$parameterName]['description']);
// Validate that the generated values actually pass validation
$validator = Validator::make([$parameterName => $results[$parameterName]['example']], $ruleset);
try {
$validator->validate();
} catch (ValidationException $e) {
dump('Value: ', $results[$parameterName]['example']);
dump($e->errors());
throw $e;
}
}
/** @test */
public function can_transform_arrays_and_objects()
{
$ruleset = [
'array_param' => 'array|required',
'array_param.*' => 'string',
];
$results = $this->strategy->parse($ruleset);
$this->assertCount(1, $results);
$this->assertEquals('string[]', $results['array_param']['type']);
$ruleset = [
'object_param' => 'array|required',
'object_param.field1.*' => 'string',
'object_param.field2' => 'integer|required',
];
$results = $this->strategy->parse($ruleset);
$this->assertCount(3, $results);
$this->assertEquals('object', $results['object_param']['type']);
$this->assertEquals('string[]', $results['object_param.field1']['type']);
$this->assertEquals('integer', $results['object_param.field2']['type']);
$ruleset = [
'array_of_objects_with_array.*.another.*.one.field1.*' => 'string|required',
'array_of_objects_with_array.*.another.*.one.field2' => 'integer',
'array_of_objects_with_array.*.another.*.two.field2' => 'numeric',
];
$results = $this->strategy->parse($ruleset);
$this->assertCount(7, $results);
$this->assertEquals('object[]', $results['array_of_objects_with_array']['type']);
$this->assertEquals('object[]', $results['array_of_objects_with_array[].another']['type']);
$this->assertEquals('object', $results['array_of_objects_with_array[].another[].one']['type']);
$this->assertEquals('object', $results['array_of_objects_with_array[].another[].two']['type']);
$this->assertEquals('string[]', $results['array_of_objects_with_array[].another[].one.field1']['type']);
$this->assertEquals('integer', $results['array_of_objects_with_array[].another[].one.field2']['type']);
$this->assertEquals('number', $results['array_of_objects_with_array[].another[].two.field2']['type']);
}
public function supportedRules()
{
$description = 'A description';
// Key is just an identifier
// First array in each key is the validation ruleset,
// Second is custom information (from bodyParameters() or comments)
// Third is expected result
yield 'string' => [
['string_param' => 'string'],
['string_param' => ['description' => $description]],
[
'type' => 'string',
'description' => $description . ".",
],
];
yield 'boolean' => [
['boolean_param' => 'boolean'],
[],
[
'type' => 'boolean',
'description' => "",
],
];
yield 'integer' => [
['integer_param' => 'integer'],
[],
[
'type' => 'integer',
'description' => "",
],
];
yield 'numeric' => [
['numeric_param' => 'numeric'],
['numeric_param' => ['description' => $description]],
[
'type' => 'number',
'description' => $description . ".",
],
];
yield 'array' => [
['array_param' => 'array'],
[],
[
'type' => 'string[]',
'description' => '',
],
];
yield 'file' => [
['file_param' => 'file|required'],
['file_param' => ['description' => $description]],
[
'description' => "$description. The value must be a file.",
'type' => 'file',
],
];
yield 'timezone' => [
['timezone_param' => 'timezone|required'],
[],
[
'description' => 'The value must be a valid time zone, such as Africa/Accra
.',
'type' => 'string',
],
];
yield 'email' => [
['email_param' => 'email|required'],
[],
[
'description' => 'The value must be a valid email address.',
'type' => 'string',
],
];
yield 'url' => [
['url_param' => 'url|required'],
['url_param' => ['description' => $description]],
[
'description' => "$description. The value must be a valid URL.",
'type' => 'string',
],
];
yield 'ip' => [
['ip_param' => 'ip|required'],
['ip_param' => ['description' => $description]],
[
'description' => "$description. The value must be a valid IP address.",
'type' => 'string',
],
];
yield 'json' => [
['json_param' => 'json|required'],
['json_param' => []],
[
'description' => 'The value must be a valid JSON string.',
'type' => 'string',
],
];
yield 'date' => [
['date_param' => 'date|required'],
[],
[
'description' => 'The value must be a valid date.',
'type' => 'string',
],
];
yield 'date_format' => [
['date_format_param' => 'date_format:Y-m-d|required'],
['date_format_param' => ['description' => $description]],
[
'description' => "$description. The value must be a valid date in the format Y-m-d.",
'type' => 'string',
],
];
yield 'in' => [
['in_param' => 'in:3,5,6'],
['in_param' => ['description' => $description]],
[
'description' => "$description. The value must be one of 3
, 5
, or 6
.",
'type' => 'string',
],
];
yield 'digits' => [
['digits_param' => 'digits:8'],
[],
[
'description' => "The value must be 8 digits.",
'type' => 'number',
],
];
yield 'digits_between' => [
['digits_between_param' => 'digits_between:2,8'],
[],
[
'description' => "The value must be between 2 and 8 digits.",
'type' => 'number',
],
];
yield 'alpha' => [
['alpha_param' => 'alpha'],
[],
[
'description' => "The value must contain only letters.",
'type' => 'string',
],
];
yield 'alpha_dash' => [
['alpha_dash_param' => 'alpha_dash'],
[],
[
'description' => "The value must contain only letters, numbers, dashes and underscores.",
'type' => 'string',
],
];
yield 'alpha_num' => [
['alpha_num_param' => 'alpha_num'],
[],
[
'description' => "The value must contain only letters and numbers.",
'type' => 'string',
],
];
yield 'ends_with' => [
['ends_with_param' => 'ends_with:go,ha'],
[],
[
'description' => "The value must end with one of go
or ha
.",
'type' => 'string',
],
];
yield 'starts_with' => [
['starts_with_param' => 'starts_with:go,ha'],
[],
[
'description' => "The value must start with one of go
or ha
.",
'type' => 'string',
],
];
yield 'uuid' => [
['uuid_param' => 'uuid'],
[],
[
'description' => "The value must be a valid UUID.",
'type' => 'string',
],
];
}
}