Вход Регистрация
Файл: vendor/laravel/framework/src/Illuminate/Testing/TestResponse.php
Строк: 1796
<?php

namespace IlluminateTesting;

use 
ArrayAccess;
use 
Closure;
use 
IlluminateContractsSupportMessageBag;
use 
IlluminateContractsViewView;
use 
IlluminateCookieCookieValuePrefix;
use 
IlluminateDatabaseEloquentCollection as EloquentCollection;
use 
IlluminateDatabaseEloquentModel;
use 
IlluminateHttpRedirectResponse;
use 
IlluminateHttpRequest;
use 
IlluminateSupportArr;
use 
IlluminateSupportCarbon;
use 
IlluminateSupportCollection;
use 
IlluminateSupportStr;
use 
IlluminateSupportTraitsConditionable;
use 
IlluminateSupportTraitsMacroable;
use 
IlluminateSupportTraitsTappable;
use 
IlluminateSupportViewErrorBag;
use 
IlluminateTestingAssert as PHPUnit;
use 
IlluminateTestingConstraintsSeeInOrder;
use 
IlluminateTestingFluentAssertableJson;
use 
LogicException;
use 
PHPUnitFrameworkExpectationFailedException;
use 
ReflectionProperty;
use 
SymfonyComponentHttpFoundationCookie;
use 
SymfonyComponentHttpFoundationStreamedJsonResponse;
use 
SymfonyComponentHttpFoundationStreamedResponse;

/**
 * @mixin IlluminateHttpResponse
 */
