Skip to content

Commit

Permalink
Update Faker and use Faker in test data (#233)
Browse files Browse the repository at this point in the history
  • Loading branch information
IanDelMar authored Sep 30, 2024
1 parent 19596c3 commit faa664c
Show file tree
Hide file tree
Showing 53 changed files with 356 additions and 347 deletions.
115 changes: 68 additions & 47 deletions tests/Faker.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,71 +5,92 @@
namespace PhpStubs\WordPress\Core\Tests;

/**
* @phpstan-type Types array{
* bool: bool,
* int: int,
* float: float,
* string: string,
* array: array<mixed>,
* resource: resource,
* object: object,
* numeric-string: numeric-string,
* null: null,
* mixed: mixed,
* true: true,
* false: false,
* callable: callable,
* iterable: iterable<mixed>,
* array-key: array-key,
* positive-int: positive-int,
* negative-int: negative-int,
* non-positive-int: non-positive-int,
* non-negative-int: non-negative-int,
* non-zero-int: non-zero-int,
* }
* Class that provides fake types via docBlocks for type testing.
*
* @method static bool bool()
* @method static true true()
* @method static false false()
* @method static int int()
* @method static positive-int positiveInt()
* @method static negative-int negativeInt()
* @method static non-positive-int nonPositiveInt()
* @method static non-negative-int nonNegativeInt()
* @method static non-zero-int nonZeroInt()
* @method static float float()
* @method static string string()
* @method static non-empty-string nonEmptyString()
* @method static numeric-string numericString()
* @method static resource resource()
* @method static object object()
* @method static mixed mixed()
* @method static callable callable()
* @method static \stdClass stdClass()
* @method static \WP_Post wpPost()
* @method static \WP_Term wpTerm()
* @method static \WP_Comment wpComment()
* @method static \WP_REST_Request wpRestRequest()
* @method static \WP_Theme wpTheme()
* @method static \WP_Translations wpTranslations()
* @method static \WP_Query wpQuery()
* @method static \WP_Widget_Factory wpWidgetFactory()
*/
class Faker
{
/**
* @var Types $types
* @phpstan-ignore-next-line
* Fakes `array<Type>`. If `$type` is `null`, fakes `array<mixed>`.
*
* @template T
* @param T $type
* @return ($type is null ? array<array-key, mixed> : array<array-key, T>)
*/
private static $types;
public static function array($type = null): array
{
return [$type];
}

/**
* @template T of string
* @param T $type
* @return Types[T]
* Fakes `array<int, Type>`. If `$type` is `null`, fakes `array<int, mixed>`.
*
* @template T
* @param T|null $type
* @return ($type is null ? array<int, mixed> : array<int, T>)
*/
public static function intArray($type = null): array
{
return [$type];
}

/**
* Fakes `array<string, Type>`. If `$type` is `null`, fakes `array<string, mixed>`.
*
* @template T
* @param T|null $type
* @return ($type is null ? array<string, mixed>: array<string, T>)
*/
public static function fake(string $type): mixed
public static function strArray($type = null): array
{
return self::$types[$type];
return [self::string() => $type];
}

/**
* @template T of string
* @template K of string
* @param T $valueType
* @param K $keyType
* @return array<Types[K], Types[T]>
* Fakes `list<Type>`. If `$type` is `null`, fakes `list<mixed>`.
*
* @template T
* @param T|null $type
* @return ($type is null ? list<mixed> : list<T>)
*/
public static function fakeArray(string $valueType, string $keyType = 'array-key'): mixed
public static function list($type = null): array
{
return [$_GET[$keyType], $_GET[$valueType]];
return [$type];
}

/**
* @template T of non-empty-array<key-of<Types>>
* @param T $types
* @return Types[value-of<T>]
* @template T
* @param T ...$types
* @return T
*/
public static function or(array $types): mixed
public static function union(...$types): mixed
{
foreach ($types as $type) {
if ($_GET['thing'] === $type) {
return self::fake($type);
}
}
return self::fake($types[0]);
return $types[0];
}
}
1 change: 1 addition & 0 deletions tests/TypeInferenceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/bool_from_yn.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/current_time.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/echo_parameter.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/Faker.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_approved_comments.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_attachment_taxonomies.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_bookmark.php');
Expand Down
63 changes: 63 additions & 0 deletions tests/data/Faker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

namespace PhpStubs\WordPress\Core\Tests;

use function PHPStan\Testing\assertType;

// Boleans
assertType('bool', Faker::bool());
assertType('true', Faker::true());
assertType('false', Faker::false());

// Numbers
assertType('int', Faker::int());
assertType('int<1, max>', Faker::positiveInt());
assertType('int<min, -1>', Faker::negativeInt());
assertType('int<min, 0>', Faker::nonPositiveInt());
assertType('int<0, max>', Faker::nonNegativeInt());
assertType('int<min, -1>|int<1, max>', Faker::nonZeroInt());
assertType('float', Faker::float());

// Strings
assertType('string', Faker::string());
assertType('numeric-string', Faker::numericString());
assertType('non-empty-string', Faker::nonEmptyString());

// Arrays with default values
assertType('array', Faker::array());
assertType('array<int, mixed>', Faker::intArray());
assertType('array<string, mixed>', Faker::strArray());
assertType('list<mixed>', Faker::list());

// Arrays with specific values
assertType('array<int>', Faker::array(Faker::int()));
assertType('array<int, string>', Faker::intArray(Faker::string()));
assertType('array<string, bool>', Faker::strArray(Faker::bool()));
assertType('list<mixed>', Faker::list());

// Unions
assertType('bool', Faker::union(Faker::bool()));
assertType('bool|int', Faker::union(Faker::bool(), Faker::int()));
assertType('bool|int|string', Faker::union(Faker::bool(), Faker::int(), Faker::string()));
assertType('array<int, int>|bool|int|string', Faker::union(Faker::bool(), Faker::int(), Faker::string(), Faker::intArray(Faker::int())));
assertType('array<int|string, int|string>', Faker::union(Faker::intArray(Faker::int()), Faker::strArray(Faker::string())));
assertType('array<int|string>', Faker::union(Faker::array(Faker::int()), Faker::strArray(Faker::string())));
assertType('array', Faker::union(Faker::array(), Faker::strArray()));
assertType('array', Faker::union(Faker::array(), Faker::intArray()));
assertType('string|null', Faker::union(Faker::string(), null));

// Other
assertType('resource', Faker::resource());
assertType('object', Faker::object());
assertType('stdClass', Faker::stdClass());
assertType('WP_Post', Faker::wpPost());
assertType('WP_Term', Faker::wpTerm());
assertType('WP_Comment', Faker::wpComment());
assertType('WP_REST_Request', Faker::wpRestRequest());
assertType('WP_Theme', Faker::wpTheme());
assertType('WP_Translations', Faker::wpTranslations());
assertType('WP_Query', Faker::wpQuery());
assertType('WP_Widget_Factory', Faker::wpWidgetFactory());
assertType('mixed', Faker::mixed());
14 changes: 6 additions & 8 deletions tests/data/_wp_json_sanity_check.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@

namespace PhpStubs\WordPress\Core\Tests;

use stdClass;

use function PHPStan\Testing\assertType;
use function _wp_json_sanity_check;

assertType('null', _wp_json_sanity_check(null, 1));
assertType('bool', _wp_json_sanity_check((bool)$_GET['value'], 1));
assertType('int', _wp_json_sanity_check((int)$_GET['value'], 1));
assertType('string', _wp_json_sanity_check((string)$_GET['value'], 1));
assertType('array', _wp_json_sanity_check((array)$_GET['value'], 1));
assertType('stdClass', _wp_json_sanity_check(new stdClass(), 1));
assertType('mixed', _wp_json_sanity_check($_GET['value'], 1));
assertType('bool', _wp_json_sanity_check(Faker::bool(), 1));
assertType('int', _wp_json_sanity_check(Faker::int(), 1));
assertType('string', _wp_json_sanity_check(Faker::string(), 1));
assertType('array', _wp_json_sanity_check(Faker::array(), 1));
assertType('stdClass', _wp_json_sanity_check(Faker::stdClass(), 1));
assertType('mixed', _wp_json_sanity_check(Faker::mixed(), 1));
23 changes: 7 additions & 16 deletions tests/data/absint.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,15 @@

namespace PhpStubs\WordPress\Core\Tests;

use stdClass;

use function absint;
use function PHPStan\Testing\assertType;

/** @var int<1, max> $posInt */
$posInt = $_GET['posInt'];

/** @var int<0, max> $nonNegInt */
$nonNegInt = $_GET['nonNegInt'];

/** @var resource $resource */
$resource = $_GET['resource'];

// Returns input for non-negative integers
assertType('0', absint(0));
assertType('1', absint(1));
assertType('10', absint(10));
assertType('int<1, max>', absint($posInt));
assertType('int<0, max>', absint($nonNegInt));
assertType('int<1, max>', absint(Faker::positiveInt()));
assertType('int<0, max>', absint(Faker::nonNegativeInt()));

// Returns 0 for "empty" input
assertType('0', absint(null));
Expand All @@ -40,15 +29,17 @@
assertType('1', absint(['key' => 'value']));

// Returns 0 or 1 for booleans
assertType('0|1', absint((bool)$_GET['bool']));
assertType('0|1', absint(Faker::bool()));

// Returns positive integer for strictly negative integer input
assertType('int<1, max>', absint(-1));
assertType('int<1, max>', absint(-10));

// Returns non-negative integer for floats, numeric strings, ressources
assertType('int<0, max>', absint(1.0));
assertType('int<0, max>', absint(Faker::float()));
assertType('int<0, max>', absint('-10'));
assertType('int<0, max>', absint($resource));
assertType('int<0, max>', absint(Faker::numericString()));
assertType('int<0, max>', absint(Faker::resource()));
// and any other type that is not a subtype of `$maybeint`
assertType('int<0, max>', absint(new stdClass()));
assertType('int<0, max>', absint(Faker::stdClass()));
2 changes: 1 addition & 1 deletion tests/data/bool_from_yn.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
assertType('true', bool_from_yn('y'));
assertType('false', bool_from_yn('n'));
assertType('false', bool_from_yn('thing'));
assertType('bool', bool_from_yn((string)$_GET['string']));
assertType('bool', bool_from_yn(Faker::string()));
4 changes: 1 addition & 3 deletions tests/data/current_time.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,4 @@
// String types
assertType('string', current_time('mysql'));
assertType('string', current_time('Hello'));

// Unknown string
assertType('int|string', current_time((string)$_GET['unknown_string']));
assertType('int|string', current_time(Faker::string()));
4 changes: 2 additions & 2 deletions tests/data/echo_parameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@
assertType('string', wp_register('', '', $value));
assertType('string', wp_title('', $value));

// Unknown value
$value = isset($_GET['foo']);
// Unknown boolean value
$value = Faker::bool();
assertType('string|null', comment_class('', null, null, $value));
assertType('string|null', edit_term_link('', '', '', null, $value));
assertType('string|null', get_calendar(true, $value));
Expand Down
16 changes: 8 additions & 8 deletions tests/data/get_attachment_taxonomies.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@
use function PHPStan\Testing\assertType;

// Default
assertType('array<int, string>', get_attachment_taxonomies((int)$_GET['id']));
assertType('array<int, string>', get_attachment_taxonomies((int)$_GET['id'], 'names'));
assertType('array<int, string>', get_attachment_taxonomies(Faker::int()));
assertType('array<int, string>', get_attachment_taxonomies(Faker::int(), 'names'));

// Objects
assertType('array<string, WP_Taxonomy>', get_attachment_taxonomies((int)$_GET['id'], 'objects'));
assertType('array<string, WP_Taxonomy>', get_attachment_taxonomies(Faker::int(), 'objects'));

// Unexpected
assertType('array<string, WP_Taxonomy>', get_attachment_taxonomies((int)$_GET['id'], 'Hello'));
assertType('array<string, WP_Taxonomy>', get_attachment_taxonomies(Faker::int(), 'Hello'));

// Unknown
assertType('array<int|string, string|WP_Taxonomy>', get_attachment_taxonomies((int)$_GET['id'], (string)$_GET['string']));
assertType('array<int|string, string|WP_Taxonomy>', get_attachment_taxonomies(Faker::int(), Faker::string()));

// Unions
assertType('array<int|string, string|WP_Taxonomy>', get_attachment_taxonomies((int)$_GET['id'], $_GET['foo'] ? 'names' : 'objects'));
assertType('array<int|string, string|WP_Taxonomy>', get_attachment_taxonomies((int)$_GET['id'], $_GET['foo'] ? (string)$_GET['string'] : 'names'));
assertType('array<int|string, string|WP_Taxonomy>', get_attachment_taxonomies((int)$_GET['id'], $_GET['foo'] ? (string)$_GET['string'] : 'objects'));
assertType('array<int|string, string|WP_Taxonomy>', get_attachment_taxonomies(Faker::int(), Faker::bool() ? 'names' : 'objects'));
assertType('array<int|string, string|WP_Taxonomy>', get_attachment_taxonomies(Faker::int(), Faker::bool() ? Faker::string() : 'names'));
assertType('array<int|string, string|WP_Taxonomy>', get_attachment_taxonomies(Faker::int(), Faker::bool() ? Faker::string() : 'objects'));
11 changes: 5 additions & 6 deletions tests/data/get_bookmark.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@
use function get_bookmark;
use function PHPStan\Testing\assertType;

/** @var \stdClass|int $bookmark */
$bookmark = $_GET['bookmark'];
$stdClassOrInt = Faker::union(Faker::stdClass(), Faker::int());

assertType('stdClass|null', get_bookmark($bookmark));
assertType('stdClass|null', get_bookmark($bookmark, 'OBJECT'));
assertType('array<string, mixed>|null', get_bookmark($bookmark, 'ARRAY_A'));
assertType('array<int, mixed>|null', get_bookmark($bookmark, 'ARRAY_N'));
assertType('stdClass|null', get_bookmark($stdClassOrInt));
assertType('stdClass|null', get_bookmark($stdClassOrInt, 'OBJECT'));
assertType('array<string, mixed>|null', get_bookmark($stdClassOrInt, 'ARRAY_A'));
assertType('array<int, mixed>|null', get_bookmark($stdClassOrInt, 'ARRAY_N'));
2 changes: 1 addition & 1 deletion tests/data/get_categories.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@

// Unknown fields value
assertType('array<int, WP_Term>', get_categories(['fields' => 'foo']));
assertType('array<int, int|string|WP_Term>', get_categories(['fields' => (string)$_GET['fields']]));
assertType('array<int, int|string|WP_Term>', get_categories(['fields' => Faker::string()]));
23 changes: 9 additions & 14 deletions tests/data/get_category.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,13 @@
use function get_category;
use function PHPStan\Testing\assertType;

/** @var object $category */
$category = $_GET['category'];
assertType('WP_Term', get_category(Faker::object()));
assertType('WP_Term', get_category(Faker::object(), 'OBJECT'));
assertType('array<string, mixed>', get_category(Faker::object(), 'ARRAY_A'));
assertType('array<int, mixed>', get_category(Faker::object(), 'ARRAY_N'));

assertType('WP_Term', get_category($category));
assertType('WP_Term', get_category($category, 'OBJECT'));
assertType('array<string, mixed>', get_category($category, 'ARRAY_A'));
assertType('array<int, mixed>', get_category($category, 'ARRAY_N'));

/** @var int|object $category */
$category = $_GET['category'];

assertType('WP_Error|WP_Term|null', get_category($category));
assertType('WP_Error|WP_Term|null', get_category($category, 'OBJECT'));
assertType('array<string, mixed>|WP_Error|null', get_category($category, 'ARRAY_A'));
assertType('array<int, mixed>|WP_Error|null', get_category($category, 'ARRAY_N'));
$intOrObject = Faker::union(Faker::int(), Faker::object());
assertType('WP_Error|WP_Term|null', get_category($intOrObject));
assertType('WP_Error|WP_Term|null', get_category($intOrObject, 'OBJECT'));
assertType('array<string, mixed>|WP_Error|null', get_category($intOrObject, 'ARRAY_A'));
assertType('array<int, mixed>|WP_Error|null', get_category($intOrObject, 'ARRAY_N'));
8 changes: 4 additions & 4 deletions tests/data/get_category_by_path.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use function get_category_by_path;
use function PHPStan\Testing\assertType;

assertType('WP_Error|WP_Term|null', get_category_by_path('', (bool)$_GET['full_match']));
assertType('WP_Error|WP_Term|null', get_category_by_path('', (bool)$_GET['full_match'], 'OBJECT'));
assertType('array<string, mixed>|WP_Error|null', get_category_by_path('', (bool)$_GET['full_match'], 'ARRAY_A'));
assertType('array<int, mixed>|WP_Error|null', get_category_by_path('', (bool)$_GET['full_match'], 'ARRAY_N'));
assertType('WP_Error|WP_Term|null', get_category_by_path('', Faker::bool()));
assertType('WP_Error|WP_Term|null', get_category_by_path('', Faker::bool(), 'OBJECT'));
assertType('array<string, mixed>|WP_Error|null', get_category_by_path('', Faker::bool(), 'ARRAY_A'));
assertType('array<int, mixed>|WP_Error|null', get_category_by_path('', Faker::bool(), 'ARRAY_N'));
Loading

0 comments on commit faa664c

Please sign in to comment.