mirror of
https://github.com/pestphp/pest.git
synced 2026-03-06 07:47:22 +01:00
Uses Collision ^7.0
This commit is contained in:
3
TODO.md
3
TODO.md
@ -2,3 +2,6 @@
|
|||||||
2. Support for `default` printer.
|
2. Support for `default` printer.
|
||||||
3. Support for `TeamCity` printer.
|
3. Support for `TeamCity` printer.
|
||||||
4. Support for `JUnit` log.
|
4. Support for `JUnit` log.
|
||||||
|
5. Plugins
|
||||||
|
6. Parallel
|
||||||
|
7. Collision's todo...
|
||||||
|
|||||||
3
bin/pest
3
bin/pest
@ -11,6 +11,9 @@ use Symfony\Component\Console\Output\ConsoleOutput;
|
|||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
(static function () {
|
(static function () {
|
||||||
|
// Ensures Collision's Printer is registered.
|
||||||
|
$_SERVER['COLLISION_PRINTER'] = 'DefaultPrinter';
|
||||||
|
|
||||||
// Used when Pest is required using composer.
|
// Used when Pest is required using composer.
|
||||||
$vendorPath = dirname(__DIR__, 4) . '/vendor/autoload.php';
|
$vendorPath = dirname(__DIR__, 4) . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.1.0",
|
"php": "^8.1.0",
|
||||||
"nunomaduro/collision": "^6.3",
|
"nunomaduro/collision": "dev-next",
|
||||||
"pestphp/pest-plugin": "^1.0.0",
|
"pestphp/pest-plugin": "^1.0.0",
|
||||||
"phpunit/phpunit": "10.0.x-dev"
|
"phpunit/phpunit": "10.0.x-dev"
|
||||||
},
|
},
|
||||||
@ -86,6 +86,7 @@
|
|||||||
"Pest\\Plugins\\Init",
|
"Pest\\Plugins\\Init",
|
||||||
"Pest\\Plugins\\Environment",
|
"Pest\\Plugins\\Environment",
|
||||||
"Pest\\Plugins\\Memory",
|
"Pest\\Plugins\\Memory",
|
||||||
|
"Pest\\Plugins\\Printer",
|
||||||
"Pest\\Plugins\\Retry",
|
"Pest\\Plugins\\Retry",
|
||||||
"Pest\\Plugins\\Version"
|
"Pest\\Plugins\\Version"
|
||||||
]
|
]
|
||||||
|
|||||||
@ -44,14 +44,13 @@ use function basename;
|
|||||||
use function class_exists;
|
use function class_exists;
|
||||||
use function get_declared_classes;
|
use function get_declared_classes;
|
||||||
|
|
||||||
|
use Pest\Contracts\HasPrintableTestCaseName;
|
||||||
use Pest\TestCases\IgnorableTestCase;
|
use Pest\TestCases\IgnorableTestCase;
|
||||||
use Pest\TestSuite;
|
use Pest\TestSuite;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
use ReflectionException;
|
use ReflectionException;
|
||||||
|
|
||||||
use function stripos;
|
|
||||||
use function strlen;
|
|
||||||
use function substr;
|
use function substr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,7 +82,6 @@ final class TestSuiteLoader
|
|||||||
{
|
{
|
||||||
$suiteClassName = $this->classNameFromFileName($suiteClassFile);
|
$suiteClassName = $this->classNameFromFileName($suiteClassFile);
|
||||||
|
|
||||||
if (!class_exists($suiteClassName, false)) {
|
|
||||||
(static function () use ($suiteClassFile) {
|
(static function () use ($suiteClassFile) {
|
||||||
include_once $suiteClassFile;
|
include_once $suiteClassFile;
|
||||||
|
|
||||||
@ -105,14 +103,22 @@ final class TestSuiteLoader
|
|||||||
if (empty(self::$loadedClasses)) {
|
if (empty(self::$loadedClasses)) {
|
||||||
return $this->exceptionFor($suiteClassName, $suiteClassFile);
|
return $this->exceptionFor($suiteClassName, $suiteClassFile);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!class_exists($suiteClassName, false)) {
|
$testCaseFound = false;
|
||||||
// this block will handle namespaced classes
|
|
||||||
$offset = 0 - strlen($suiteClassName);
|
|
||||||
|
|
||||||
foreach (self::$loadedClasses as $loadedClass) {
|
foreach (self::$loadedClasses as $loadedClass) {
|
||||||
if (stripos(substr($loadedClass, $offset - 1), '\\' . $suiteClassName) === 0) {
|
if (is_subclass_of($loadedClass, HasPrintableTestCaseName::class)) {
|
||||||
|
$suiteClassName = $loadedClass;
|
||||||
|
|
||||||
|
$testCaseFound = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$testCaseFound) {
|
||||||
|
foreach (self::$loadedClasses as $loadedClass) {
|
||||||
|
if (is_subclass_of($loadedClass, TestCase::class)) {
|
||||||
$suiteClassName = $loadedClass;
|
$suiteClassName = $loadedClass;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
17
phpunit.xml
17
phpunit.xml
@ -1,8 +1,25 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd"
|
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd"
|
||||||
|
backupGlobals="false"
|
||||||
|
beStrictAboutTestsThatDoNotTestAnything="true"
|
||||||
|
beStrictAboutOutputDuringTests="true"
|
||||||
|
bootstrap="vendor/autoload.php"
|
||||||
|
cacheResult="false"
|
||||||
colors="true"
|
colors="true"
|
||||||
|
failOnRisky="true"
|
||||||
|
failOnWarning="true"
|
||||||
|
processIsolation="false"
|
||||||
|
stopOnError="false"
|
||||||
|
stopOnFailure="false"
|
||||||
cacheDirectory=".phpunit.cache"
|
cacheDirectory=".phpunit.cache"
|
||||||
|
backupStaticProperties="false"
|
||||||
|
displayDetailsOnIncompleteTests="true"
|
||||||
|
displayDetailsOnSkippedTests="true"
|
||||||
|
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||||
|
displayDetailsOnTestsThatTriggerErrors="true"
|
||||||
|
displayDetailsOnTestsThatTriggerNotices="true"
|
||||||
|
displayDetailsOnTestsThatTriggerWarnings="true"
|
||||||
>
|
>
|
||||||
<testsuites>
|
<testsuites>
|
||||||
<testsuite name="default">
|
<testsuite name="default">
|
||||||
|
|||||||
@ -9,13 +9,21 @@ use Pest\Support\ChainableClosure;
|
|||||||
use Pest\Support\ExceptionTrace;
|
use Pest\Support\ExceptionTrace;
|
||||||
use Pest\Support\Reflection;
|
use Pest\Support\Reflection;
|
||||||
use Pest\TestSuite;
|
use Pest\TestSuite;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
*
|
||||||
|
* @mixin TestCase
|
||||||
*/
|
*/
|
||||||
trait Testable
|
trait Testable
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Test method description.
|
||||||
|
*/
|
||||||
|
private static string $__description;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Test Case "test" closure.
|
* The Test Case "test" closure.
|
||||||
*/
|
*/
|
||||||
@ -118,14 +126,6 @@ trait Testable
|
|||||||
: $hook;
|
: $hook;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Test Case filename.
|
|
||||||
*/
|
|
||||||
public static function __getFilename(): string
|
|
||||||
{
|
|
||||||
return self::$__filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called before the first test of this Test Case is run.
|
* This method is called before the first test of this Test Case is run.
|
||||||
*/
|
*/
|
||||||
@ -211,6 +211,13 @@ trait Testable
|
|||||||
*/
|
*/
|
||||||
private function __resolveTestArguments(array $arguments): array
|
private function __resolveTestArguments(array $arguments): array
|
||||||
{
|
{
|
||||||
|
$method = TestSuite::getInstance()->tests->get(self::$__filename)->getMethod($this->name());
|
||||||
|
if ($this->dataName()) {
|
||||||
|
self::$__description = $method->description . ' with ' . $this->dataName();
|
||||||
|
} else {
|
||||||
|
self::$__description = $method->description;
|
||||||
|
}
|
||||||
|
|
||||||
if (count($arguments) !== 1) {
|
if (count($arguments) !== 1) {
|
||||||
return $arguments;
|
return $arguments;
|
||||||
}
|
}
|
||||||
@ -246,8 +253,16 @@ trait Testable
|
|||||||
/**
|
/**
|
||||||
* Gets the Test Case name that should be used by printers.
|
* Gets the Test Case name that should be used by printers.
|
||||||
*/
|
*/
|
||||||
public function getPrintableTestCaseName(): string
|
public static function getPrintableTestCaseName(): string
|
||||||
{
|
{
|
||||||
return ltrim(self::class, 'P\\');
|
return ltrim(self::class, 'P\\');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Test Case name that should be used by printers.
|
||||||
|
*/
|
||||||
|
public static function getPrintableTestCaseMethodName(): string
|
||||||
|
{
|
||||||
|
return self::$__description;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,9 +12,9 @@ interface HandlesArguments
|
|||||||
/**
|
/**
|
||||||
* Adds arguments before of the Test Suite execution.
|
* Adds arguments before of the Test Suite execution.
|
||||||
*
|
*
|
||||||
* @param array<int, string> $argv
|
* @param array<int, string> $arguments
|
||||||
*
|
*
|
||||||
* @return array<int, string>
|
* @return array<int, string>
|
||||||
*/
|
*/
|
||||||
public function handleArguments(array $argv): array;
|
public function handleArguments(array $arguments): array;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ final class ShouldNotHappen extends RuntimeException
|
|||||||
{
|
{
|
||||||
$message = $exception->getMessage();
|
$message = $exception->getMessage();
|
||||||
|
|
||||||
parent::__construct(sprintf(<<<EOF
|
parent::__construct(sprintf(<<<'EOF'
|
||||||
|
|
||||||
This should not happen - please create an new issue here: https://github.com/pestphp/pest.
|
This should not happen - please create an new issue here: https://github.com/pestphp/pest.
|
||||||
|
|
||||||
|
|||||||
@ -186,6 +186,7 @@ final class Expectation
|
|||||||
foreach ($values as $key => $item) {
|
foreach ($values as $key => $item) {
|
||||||
if ($callbacks[$key] instanceof Closure) {
|
if ($callbacks[$key] instanceof Closure) {
|
||||||
call_user_func($callbacks[$key], new self($item), new self($keys[$key]));
|
call_user_func($callbacks[$key], new self($item), new self($keys[$key]));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,6 +221,7 @@ final class Expectation
|
|||||||
|
|
||||||
if (is_callable($callback)) {
|
if (is_callable($callback)) {
|
||||||
$callback(new self($this->value));
|
$callback(new self($this->value));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -121,7 +121,17 @@ final class TestCaseFactory
|
|||||||
$filename = str_replace('\\\\', '\\', addslashes((string) realpath($filename)));
|
$filename = str_replace('\\\\', '\\', addslashes((string) realpath($filename)));
|
||||||
$rootPath = TestSuite::getInstance()->rootPath;
|
$rootPath = TestSuite::getInstance()->rootPath;
|
||||||
$relativePath = str_replace($rootPath . DIRECTORY_SEPARATOR, '', $filename);
|
$relativePath = str_replace($rootPath . DIRECTORY_SEPARATOR, '', $filename);
|
||||||
$relativePath = dirname(ucfirst($relativePath)) . DIRECTORY_SEPARATOR . basename($relativePath, '.php');
|
|
||||||
|
$basename = basename($relativePath, '.php');
|
||||||
|
|
||||||
|
$dotPos = strpos($basename, '.');
|
||||||
|
|
||||||
|
if ($dotPos !== false) {
|
||||||
|
$basename = substr($basename, 0, $dotPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
$relativePath = dirname(ucfirst($relativePath)) . DIRECTORY_SEPARATOR . $basename;
|
||||||
|
|
||||||
$relativePath = str_replace(DIRECTORY_SEPARATOR, '\\', $relativePath);
|
$relativePath = str_replace(DIRECTORY_SEPARATOR, '\\', $relativePath);
|
||||||
|
|
||||||
// Strip out any %-encoded octets.
|
// Strip out any %-encoded octets.
|
||||||
@ -132,6 +142,7 @@ final class TestCaseFactory
|
|||||||
$relativePath = (string) preg_replace('/[^A-Za-z0-9\\\\]/', '', $relativePath);
|
$relativePath = (string) preg_replace('/[^A-Za-z0-9\\\\]/', '', $relativePath);
|
||||||
|
|
||||||
$classFQN = 'P\\' . $relativePath;
|
$classFQN = 'P\\' . $relativePath;
|
||||||
|
|
||||||
if (class_exists($classFQN)) {
|
if (class_exists($classFQN)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -179,12 +190,11 @@ final class TestCaseFactory
|
|||||||
));
|
));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
eval("
|
$classCode = <<<PHP
|
||||||
namespace $namespace;
|
namespace $namespace;
|
||||||
|
|
||||||
use Pest\Repositories\DatasetsRepository as __PestDatasets;
|
use Pest\Repositories\DatasetsRepository as __PestDatasets;
|
||||||
use Pest\TestSuite as __PestTestSuite;
|
use Pest\TestSuite as __PestTestSuite;
|
||||||
|
|
||||||
$classAttributesCode
|
$classAttributesCode
|
||||||
#[\AllowDynamicProperties]
|
#[\AllowDynamicProperties]
|
||||||
final class $className extends $baseClass implements $hasPrintableTestCaseClassFQN {
|
final class $className extends $baseClass implements $hasPrintableTestCaseClassFQN {
|
||||||
@ -194,7 +204,9 @@ final class TestCaseFactory
|
|||||||
|
|
||||||
$methodsCode
|
$methodsCode
|
||||||
}
|
}
|
||||||
");
|
PHP;
|
||||||
|
|
||||||
|
eval($classCode);
|
||||||
} catch (ParseError $caught) {
|
} catch (ParseError $caught) {
|
||||||
throw new RuntimeException(sprintf('Unable to create test case for test file at %s', $filename), 1, $caught);
|
throw new RuntimeException(sprintf('Unable to create test case for test file at %s', $filename), 1, $caught);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -91,7 +91,6 @@ final class TestCaseMethodFactory
|
|||||||
|
|
||||||
return function () use ($testCase, $method, $closure): mixed { // @phpstan-ignore-line
|
return function () use ($testCase, $method, $closure): mixed { // @phpstan-ignore-line
|
||||||
/* @var TestCase $this */
|
/* @var TestCase $this */
|
||||||
|
|
||||||
$testCase->proxies->proxy($this);
|
$testCase->proxies->proxy($this);
|
||||||
$method->proxies->proxy($this);
|
$method->proxies->proxy($this);
|
||||||
|
|
||||||
@ -155,21 +154,22 @@ final class TestCaseMethodFactory
|
|||||||
static fn ($attribute) => sprintf("\n %s", $attribute), $attributes,
|
static fn ($attribute) => sprintf("\n %s", $attribute), $attributes,
|
||||||
));
|
));
|
||||||
|
|
||||||
return <<<EOF
|
return <<<PHP
|
||||||
|
|
||||||
/**$annotations
|
/**$annotations
|
||||||
*/
|
*/
|
||||||
$attributes
|
$attributes
|
||||||
public function $methodName()
|
public function $methodName()
|
||||||
{
|
{
|
||||||
|
\$test = \Pest\TestSuite::getInstance()->tests->get(self::\$__filename)->getMethod(\$this->name())->getClosure(\$this);
|
||||||
|
|
||||||
return \$this->__runTest(
|
return \$this->__runTest(
|
||||||
\$this->__test,
|
\$test,
|
||||||
...func_get_args(),
|
...func_get_args(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$datasetsCode
|
$datasetsCode
|
||||||
EOF;
|
PHP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -19,6 +19,20 @@ trait HandleArguments
|
|||||||
return in_array($argument, $arguments, true);
|
return in_array($argument, $arguments, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given argument and value to the list of arguments.
|
||||||
|
*
|
||||||
|
* @param array<int, string> $arguments
|
||||||
|
*
|
||||||
|
* @return array<int, string>
|
||||||
|
*/
|
||||||
|
public function pushArgument(string $argument, array $arguments): array
|
||||||
|
{
|
||||||
|
$arguments[] = $argument;
|
||||||
|
|
||||||
|
return $arguments;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pops the given argument from the arguments.
|
* Pops the given argument from the arguments.
|
||||||
*
|
*
|
||||||
|
|||||||
27
src/Plugins/Printer.php
Normal file
27
src/Plugins/Printer.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Pest\Plugins;
|
||||||
|
|
||||||
|
use Pest\Contracts\Plugins\HandlesArguments;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class Printer implements HandlesArguments
|
||||||
|
{
|
||||||
|
use Concerns\HandleArguments;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function handleArguments(array $arguments): array
|
||||||
|
{
|
||||||
|
if (! array_key_exists('COLLISION_PRINTER', $_SERVER)) {
|
||||||
|
return $arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->pushArgument('--no-output', $arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -57,6 +57,11 @@ final class DatasetsRepository
|
|||||||
self::$withs[$filename . '>>>' . $description] = $with;
|
self::$withs[$filename . '>>>' . $description] = $with;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function has(string $filename, string $description): bool
|
||||||
|
{
|
||||||
|
return array_key_exists($filename . '>>>' . $description, self::$withs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Closure|iterable<int|string, mixed>|never
|
* @return Closure|iterable<int|string, mixed>|never
|
||||||
*
|
*
|
||||||
@ -107,7 +112,7 @@ final class DatasetsRepository
|
|||||||
$values = array_merge($values, $datasetCombinationElement['values']);
|
$values = array_merge($values, $datasetCombinationElement['values']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$datasetDescriptions[] = $description . ' with ' . implode(' / ', $partialDescriptions);
|
$datasetDescriptions[] = implode(' / ', $partialDescriptions);
|
||||||
$datasetValues[] = $values;
|
$datasetValues[] = $values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,7 @@ final class ExceptionTrace
|
|||||||
|
|
||||||
$cleanedTrace = [];
|
$cleanedTrace = [];
|
||||||
foreach ($trace as $item) {
|
foreach ($trace as $item) {
|
||||||
if (key_exists('file', $item) && mb_strpos($item['file'], 'vendor/pestphp/pest/') > 0) {
|
if (array_key_exists('file', $item) && mb_strpos($item['file'], 'vendor/pestphp/pest/') > 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,6 +13,7 @@ abstract class Printer implements \PHPUnit\Util\Printer
|
|||||||
private $stream;
|
private $stream;
|
||||||
|
|
||||||
private bool $isPhpStream;
|
private bool $isPhpStream;
|
||||||
|
|
||||||
private bool $isOpen;
|
private bool $isOpen;
|
||||||
|
|
||||||
private function __construct(string $out)
|
private function __construct(string $out)
|
||||||
|
|||||||
@ -12,11 +12,4 @@ use PHPUnit\Framework\TestCase;
|
|||||||
*/
|
*/
|
||||||
class IgnorableTestCase extends TestCase
|
class IgnorableTestCase extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
*/
|
|
||||||
public function fake(): void
|
|
||||||
{
|
|
||||||
self::markTestIncomplete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,4 @@
|
|||||||
|
|
||||||
PASS Tests\CustomTestCase\ExecutedTest
|
|
||||||
✓ that gets executed
|
|
||||||
|
|
||||||
PASS Tests\Features\AfterAll
|
PASS Tests\Features\AfterAll
|
||||||
✓ deletes file after all
|
✓ deletes file after all
|
||||||
|
|
||||||
@ -23,6 +20,15 @@
|
|||||||
✓ it adds coverage if --min exist
|
✓ it adds coverage if --min exist
|
||||||
✓ it generates coverage based on file input
|
✓ it generates coverage based on file input
|
||||||
|
|
||||||
|
PASS Tests\Features\Covers
|
||||||
|
✓ it uses the correct PHPUnit attribute for class
|
||||||
|
✓ it uses the correct PHPUnit attribute for function
|
||||||
|
✓ it removes duplicated attributes
|
||||||
|
✓ it guesses if the given argument is a class or function
|
||||||
|
✓ it appends CoversNothing to method attributes
|
||||||
|
✓ it does not append CoversNothing to other methods
|
||||||
|
✓ it throws exception if no class nor method has been found
|
||||||
|
|
||||||
PASS Tests\Features\Datasets
|
PASS Tests\Features\Datasets
|
||||||
✓ it throws exception if dataset does not exist
|
✓ it throws exception if dataset does not exist
|
||||||
✓ it throws exception if dataset already exist
|
✓ it throws exception if dataset already exist
|
||||||
@ -111,16 +117,35 @@
|
|||||||
✓ it can correctly resolve a bound dataset that returns an array with (Closure Object (...))
|
✓ it can correctly resolve a bound dataset that returns an array with (Closure Object (...))
|
||||||
✓ it can correctly resolve a bound dataset that returns an array but wants to be spread with (Closure Object (...))
|
✓ it can correctly resolve a bound dataset that returns an array but wants to be spread with (Closure Object (...))
|
||||||
|
|
||||||
|
PASS Tests\Features\Depends
|
||||||
|
✓ first
|
||||||
|
✓ second
|
||||||
|
✓ depends
|
||||||
|
✓ depends with ...params
|
||||||
|
✓ depends with defined arguments
|
||||||
|
✓ depends run test only once
|
||||||
|
✓ it asserts true is true
|
||||||
|
✓ depends works with the correct test name
|
||||||
|
|
||||||
|
PASS Tests\Features\DependsInheritance
|
||||||
|
✓ it is a test
|
||||||
|
✓ it uses correct parent class
|
||||||
|
|
||||||
PASS Tests\Features\Exceptions
|
PASS Tests\Features\Exceptions
|
||||||
✓ it gives access the the underlying expectException
|
✓ it gives access the the underlying expectException
|
||||||
✓ it catch exceptions
|
✓ it catch exceptions
|
||||||
✓ it catch exceptions and messages
|
✓ it catch exceptions and messages
|
||||||
|
✓ it catch exceptions, messages and code
|
||||||
✓ it can just define the message
|
✓ it can just define the message
|
||||||
|
✓ it can just define the code
|
||||||
✓ it not catch exceptions if given condition is false
|
✓ it not catch exceptions if given condition is false
|
||||||
✓ it catch exceptions if given condition is true
|
✓ it catch exceptions if given condition is true
|
||||||
✓ it catch exceptions and messages if given condition is true
|
✓ it catch exceptions and messages if given condition is true
|
||||||
|
✓ it catch exceptions, messages and code if given condition is true
|
||||||
✓ it can just define the message if given condition is true
|
✓ it can just define the message if given condition is true
|
||||||
|
✓ it can just define the code if given condition is true
|
||||||
✓ it can just define the message if given condition is 1
|
✓ it can just define the message if given condition is 1
|
||||||
|
✓ it can just define the code if given condition is 1
|
||||||
|
|
||||||
PASS Tests\Features\Expect\HigherOrder\methods
|
PASS Tests\Features\Expect\HigherOrder\methods
|
||||||
✓ it can access methods
|
✓ it can access methods
|
||||||
@ -133,6 +158,8 @@
|
|||||||
✓ it can compose complex expectations
|
✓ it can compose complex expectations
|
||||||
✓ it can handle nested method calls
|
✓ it can handle nested method calls
|
||||||
✓ it works with higher order tests
|
✓ it works with higher order tests
|
||||||
|
✓ it can use the scoped method to lock into the given level for expectations
|
||||||
|
✓ it works consistently with the json expectation method
|
||||||
|
|
||||||
PASS Tests\Features\Expect\HigherOrder\methodsAndProperties
|
PASS Tests\Features\Expect\HigherOrder\methodsAndProperties
|
||||||
✓ it can access methods and properties
|
✓ it can access methods and properties
|
||||||
@ -140,6 +167,7 @@
|
|||||||
✓ it works with higher order tests
|
✓ it works with higher order tests
|
||||||
✓ it can start a new higher order expectation using the and syntax
|
✓ it can start a new higher order expectation using the and syntax
|
||||||
✓ it can start a new higher order expectation using the and syntax in higher order tests
|
✓ it can start a new higher order expectation using the and syntax in higher order tests
|
||||||
|
✓ it can start a new higher order expectation using the and syntax without nesting expectations
|
||||||
|
|
||||||
PASS Tests\Features\Expect\HigherOrder\properties
|
PASS Tests\Features\Expect\HigherOrder\properties
|
||||||
✓ it allows properties to be accessed from the value
|
✓ it allows properties to be accessed from the value
|
||||||
@ -161,6 +189,7 @@
|
|||||||
✓ chained opposite and non-opposite expectations
|
✓ chained opposite and non-opposite expectations
|
||||||
✓ it can add expectations via "and"
|
✓ it can add expectations via "and"
|
||||||
✓ it accepts callables
|
✓ it accepts callables
|
||||||
|
✓ it passes the key of the current item to callables
|
||||||
|
|
||||||
PASS Tests\Features\Expect\extend
|
PASS Tests\Features\Expect\extend
|
||||||
✓ it macros true is true
|
✓ it macros true is true
|
||||||
@ -186,15 +215,16 @@
|
|||||||
PASS Tests\Features\Expect\not
|
PASS Tests\Features\Expect\not
|
||||||
✓ not property calls
|
✓ not property calls
|
||||||
|
|
||||||
PASS Tests\Features\Expect\pipe
|
PASS Tests\Features\Expect\pipes
|
||||||
✓ pipe is applied and can stop pipeline
|
✓ pipe is applied and can stop pipeline
|
||||||
✓ interceptor works with negated expectation
|
|
||||||
✓ pipe works with negated expectation
|
|
||||||
✓ pipe is run and can let the pipeline keep going
|
✓ pipe is run and can let the pipeline keep going
|
||||||
✓ intercept is applied
|
✓ pipe works with negated expectation
|
||||||
✓ intercept stops the pipeline
|
✓ interceptor is applied
|
||||||
✓ interception is called only when filter is met
|
✓ interceptor stops the pipeline
|
||||||
✓ intercept can be filtered with a closure
|
✓ interceptor is called only when filter is met
|
||||||
|
✓ interceptor can be filtered with a closure
|
||||||
|
✓ interceptor can be filter the expected parameter as well
|
||||||
|
✓ interceptor works with negated expectation
|
||||||
✓ intercept can add new parameters to the expectation
|
✓ intercept can add new parameters to the expectation
|
||||||
|
|
||||||
PASS Tests\Features\Expect\ray
|
PASS Tests\Features\Expect\ray
|
||||||
@ -405,6 +435,11 @@
|
|||||||
✓ not failures with multiple needles (all failing)
|
✓ not failures with multiple needles (all failing)
|
||||||
✓ not failures with multiple needles (some failing)
|
✓ not failures with multiple needles (some failing)
|
||||||
|
|
||||||
|
PASS Tests\Features\Expect\toContainOnlyInstancesOf
|
||||||
|
✓ pass
|
||||||
|
✓ failures
|
||||||
|
✓ not failures
|
||||||
|
|
||||||
PASS Tests\Features\Expect\toEndWith
|
PASS Tests\Features\Expect\toEndWith
|
||||||
✓ pass
|
✓ pass
|
||||||
✓ failures
|
✓ failures
|
||||||
@ -452,8 +487,11 @@
|
|||||||
|
|
||||||
PASS Tests\Features\Expect\toHaveKeys
|
PASS Tests\Features\Expect\toHaveKeys
|
||||||
✓ pass
|
✓ pass
|
||||||
|
✓ pass with multi-dimensional arrays
|
||||||
✓ failures
|
✓ failures
|
||||||
|
✓ failures with multi-dimensional arrays
|
||||||
✓ not failures
|
✓ not failures
|
||||||
|
✓ not failures with multi-dimensional arrays
|
||||||
|
|
||||||
PASS Tests\Features\Expect\toHaveLength
|
PASS Tests\Features\Expect\toHaveLength
|
||||||
✓ it passes with ('Fortaleza')
|
✓ it passes with ('Fortaleza')
|
||||||
@ -496,6 +534,7 @@
|
|||||||
|
|
||||||
PASS Tests\Features\Expect\toMatchObject
|
PASS Tests\Features\Expect\toMatchObject
|
||||||
✓ pass
|
✓ pass
|
||||||
|
✓ pass with class
|
||||||
✓ failures
|
✓ failures
|
||||||
✓ not failures
|
✓ not failures
|
||||||
|
|
||||||
@ -516,6 +555,8 @@
|
|||||||
✓ not failures
|
✓ not failures
|
||||||
✓ closure missing parameter
|
✓ closure missing parameter
|
||||||
✓ closure missing type-hint
|
✓ closure missing type-hint
|
||||||
|
✓ it can handle a non-defined exception
|
||||||
|
✓ it can handle a class not found Error
|
||||||
|
|
||||||
PASS Tests\Features\Expect\unless
|
PASS Tests\Features\Expect\unless
|
||||||
✓ it pass
|
✓ it pass
|
||||||
@ -548,9 +589,9 @@
|
|||||||
✓ it is capable doing multiple assertions
|
✓ it is capable doing multiple assertions
|
||||||
✓ it resolves expect callables correctly
|
✓ it resolves expect callables correctly
|
||||||
✓ does not treat method names as callables
|
✓ does not treat method names as callables
|
||||||
✓ it can tap into the test
|
✓ it can defer a method until after test setup
|
||||||
✓ it can pass datasets into the expect callables with (1, 2, 3)
|
✓ it can pass datasets into the expect callables with (1, 2, 3)
|
||||||
✓ it can pass datasets into the tap callable with (1, 2, 3)
|
✓ it can pass datasets into the defer callable with (1, 2, 3)
|
||||||
✓ it can pass shared datasets into callables with (1)
|
✓ it can pass shared datasets into callables with (1)
|
||||||
✓ it can pass shared datasets into callables with (2)
|
✓ it can pass shared datasets into callables with (2)
|
||||||
|
|
||||||
@ -578,7 +619,7 @@
|
|||||||
|
|
||||||
WARN Tests\Features\Skip
|
WARN Tests\Features\Skip
|
||||||
✓ it do not skips
|
✓ it do not skips
|
||||||
- it skips with truthy
|
- it skips with truthy → 1
|
||||||
- it skips with truthy condition by default
|
- it skips with truthy condition by default
|
||||||
- it skips with message → skipped because bar
|
- it skips with message → skipped because bar
|
||||||
- it skips with truthy closure condition
|
- it skips with truthy closure condition
|
||||||
@ -592,6 +633,10 @@
|
|||||||
✓ a test
|
✓ a test
|
||||||
✓ higher order message test
|
✓ higher order message test
|
||||||
|
|
||||||
|
PASS Tests\Features\ThrowsNoExceptions
|
||||||
|
✓ it allows access to the underlying expectNotToPerformAssertions method
|
||||||
|
✓ it allows performing no expectations without being risky
|
||||||
|
|
||||||
PASS Tests\Fixtures\DirectoryWithTests\ExampleTest
|
PASS Tests\Fixtures\DirectoryWithTests\ExampleTest
|
||||||
✓ it example 1
|
✓ it example 1
|
||||||
|
|
||||||
@ -618,14 +663,14 @@
|
|||||||
PASS Tests\PHPUnit\CustomAffixes\ATestWithSpaces
|
PASS Tests\PHPUnit\CustomAffixes\ATestWithSpaces
|
||||||
✓ it runs file names like `A Test With Spaces.php`
|
✓ it runs file names like `A Test With Spaces.php`
|
||||||
|
|
||||||
PASS Tests\PHPUnit\CustomAffixes\AdditionalFileExtensionspec
|
PASS Tests\PHPUnit\CustomAffixes\AdditionalFileExtension
|
||||||
✓ it runs file names like `AdditionalFileExtension.spec.php`
|
✓ it runs file names like `AdditionalFileExtension.spec.php`
|
||||||
|
|
||||||
PASS Tests\PHPUnit\CustomAffixes\FolderWithAn\ExampleTest
|
PASS Tests\PHPUnit\CustomAffixes\FolderWithAn\ExampleTest
|
||||||
✓ custom traits can be used
|
✓ custom traits can be used
|
||||||
✓ trait applied in this file
|
✓ trait applied in this file
|
||||||
|
|
||||||
PASS Tests\PHPUnit\CustomAffixes\ManyExtensionsclasstest
|
PASS Tests\PHPUnit\CustomAffixes\ManyExtensions
|
||||||
✓ it runs file names like `ManyExtensions.class.test.php`
|
✓ it runs file names like `ManyExtensions.class.test.php`
|
||||||
|
|
||||||
PASS Tests\PHPUnit\CustomAffixes\TestCaseWithQuotes
|
PASS Tests\PHPUnit\CustomAffixes\TestCaseWithQuotes
|
||||||
@ -654,18 +699,14 @@
|
|||||||
✓ it allows global uses
|
✓ it allows global uses
|
||||||
✓ it allows multiple global uses registered in the same path
|
✓ it allows multiple global uses registered in the same path
|
||||||
|
|
||||||
PASS Tests\Unit\Actions\AddsDefaults
|
WARN Tests\Unit\ConfigLoader
|
||||||
✓ it sets defaults
|
✓ it fallbacks to default path if no phpunit file is found
|
||||||
✓ it does not override options
|
- it fallbacks to default path if phpunit is not a valid XML
|
||||||
|
- it fallbacks to default path if failing to read phpunit content
|
||||||
PASS Tests\Unit\Actions\AddsTests
|
- it fallbacks to default path if there is no test suites directory
|
||||||
✓ default php unit tests
|
- it fallbacks to default path if test suite directory has no value
|
||||||
✓ it removes warnings
|
- it fallbacks to default path if test suite directory does not exist
|
||||||
|
- it returns the parent folder of first test suite directory
|
||||||
PASS Tests\Unit\Actions\ValidatesConfiguration
|
|
||||||
✓ it throws exception when configuration not found
|
|
||||||
✓ it throws exception when `process isolation` is true
|
|
||||||
✓ it do not throws exception when `process isolation` is false
|
|
||||||
|
|
||||||
PASS Tests\Unit\Console\Help
|
PASS Tests\Unit\Console\Help
|
||||||
✓ it outputs the help information when --help is used
|
✓ it outputs the help information when --help is used
|
||||||
@ -681,6 +722,9 @@
|
|||||||
✓ environment is set to CI when --ci option is used
|
✓ environment is set to CI when --ci option is used
|
||||||
✓ environment is set to Local when --ci option is not used
|
✓ environment is set to Local when --ci option is not used
|
||||||
|
|
||||||
|
PASS Tests\Unit\Plugins\Retry
|
||||||
|
✓ it retries if --retry argument is used
|
||||||
|
|
||||||
PASS Tests\Unit\Plugins\Version
|
PASS Tests\Unit\Plugins\Version
|
||||||
✓ it outputs the version when --version is used
|
✓ it outputs the version when --version is used
|
||||||
✓ it do not outputs version when --version is not used
|
✓ it do not outputs version when --version is not used
|
||||||
@ -708,37 +752,66 @@
|
|||||||
✓ it can filter the test suite filenames to those with the only method
|
✓ it can filter the test suite filenames to those with the only method
|
||||||
✓ it does not filter the test suite filenames to those with the only method when working in CI pipeline
|
✓ it does not filter the test suite filenames to those with the only method when working in CI pipeline
|
||||||
|
|
||||||
PASS Tests\Visual\Help
|
WARN Tests\Visual\Help
|
||||||
✓ visual snapshot of help command output
|
- visual snapshot of help command output → Not supported yet.
|
||||||
|
|
||||||
PASS Tests\Visual\JUnit
|
WARN Tests\Visual\JUnit
|
||||||
✓ it is can successfully call all public methods
|
- it is can successfully call all public methods → Not supported yet.
|
||||||
|
|
||||||
PASS Tests\Visual\SingleTestOrDirectory
|
FAIL Tests\Visual\SingleTestOrDirectory
|
||||||
✓ allows to run a single test
|
✓ allows to run a single test
|
||||||
✓ allows to run a directory
|
✓ allows to run a directory
|
||||||
✓ it has ascii chars
|
⨯ it has ascii chars
|
||||||
✓ it disable decorating printer when colors is set to never
|
✓ it disable decorating printer when colors is set to never
|
||||||
|
|
||||||
WARN Tests\Visual\Success
|
WARN Tests\Visual\Success
|
||||||
- visual snapshot of test suite on success
|
- visual snapshot of test suite on success
|
||||||
|
|
||||||
PASS Tests\Visual\TeamCity
|
WARN Tests\Visual\TeamCity
|
||||||
✓ it is can successfully call all public methods
|
- it is can successfully call all public methods → Not supported yet.
|
||||||
|
|
||||||
PASS Tests\Features\Depends
|
PHPUnit\Framework\ExpectationFailedException
|
||||||
✓ first
|
|
||||||
✓ second
|
|
||||||
✓ it asserts true is true
|
|
||||||
✓ depends
|
|
||||||
✓ depends with ...params
|
|
||||||
✓ depends with defined arguments
|
|
||||||
✓ depends run test only once
|
|
||||||
✓ depends works with the correct test name
|
|
||||||
|
|
||||||
PASS Tests\Features\DependsInheritance
|
Failed asserting that '\n
|
||||||
✓ it is a test
|
PASS Tests\Fixtures\DirectoryWithTests\ExampleTest\n
|
||||||
✓ it uses correct parent class
|
✓ it example 1\n
|
||||||
|
\n
|
||||||
|
Tests: 1 passed\n
|
||||||
|
Time: 0.00s\n
|
||||||
|
\n
|
||||||
|
' contains "
|
||||||
|
PASS Tests\Fixtures\DirectoryWithTests\ExampleTest
|
||||||
|
✓ it example 1
|
||||||
|
|
||||||
Tests: 4 incompleted, 9 skipped, 487 passed
|
Tests: 1 passed
|
||||||
|
".
|
||||||
|
|
||||||
|
/Users/nunomaduro/Work/Code/pest/src/Mixins/Expectation.php:181
|
||||||
|
/Users/nunomaduro/Work/Code/pest/src/Support/ExpectationPipeline.php:80
|
||||||
|
/Users/nunomaduro/Work/Code/pest/src/Support/ExpectationPipeline.php:84
|
||||||
|
/Users/nunomaduro/Work/Code/pest/src/Expectation.php:297
|
||||||
|
/Users/nunomaduro/Work/Code/pest/tests/Visual/SingleTestOrDirectory.php:32
|
||||||
|
/Users/nunomaduro/Work/Code/pest/src/Factories/TestCaseMethodFactory.php:101
|
||||||
|
/Users/nunomaduro/Work/Code/pest/src/Concerns/Testable.php:251
|
||||||
|
/Users/nunomaduro/Work/Code/pest/src/Support/ExceptionTrace.php:29
|
||||||
|
/Users/nunomaduro/Work/Code/pest/src/Concerns/Testable.php:251
|
||||||
|
/Users/nunomaduro/Work/Code/pest/src/Concerns/Testable.php:205
|
||||||
|
/Users/nunomaduro/Work/Code/pest/src/Kernel.php:57
|
||||||
|
|
||||||
|
at src/Mixins/Expectation.php:181
|
||||||
|
177▕ {
|
||||||
|
178▕ foreach ($needles as $needle) {
|
||||||
|
179▕ if (is_string($this->value)) {
|
||||||
|
180▕ // @phpstan-ignore-next-line
|
||||||
|
➜ 181▕ Assert::assertStringContainsString((string) $needle, $this->value);
|
||||||
|
182▕ } else {
|
||||||
|
183▕ if (!is_iterable($this->value)) {
|
||||||
|
184▕ InvalidExpectationValue::expected('iterable');
|
||||||
|
185▕ }
|
||||||
|
|
||||||
|
1 src/Mixins/Expectation.php:181
|
||||||
|
2 src/Support/ExpectationPipeline.php:80
|
||||||
|
|
||||||
|
|
||||||
|
Tests: 1 failed, 4 incompleted, 18 skipped, 514 passed, 8 pending
|
||||||
|
|
||||||
@ -1,11 +1,19 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
dataset('bound.closure', function () {
|
dataset('bound.closure', function () {
|
||||||
yield function () { return 1; };
|
yield function () {
|
||||||
yield function () { return 2; };
|
return 1;
|
||||||
|
};
|
||||||
|
yield function () {
|
||||||
|
return 2;
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
dataset('bound.array', [
|
dataset('bound.array', [
|
||||||
function () { return 1; },
|
function () {
|
||||||
function () { return 2; },
|
return 1;
|
||||||
|
},
|
||||||
|
function () {
|
||||||
|
return 2;
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -9,7 +9,6 @@ it('has plugin')->assertTrue(class_exists(CoveragePlugin::class));
|
|||||||
|
|
||||||
it('adds coverage if --coverage exist', function () {
|
it('adds coverage if --coverage exist', function () {
|
||||||
$plugin = new CoveragePlugin(new ConsoleOutput());
|
$plugin = new CoveragePlugin(new ConsoleOutput());
|
||||||
$testSuite = TestSuite::getInstance();
|
|
||||||
|
|
||||||
expect($plugin->coverage)->toBeFalse();
|
expect($plugin->coverage)->toBeFalse();
|
||||||
$arguments = $plugin->handleArguments([]);
|
$arguments = $plugin->handleArguments([]);
|
||||||
|
|||||||
@ -28,23 +28,23 @@ it('sets closures', function () {
|
|||||||
yield [1];
|
yield [1];
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(DatasetsRepository::resolve('foo', ['foo']))->toBe(['foo with (1)' => [1]]);
|
expect(DatasetsRepository::resolve('foo', ['foo']))->toBe(['(1)' => [1]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets arrays', function () {
|
it('sets arrays', function () {
|
||||||
DatasetsRepository::set('bar', [[2]]);
|
DatasetsRepository::set('bar', [[2]]);
|
||||||
|
|
||||||
expect(DatasetsRepository::resolve('bar', ['bar']))->toBe(['bar with (2)' => [2]]);
|
expect(DatasetsRepository::resolve('bar', ['bar']))->toBe(['(2)' => [2]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('gets bound to test case object', function () {
|
it('gets bound to test case object', function ($value) {
|
||||||
$this->assertTrue(true);
|
$this->assertTrue(true);
|
||||||
})->with([['a'], ['b']]);
|
})->with([['a'], ['b']]);
|
||||||
|
|
||||||
test('it truncates the description', function () {
|
test('it truncates the description', function () {
|
||||||
expect(true)->toBe(true);
|
expect(true)->toBe(true);
|
||||||
// it gets tested by the integration test
|
// it gets tested by the integration test
|
||||||
})->with([str_repeat('Fooo', 10000000)]);
|
})->with([str_repeat('Fooo', 10)]);
|
||||||
|
|
||||||
$state = new stdClass();
|
$state = new stdClass();
|
||||||
$state->text = '';
|
$state->text = '';
|
||||||
@ -233,8 +233,12 @@ test('more than two datasets did the job right', function () use ($state) {
|
|||||||
it('can resolve a dataset after the test case is available', function ($result) {
|
it('can resolve a dataset after the test case is available', function ($result) {
|
||||||
expect($result)->toBe('bar');
|
expect($result)->toBe('bar');
|
||||||
})->with([
|
})->with([
|
||||||
function () { return $this->foo; },
|
function () {
|
||||||
[function () { return $this->foo; }],
|
return $this->foo;
|
||||||
|
},
|
||||||
|
[function () {
|
||||||
|
return $this->foo;
|
||||||
|
}],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
it('can resolve a dataset after the test case is available with shared yield sets', function ($result) {
|
it('can resolve a dataset after the test case is available with shared yield sets', function ($result) {
|
||||||
@ -249,38 +253,54 @@ it('resolves a potential bound dataset logically', function ($foo, $bar) {
|
|||||||
expect($foo)->toBe('foo');
|
expect($foo)->toBe('foo');
|
||||||
expect($bar())->toBe('bar');
|
expect($bar())->toBe('bar');
|
||||||
})->with([
|
})->with([
|
||||||
['foo', function () { return 'bar'; }], // This should be passed as a closure because we've passed multiple arguments
|
['foo', function () {
|
||||||
|
return 'bar';
|
||||||
|
}], // This should be passed as a closure because we've passed multiple arguments
|
||||||
]);
|
]);
|
||||||
|
|
||||||
it('resolves a potential bound dataset logically even when the closure comes first', function ($foo, $bar) {
|
it('resolves a potential bound dataset logically even when the closure comes first', function ($foo, $bar) {
|
||||||
expect($foo())->toBe('foo');
|
expect($foo())->toBe('foo');
|
||||||
expect($bar)->toBe('bar');
|
expect($bar)->toBe('bar');
|
||||||
})->with([
|
})->with([
|
||||||
[function () { return 'foo'; }, 'bar'], // This should be passed as a closure because we've passed multiple arguments
|
[function () {
|
||||||
|
return 'foo';
|
||||||
|
}, 'bar'], // This should be passed as a closure because we've passed multiple arguments
|
||||||
]);
|
]);
|
||||||
|
|
||||||
it('will not resolve a closure if it is type hinted as a closure', function (Closure $data) {
|
it('will not resolve a closure if it is type hinted as a closure', function (Closure $data) {
|
||||||
expect($data())->toBeString();
|
expect($data())->toBeString();
|
||||||
})->with([
|
})->with([
|
||||||
function () { return 'foo'; },
|
function () {
|
||||||
function () { return 'bar'; },
|
return 'foo';
|
||||||
|
},
|
||||||
|
function () {
|
||||||
|
return 'bar';
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
it('will not resolve a closure if it is type hinted as a callable', function (callable $data) {
|
it('will not resolve a closure if it is type hinted as a callable', function (callable $data) {
|
||||||
expect($data())->toBeString();
|
expect($data())->toBeString();
|
||||||
})->with([
|
})->with([
|
||||||
function () { return 'foo'; },
|
function () {
|
||||||
function () { return 'bar'; },
|
return 'foo';
|
||||||
|
},
|
||||||
|
function () {
|
||||||
|
return 'bar';
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
it('can correctly resolve a bound dataset that returns an array', function (array $data) {
|
it('can correctly resolve a bound dataset that returns an array', function (array $data) {
|
||||||
expect($data)->toBe(['foo', 'bar', 'baz']);
|
expect($data)->toBe(['foo', 'bar', 'baz']);
|
||||||
})->with([
|
})->with([
|
||||||
function () { return ['foo', 'bar', 'baz']; },
|
function () {
|
||||||
|
return ['foo', 'bar', 'baz'];
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
it('can correctly resolve a bound dataset that returns an array but wants to be spread', function (string $foo, string $bar, string $baz) {
|
it('can correctly resolve a bound dataset that returns an array but wants to be spread', function (string $foo, string $bar, string $baz) {
|
||||||
expect([$foo, $bar, $baz])->toBe(['foo', 'bar', 'baz']);
|
expect([$foo, $bar, $baz])->toBe(['foo', 'bar', 'baz']);
|
||||||
})->with([
|
})->with([
|
||||||
function () { return ['foo', 'bar', 'baz']; },
|
function () {
|
||||||
|
return ['foo', 'bar', 'baz'];
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -32,7 +32,9 @@ it('not catch exceptions if given condition is false', function () {
|
|||||||
|
|
||||||
it('catch exceptions if given condition is true', function () {
|
it('catch exceptions if given condition is true', function () {
|
||||||
throw new Exception('Something bad happened');
|
throw new Exception('Something bad happened');
|
||||||
})->throwsIf(function () { return true; }, Exception::class);
|
})->throwsIf(function () {
|
||||||
|
return true;
|
||||||
|
}, Exception::class);
|
||||||
|
|
||||||
it('catch exceptions and messages if given condition is true', function () {
|
it('catch exceptions and messages if given condition is true', function () {
|
||||||
throw new Exception('Something bad happened');
|
throw new Exception('Something bad happened');
|
||||||
|
|||||||
@ -40,8 +40,12 @@ it('works inside of each', function () {
|
|||||||
it('works with sequence', function () {
|
it('works with sequence', function () {
|
||||||
expect(new HasMethods())
|
expect(new HasMethods())
|
||||||
->books()->sequence(
|
->books()->sequence(
|
||||||
function ($book) { $book->title->toEqual('Foo')->cost->toEqual(20); },
|
function ($book) {
|
||||||
function ($book) { $book->title->toEqual('Bar')->cost->toEqual(30); },
|
$book->title->toEqual('Foo')->cost->toEqual(20);
|
||||||
|
},
|
||||||
|
function ($book) {
|
||||||
|
$book->title->toEqual('Bar')->cost->toEqual(30);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -54,8 +58,12 @@ it('can compose complex expectations', function () {
|
|||||||
->attributes()->toBeArray()
|
->attributes()->toBeArray()
|
||||||
->books()->toBeArray->each->not->toBeEmpty
|
->books()->toBeArray->each->not->toBeEmpty
|
||||||
->books()->sequence(
|
->books()->sequence(
|
||||||
function ($book) { $book->title->toEqual('Foo')->cost->toEqual(20); },
|
function ($book) {
|
||||||
function ($book) { $book->title->toEqual('Bar')->cost->toEqual(30); },
|
$book->title->toEqual('Foo')->cost->toEqual(20);
|
||||||
|
},
|
||||||
|
function ($book) {
|
||||||
|
$book->title->toEqual('Bar')->cost->toEqual(30);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -9,8 +9,12 @@ it('can access methods and properties', function () {
|
|||||||
})->books()->toBeArray()
|
})->books()->toBeArray()
|
||||||
->posts->toBeArray->each->not->toBeEmpty
|
->posts->toBeArray->each->not->toBeEmpty
|
||||||
->books()->sequence(
|
->books()->sequence(
|
||||||
function ($book) { $book->title->toEqual('Foo')->cost->toEqual(20); },
|
function ($book) {
|
||||||
function ($book) { $book->title->toEqual('Bar')->cost->toEqual(30); },
|
$book->title->toEqual('Foo')->cost->toEqual(20);
|
||||||
|
},
|
||||||
|
function ($book) {
|
||||||
|
$book->title->toEqual('Bar')->cost->toEqual(30);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -53,7 +57,9 @@ it('can start a new higher order expectation using the and syntax without nestin
|
|||||||
->toBeInstanceOf(HasMethodsAndProperties::class)
|
->toBeInstanceOf(HasMethodsAndProperties::class)
|
||||||
->meta
|
->meta
|
||||||
->sequence(
|
->sequence(
|
||||||
function ($value, $key) { $value->toBeArray()->and($key)->toBe('foo'); },
|
function ($value, $key) {
|
||||||
|
$value->toBeArray()->and($key)->toBe('foo');
|
||||||
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -35,8 +35,12 @@ it('works inside of each', function () {
|
|||||||
it('works with sequence', function () {
|
it('works with sequence', function () {
|
||||||
expect(['books' => [['title' => 'Foo', 'cost' => 20], ['title' => 'Bar', 'cost' => 30]]])
|
expect(['books' => [['title' => 'Foo', 'cost' => 20], ['title' => 'Bar', 'cost' => 30]]])
|
||||||
->books->sequence(
|
->books->sequence(
|
||||||
function ($book) { $book->title->toEqual('Foo')->cost->toEqual(20); },
|
function ($book) {
|
||||||
function ($book) { $book->title->toEqual('Bar')->cost->toEqual(30); },
|
$book->title->toEqual('Foo')->cost->toEqual(20);
|
||||||
|
},
|
||||||
|
function ($book) {
|
||||||
|
$book->title->toEqual('Bar')->cost->toEqual(30);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -51,10 +55,16 @@ it('can compose complex expectations', function () {
|
|||||||
it('works with objects', function () {
|
it('works with objects', function () {
|
||||||
expect(new HasProperties())
|
expect(new HasProperties())
|
||||||
->name->toEqual('foo')->not->toEqual('world')
|
->name->toEqual('foo')->not->toEqual('world')
|
||||||
->posts->toHaveCount(2)->each(function ($post) { $post->is_published->toBeTrue(); })
|
->posts->toHaveCount(2)->each(function ($post) {
|
||||||
|
$post->is_published->toBeTrue();
|
||||||
|
})
|
||||||
->posts->sequence(
|
->posts->sequence(
|
||||||
function ($post) { $post->title->toEqual('Foo'); },
|
function ($post) {
|
||||||
function ($post) { $post->title->toEqual('Bar'); },
|
$post->title->toEqual('Foo');
|
||||||
|
},
|
||||||
|
function ($post) {
|
||||||
|
$post->title->toEqual('Bar');
|
||||||
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -82,7 +82,9 @@ it('runs with falsy', function () {
|
|||||||
it('runs with truthy closure condition', function () {
|
it('runs with truthy closure condition', function () {
|
||||||
expect('foo')
|
expect('foo')
|
||||||
->match(
|
->match(
|
||||||
function () { return '1'; }, [
|
function () {
|
||||||
|
return '1';
|
||||||
|
}, [
|
||||||
'bar' => function ($value) {
|
'bar' => function ($value) {
|
||||||
$this->matched = 'bar';
|
$this->matched = 'bar';
|
||||||
|
|
||||||
@ -103,7 +105,9 @@ it('runs with truthy closure condition', function () {
|
|||||||
it('runs with falsy closure condition', function () {
|
it('runs with falsy closure condition', function () {
|
||||||
expect('foo')
|
expect('foo')
|
||||||
->match(
|
->match(
|
||||||
function () { return '0'; }, [
|
function () {
|
||||||
|
return '0';
|
||||||
|
}, [
|
||||||
'bar' => function ($value) {
|
'bar' => function ($value) {
|
||||||
$this->matched = 'bar';
|
$this->matched = 'bar';
|
||||||
|
|
||||||
@ -137,7 +141,9 @@ it('fails with unhandled match', function () {
|
|||||||
it('can be used in higher order tests')
|
it('can be used in higher order tests')
|
||||||
->expect(true)
|
->expect(true)
|
||||||
->match(
|
->match(
|
||||||
function () { return true; }, [
|
function () {
|
||||||
|
return true;
|
||||||
|
}, [
|
||||||
false => function ($value) {
|
false => function ($value) {
|
||||||
return $value->toBeFalse();
|
return $value->toBeFalse();
|
||||||
},
|
},
|
||||||
|
|||||||
@ -37,6 +37,7 @@ class Symbol
|
|||||||
class State
|
class State
|
||||||
{
|
{
|
||||||
public array $runCount = [];
|
public array $runCount = [];
|
||||||
|
|
||||||
public array $appliedCount = [];
|
public array $appliedCount = [];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
|
|||||||
@ -9,9 +9,15 @@ test('an exception is thrown if the the type is not iterable', function () {
|
|||||||
test('allows for sequences of checks to be run on iterable data', function () {
|
test('allows for sequences of checks to be run on iterable data', function () {
|
||||||
expect([1, 2, 3])
|
expect([1, 2, 3])
|
||||||
->sequence(
|
->sequence(
|
||||||
function ($expectation) { $expectation->toBeInt()->toEqual(1); },
|
function ($expectation) {
|
||||||
function ($expectation) { $expectation->toBeInt()->toEqual(2); },
|
$expectation->toBeInt()->toEqual(1);
|
||||||
function ($expectation) { $expectation->toBeInt()->toEqual(3); },
|
},
|
||||||
|
function ($expectation) {
|
||||||
|
$expectation->toBeInt()->toEqual(2);
|
||||||
|
},
|
||||||
|
function ($expectation) {
|
||||||
|
$expectation->toBeInt()->toEqual(3);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(static::getCount())->toBe(6);
|
expect(static::getCount())->toBe(6);
|
||||||
@ -20,9 +26,15 @@ test('allows for sequences of checks to be run on iterable data', function () {
|
|||||||
test('loops back to the start if it runs out of sequence items', function () {
|
test('loops back to the start if it runs out of sequence items', function () {
|
||||||
expect([1, 2, 3, 1, 2, 3, 1, 2])
|
expect([1, 2, 3, 1, 2, 3, 1, 2])
|
||||||
->sequence(
|
->sequence(
|
||||||
function ($expectation) { $expectation->toBeInt()->toEqual(1); },
|
function ($expectation) {
|
||||||
function ($expectation) { $expectation->toBeInt()->toEqual(2); },
|
$expectation->toBeInt()->toEqual(1);
|
||||||
function ($expectation) { $expectation->toBeInt()->toEqual(3); },
|
},
|
||||||
|
function ($expectation) {
|
||||||
|
$expectation->toBeInt()->toEqual(2);
|
||||||
|
},
|
||||||
|
function ($expectation) {
|
||||||
|
$expectation->toBeInt()->toEqual(3);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(static::getCount())->toBe(16);
|
expect(static::getCount())->toBe(16);
|
||||||
@ -31,9 +43,15 @@ test('loops back to the start if it runs out of sequence items', function () {
|
|||||||
test('fails if the number of iterable items is greater than the number of expectations', function () {
|
test('fails if the number of iterable items is greater than the number of expectations', function () {
|
||||||
expect([1, 2])
|
expect([1, 2])
|
||||||
->sequence(
|
->sequence(
|
||||||
function ($expectation) { $expectation->toBeInt()->toEqual(1); },
|
function ($expectation) {
|
||||||
function ($expectation) { $expectation->toBeInt()->toEqual(2); },
|
$expectation->toBeInt()->toEqual(1);
|
||||||
function ($expectation) { $expectation->toBeInt()->toEqual(3); },
|
},
|
||||||
|
function ($expectation) {
|
||||||
|
$expectation->toBeInt()->toEqual(2);
|
||||||
|
},
|
||||||
|
function ($expectation) {
|
||||||
|
$expectation->toBeInt()->toEqual(3);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
})->throws(ExpectationFailedException::class);
|
})->throws(ExpectationFailedException::class);
|
||||||
|
|
||||||
@ -60,7 +78,9 @@ test('it can be passed non-callable values', function () {
|
|||||||
test('it can be passed a mixture of value types', function () {
|
test('it can be passed a mixture of value types', function () {
|
||||||
expect(['foo', 'bar', 'baz'])->sequence(
|
expect(['foo', 'bar', 'baz'])->sequence(
|
||||||
'foo',
|
'foo',
|
||||||
function ($expectation) { $expectation->toEqual('bar')->toBeString(); },
|
function ($expectation) {
|
||||||
|
$expectation->toEqual('bar')->toBeString();
|
||||||
|
},
|
||||||
'baz'
|
'baz'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,8 @@
|
|||||||
use PHPUnit\Framework\ExpectationFailedException;
|
use PHPUnit\Framework\ExpectationFailedException;
|
||||||
|
|
||||||
test('pass', function () {
|
test('pass', function () {
|
||||||
expect(function () {})->toBeCallable();
|
expect(function () {
|
||||||
|
})->toBeCallable();
|
||||||
expect(null)->not->toBeCallable();
|
expect(null)->not->toBeCallable();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -14,5 +15,7 @@ test('failures', function () {
|
|||||||
})->throws(ExpectationFailedException::class);
|
})->throws(ExpectationFailedException::class);
|
||||||
|
|
||||||
test('not failures', function () {
|
test('not failures', function () {
|
||||||
expect(function () { return 42; })->not->toBeCallable();
|
expect(function () {
|
||||||
|
return 42;
|
||||||
|
})->not->toBeCallable();
|
||||||
})->throws(ExpectationFailedException::class);
|
})->throws(ExpectationFailedException::class);
|
||||||
|
|||||||
@ -20,6 +20,7 @@ test('pass', function () {
|
|||||||
test('pass with class', function () {
|
test('pass with class', function () {
|
||||||
expect(new class() {
|
expect(new class() {
|
||||||
public $name = 'Nuno';
|
public $name = 'Nuno';
|
||||||
|
|
||||||
public $email = 'enunomaduro@gmail.com';
|
public $email = 'enunomaduro@gmail.com';
|
||||||
})->toMatchObject([
|
})->toMatchObject([
|
||||||
'name' => 'Nuno',
|
'name' => 'Nuno',
|
||||||
|
|||||||
@ -3,60 +3,98 @@
|
|||||||
use PHPUnit\Framework\ExpectationFailedException;
|
use PHPUnit\Framework\ExpectationFailedException;
|
||||||
|
|
||||||
test('passes', function () {
|
test('passes', function () {
|
||||||
expect(function () { throw new RuntimeException(); })->toThrow(RuntimeException::class);
|
expect(function () {
|
||||||
expect(function () { throw new RuntimeException(); })->toThrow(Exception::class);
|
throw new RuntimeException();
|
||||||
expect(function () { throw new RuntimeException(); })->toThrow(function (RuntimeException $e) {});
|
})->toThrow(RuntimeException::class);
|
||||||
expect(function () { throw new RuntimeException('actual message'); })->toThrow(function (Exception $e) {
|
expect(function () {
|
||||||
|
throw new RuntimeException();
|
||||||
|
})->toThrow(Exception::class);
|
||||||
|
expect(function () {
|
||||||
|
throw new RuntimeException();
|
||||||
|
})->toThrow(function (RuntimeException $e) {
|
||||||
|
});
|
||||||
|
expect(function () {
|
||||||
|
throw new RuntimeException('actual message');
|
||||||
|
})->toThrow(function (Exception $e) {
|
||||||
expect($e->getMessage())->toBe('actual message');
|
expect($e->getMessage())->toBe('actual message');
|
||||||
});
|
});
|
||||||
expect(function () {})->not->toThrow(Exception::class);
|
expect(function () {
|
||||||
expect(function () { throw new RuntimeException('actual message'); })->toThrow('actual message');
|
})->not->toThrow(Exception::class);
|
||||||
expect(function () { throw new Exception(); })->not->toThrow(RuntimeException::class);
|
expect(function () {
|
||||||
expect(function () { throw new RuntimeException('actual message'); })->toThrow(RuntimeException::class, 'actual message');
|
throw new RuntimeException('actual message');
|
||||||
expect(function () { throw new RuntimeException('actual message'); })->toThrow(function (RuntimeException $e) {}, 'actual message');
|
})->toThrow('actual message');
|
||||||
|
expect(function () {
|
||||||
|
throw new Exception();
|
||||||
|
})->not->toThrow(RuntimeException::class);
|
||||||
|
expect(function () {
|
||||||
|
throw new RuntimeException('actual message');
|
||||||
|
})->toThrow(RuntimeException::class, 'actual message');
|
||||||
|
expect(function () {
|
||||||
|
throw new RuntimeException('actual message');
|
||||||
|
})->toThrow(function (RuntimeException $e) {
|
||||||
|
}, 'actual message');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('failures 1', function () {
|
test('failures 1', function () {
|
||||||
expect(function () {})->toThrow(RuntimeException::class);
|
expect(function () {
|
||||||
|
})->toThrow(RuntimeException::class);
|
||||||
})->throws(ExpectationFailedException::class, 'Exception "' . RuntimeException::class . '" not thrown.');
|
})->throws(ExpectationFailedException::class, 'Exception "' . RuntimeException::class . '" not thrown.');
|
||||||
|
|
||||||
test('failures 2', function () {
|
test('failures 2', function () {
|
||||||
expect(function () {})->toThrow(function (RuntimeException $e) {});
|
expect(function () {
|
||||||
|
})->toThrow(function (RuntimeException $e) {
|
||||||
|
});
|
||||||
})->throws(ExpectationFailedException::class, 'Exception "' . RuntimeException::class . '" not thrown.');
|
})->throws(ExpectationFailedException::class, 'Exception "' . RuntimeException::class . '" not thrown.');
|
||||||
|
|
||||||
test('failures 3', function () {
|
test('failures 3', function () {
|
||||||
expect(function () { throw new Exception(); })->toThrow(function (RuntimeException $e) {});
|
expect(function () {
|
||||||
|
throw new Exception();
|
||||||
|
})->toThrow(function (RuntimeException $e) {
|
||||||
|
});
|
||||||
})->throws(ExpectationFailedException::class, 'Failed asserting that Exception Object');
|
})->throws(ExpectationFailedException::class, 'Failed asserting that Exception Object');
|
||||||
|
|
||||||
test('failures 4', function () {
|
test('failures 4', function () {
|
||||||
expect(function () { throw new Exception('actual message'); })
|
expect(function () {
|
||||||
|
throw new Exception('actual message');
|
||||||
|
})
|
||||||
->toThrow(function (Exception $e) {
|
->toThrow(function (Exception $e) {
|
||||||
expect($e->getMessage())->toBe('expected message');
|
expect($e->getMessage())->toBe('expected message');
|
||||||
});
|
});
|
||||||
})->throws(ExpectationFailedException::class, 'Failed asserting that two strings are identical');
|
})->throws(ExpectationFailedException::class, 'Failed asserting that two strings are identical');
|
||||||
|
|
||||||
test('failures 5', function () {
|
test('failures 5', function () {
|
||||||
expect(function () { throw new Exception('actual message'); })->toThrow('expected message');
|
expect(function () {
|
||||||
|
throw new Exception('actual message');
|
||||||
|
})->toThrow('expected message');
|
||||||
})->throws(ExpectationFailedException::class, 'Failed asserting that \'actual message\' contains "expected message".');
|
})->throws(ExpectationFailedException::class, 'Failed asserting that \'actual message\' contains "expected message".');
|
||||||
|
|
||||||
test('failures 6', function () {
|
test('failures 6', function () {
|
||||||
expect(function () {})->toThrow('actual message');
|
expect(function () {
|
||||||
|
})->toThrow('actual message');
|
||||||
})->throws(ExpectationFailedException::class, 'Exception with message "actual message" not thrown');
|
})->throws(ExpectationFailedException::class, 'Exception with message "actual message" not thrown');
|
||||||
|
|
||||||
test('failures 7', function () {
|
test('failures 7', function () {
|
||||||
expect(function () { throw new RuntimeException('actual message'); })->toThrow(RuntimeException::class, 'expected message');
|
expect(function () {
|
||||||
|
throw new RuntimeException('actual message');
|
||||||
|
})->toThrow(RuntimeException::class, 'expected message');
|
||||||
})->throws(ExpectationFailedException::class);
|
})->throws(ExpectationFailedException::class);
|
||||||
|
|
||||||
test('not failures', function () {
|
test('not failures', function () {
|
||||||
expect(function () { throw new RuntimeException(); })->not->toThrow(RuntimeException::class);
|
expect(function () {
|
||||||
|
throw new RuntimeException();
|
||||||
|
})->not->toThrow(RuntimeException::class);
|
||||||
})->throws(ExpectationFailedException::class);
|
})->throws(ExpectationFailedException::class);
|
||||||
|
|
||||||
test('closure missing parameter', function () {
|
test('closure missing parameter', function () {
|
||||||
expect(function () {})->toThrow(function () {});
|
expect(function () {
|
||||||
|
})->toThrow(function () {
|
||||||
|
});
|
||||||
})->throws(InvalidArgumentException::class, 'The given closure must have a single parameter type-hinted as the class string.');
|
})->throws(InvalidArgumentException::class, 'The given closure must have a single parameter type-hinted as the class string.');
|
||||||
|
|
||||||
test('closure missing type-hint', function () {
|
test('closure missing type-hint', function () {
|
||||||
expect(function () {})->toThrow(function ($e) {});
|
expect(function () {
|
||||||
|
})->toThrow(function ($e) {
|
||||||
|
});
|
||||||
})->throws(InvalidArgumentException::class, 'The given closure\'s parameter must be type-hinted as the class string.');
|
})->throws(InvalidArgumentException::class, 'The given closure\'s parameter must be type-hinted as the class string.');
|
||||||
|
|
||||||
it('can handle a non-defined exception', function () {
|
it('can handle a non-defined exception', function () {
|
||||||
|
|||||||
@ -67,7 +67,9 @@ it('skips with falsy', function () {
|
|||||||
it('runs with truthy closure condition', function () {
|
it('runs with truthy closure condition', function () {
|
||||||
expect($this->unlessObject)
|
expect($this->unlessObject)
|
||||||
->unless(
|
->unless(
|
||||||
function () { return '0'; },
|
function () {
|
||||||
|
return '0';
|
||||||
|
},
|
||||||
function ($value) {
|
function ($value) {
|
||||||
return $value->trueValue->toBeTrue();
|
return $value->trueValue->toBeTrue();
|
||||||
}
|
}
|
||||||
@ -80,7 +82,9 @@ it('runs with truthy closure condition', function () {
|
|||||||
it('skips with falsy closure condition', function () {
|
it('skips with falsy closure condition', function () {
|
||||||
expect($this->unlessObject)
|
expect($this->unlessObject)
|
||||||
->unless(
|
->unless(
|
||||||
function () { return '1'; },
|
function () {
|
||||||
|
return '1';
|
||||||
|
},
|
||||||
function ($value) {
|
function ($value) {
|
||||||
return $value->trueValue->toBeFalse(); // fails
|
return $value->trueValue->toBeFalse(); // fails
|
||||||
}
|
}
|
||||||
@ -93,7 +97,9 @@ it('skips with falsy closure condition', function () {
|
|||||||
it('can be used in higher order tests')
|
it('can be used in higher order tests')
|
||||||
->expect(true)
|
->expect(true)
|
||||||
->unless(
|
->unless(
|
||||||
function () { return false; },
|
function () {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
function ($value) {
|
function ($value) {
|
||||||
return $value->toBeFalse();
|
return $value->toBeFalse();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -67,7 +67,9 @@ it('skips with falsy', function () {
|
|||||||
it('runs with truthy closure condition', function () {
|
it('runs with truthy closure condition', function () {
|
||||||
expect($this->whenObject)
|
expect($this->whenObject)
|
||||||
->when(
|
->when(
|
||||||
function () { return '1'; },
|
function () {
|
||||||
|
return '1';
|
||||||
|
},
|
||||||
function ($value) {
|
function ($value) {
|
||||||
return $value->trueValue->toBeTrue();
|
return $value->trueValue->toBeTrue();
|
||||||
}
|
}
|
||||||
@ -80,7 +82,9 @@ it('runs with truthy closure condition', function () {
|
|||||||
it('skips with falsy closure condition', function () {
|
it('skips with falsy closure condition', function () {
|
||||||
expect($this->whenObject)
|
expect($this->whenObject)
|
||||||
->when(
|
->when(
|
||||||
function () { return '0'; },
|
function () {
|
||||||
|
return '0';
|
||||||
|
},
|
||||||
function ($value) {
|
function ($value) {
|
||||||
return $value->trueValue->toBeFalse(); // fails
|
return $value->trueValue->toBeFalse(); // fails
|
||||||
}
|
}
|
||||||
@ -93,7 +97,9 @@ it('skips with falsy closure condition', function () {
|
|||||||
it('can be used in higher order tests')
|
it('can be used in higher order tests')
|
||||||
->expect(false)
|
->expect(false)
|
||||||
->when(
|
->when(
|
||||||
function () { return true; },
|
function () {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
function ($value) {
|
function ($value) {
|
||||||
return $value->toBeTrue();
|
return $value->toBeTrue();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,9 @@ it('is capable doing multiple assertions')
|
|||||||
->assertFalse(false);
|
->assertFalse(false);
|
||||||
|
|
||||||
it('resolves expect callables correctly')
|
it('resolves expect callables correctly')
|
||||||
->expect(function () { return 'foo'; })
|
->expect(function () {
|
||||||
|
return 'foo';
|
||||||
|
})
|
||||||
->toBeString()
|
->toBeString()
|
||||||
->toBe('foo')
|
->toBe('foo')
|
||||||
->and('bar')
|
->and('bar')
|
||||||
@ -23,24 +25,38 @@ test('does not treat method names as callables')
|
|||||||
|
|
||||||
it('can defer a method until after test setup')
|
it('can defer a method until after test setup')
|
||||||
->expect('foo')->toBeString()
|
->expect('foo')->toBeString()
|
||||||
->defer(function () { expect($this)->toBeInstanceOf(TestCase::class); })
|
->defer(function () {
|
||||||
|
expect($this)->toBeInstanceOf(TestCase::class);
|
||||||
|
})
|
||||||
->toBe('foo')
|
->toBe('foo')
|
||||||
->and('hello world')->toBeString();
|
->and('hello world')->toBeString();
|
||||||
|
|
||||||
it('can pass datasets into the expect callables')
|
it('can pass datasets into the expect callables')
|
||||||
->with([[1, 2, 3]])
|
->with([[1, 2, 3]])
|
||||||
->expect(function (...$numbers) { return $numbers; })->toBe([1, 2, 3])
|
->expect(function (...$numbers) {
|
||||||
->and(function (...$numbers) { return $numbers; })->toBe([1, 2, 3]);
|
return $numbers;
|
||||||
|
})->toBe([1, 2, 3])
|
||||||
|
->and(function (...$numbers) {
|
||||||
|
return $numbers;
|
||||||
|
})->toBe([1, 2, 3]);
|
||||||
|
|
||||||
it('can pass datasets into the defer callable')
|
it('can pass datasets into the defer callable')
|
||||||
->with([[1, 2, 3]])
|
->with([[1, 2, 3]])
|
||||||
->defer(function (...$numbers) { expect($numbers)->toBe([1, 2, 3]); });
|
->defer(function (...$numbers) {
|
||||||
|
expect($numbers)->toBe([1, 2, 3]);
|
||||||
|
});
|
||||||
|
|
||||||
it('can pass shared datasets into callables')
|
it('can pass shared datasets into callables')
|
||||||
->with('numbers.closure.wrapped')
|
->with('numbers.closure.wrapped')
|
||||||
->expect(function ($value) { return $value; })
|
->expect(function ($value) {
|
||||||
->and(function ($value) { return $value; })
|
return $value;
|
||||||
->defer(function ($value) { expect($value)->toBeInt(); })
|
})
|
||||||
|
->and(function ($value) {
|
||||||
|
return $value;
|
||||||
|
})
|
||||||
|
->defer(function ($value) {
|
||||||
|
expect($value)->toBeInt();
|
||||||
|
})
|
||||||
->toBeInt();
|
->toBeInt();
|
||||||
|
|
||||||
afterEach()->assertTrue(true);
|
afterEach()->assertTrue(true);
|
||||||
|
|||||||
@ -21,11 +21,15 @@ it('skips with message')
|
|||||||
->assertTrue(false);
|
->assertTrue(false);
|
||||||
|
|
||||||
it('skips with truthy closure condition')
|
it('skips with truthy closure condition')
|
||||||
->skip(function () { return '1'; })
|
->skip(function () {
|
||||||
|
return '1';
|
||||||
|
})
|
||||||
->assertTrue(false);
|
->assertTrue(false);
|
||||||
|
|
||||||
it('do not skips with falsy closure condition')
|
it('do not skips with falsy closure condition')
|
||||||
->skip(function () { return false; })
|
->skip(function () {
|
||||||
|
return false;
|
||||||
|
})
|
||||||
->assertTrue(true);
|
->assertTrue(true);
|
||||||
|
|
||||||
it('skips with condition and message')
|
it('skips with condition and message')
|
||||||
@ -37,10 +41,16 @@ it('skips when skip after assertion')
|
|||||||
->skip();
|
->skip();
|
||||||
|
|
||||||
it('can use something in the test case as a condition')
|
it('can use something in the test case as a condition')
|
||||||
->skip(function () { return $this->shouldSkip; }, 'This test was skipped')
|
->skip(function () {
|
||||||
|
return $this->shouldSkip;
|
||||||
|
}, 'This test was skipped')
|
||||||
->assertTrue(false);
|
->assertTrue(false);
|
||||||
|
|
||||||
it('can user higher order callables and skip')
|
it('can user higher order callables and skip')
|
||||||
->skip(function () { return $this->shouldSkip; })
|
->skip(function () {
|
||||||
->expect(function () { return $this->shouldSkip; })
|
return $this->shouldSkip;
|
||||||
|
})
|
||||||
|
->expect(function () {
|
||||||
|
return $this->shouldSkip;
|
||||||
|
})
|
||||||
->toBeFalse();
|
->toBeFalse();
|
||||||
|
|||||||
@ -10,8 +10,8 @@ it('show only the names of named datasets in their description', function () {
|
|||||||
],
|
],
|
||||||
]));
|
]));
|
||||||
|
|
||||||
expect($descriptions[0])->toBe('test description with data set "one"');
|
expect($descriptions[0])->toBe('data set "one"')
|
||||||
expect($descriptions[1])->toBe('test description with data set "two"');
|
->and($descriptions[1])->toBe('data set "two"');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('show the actual dataset of non-named datasets in their description', function () {
|
it('show the actual dataset of non-named datasets in their description', function () {
|
||||||
@ -22,8 +22,8 @@ it('show the actual dataset of non-named datasets in their description', functio
|
|||||||
],
|
],
|
||||||
]));
|
]));
|
||||||
|
|
||||||
expect($descriptions[0])->toBe('test description with (1)');
|
expect($descriptions[0])->toBe('(1)');
|
||||||
expect($descriptions[1])->toBe('test description with (array(2))');
|
expect($descriptions[1])->toBe('(array(2))');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('show only the names of multiple named datasets in their description', function () {
|
it('show only the names of multiple named datasets in their description', function () {
|
||||||
@ -38,10 +38,10 @@ it('show only the names of multiple named datasets in their description', functi
|
|||||||
],
|
],
|
||||||
]));
|
]));
|
||||||
|
|
||||||
expect($descriptions[0])->toBe('test description with data set "one" / data set "three"');
|
expect($descriptions[0])->toBe('data set "one" / data set "three"');
|
||||||
expect($descriptions[1])->toBe('test description with data set "one" / data set "four"');
|
expect($descriptions[1])->toBe('data set "one" / data set "four"');
|
||||||
expect($descriptions[2])->toBe('test description with data set "two" / data set "three"');
|
expect($descriptions[2])->toBe('data set "two" / data set "three"');
|
||||||
expect($descriptions[3])->toBe('test description with data set "two" / data set "four"');
|
expect($descriptions[3])->toBe('data set "two" / data set "four"');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('show the actual dataset of multiple non-named datasets in their description', function () {
|
it('show the actual dataset of multiple non-named datasets in their description', function () {
|
||||||
@ -56,10 +56,10 @@ it('show the actual dataset of multiple non-named datasets in their description'
|
|||||||
],
|
],
|
||||||
]));
|
]));
|
||||||
|
|
||||||
expect($descriptions[0])->toBe('test description with (1) / (3)');
|
expect($descriptions[0])->toBe('(1) / (3)');
|
||||||
expect($descriptions[1])->toBe('test description with (1) / (array(4))');
|
expect($descriptions[1])->toBe('(1) / (array(4))');
|
||||||
expect($descriptions[2])->toBe('test description with (array(2)) / (3)');
|
expect($descriptions[2])->toBe('(array(2)) / (3)');
|
||||||
expect($descriptions[3])->toBe('test description with (array(2)) / (array(4))');
|
expect($descriptions[3])->toBe('(array(2)) / (array(4))');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('show the correct description for mixed named and not-named datasets', function () {
|
it('show the correct description for mixed named and not-named datasets', function () {
|
||||||
@ -74,8 +74,8 @@ it('show the correct description for mixed named and not-named datasets', functi
|
|||||||
],
|
],
|
||||||
]));
|
]));
|
||||||
|
|
||||||
expect($descriptions[0])->toBe('test description with data set "one" / (3)');
|
expect($descriptions[0])->toBe('data set "one" / (3)');
|
||||||
expect($descriptions[1])->toBe('test description with data set "one" / data set "four"');
|
expect($descriptions[1])->toBe('data set "one" / data set "four"');
|
||||||
expect($descriptions[2])->toBe('test description with (array(2)) / (3)');
|
expect($descriptions[2])->toBe('(array(2)) / (3)');
|
||||||
expect($descriptions[3])->toBe('test description with (array(2)) / data set "four"');
|
expect($descriptions[3])->toBe('(array(2)) / data set "four"');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -20,7 +20,8 @@ it('does not allow to add the same test description twice', function () {
|
|||||||
it('alerts users about tests with arguments but no input', function () {
|
it('alerts users about tests with arguments but no input', function () {
|
||||||
$testSuite = new TestSuite(getcwd(), 'tests');
|
$testSuite = new TestSuite(getcwd(), 'tests');
|
||||||
|
|
||||||
$method = new TestCaseMethodFactory('foo', 'bar', function (int $arg) {});
|
$method = new TestCaseMethodFactory('foo', 'bar', function (int $arg) {
|
||||||
|
});
|
||||||
|
|
||||||
$testSuite->tests->set($method);
|
$testSuite->tests->set($method);
|
||||||
})->throws(
|
})->throws(
|
||||||
@ -29,7 +30,7 @@ it('alerts users about tests with arguments but no input', function () {
|
|||||||
);
|
);
|
||||||
|
|
||||||
it('can return an array of all test suite filenames', function () {
|
it('can return an array of all test suite filenames', function () {
|
||||||
$testSuite = TestSuite::getInstance(getcwd(), 'tests');
|
$testSuite = new TestSuite(getcwd(), 'tests');
|
||||||
|
|
||||||
$testSuite->tests->set(new TestCaseMethodFactory('a', 'b', null));
|
$testSuite->tests->set(new TestCaseMethodFactory('a', 'b', null));
|
||||||
$testSuite->tests->set(new TestCaseMethodFactory('c', 'd', null));
|
$testSuite->tests->set(new TestCaseMethodFactory('c', 'd', null));
|
||||||
@ -57,9 +58,10 @@ it('can filter the test suite filenames to those with the only method', function
|
|||||||
it('does not filter the test suite filenames to those with the only method when working in CI pipeline', function () {
|
it('does not filter the test suite filenames to those with the only method when working in CI pipeline', function () {
|
||||||
$previousEnvironment = Environment::name();
|
$previousEnvironment = Environment::name();
|
||||||
Environment::name(Environment::CI);
|
Environment::name(Environment::CI);
|
||||||
$testSuite = TestSuite::getInstance(getcwd(), 'tests');
|
$testSuite = new TestSuite(getcwd(), 'tests');
|
||||||
|
|
||||||
$test = function () {};
|
$test = function () {
|
||||||
|
};
|
||||||
|
|
||||||
$testWithOnly = new TestCaseMethodFactory('a', 'b', null);
|
$testWithOnly = new TestCaseMethodFactory('a', 'b', null);
|
||||||
$testWithOnly->only = true;
|
$testWithOnly->only = true;
|
||||||
|
|||||||
@ -24,4 +24,4 @@ test('visual snapshot of help command output', function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
expect($output())->toContain(file_get_contents($snapshot));
|
expect($output())->toContain(file_get_contents($snapshot));
|
||||||
})->skip(PHP_OS_FAMILY === 'Windows');
|
})->skip(PHP_OS_FAMILY === 'Windows')->skip('Not supported yet.');
|
||||||
|
|||||||
@ -22,7 +22,7 @@ it('is can successfully call all public methods', function () {
|
|||||||
$junit->endTest($this, 0);
|
$junit->endTest($this, 0);
|
||||||
$junit->endTestSuite(new TestSuite());
|
$junit->endTestSuite(new TestSuite());
|
||||||
$this->expectNotToPerformAssertions();
|
$this->expectNotToPerformAssertions();
|
||||||
});
|
})->skip('Not supported yet.');
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
unlink(__DIR__ . '/junit.html');
|
unlink(__DIR__ . '/junit.html');
|
||||||
|
|||||||
@ -9,7 +9,11 @@ test('visual snapshot of test suite on success', function () {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$output = function () use ($testsPath) {
|
$output = function () use ($testsPath) {
|
||||||
$process = (new Symfony\Component\Process\Process(['php', 'bin/pest'], dirname($testsPath), ['EXCLUDE' => 'integration', 'REBUILD_SNAPSHOTS' => false, 'PARATEST' => 0]));
|
$process = (new Symfony\Component\Process\Process(
|
||||||
|
['php', 'bin/pest'],
|
||||||
|
dirname($testsPath),
|
||||||
|
['EXCLUDE' => 'integration', 'REBUILD_SNAPSHOTS' => false, 'PARATEST' => 0, 'COLLISION_PRINTER' => 'DefaultPrinter'],
|
||||||
|
));
|
||||||
|
|
||||||
$process->run();
|
$process->run();
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@ it('is can successfully call all public methods', function () {
|
|||||||
$teamCity->endTest($this, 0);
|
$teamCity->endTest($this, 0);
|
||||||
$teamCity->printResult(new TestResult());
|
$teamCity->printResult(new TestResult());
|
||||||
$teamCity->endTestSuite(new TestSuite());
|
$teamCity->endTestSuite(new TestSuite());
|
||||||
});
|
})->skip('Not supported yet.');
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
unlink(__DIR__ . '/output.txt');
|
unlink(__DIR__ . '/output.txt');
|
||||||
|
|||||||
Reference in New Issue
Block a user