class TestResponse implements ArrayAccess
{
    use 
ConcernsAssertsStatusCodesConditionableTappableMacroable {
        
__call as macroCall;
    }

    
/**
     * The response to delegate to.
     *
     * @var IlluminateHttpResponse
     */
    
public $baseResponse;

    
/**
     * The collection of logged exceptions for the request.
     *
     * @var IlluminateSupportCollection
     */
    
public $exceptions;

    
/**
     * The streamed content of the response.
     *
     * @var string
     */
    
protected $streamedContent;

    
/**
     * Create a new test response instance.
     *
     * @param  IlluminateHttpResponse  $response
     * @return void
     */
    
public function __construct($response)
    {
        
$this->baseResponse $response;
        
$this->exceptions = new Collection;
    }

    
/**
     * Create a new TestResponse from another response.
     *
     * @param  IlluminateHttpResponse  $response
     * @return static
     */
    
public static function fromBaseResponse($response)
    {
        return new static(
$response);
    }

    
/**
     * Assert that the response has a successful status code.
     *
     * @return $this
     */
    
public function assertSuccessful()
    {
        
PHPUnit::assertTrue(
            
$this->isSuccessful(),
            
$this->statusMessageWithDetails('>=200, <300'$this->getStatusCode())
        );

        return 
$this;
    }

    
/**
     * Assert that the Precognition request was successful.
     *
     * @return $this
     */
    
public function assertSuccessfulPrecognition()
    {
        
$this->assertNoContent();

        
PHPUnit::assertTrue(
            
$this->headers->has('Precognition-Success'),
            
'Header [Precognition-Success] not present on response.'
        
);

        
PHPUnit::assertSame(
            
'true',
            
$this->headers->get('Precognition-Success'),
            
'The Precognition-Success header was found, but the value is not `true`.'
        
);

        return 
$this;
    }

    
/**
     * Assert that the response is a server error.
     *
     * @return $this
     */
    
public function assertServerError()
    {
        
PHPUnit::assertTrue(
            
$this->isServerError(),
            
$this->statusMessageWithDetails('>=500, < 600'$this->getStatusCode())
        );

        return 
$this;
    }

    
/**
     * Assert that the response has the given status code.
     *
     * @param  int  $status
     * @return $this
     */
    
public function assertStatus($status)
    {
        
$message $this->statusMessageWithDetails($status$actual $this->getStatusCode());

        
PHPUnit::assertSame($status$actual$message);

        return 
$this;
    }

    
/**
     * Get an assertion message for a status assertion containing extra details when available.
     *
     * @param  string|int  $expected
     * @param  string|int  $actual
     * @return string
     */
    
protected function statusMessageWithDetails($expected$actual)
    {
        return 
"Expected response status code [{$expected}] but received {$actual}.";
    }

    
/**
     * Assert whether the response is redirecting to a given URI.
     *
     * @param  string|null  $uri
     * @return $this
     */
    
public function assertRedirect($uri null)
    {
        
PHPUnit::assertTrue(
            
$this->isRedirect(),
            
$this->statusMessageWithDetails('201, 301, 302, 303, 307, 308'$this->getStatusCode()),
        );

        if (! 
is_null($uri)) {
            
$this->assertLocation($uri);
        }

        return 
$this;
    }

    
/**
     * Assert whether the response is redirecting to a URI that contains the given URI.
     *
     * @param  string  $uri
     * @return $this
     */
    
public function assertRedirectContains($uri)
    {
        
PHPUnit::assertTrue(
            
$this->isRedirect(),
            
$this->statusMessageWithDetails('201, 301, 302, 303, 307, 308'$this->getStatusCode()),
        );

        
PHPUnit::assertTrue(
            
Str::contains($this->headers->get('Location'), $uri), 'Redirect location ['.$this->headers->get('Location').'] does not contain ['.$uri.'].'
        
);

        return 
$this;
    }

    
/**
     * Assert whether the response is redirecting to a given route.
     *
     * @param  string  $name
     * @param  mixed  $parameters
     * @return $this
     */
    
public function assertRedirectToRoute($name$parameters = [])
    {
        
$uri route($name$parameters);

        
PHPUnit::assertTrue(
            
$this->isRedirect(),
            
$this->statusMessageWithDetails('201, 301, 302, 303, 307, 308'$this->getStatusCode()),
        );

        
$this->assertLocation($uri);

        return 
$this;
    }

    
/**
     * Assert whether the response is redirecting to a given signed route.
     *
     * @param  string|null  $name
     * @param  mixed  $parameters
     * @return $this
     */
    
public function assertRedirectToSignedRoute($name null$parameters = [])
    {
        if (! 
is_null($name)) {
            
$uri route($name$parameters);
        }

        
PHPUnit::assertTrue(
            
$this->isRedirect(),
            
$this->statusMessageWithDetails('201, 301, 302, 303, 307, 308'$this->getStatusCode()),
        );

        
$request Request::create($this->headers->get('Location'));

        
PHPUnit::assertTrue(
            
$request->hasValidSignature(), 'The response is not a redirect to a signed route.'
        
);

        if (! 
is_null($name)) {
            
$expectedUri rtrim($request->fullUrlWithQuery([
                
'signature' => null,
                
'expires' => null,
            ]), 
'?');

            
PHPUnit::assertEquals(
                
app('url')->to($uri), $expectedUri
            
);
        }

        return 
$this;
    }

    
/**
     * Asserts that the response contains the given header and equals the optional value.
     *
     * @param  string  $headerName
     * @param  mixed  $value
     * @return $this
     */
    
public function assertHeader($headerName$value null)
    {
        
PHPUnit::assertTrue(
            
$this->headers->has($headerName), "Header [{$headerName}] not present on response."
        
);

        
$actual $this->headers->get($headerName);

        if (! 
is_null($value)) {
            
PHPUnit::assertEquals(
                
$value$this->headers->get($headerName),
                
"Header [{$headerName}] was found, but value [{$actual}] does not match [{$value}]."
            
);
        }

        return 
$this;
    }

    
/**
     * Asserts that the response does not contain the given header.
     *
     * @param  string  $headerName
     * @return $this
     */
    
public function assertHeaderMissing($headerName)
    {
        
PHPUnit::assertFalse(
            
$this->headers->has($headerName), "Unexpected header [{$headerName}] is present on response."
        
);

        return 
$this;
    }

    
/**
     * Assert that the current location header matches the given URI.
     *
     * @param  string  $uri
     * @return $this
     */
    
public function assertLocation($uri)
    {
        
PHPUnit::assertEquals(
            
app('url')->to($uri), app('url')->to($this->headers->get('Location'''))
        );

        return 
$this;
    }

    
/**
     * Assert that the response offers a file download.
     *
     * @param  string|null  $filename
     * @return $this
     */
    
public function assertDownload($filename null)
    {
        
$contentDisposition explode(';'$this->headers->get('content-disposition'''));

        if (
trim($contentDisposition[0]) !== 'attachment') {
            
PHPUnit::fail(
                
'Response does not offer a file download.'.PHP_EOL.
                
'Disposition ['.trim($contentDisposition[0]).'] found in header, [attachment] expected.'
            
);
        }

        if (! 
is_null($filename)) {
            if (isset(
$contentDisposition[1]) &&
                
trim(explode('='$contentDisposition[1])[0]) !== 'filename') {
                
PHPUnit::fail(
                    
'Unsupported Content-Disposition header provided.'.PHP_EOL.
                    
'Disposition ['.trim(explode('='$contentDisposition[1])[0]).'] found in header, [filename] expected.'
                
);
            }

            
$message "Expected file [{$filename}] is not present in Content-Disposition header.";

            if (! isset(
$contentDisposition[1])) {
                
PHPUnit::fail($message);
            } else {
                
PHPUnit::assertSame(
                    
$filename,
                    isset(
explode('='$contentDisposition[1])[1])
                        ? 
trim(explode('='$contentDisposition[1])[1], " "'")
                        : '',
                    $message
                );

                return $this;
            }
        } else {
            PHPUnit::assertTrue(true);

            return $this;
        }
    }

    /**
     * Asserts that the response contains the given cookie and equals the optional value.
     *
     * @param  string  $cookieName
     * @param  mixed  $value
     * @return $this
     */
    public function assertPlainCookie($cookieName, $value = null)
    {
        $this->assertCookie($cookieName, $value, false);

        return $this;
    }

    /**
     * Asserts that the response contains the given cookie and equals the optional value.
     *
     * @param  string  $cookieName
     * @param  mixed  $value
     * @param  bool  $encrypted
     * @param  bool  $unserialize
     * @return $this
     */
    public function assertCookie($cookieName, $value = null, $encrypted = true, $unserialize = false)
    {
        PHPUnit::assertNotNull(
            $cookie = $this->getCookie($cookieName, $encrypted && ! is_null($value), $unserialize),
            "Cookie [{$cookieName}] not present on response."
        );

        if (! $cookie || is_null($value)) {
            return $this;
        }

        $cookieValue = $cookie->getValue();

        PHPUnit::assertEquals(
            $value, $cookieValue,
            "Cookie [{$cookieName}] was found, but value [{$cookieValue}] does not match [{$value}]."
        );

        return $this;
    }

    /**
     * Asserts that the response contains the given cookie and is expired.
     *
     * @param  string  $cookieName
     * @return $this
     */
    public function assertCookieExpired($cookieName)
    {
        PHPUnit::assertNotNull(
            $cookie = $this->getCookie($cookieName, false),
            "Cookie [{$cookieName}] not present on response."
        );

        $expiresAt = Carbon::createFromTimestamp($cookie->getExpiresTime());

        PHPUnit::assertTrue(
            $cookie->getExpiresTime() !== 0 && $expiresAt->lessThan(Carbon::now()),
            "Cookie [{$cookieName}] is not expired, it expires at [{$expiresAt}]."
        );

        return $this;
    }

    /**
     * Asserts that the response contains the given cookie and is not expired.
     *
     * @param  string  $cookieName
     * @return $this
     */
    public function assertCookieNotExpired($cookieName)
    {
        PHPUnit::assertNotNull(
            $cookie = $this->getCookie($cookieName, false),
            "Cookie [{$cookieName}] not present on response."
        );

        $expiresAt = Carbon::createFromTimestamp($cookie->getExpiresTime());

        PHPUnit::assertTrue(
            $cookie->getExpiresTime() === 0 || $expiresAt->greaterThan(Carbon::now()),
            "Cookie [{$cookieName}] is expired, it expired at [{$expiresAt}]."
        );

        return $this;
    }

    /**
     * Asserts that the response does not contain the given cookie.
     *
     * @param  string  $cookieName
     * @return $this
     */
    public function assertCookieMissing($cookieName)
    {
        PHPUnit::assertNull(
            $this->getCookie($cookieName, false),
            "Cookie [{$cookieName}] is present on response."
        );

        return $this;
    }

    /**
     * Get the given cookie from the response.
     *
     * @param  string  $cookieName
     * @param  bool  $decrypt
     * @param  bool  $unserialize
     * @return SymfonyComponentHttpFoundationCookie|null
     */
    public function getCookie($cookieName, $decrypt = true, $unserialize = false)
    {
        foreach ($this->headers->getCookies() as $cookie) {
            if ($cookie->getName() === $cookieName) {
                if (! $decrypt) {
                    return $cookie;
                }

                $decryptedValue = CookieValuePrefix::remove(
                    app('
encrypter')->decrypt($cookie->getValue(), $unserialize)
                );

                return new Cookie(
                    $cookie->getName(),
                    $decryptedValue,
                    $cookie->getExpiresTime(),
                    $cookie->getPath(),
                    $cookie->getDomain(),
                    $cookie->isSecure(),
                    $cookie->isHttpOnly(),
                    $cookie->isRaw(),
                    $cookie->getSameSite(),
                    $cookie->isPartitioned()
                );
            }
        }
    }

    /**
     * Assert that the given string matches the response content.
     *
     * @param  string  $value
     * @return $this
     */
    public function assertContent($value)
    {
        PHPUnit::assertSame($value, $this->content());

        return $this;
    }

    /**
     * Assert that the given string matches the streamed response content.
     *
     * @param  string  $value
     * @return $this
     */
    public function assertStreamedContent($value)
    {
        PHPUnit::assertSame($value, $this->streamedContent());

        return $this;
    }

    /**
     * Assert that the given array matches the streamed JSON response content.
     *
     * @param  array  $value
     * @return $this
     */
    public function assertStreamedJsonContent($value)
    {
        return $this->assertStreamedContent(json_encode($value, JSON_THROW_ON_ERROR));
    }

    /**
     * Assert that the given string or array of strings are contained within the response.
     *
     * @param  string|array  $value
     * @param  bool  $escape
     * @return $this
     */
    public function assertSee($value, $escape = true)
    {
        $value = Arr::wrap($value);

        $values = $escape ? array_map('
e', $value) : $value;

        foreach ($values as $value) {
            PHPUnit::assertStringContainsString((string) $value, $this->getContent());
        }

        return $this;
    }

    /**
     * Assert that the given strings are contained in order within the response.
     *
     * @param  array  $values
     * @param  bool  $escape
     * @return $this
     */
    public function assertSeeInOrder(array $values, $escape = true)
    {
        $values = $escape ? array_map('
e', $values) : $values;

        PHPUnit::assertThat($values, new SeeInOrder($this->getContent()));

        return $this;
    }

    /**
     * Assert that the given string or array of strings are contained within the response text.
     *
     * @param  string|array  $value
     * @param  bool  $escape
     * @return $this
     */
    public function assertSeeText($value, $escape = true)
    {
        $value = Arr::wrap($value);

        $values = $escape ? array_map('
e', $value) : $value;

        $content = strip_tags($this->getContent());

        foreach ($values as $value) {
            PHPUnit::assertStringContainsString((string) $value, $content);
        }

        return $this;
    }

    /**
     * Assert that the given strings are contained in order within the response text.
     *
     * @param  array  $values
     * @param  bool  $escape
     * @return $this
     */
    public function assertSeeTextInOrder(array $values, $escape = true)
    {
        $values = $escape ? array_map('
e', $values) : $values;

        PHPUnit::assertThat($values, new SeeInOrder(strip_tags($this->getContent())));

        return $this;
    }

    /**
     * Assert that the given string or array of strings are not contained within the response.
     *
     * @param  string|array  $value
     * @param  bool  $escape
     * @return $this
     */
    public function assertDontSee($value, $escape = true)
    {
        $value = Arr::wrap($value);

        $values = $escape ? array_map('
e', $value) : $value;

        foreach ($values as $value) {
            PHPUnit::assertStringNotContainsString((string) $value, $this->getContent());
        }

        return $this;
    }

    /**
     * Assert that the given string or array of strings are not contained within the response text.
     *
     * @param  string|array  $value
     * @param  bool  $escape
     * @return $this
     */
    public function assertDontSeeText($value, $escape = true)
    {
        $value = Arr::wrap($value);

        $values = $escape ? array_map('
e', $value) : $value;

        $content = strip_tags($this->getContent());

        foreach ($values as $value) {
            PHPUnit::assertStringNotContainsString((string) $value, $content);
        }

        return $this;
    }

    /**
     * Assert that the response is a superset of the given JSON.
     *
     * @param  array|callable  $value
     * @param  bool  $strict
     * @return $this
     */
    public function assertJson($value, $strict = false)
    {
        $json = $this->decodeResponseJson();

        if (is_array($value)) {
            $json->assertSubset($value, $strict);
        } else {
            $assert = AssertableJson::fromAssertableJsonString($json);

            $value($assert);

            if (Arr::isAssoc($assert->toArray())) {
                $assert->interacted();
            }
        }

        return $this;
    }

    /**
     * Assert that the expected value and type exists at the given path in the response.
     *
     * @param  string  $path
     * @param  mixed  $expect
     * @return $this
     */
    public function assertJsonPath($path, $expect)
    {
        $this->decodeResponseJson()->assertPath($path, $expect);

        return $this;
    }

    /**
     * Assert that the given path in the response contains all of the expected values without looking at the order.
     *
     * @param  string  $path
     * @param  array  $expect
     * @return $this
     */
    public function assertJsonPathCanonicalizing($path, array $expect)
    {
        $this->decodeResponseJson()->assertPathCanonicalizing($path, $expect);

        return $this;
    }

    /**
     * Assert that the response has the exact given JSON.
     *
     * @param  array  $data
     * @return $this
     */
    public function assertExactJson(array $data)
    {
        $this->decodeResponseJson()->assertExact($data);

        return $this;
    }

    /**
     * Assert that the response has the similar JSON as given.
     *
     * @param  array  $data
     * @return $this
     */
    public function assertSimilarJson(array $data)
    {
        $this->decodeResponseJson()->assertSimilar($data);

        return $this;
    }

    /**
     * Assert that the response contains the given JSON fragment.
     *
     * @param  array  $data
     * @return $this
     */
    public function assertJsonFragment(array $data)
    {
        $this->decodeResponseJson()->assertFragment($data);

        return $this;
    }

    /**
     * Assert that the response does not contain the given JSON fragment.
     *
     * @param  array  $data
     * @param  bool  $exact
     * @return $this
     */
    public function assertJsonMissing(array $data, $exact = false)
    {
        $this->decodeResponseJson()->assertMissing($data, $exact);

        return $this;
    }

    /**
     * Assert that the response does not contain the exact JSON fragment.
     *
     * @param  array  $data
     * @return $this
     */
    public function assertJsonMissingExact(array $data)
    {
        $this->decodeResponseJson()->assertMissingExact($data);

        return $this;
    }

    /**
     * Assert that the response does not contain the given path.
     *
     * @param  string  $path
     * @return $this
     */
    public function assertJsonMissingPath(string $path)
    {
        $this->decodeResponseJson()->assertMissingPath($path);

        return $this;
    }

    /**
     * Assert that the response has a given JSON structure.
     *
     * @param  array|null  $structure
     * @param  array|null  $responseData
     * @return $this
     */
    public function assertJsonStructure(?array $structure = null, $responseData = null)
    {
        $this->decodeResponseJson()->assertStructure($structure, $responseData);

        return $this;
    }

    /**
     * Assert that the response JSON has the expected count of items at the given key.
     *
     * @param  int  $count
     * @param  string|null  $key
     * @return $this
     */
    public function assertJsonCount(int $count, $key = null)
    {
        $this->decodeResponseJson()->assertCount($count, $key);

        return $this;
    }

    /**
     * Assert that the response has the given JSON validation errors.
     *
     * @param  string|array  $errors
     * @param  string  $responseKey
     * @return $this
     */
    public function assertJsonValidationErrors($errors, $responseKey = '
errors')
    {
        $errors = Arr::wrap($errors);

        PHPUnit::assertNotEmpty($errors, '
No validation errors were provided.');

        $jsonErrors = Arr::get($this->json(), $responseKey) ?? [];

        $errorMessage = $jsonErrors
                ? '
Response has the following JSON validation errors:'.
                        PHP_EOL.PHP_EOL.json_encode($jsonErrors, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE).PHP_EOL
                : '
Response does not have JSON validation errors.';

        foreach ($errors as $key => $value) {
            if (is_int($key)) {
                $this->assertJsonValidationErrorFor($value, $responseKey);

                continue;
            }

            $this->assertJsonValidationErrorFor($key, $responseKey);

            foreach (Arr::wrap($value) as $expectedMessage) {
                $errorMissing = true;

                foreach (Arr::wrap($jsonErrors[$key]) as $jsonErrorMessage) {
                    if (Str::contains($jsonErrorMessage, $expectedMessage)) {
                        $errorMissing = false;

                        break;
                    }
                }
            }

            if ($errorMissing) {
                PHPUnit::fail(
                    "Failed to find a validation error in the response for key and message: '
$key' => '$expectedMessage'".PHP_EOL.PHP_EOL.$errorMessage
                );
            }
        }

        return $this;
    }

    /**
     * Assert the response has any JSON validation errors for the given key.
     *
     * @param  string  $key
     * @param  string  $responseKey
     * @return $this
     */
    public function assertJsonValidationErrorFor($key, $responseKey = '
errors')
    {
        $jsonErrors = Arr::get($this->json(), $responseKey) ?? [];

        $errorMessage = $jsonErrors
            ? '
Response has the following JSON validation errors:'.
            PHP_EOL.PHP_EOL.json_encode($jsonErrors, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE).PHP_EOL
            : '
Response does not have JSON validation errors.';

        PHPUnit::assertArrayHasKey(
            $key,
            $jsonErrors,
            "Failed to find a validation error in the response for key: '
{$key}'".PHP_EOL.PHP_EOL.$errorMessage
        );

        return $this;
    }

    /**
     * Assert that the response has no JSON validation errors for the given keys.
     *
     * @param  string|array|null  $keys
     * @param  string  $responseKey
     * @return $this
     */
    public function assertJsonMissingValidationErrors($keys = null, $responseKey = '
errors')
    {
        if ($this->getContent() === '') {
            PHPUnit::assertTrue(true);

            return $this;
        }

        $json = $this->json();

        if (! Arr::has($json, $responseKey)) {
            PHPUnit::assertTrue(true);

            return $this;
        }

        $errors = Arr::get($json, $responseKey, []);

        if (is_null($keys) && count($errors) > 0) {
            PHPUnit::fail(
                '
Response has unexpected validation errors'.PHP_EOL.PHP_EOL.
                json_encode($errors, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
            );
        }

        foreach (Arr::wrap($keys) as $key) {
            PHPUnit::assertFalse(
                isset($errors[$key]),
                "Found unexpected validation error for key: '
{$key}'"
            );
        }

        return $this;
    }

    /**
     * Assert that the given key is a JSON array.
     *
     * @param  string|null  $key
     * @return $this
     */
    public function assertJsonIsArray($key = null)
    {
        $data = $this->json($key);

        $encodedData = json_encode($data);

        PHPUnit::assertTrue(
            is_array($data)
            && str_starts_with($encodedData, '
[')
            && str_ends_with($encodedData, '
]')
        );

        return $this;
    }

    /**
     * Assert that the given key is a JSON object.
     *
     * @param  string|null  $key
     * @return $this
     */
    public function assertJsonIsObject($key = null)
    {
        $data = $this->json($key);

        $encodedData = json_encode($data);

        PHPUnit::assertTrue(
            is_array($data)
            && str_starts_with($encodedData, '
{')
            && str_ends_with($encodedData, '
}')
        );

        return $this;
    }

    /**
     * Validate and return the decoded response JSON.
     *
     * @return IlluminateTestingAssertableJsonString
     *
     * @throws Throwable
     */
    public function decodeResponseJson()
    {
        $testJson = new AssertableJsonString($this->getContent());

        $decodedResponse = $testJson->json();

        if (is_null($decodedResponse) || $decodedResponse === false) {
            if ($this->exception) {
                throw $this->exception;
            } else {
                PHPUnit::fail('
Invalid JSON was returned from the route.');
            }
        }

        return $testJson;
    }

    /**
     * Validate and return the decoded response JSON.
     *
     * @param  string|null  $key
     * @return mixed
     */
    public function json($key = null)
    {
        return $this->decodeResponseJson()->json($key);
    }

    /**
     * Get the JSON decoded body of the response as a collection.
     *
     * @param  string|null  $key
     * @return IlluminateSupportCollection
     */
    public function collect($key = null)
    {
        return Collection::make($this->json($key));
    }

    /**
     * Assert that the response view equals the given value.
     *
     * @param  string  $value
     * @return $this
     */
    public function assertViewIs($value)
    {
        $this->ensureResponseHasView();

        PHPUnit::assertEquals($value, $this->original->name());

        return $this;
    }

    /**
     * Assert that the response view has a given piece of bound data.
     *
     * @param  string|array  $key
     * @param  mixed  $value
     * @return $this
     */
    public function assertViewHas($key, $value = null)
    {
        if (is_array($key)) {
            return $this->assertViewHasAll($key);
        }

        $this->ensureResponseHasView();

        if (is_null($value)) {
            PHPUnit::assertTrue(Arr::has($this->original->gatherData(), $key));
        } elseif ($value instanceof Closure) {
            PHPUnit::assertTrue($value(Arr::get($this->original->gatherData(), $key)));
        } elseif ($value instanceof Model) {
            PHPUnit::assertTrue($value->is(Arr::get($this->original->gatherData(), $key)));
        } elseif ($value instanceof EloquentCollection) {
            $actual = Arr::get($this->original->gatherData(), $key);

            PHPUnit::assertInstanceOf(EloquentCollection::class, $actual);
            PHPUnit::assertSameSize($value, $actual);

            $value->each(fn ($item, $index) => PHPUnit::assertTrue($actual->get($index)->is($item)));
        } else {
            PHPUnit::assertEquals($value, Arr::get($this->original->gatherData(), $key));
        }

        return $this;
    }

    /**
     * Assert that the response view has a given list of bound data.
     *
     * @param  array  $bindings
     * @return $this
     */
    public function assertViewHasAll(array $bindings)
    {
        foreach ($bindings as $key => $value) {
            if (is_int($key)) {
                $this->assertViewHas($value);
            } else {
                $this->assertViewHas($key, $value);
            }
        }

        return $this;
    }

    /**
     * Get a piece of data from the original view.
     *
     * @param  string  $key
     * @return mixed
     */
    public function viewData($key)
    {
        $this->ensureResponseHasView();

        return $this->original->gatherData()[$key];
    }

    /**
     * Assert that the response view is missing a piece of bound data.
     *
     * @param  string  $key
     * @return $this
     */
    public function assertViewMissing($key)
    {
        $this->ensureResponseHasView();

        PHPUnit::assertFalse(Arr::has($this->original->gatherData(), $key));

        return $this;
    }

    /**
     * Ensure that the response has a view as its original content.
     *
     * @return $this
     */
    protected function ensureResponseHasView()
    {
        if (! $this->responseHasView()) {
            return PHPUnit::fail('
The response is not a view.');
        }

        return $this;
    }

    /**
     * Determine if the original response is a view.
     *
     * @return bool
     */
    protected function responseHasView()
    {
        return isset($this->original) && $this->original instanceof View;
    }

    /**
     * Assert that the given keys do not have validation errors.
     *
     * @param  string|array|null  $keys
     * @param  string  $errorBag
     * @param  string  $responseKey
     * @return $this
     */
    public function assertValid($keys = null, $errorBag = '
default', $responseKey = 'errors')
    {
        if ($this->baseResponse->headers->get('
Content-Type') === 'application/json') {
            return $this->assertJsonMissingValidationErrors($keys, $responseKey);
        }

        if ($this->session()->get('
errors')) {
            $errors = $this->session()->get('
errors')->getBag($errorBag)->getMessages();
        } else {
            $errors = [];
        }

        if (empty($errors)) {
            PHPUnit::assertTrue(true);

            return $this;
        }

        if (is_null($keys) && count($errors) > 0) {
            PHPUnit::fail(
                '
Response has unexpected validation errors'.PHP_EOL.PHP_EOL.
                json_encode($errors, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
            );
        }

        foreach (Arr::wrap($keys) as $key) {
            PHPUnit::assertFalse(
                isset($errors[$key]),
                "Found unexpected validation error for key: '
{$key}'"
            );
        }

        return $this;
    }

    /**
     * Assert that the response has the given validation errors.
     *
     * @param  string|array|null  $errors
     * @param  string  $errorBag
     * @param  string  $responseKey
     * @return $this
     */
    public function assertInvalid($errors = null,
                                  $errorBag = '
default',
                                  $responseKey = '
errors')
    {
        if ($this->baseResponse->headers->get('
Content-Type') === 'application/json') {
            return $this->assertJsonValidationErrors($errors, $responseKey);
        }

        $this->assertSessionHas('
errors');

        $sessionErrors = $this->session()->get('
errors')->getBag($errorBag)->getMessages();

        $errorMessage = $sessionErrors
                ? '
Response has the following validation errors in the session:'.
                        PHP_EOL.PHP_EOL.json_encode($sessionErrors, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE).PHP_EOL
                : '
Response does not have validation errors in the session.';

        foreach (Arr::wrap($errors) as $key => $value) {
            PHPUnit::assertArrayHasKey(
                $resolvedKey = (is_int($key)) ? $value : $key,
                $sessionErrors,
                "Failed to find a validation error in session for key: '
{$resolvedKey}'".PHP_EOL.PHP_EOL.$errorMessage
            );

            foreach (Arr::wrap($value) as $message) {
                if (! is_int($key)) {
                    $hasError = false;

                    foreach (Arr::wrap($sessionErrors[$key]) as $sessionErrorMessage) {
                        if (Str::contains($sessionErrorMessage, $message)) {
                            $hasError = true;

                            break;
                        }
                    }

                    if (! $hasError) {
                        PHPUnit::fail(
                            "Failed to find a validation error for key and message: '
$key' => '$message'".PHP_EOL.PHP_EOL.$errorMessage
                        );
                    }
                }
            }
        }

        return $this;
    }

    /**
     * Assert that the session has a given value.
     *
     * @param  string|array  $key
     * @param  mixed  $value
     * @return $this
     */
    public function assertSessionHas($key, $value = null)
    {
        if (is_array($key)) {
            return $this->assertSessionHasAll($key);
        }

        if (is_null($value)) {
            PHPUnit::assertTrue(
                $this->session()->has($key),
                "Session is missing expected key [{$key}]."
            );
        } elseif ($value instanceof Closure) {
            PHPUnit::assertTrue($value($this->session()->get($key)));
        } else {
            PHPUnit::assertEquals($value, $this->session()->get($key));
        }

        return $this;
    }

    /**
     * Assert that the session has a given list of values.
     *
     * @param  array  $bindings
     * @return $this
     */
    public function assertSessionHasAll(array $bindings)
    {
        foreach ($bindings as $key => $value) {
            if (is_int($key)) {
                $this->assertSessionHas($value);
            } else {
                $this->assertSessionHas($key, $value);
            }
        }

        return $this;
    }

    /**
     * Assert that the session has a given value in the flashed input array.
     *
     * @param  string|array  $key
     * @param  mixed  $value
     * @return $this
     */
    public function assertSessionHasInput($key, $value = null)
    {
        if (is_array($key)) {
            foreach ($key as $k => $v) {
                if (is_int($k)) {
                    $this->assertSessionHasInput($v);
                } else {
                    $this->assertSessionHasInput($k, $v);
                }
            }

            return $this;
        }

        if (is_null($value)) {
            PHPUnit::assertTrue(
                $this->session()->hasOldInput($key),
                "Session is missing expected key [{$key}]."
            );
        } elseif ($value instanceof Closure) {
            PHPUnit::assertTrue($value($this->session()->getOldInput($key)));
        } else {
            PHPUnit::assertEquals($value, $this->session()->getOldInput($key));
        }

        return $this;
    }

    /**
     * Assert that the session has the given errors.
     *
     * @param  string|array  $keys
     * @param  mixed  $format
     * @param  string  $errorBag
     * @return $this
     */
    public function assertSessionHasErrors($keys = [], $format = null, $errorBag = '
default')
    {
        $this->assertSessionHas('
errors');

        $keys = (array) $keys;

        $errors = $this->session()->get('
errors')->getBag($errorBag);

        foreach ($keys as $key => $value) {
            if (is_int($key)) {
                PHPUnit::assertTrue($errors->has($value), "Session missing error: $value");
            } else {
                PHPUnit::assertContains(is_bool($value) ? (string) $value : $value, $errors->get($key, $format));
            }
        }

        return $this;
    }

    /**
     * Assert that the session is missing the given errors.
     *
     * @param  string|array  $keys
     * @param  string|null  $format
     * @param  string  $errorBag
     * @return $this
     */
    public function assertSessionDoesntHaveErrors($keys = [], $format = null, $errorBag = '
default')
    {
        $keys = (array) $keys;

        if (empty($keys)) {
            return $this->assertSessionHasNoErrors();
        }

        if (is_null($this->session()->get('
errors'))) {
            PHPUnit::assertTrue(true);

            return $this;
        }

        $errors = $this->session()->get('
errors')->getBag($errorBag);

        foreach ($keys as $key => $value) {
            if (is_int($key)) {
                PHPUnit::assertFalse($errors->has($value), "Session has unexpected error: $value");
            } else {
                PHPUnit::assertNotContains($value, $errors->get($key, $format));
            }
        }

        return $this;
    }

    /**
     * Assert that the session has no errors.
     *
     * @return $this
     */
    public function assertSessionHasNoErrors()
    {
        $hasErrors = $this->session()->has('
errors');

        PHPUnit::assertFalse(
            $hasErrors,
            '
Session has unexpected errors'.PHP_EOL.PHP_EOL.
            json_encode((function () use ($hasErrors) {
                $errors = [];

                $sessionErrors = $this->session()->get('
errors');

                if ($hasErrors && is_a($sessionErrors, ViewErrorBag::class)) {
                    foreach ($sessionErrors->getBags() as $bag => $messages) {
                        if (is_a($messages, MessageBag::class)) {
                            $errors[$bag] = $messages->all();
                        }
                    }
                }

                return $errors;
            })(), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE),
        );

        return $this;
    }

    /**
     * Assert that the session has the given errors.
     *
     * @param  string  $errorBag
     * @param  string|array  $keys
     * @param  mixed  $format
     * @return $this
     */
    public function assertSessionHasErrorsIn($errorBag, $keys = [], $format = null)
    {
        return $this->assertSessionHasErrors($keys, $format, $errorBag);
    }

    /**
     * Assert that the session does not have a given key.
     *
     * @param  string|array  $key
     * @return $this
     */
    public function assertSessionMissing($key)
    {
        if (is_array($key)) {
            foreach ($key as $value) {
                $this->assertSessionMissing($value);
            }
        } else {
            PHPUnit::assertFalse(
                $this->session()->has($key),
                "Session has unexpected key [{$key}]."
            );
        }

        return $this;
    }

    /**
     * Get the current session store.
     *
     * @return IlluminateSessionStore
     */
    protected function session()
    {
        $session = app('
session.store');

        if (! $session->isStarted()) {
            $session->start();
        }

        return $session;
    }

    /**
     * Dump the content from the response and end the script.
     *
     * @return never
     */
    public function dd()
    {
        $this->dump();

        exit(1);
    }

    /**
     * Dump the headers from the response and end the script.
     *
     * @return never
     */
    public function ddHeaders()
    {
        $this->dumpHeaders();

        exit(1);
    }

    /**
     * Dump the session from the response and end the script.
     *
     * @param  string|array  $keys
     * @return never
     */
    public function ddSession($keys = [])
    {
        $this->dumpSession($keys);

        exit(1);
    }

    /**
     * Dump the content from the response.
     *
     * @param  string|null  $key
     * @return $this
     */
    public function dump($key = null)
    {
        $content = $this->getContent();

        $json = json_decode($content);

        if (json_last_error() === JSON_ERROR_NONE) {
            $content = $json;
        }

        if (! is_null($key)) {
            dump(data_get($content, $key));
        } else {
            dump($content);
        }

        return $this;
    }

    /**
     * Dump the headers from the response.
     *
     * @return $this
     */
    public function dumpHeaders()
    {
        dump($this->headers->all());

        return $this;
    }

    /**
     * Dump the session from the response.
     *
     * @param  string|array  $keys
     * @return $this
     */
    public function dumpSession($keys = [])
    {
        $keys = (array) $keys;

        if (empty($keys)) {
            dump($this->session()->all());
        } else {
            dump($this->session()->only($keys));
        }

        return $this;
    }

    /**
     * Get the streamed content from the response.
     *
     * @return string
     */
    public function streamedContent()
    {
        if (! is_null($this->streamedContent)) {
            return $this->streamedContent;
        }

        if (! $this->baseResponse instanceof StreamedResponse
            && ! $this->baseResponse instanceof StreamedJsonResponse) {
            PHPUnit::fail('
The response is not a streamed response.');
        }

        ob_start(function (string $buffer): string {
            $this->streamedContent .= $buffer;

            return '';
        });

        $this->sendContent();

        ob_end_clean();

        return $this->streamedContent;
    }

    /**
     * Set the previous exceptions on the response.
     *
     * @param  IlluminateSupportCollection  $exceptions
     * @return $this
     */
    public function withExceptions(Collection $exceptions)
    {
        $this->exceptions = $exceptions;

        return $this;
    }

    /**
     * This method is called when test method did not execute successfully.
     *
     * @param  Throwable  $exception
     * @return Throwable
     */
    public function transformNotSuccessfulException($exception)
    {
        if (! $exception instanceof ExpectationFailedException) {
            return $exception;
        }

        if ($lastException = $this->exceptions->last()) {
            return $this->appendExceptionToException($lastException, $exception);
        }

        if ($this->baseResponse instanceof RedirectResponse) {
            $session = $this->baseResponse->getSession();

            if (! is_null($session) && $session->has('
errors')) {
                return $this->appendErrorsToException($session->get('
errors')->all(), $exception);
            }
        }

        if ($this->baseResponse->headers->get('
Content-Type') === 'application/json') {
            $testJson = new AssertableJsonString($this->getContent());

            if (isset($testJson['
errors'])) {
                return $this->appendErrorsToException($testJson->json(), $exception, true);
            }
        }

        return $exception;
    }

    /**
     * Append an exception to the message of another exception.
     *
     * @param  Throwable  $exceptionToAppend
     * @param  Throwable  $exception
     * @return Throwable
     */
    protected function appendExceptionToException($exceptionToAppend, $exception)
    {
        $exceptionMessage = is_string($exceptionToAppend) ? $exceptionToAppend : $exceptionToAppend->getMessage();

        $exceptionToAppend = (string) $exceptionToAppend;

        $message = <<<"EOF"
            The following exception occurred during the last request:

            $exceptionToAppend

            ----------------------------------------------------------------------------------

            $exceptionMessage
            EOF;

        return $this->appendMessageToException($message, $exception);
    }

    /**
     * Append errors to an exception message.
     *
     * @param  array  $errors
     * @param  Throwable  $exception
     * @param  bool  $json
     * @return Throwable
     */
    protected function appendErrorsToException($errors, $exception, $json = false)
    {
        $errors = $json
            ? json_encode($errors, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
            : implode(PHP_EOL, Arr::flatten($errors));

        // JSON error messages may already contain the errors, so we shouldn'
t duplicate them...
        if (
str_contains($exception->getMessage(), $errors)) {
            return 
$exception;
        }

        
$message = <<<"EOF"
            The following errors occurred during the last request:

            
$errors
            EOF;

        return 
$this->appendMessageToException($message$exception);
    }

    
/**
     * Append a message to an exception.
     *
     * @param  string  $message
     * @param  Throwable  $exception
     * @return Throwable
     */
    
protected function appendMessageToException($message$exception)
    {
        
$property = new ReflectionProperty($exception'message');

        
$property->setValue(
            
$exception,
            
$exception->getMessage().PHP_EOL.PHP_EOL.$message.PHP_EOL
        
);

        return 
$exception;
    }

    
/**
     * Dynamically access base response parameters.
     *
     * @param  string  $key
     * @return mixed
     */
    
public function __get($key)
    {
        return 
$this->baseResponse->{$key};
    }

    
/**
     * Proxy isset() checks to the underlying base response.
     *
     * @param  string  $key
     * @return bool
     */
    
public function __isset($key)
    {
        return isset(
$this->baseResponse->{$key});
    }

    
/**
     * Determine if the given offset exists.
     *
     * @param  string  $offset
     * @return bool
     */
    
public function offsetExists($offset): bool
    
{
        return 
$this->responseHasView()
                    ? isset(
$this->original->gatherData()[$offset])
                    : isset(
$this->json()[$offset]);
    }

    
/**
     * Get the value for a given offset.
     *
     * @param  string  $offset
     * @return mixed
     */
    
public function offsetGet($offset): mixed
    
{
        return 
$this->responseHasView()
                    ? 
$this->viewData($offset)
                    : 
$this->json()[$offset];
    }

    
/**
     * Set the value at the given offset.
     *
     * @param  string  $offset
     * @param  mixed  $value
     * @return void
     *
     * @throws LogicException
     */
    
public function offsetSet($offset$value): void
    
{
        throw new 
LogicException('Response data may not be mutated using array access.');
    }

    
/**
     * Unset the value at the given offset.
     *
     * @param  string  $offset
     * @return void
     *
     * @throws LogicException
     */
    
public function offsetUnset($offset): void
    
{
        throw new 
LogicException('Response data may not be mutated using array access.');
    }

    
/**
     * Handle dynamic calls into macros or pass missing methods to the base response.
     *
     * @param  string  $method
     * @param  array  $args
     * @return mixed
     */
    
public function __call($method$args)
    {
        if (static::
hasMacro($method)) {
            return 
$this->macroCall($method$args);
        }

        return 
$this->baseResponse->{$method}(...$args);
    }
}
Онлайн: 0
Реклама