Skip to content

Commit

Permalink
Improve how we handle data providers
Browse files Browse the repository at this point in the history
We frequently repeat ourselves in the data providers. There's a clear
advantage to that, as it increases the number of possibilities with the
test, but it can also be annoying when we have to repeat ourselves.

Signed-off-by: Henrique Moody <[email protected]>
  • Loading branch information
henriquemoody committed Mar 17, 2024
1 parent 28b3f88 commit b2250c6
Show file tree
Hide file tree
Showing 6 changed files with 298 additions and 202 deletions.
167 changes: 167 additions & 0 deletions tests/fixtures/data-provider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<?php

/*
* Copyright (c) Alexandre Gomes Gaigalas <[email protected]>
* SPDX-License-Identifier: MIT
*/

declare(strict_types=1);

use Respect\Validation\Test\Stubs\WithProperties;
use Respect\Validation\Test\Stubs\WithStaticProperties;
use Respect\Validation\Test\Stubs\WithUninitialized;

return [
'null' => [
'value' => [null],
'tags' => ['nullType', 'empty', 'undefined'],
],

// BooleanTypes
'false' => [
'value' => [false],
'tags' => ['boolType', 'false', 'empty'],
],
'true' => [
'value' => [true],
'tags' => ['boolType', 'true'],
],

// IntegerTypes
'zero integer' => [
'value' => [0],
'tags' => ['intType', 'zero'],
],
'positive integer' => [
'value' => [PHP_INT_MAX],
'tags' => ['intType', 'positive'],
],
'negative integer' => [
'value' => [PHP_INT_MIN],
'tags' => ['intType', 'negative'],
],

// StringTypes
'string' => [
'value' => ['string'],
'tags' => ['stringType'],
],
'empty string' => [
'value' => [''],
'tags' => ['stringType', 'empty', 'undefined'],
],
'integer string' => [
'value' => ['500'],
'tags' => ['stringType', 'intVal', 'positive'],
],
'float string' => [
'value' => ['56.8'],
'tags' => ['stringType', 'floatVal', 'positive'],
],
'zero string' => [
'value' => ['0'],
'tags' => ['stringType', 'intVal', 'zero'],
],

// Float types
'zero float' => [
'value' => [0.0],
'tags' => ['floatType', 'zero'],
],
'positive float' => [
'value' => [32.890],
'tags' => ['floatType', 'positive'],
],
'negative float' => [
'value' => [-893.1],
'tags' => ['floatType', 'negative'],
],

// Array types
'array list' => [
'value' => [[4, 5, 6]],
'tags' => ['arrayType', 'iterableType', 'countable'],
],
'array associative with string keys' => [
'value' => [['broccoli' => 89, 'spinach' => 123, 'beets' => 90]],
'tags' => ['arrayType', 'iterableType', 'countable'],
],
'array associative with int keys' => [
'value' => [[1 => 'cauliflower', 2 => 'eggplant', 3 => 'asparagus']],
'tags' => ['arrayType', 'iterableType', 'countable'],
],
'empty array' => [
'value' => [[]],
'tags' => ['arrayType', 'iterableType', 'countable', 'empty'],
],

// Array values
'ArrayObject' => [
'value' => [new ArrayObject([1, 2, 3])],
'tags' => ['objectType', 'iterableType', 'ArrayObject', 'countable'],
],
'empty ArrayObject' => [
'value' => [new ArrayObject([])],
'tags' => ['objectType', 'iterableType', 'ArrayObject', 'countable', 'empty'],
],

// Iterable types
'generator' => [
'value' => [(static fn() => yield 7)()], // phpcs:ignore
'tags' => ['objectType', 'iterableType', 'generator'],
],
'empty generator' => [
'value' => [(static fn() => yield from [])()],
'tags' => ['objectType', 'iterableType', 'generator', 'empty'],
],

// Callable types
'closure' => [
'value' => [static fn() => 'foo'],
'tags' => ['objectType', 'callable'],
],

// Object types
'object' => [
'value' => [new stdClass()],
'tags' => ['objectType'],
],
'object with properties' => [
'value' => [new WithProperties()],
'tags' => ['objectType'],
],
'object with uninitialized properties' => [
'value' => [new WithUninitialized()],
'tags' => ['objectType'],
],
'object with static properties' => [
'value' => [new WithStaticProperties()],
'tags' => ['objectType'],
],

// Resource types
'stream-context resource' => [
'value' => [stream_context_create()],
'tags' => ['resourceType'],
],
'stream resource' => [
'value' => [tmpfile()],
'tags' => ['resourceType'],
],

// Closed resource (is not a resourceType)
'resource (closed)' => [
'value' => [
(static function () {
$resource = tmpfile();
if ($resource === false) {
throw new RuntimeException('Failed to create temporary file.');
}
fclose($resource);

return $resource;
})(),
],
'tags' => ['closedResource'],
],
];
64 changes: 64 additions & 0 deletions tests/library/DataProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

/*
* Copyright (c) Alexandre Gomes Gaigalas <[email protected]>
* SPDX-License-Identifier: MIT
*/

declare(strict_types=1);

namespace Respect\Validation\Test;

use ArrayIterator;
use IteratorAggregate;
use Traversable;

use function array_filter;
use function array_intersect;
use function array_map;

/**
* @implements IteratorAggregate<array<array{mixed}>>
*/
final class DataProvider implements IteratorAggregate
{
/**
* @param array<mixed> $data
*/
public function __construct(
private readonly array $data
) {
}

public function with(string ...$tags): self
{
return new self(array_filter(
$this->data,
static fn($value) => array_intersect($tags, $value['tags']) === $tags
));
}

public function withAny(string ...$tags): self
{
return new self(array_filter(
$this->data,
static fn($value) => array_intersect($tags, $value['tags']) !== []
));
}

public function without(string ...$tags): self
{
return new self(array_filter(
$this->data,
static fn($value) => array_intersect($tags, $value['tags']) === []
));
}

/**
* @return Traversable<array<mixed>>
*/
public function getIterator(): Traversable
{
return new ArrayIterator(array_map(static fn(array $value) => $value['value'], $this->data));
}
}
40 changes: 0 additions & 40 deletions tests/library/DataProvider/UndefinedProvider.php

This file was deleted.

Loading

0 comments on commit b2250c6

Please sign in to comment.