Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Faker and use Faker in test data #233

Merged
merged 1 commit into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading