Assert - Assertions to validate method input/output with nice error messages.

Overview

Webmozart Assert

Latest Stable Version Total Downloads

This library contains efficient assertions to test the input and output of your methods. With these assertions, you can greatly reduce the amount of coding needed to write a safe implementation.

All assertions in the Assert class throw an Webmozart\Assert\InvalidArgumentException if they fail.

FAQ

What's the difference to beberlei/assert?

This library is heavily inspired by Benjamin Eberlei's wonderful assert package, but fixes a usability issue with error messages that can't be fixed there without breaking backwards compatibility.

This package features usable error messages by default. However, you can also easily write custom error messages:

Assert::string($path, 'The path is expected to be a string. Got: %s');

In beberlei/assert, the ordering of the %s placeholders is different for every assertion. This package, on the contrary, provides consistent placeholder ordering for all assertions:

  • %s: The tested value as string, e.g. "/foo/bar".
  • %2$s, %3$s, ...: Additional assertion-specific values, e.g. the minimum/maximum length, allowed values, etc.

Check the source code of the assertions to find out details about the additional available placeholders.

Installation

Use Composer to install the package:

composer require webmozart/assert

Example

use Webmozart\Assert\Assert;

class Employee
{
    public function __construct($id)
    {
        Assert::integer($id, 'The employee ID must be an integer. Got: %s');
        Assert::greaterThan($id, 0, 'The employee ID must be a positive integer. Got: %s');
    }
}

If you create an employee with an invalid ID, an exception is thrown:

new Employee('foobar');
// => Webmozart\Assert\InvalidArgumentException:
//    The employee ID must be an integer. Got: string

new Employee(-10);
// => Webmozart\Assert\InvalidArgumentException:
//    The employee ID must be a positive integer. Got: -10

Assertions

The Assert class provides the following assertions:

Type Assertions

Method Description
string($value, $message = '') Check that a value is a string
stringNotEmpty($value, $message = '') Check that a value is a non-empty string
integer($value, $message = '') Check that a value is an integer
integerish($value, $message = '') Check that a value casts to an integer
positiveInteger($value, $message = '') Check that a value is a positive (non-zero) integer
float($value, $message = '') Check that a value is a float
numeric($value, $message = '') Check that a value is numeric
natural($value, $message= ''') Check that a value is a non-negative integer
boolean($value, $message = '') Check that a value is a boolean
scalar($value, $message = '') Check that a value is a scalar
object($value, $message = '') Check that a value is an object
resource($value, $type = null, $message = '') Check that a value is a resource
isCallable($value, $message = '') Check that a value is a callable
isArray($value, $message = '') Check that a value is an array
isTraversable($value, $message = '') (deprecated) Check that a value is an array or a \Traversable
isIterable($value, $message = '') Check that a value is an array or a \Traversable
isCountable($value, $message = '') Check that a value is an array or a \Countable
isInstanceOf($value, $class, $message = '') Check that a value is an instanceof a class
isInstanceOfAny($value, array $classes, $message = '') Check that a value is an instanceof at least one class on the array of classes
notInstanceOf($value, $class, $message = '') Check that a value is not an instanceof a class
isAOf($value, $class, $message = '') Check that a value is of the class or has one of its parents
isAnyOf($value, array $classes, $message = '') Check that a value is of at least one of the classes or has one of its parents
isNotA($value, $class, $message = '') Check that a value is not of the class or has not one of its parents
isArrayAccessible($value, $message = '') Check that a value can be accessed as an array
uniqueValues($values, $message = '') Check that the given array contains unique values

Comparison Assertions

Method Description
true($value, $message = '') Check that a value is true
false($value, $message = '') Check that a value is false
notFalse($value, $message = '') Check that a value is not false
null($value, $message = '') Check that a value is null
notNull($value, $message = '') Check that a value is not null
isEmpty($value, $message = '') Check that a value is empty()
notEmpty($value, $message = '') Check that a value is not empty()
eq($value, $value2, $message = '') Check that a value equals another (==)
notEq($value, $value2, $message = '') Check that a value does not equal another (!=)
same($value, $value2, $message = '') Check that a value is identical to another (===)
notSame($value, $value2, $message = '') Check that a value is not identical to another (!==)
greaterThan($value, $value2, $message = '') Check that a value is greater than another
greaterThanEq($value, $value2, $message = '') Check that a value is greater than or equal to another
lessThan($value, $value2, $message = '') Check that a value is less than another
lessThanEq($value, $value2, $message = '') Check that a value is less than or equal to another
range($value, $min, $max, $message = '') Check that a value is within a range
inArray($value, array $values, $message = '') Check that a value is one of a list of values
oneOf($value, array $values, $message = '') Check that a value is one of a list of values (alias of inArray)

String Assertions

You should check that a value is a string with Assert::string() before making any of the following assertions.

Method Description
contains($value, $subString, $message = '') Check that a string contains a substring
notContains($value, $subString, $message = '') Check that a string does not contain a substring
startsWith($value, $prefix, $message = '') Check that a string has a prefix
notStartsWith($value, $prefix, $message = '') Check that a string does not have a prefix
startsWithLetter($value, $message = '') Check that a string starts with a letter
endsWith($value, $suffix, $message = '') Check that a string has a suffix
notEndsWith($value, $suffix, $message = '') Check that a string does not have a suffix
regex($value, $pattern, $message = '') Check that a string matches a regular expression
notRegex($value, $pattern, $message = '') Check that a string does not match a regular expression
unicodeLetters($value, $message = '') Check that a string contains Unicode letters only
alpha($value, $message = '') Check that a string contains letters only
digits($value, $message = '') Check that a string contains digits only
alnum($value, $message = '') Check that a string contains letters and digits only
lower($value, $message = '') Check that a string contains lowercase characters only
upper($value, $message = '') Check that a string contains uppercase characters only
length($value, $length, $message = '') Check that a string has a certain number of characters
minLength($value, $min, $message = '') Check that a string has at least a certain number of characters
maxLength($value, $max, $message = '') Check that a string has at most a certain number of characters
lengthBetween($value, $min, $max, $message = '') Check that a string has a length in the given range
uuid($value, $message = '') Check that a string is a valid UUID
ip($value, $message = '') Check that a string is a valid IP (either IPv4 or IPv6)
ipv4($value, $message = '') Check that a string is a valid IPv4
ipv6($value, $message = '') Check that a string is a valid IPv6
email($value, $message = '') Check that a string is a valid e-mail address
notWhitespaceOnly($value, $message = '') Check that a string contains at least one non-whitespace character

File Assertions

Method Description
fileExists($value, $message = '') Check that a value is an existing path
file($value, $message = '') Check that a value is an existing file
directory($value, $message = '') Check that a value is an existing directory
readable($value, $message = '') Check that a value is a readable path
writable($value, $message = '') Check that a value is a writable path

Object Assertions

Method Description
classExists($value, $message = '') Check that a value is an existing class name
subclassOf($value, $class, $message = '') Check that a class is a subclass of another
interfaceExists($value, $message = '') Check that a value is an existing interface name
implementsInterface($value, $class, $message = '') Check that a class implements an interface
propertyExists($value, $property, $message = '') Check that a property exists in a class/object
propertyNotExists($value, $property, $message = '') Check that a property does not exist in a class/object
methodExists($value, $method, $message = '') Check that a method exists in a class/object
methodNotExists($value, $method, $message = '') Check that a method does not exist in a class/object

Array Assertions

Method Description
keyExists($array, $key, $message = '') Check that a key exists in an array
keyNotExists($array, $key, $message = '') Check that a key does not exist in an array
validArrayKey($key, $message = '') Check that a value is a valid array key (int or string)
count($array, $number, $message = '') Check that an array contains a specific number of elements
minCount($array, $min, $message = '') Check that an array contains at least a certain number of elements
maxCount($array, $max, $message = '') Check that an array contains at most a certain number of elements
countBetween($array, $min, $max, $message = '') Check that an array has a count in the given range
isList($array, $message = '') Check that an array is a non-associative list
isNonEmptyList($array, $message = '') Check that an array is a non-associative list, and not empty
isMap($array, $message = '') Check that an array is associative and has strings as keys
isNonEmptyMap($array, $message = '') Check that an array is associative and has strings as keys, and is not empty

Function Assertions

Method Description
throws($closure, $class, $message = '') Check that a function throws a certain exception. Subclasses of the exception class will be accepted.

Collection Assertions

All of the above assertions can be prefixed with all*() to test the contents of an array or a \Traversable:

Assert::allIsInstanceOf($employees, 'Acme\Employee');

Nullable Assertions

All of the above assertions can be prefixed with nullOr*() to run the assertion only if it the value is not null:

Assert::nullOrString($middleName, 'The middle name must be a string or null. Got: %s');

Extending Assert

The Assert class comes with a few methods, which can be overridden to change the class behaviour. You can also extend it to add your own assertions.

Overriding methods

Overriding the following methods in your assertion class allows you to change the behaviour of the assertions:

  • public static function __callStatic($name, $arguments)
    • This method is used to 'create' the nullOr and all versions of the assertions.
  • protected static function valueToString($value)
    • This method is used for error messages, to convert the value to a string value for displaying. You could use this for representing a value object with a __toString method for example.
  • protected static function typeToString($value)
    • This method is used for error messages, to convert the a value to a string representing its type.
  • protected static function strlen($value)
    • This method is used to calculate string length for relevant methods, using the mb_strlen if available and useful.
  • protected static function reportInvalidArgument($message)
    • This method is called when an assertion fails, with the specified error message. Here you can throw your own exception, or log something.

Static analysis support

Where applicable, assertion functions are annotated to support Psalm's Assertion syntax. A dedicated PHPStan Plugin is required for proper type support.

Authors

Contribute

Contributions to the package are always welcome!

License

All contents of this package are licensed under the MIT license.

Comments
  • Discussion: first draft of the nullOr/all assertions implementation

    Discussion: first draft of the nullOr/all assertions implementation

    The generate.php in this PR is really a quick and dirty implementation of a generator and it should not be looked too closely: the final implementation would be re-done almost entirely (though the idea would be kept).

    What I want to suggest you for discussion is the Webmozart\Assert\Extra class.

    In the final implementation I suggest to rename the currently existing Webmozart\Assert\Assert to Webmozart\Assert\Base, and then Webmozart\Assert\Extra to Webmozart\Assert\Assert so that it was all transparent for the users.

    The final implementation would come with a test that checks that the currently generated version and committed version is identical to the one that would have been generated now should you run php generate.php.

    The current implementation generates 47 functions out of the list of all allX or nullOrX functions, and 9 are not supported probably due to possible psalm bugs (need investigation). You can see list of those in the $temporaryUnsupported variable.

    Thoughts?

    /cc @Ocramius

    opened by zerkms 44
  • [RFC] add throws assertion

    [RFC] add throws assertion

    hey there!

    I was thinking about the simplest way to assert exceptions are thrown and thought it was currently missing.

    Do you think it's a viable solution? If so, I'll add some tests.

    current usage:

    Assert::throws(function() {
        $this->products->findOrThrow('some-id'), new \LogicException);
    }, \LogicException::class);
    

    It will only check the exception type right now, not comparing the message.

    opened by docteurklein 38
  • Added type assertions for multiple methods not covered by existing `@psalm-assert` functionality

    Added type assertions for multiple methods not covered by existing `@psalm-assert` functionality

    Related:

    • [x] https://github.com/vimeo/psalm/issues/2449
    • [x] https://github.com/vimeo/psalm/issues/2450
    • [x] https://github.com/vimeo/psalm/issues/2451
    • [x] https://github.com/vimeo/psalm/issues/2452
    • [x] https://github.com/vimeo/psalm/issues/2456
    opened by Ocramius 29
  • #213 implemented `Assert::positiveInteger()` to have psalm `positive-int` assertions

    #213 implemented `Assert::positiveInteger()` to have psalm `positive-int` assertions

    Fixes #213

    Needs:

    • [x] https://github.com/vimeo/psalm/pull/5050 (and update vimeo/psalm conflict)
    • [x] ~~https://github.com/vimeo/psalm/issues/5051~~ worked around by removing @mixin
    • [x] ~~https://github.com/vimeo/psalm/issues/5052~~ (skipped - suppressed for now, IMO not a blocker)
    • [x] ~~https://github.com/vimeo/psalm/issues/5310~~ (not fixed - reported regression in upstream, then locked dependency here)
    • [x] upgrade vimeo/psalm, update vimeo/psalm conflict constraint

    Fixes #213 Fixes #214 Fixes #97 Fixes #229

    enhancement 
    opened by Ocramius 19
  • Native type hints

    Native type hints

    Given now https://github.com/webmozarts/assert/commit/1838a0fb31b481772481fc7e300e587d3380ac56 only php>=7.2 is supported, how about switching to native type hints for arguments and return values where possible?

    opened by zerkms 17
  • WIP: psalm-specific annotations for restricting post-assertion value types

    WIP: psalm-specific annotations for restricting post-assertion value types

    As discussed with @Nyholm, this is a WIP patch containing happy-path scenarios (some of which are marked as .disabled, will talk to @muglug about those) that ensure the added type declarations work as expected.

    The idea is that after a @psalm-assert int $value, the caller of Assert::integer($value) can assume $value to be int.

    This is equivalent to the behavior of https://github.com/phpstan/phpstan-webmozart-assert, but the declarations are now closer to the source, and that makes for easier usage from the ecosystem (support by phpstan and phpstorm may come soon ;-) )

    As for the prefixed annotation format: that is required to not trip over tools like doctrine/annotations.

    Other similar patches, for reference (since this is quite new stuff):

    • https://github.com/doctrine/collections/pull/177
    • https://github.com/Ocramius/ProxyManager/pull/465
    • https://github.com/sebastianbergmann/phpunit/pull/3708
    opened by Ocramius 16
  • Flip expected/actual arguments?

    Flip expected/actual arguments?

    Currently, when one is used to assertions in PHPUnit (first argument "expected", second "actual"), it's easy to get the assertions in this library wrong (first argument "actual", second "expected"). What do you think about flipping the arguments and releasing a 2.0?

    opened by webmozart 15
  • Custom exceptions

    Custom exceptions

    Hi,

    I'm looking for a way to raise custom exceptions per assertion.. Looking at the code, it currently seems only possible to override Assert::reportInvalidArgument for all assertions.. The only way I see around this is to add an optional argument to every assertion, allowing to pass a custom exception class.. Would you be open for a PR to support this? Or do you see another way to achieve what I'm after?

    opened by tvdijen 14
  • Proposal: Drop support for PHP versions that are EOL

    Proposal: Drop support for PHP versions that are EOL

    All PHP versions < 7.2 are end of life and should no longer be used. It is harmful to support these outdated versions in the future.

    Why?

    • PHPUnit cannot be upgraded to 8 and above
    • Newer language features cannot be adopted resulting in bloated or less readable code
    • Users should not be encouraged to build technical debt
    opened by tux-rampage 10
  • Add flexibility to report problems in different ways

    Add flexibility to report problems in different ways

    Hi !

    Further extending of #19 to allow report a problem in different ways via extending the class, while default behaviour is not changed.

    Use case - I have a library used with a lot of messy, invalid input from it's users that needs to be fixed by the users of library. When I do the assertions that raising the exceptions - it will crash their app. So far even if their input is not perfect, it works somehow (not in the best way, but at least some functionality is working due to autoconverting).

    The goal is to be strict and raise an exception when user of lib will pass invalid input. But as a middle step I want to make extra release which will just warn him (like triggering a warning instead of breaking the flow with exception). Currently one can't override the library to do anything else than raising an exception. With this change it would become possible.

    What do you think @webmozart ?

    opened by keradus 10
  • Proposal: array/object property path assertions

    Proposal: array/object property path assertions

    I would like to do something like that:

    Assert::allKeyPathsExists($collection, [
        'page',
        'pages',
        'total',
        'limit',
        '_embedded.items',
        '_links.self',
        '_links.first',
        '_links.last'
    ]);
    
    // or 
    Assert::keyPathExists($collection, '_links.last.href');
    

    Currently I have something like that:

    use Webmozart\Assert\Assert as BaseAssert;
    
    /**
     * Class Assert
     * @package AppBundle\Test
     */
    class Assert extends BaseAssert
    {
        /**
         * @param array $value
         * @param string $keyPath
         * @param string|null $message
         * @throws
         */
        public static function keyPathExists($value, $keyPath, $message = null)
        {
            $pointer  =& $value;
            $keys     = explode('.', $keyPath);
            $position = [];
            $message  = $message ?: 'expected key-path "%s" to exist. Failed at position "%2$s".';
    
            foreach ($keys as $key) {
                $position[] = $key;
                static::keyExists($pointer, $key, sprintf($message, $keyPath, implode('.', $position)));
                $pointer =& $pointer[$key];
            }
        }
    
        /**
         * @param array $value
         * @param array $keyPaths
         * @param string|null $message
         */
        public static function allKeyPathsExists($value, array $keyPaths, $message = null)
        {
            foreach ($keyPaths as $keyPath) {
                static::keyPathExists($value, $keyPath, $message);
            }
        }
    }
    

    Which works. I did also a different implementation using __callStatic and adding a prefix apply which could take a subject (value) and apply an assertion with different sets of arguments (and if needed messages).

    I'v noticed, what I actually need is the possibilities to also apply such path tests to type-checks like integer or string.

    So actually what is needed is some sort of __callStatic to operate over a path of array-keys or object-properties. Without that writing assertions pains. The example above delivered understandable error messages and the customization concept in this project is good, so I think you would not get some super generic (not understandable) messages, if scaled the way I did in the example.

    The API could looks like this:

    // 1. array subject of test, 2. array keyPaths to test, 3-n. assertion-arguments
    Assert::arrayEveryKeyExists(array $subject, array $subjectKeyPaths)
    Assert::arrayEveryInteger(array $subject, array $subjectKeyPaths);
    Assert::arrayEveryIsInstance(array $subject, array $subjectKeyPaths, SomeClass::class);
    // or Assert::arrayAllKeyExists, Assert::arrayAllInteger but the readability is worker here.
    
    opened by akomm 10
  • allIsAOf

    allIsAOf

    In tests/static-analysis/assert-isAOf.php there is the following mehod:

    function allIsAOf($value)
    {
        Assert::allIsAOf($value, Serializable::class);
    
        return $value;
    }
    

    however no such method exists in the Assert class.

    opened by karelVanGeerdeghom 0
  • Return validated value

    Return validated value

    I've faced the fact that it is required to create temporary variables to validate values:

    $firstName = getParam('firstName');
    $lastName = getParam('lastName');
    Assert::notNull($firstName);
    Assert::notNull($lastName);
    
    createCustomer(
        $firstName,
        $lastName
    );
    

    We can rid of temporary variables if the assertion function returns a valid value:

    createCustomer(
        Assert::notNull(getParam('firstName')),
        Assert::notNull(getParam('lastName'))
    );
    

    For some of the assertion functions, we can simply return the valid value. The changes should be BC-safe.

    Possible implementation: https://github.com/webmozarts/assert/pull/281 Psalm support demonstration: https://psalm.dev/r/c3a23fe473

    References:

    1. Similar Java implementation: https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/Validate.html#notNull(T)
    opened by dbalabka 0
  • Fix static analysis in ci

    Fix static analysis in ci

    This PR fixes #275, the first commit upgrades pslam so that psalm can be run from a subdirectory again. And the second commit fixes all currently occurring errors.

    opened by leonhusmann 0
  • Fix `implementsInterface()` PHPDoc

    Fix `implementsInterface()` PHPDoc

    class_implements accepts either an object or a class-string, but the PHPDoc for the assert function is wrong and limits its functionality to a class-string only. I'm not entirely sure if this was on purpose, the README just mentions "Check that a class implements an interface", but it would work with either an instance of a class or a class-string and the assertion is under the "object" category.

    See also https://phpstan.org/r/c72bb8af-4f27-462b-85f6-e2d3b81b9786 where this is tested in PHPStan (which just got support for PHPDoc-based type narrowing, this is not released yet)

    Refs: https://github.com/phpstan/phpstan-webmozart-assert/pull/144#issuecomment-1268122389

    I could not cleanly run psalm locally without unrelated errors, let's see what happens on CI 🤞

    opened by herndlm 3
Releases(1.11.0)
Owner
Webmozarts GmbH
Web and App Development in Vienna, Budapest and Barcelona
Webmozarts GmbH
Symfony kafka bundle to produce and consume messages.

Technology stack Quick start Example project Basic Configuration Consuming messages Retrying failed messages Handling offsets Decoders Denormalizers V

STS Gaming Group 25 Oct 3, 2022
Blackfire Player is a powerful Web Crawling, Web Testing, and Web Scraper application. It provides a nice DSL to crawl HTTP services, assert responses, and extract data from HTML/XML/JSON responses.

Blackfire Player Blackfire Player is a powerful Web Crawling, Web Testing, and Web Scraper application. It provides a nice DSL to crawl HTTP services,

Blackfire 485 Dec 31, 2022
Capture and monitor detailed error logs with nice dashboard and UI

Capture and monitor detailed error logs with nice dashboard and UI Requirements Check Laravel 6 requirements Check Laravel 7 requirements Installation

Bugphix 107 Dec 12, 2022
Enjoy realtime input validation by passing your rules in your input itself.

Laravel Realtime input Enjoy realtime input validation by passing your rules in your input itself. Requirments This package is tested with Laravel v8

Yemeni Open Source 50 Nov 20, 2022
Methods to allow the mapping of cases to snake / camel for input / output

Methods to allow the mapping of cases to snake / camel for input / output This is where your description should go. Limit it to a paragraph or two. Co

Craig Smith 4 Aug 31, 2022
A Laravel package to output a specific sql to your favourite debugging tool. The supported log output is Laravel Telescope, Laravel Log, Ray, Clockwork, Laravel Debugbar and your browser.

Laravel showsql A Laravel package to output a specific sql to your favourite debugging tool, your browser or your log file. Use case You often want to

Dieter Coopman 196 Dec 28, 2022
Validate your input data in a simple way, an easy way and right way. no framework required. For simple or large. project.

wepesi_validation this module will help to do your own input validation from http request POST or GET. INTEGRATION The integration is the simple thing

Boss 4 Dec 17, 2022
Enable method chaining or fluent expressions for any value and method.

PHP Pipe Operator A (hopefully) temporary solution to implement the pipe operator in PHP. Table of contents Requirements How to install How to use The

Sebastiaan Luca 268 Dec 26, 2022
A super simple, clean and pretty error handler that replace the default error handler of PHP. You need only include this file!

php-custom-error-handler A super simple, clean and pretty error handler that replace the default error handler of PHP. You need just include only this

null 6 Nov 7, 2022
This Validate Class is for those who are looking for a validator that returns a code for every each error (Laravel/Api)

Validator-Class This Validate Class is for those who are looking for a validator that returns a code for every each error (Laravel/Api) Requirements A

Barbod 3 Jul 18, 2022
Remove messages from the error log that are from a certain folder

Error-Focus A package to stay focused on relevant entries in your error-log Scope This package allows you to declare folders that are not under your d

Andreas Heigl 7 Jul 25, 2022
PHPUnit assertions for testing ReactPHP promises

ReactPHP Promises Testing A library that provides a set of convenient assertions for testing ReactPHP promises. Under the hood uses clue/php-block-rea

Sergey Zhuk 30 Dec 8, 2022
🧑‍🔬 The missing assertions for your views in your Laravel applications.

Laravel View Assertions The missing assertions for your views in your Laravel applications. Installation You'll have to follow a couple of simple step

Sven Luijten 4 Dec 21, 2022
Few additional testing assertions for Laravel views

Laravel View Test Assertions Few additional assertions for testing Laravel views. Why Laravel has well established and documented way of testing reque

null 13 Jun 12, 2022
Trigger email failures to assert what happens on your Laravel Application when an email fails to send

Laravel Email Failer composer require --dev rogervila/laravel-email-failer About Trigger email failures to assert what happens on your Laravel Applica

Roger Vilà 30 Jul 17, 2022
Trait for Laravel testing to count/assert about database queries

counts_database_queries Trait for Laravel testing to count/assert about database queries Installing composer require ohffs/counts-database-queries-tra

null 1 Feb 23, 2022
The main scope of this extension is to help phpstan to detect the type of object after the Assert\Assertion validation.

PHPStan beberlei/assert extension PHPStan beberlei/assert Description The main scope of this extension is to help phpstan to detect the type of object

PHPStan 33 Jan 2, 2023
PHPStan extension for webmozart/assert

PHPStan webmozart/assert extension PHPStan webmozart/assert Description The main scope of this extension is to help phpstan to detect the type of obje

PHPStan 139 Dec 22, 2022
Additional PHPUnit assertions and helper functions

Jasny PHPUnit extension Additional functionality for PHPUnit. Callback mock - assert that callback is called with correct arguments. Safe mocks - disa

Arnold Daniels 2 Jul 24, 2022
A set of helpful assertions when testing Laravel applications.

Installation composer require amirrezam75/laravel-assertions I was working on a project and in order to test oauth2 redirection, I ended up with somet

Amir Reza Mehrbakhsh 2 Sep 23, 2022