Passed
Pull Request — master (#82)
by Joao
01:44
created

ApiTestCase::assertRequestException()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 8
c 2
b 0
f 0
dl 0
loc 14
rs 10
cc 3
nc 3
nop 4
1
<?php
2
3
namespace ByJG\ApiTools;
4
5
use ByJG\ApiTools\Base\Schema;
6
use ByJG\ApiTools\Exception\DefinitionNotFoundException;
7
use ByJG\ApiTools\Exception\GenericSwaggerException;
8
use ByJG\ApiTools\Exception\HttpMethodNotFoundException;
9
use ByJG\ApiTools\Exception\InvalidDefinitionException;
10
use ByJG\ApiTools\Exception\InvalidRequestException;
11
use ByJG\ApiTools\Exception\NotMatchedException;
12
use ByJG\ApiTools\Exception\PathNotFoundException;
13
use ByJG\ApiTools\Exception\RequiredArgumentNotFound;
14
use ByJG\ApiTools\Exception\StatusCodeNotMatchedException;
15
use ByJG\WebRequest\Psr7\Response;
16
use PHPUnit\Framework\TestCase;
17
use Psr\Http\Message\ResponseInterface;
18
use Throwable;
19
20
abstract class ApiTestCase extends TestCase
21
{
22
    /**
23
     * @var Schema|null
24
     */
25
    protected ?Schema $schema = null;
26
27
    /**
28
     * @var AbstractRequester|null
29
     */
30
    protected ?AbstractRequester $requester = null;
31
32
    /**
33
     * configure the schema to use for requests
34
     *
35
     * When set, all requests without an own schema use this one instead.
36
     *
37
     * @param Schema|null $schema
38
     */
39
    public function setSchema(?Schema $schema): void
40
    {
41
        $this->schema = $schema;
42
    }
43
44
    public function setRequester(AbstractRequester $requester): void
45
    {
46
        $this->requester = $requester;
47
    }
48
49
    /**
50
     * @return AbstractRequester|null
51
     */
52
    protected function getRequester(): AbstractRequester|null
53
    {
54
        if (is_null($this->requester)) {
55
            $this->requester = new ApiRequester();
56
        }
57
        return $this->requester;
58
    }
59
60
    /**
61
     * @param string $method The HTTP Method: GET, PUT, DELETE, POST, etc
62
     * @param string $path The REST path call
63
     * @param int $statusExpected
64
     * @param string|array|null $query
65
     * @param array|string|null $requestBody
66
     * @param array $requestHeader
67
     * @return mixed
68
     * @throws DefinitionNotFoundException
69
     * @throws GenericSwaggerException
70
     * @throws HttpMethodNotFoundException
71
     * @throws InvalidDefinitionException
72
     * @throws InvalidRequestException
73
     * @throws NotMatchedException
74
     * @throws PathNotFoundException
75
     * @throws RequiredArgumentNotFound
76
     * @throws StatusCodeNotMatchedException
77
     * @deprecated Use assertRequest instead
78
     */
79
    protected function makeRequest(
80
        string $method,
81
        string $path,
82
        int $statusExpected = 200,
83
        string|array|null $query = null,
84
        array|string $requestBody = null,
85
        array $requestHeader = []
86
    ): ResponseInterface {
87
        $this->checkSchema();
88
        $body = $this->requester
89
            ->withSchema($this->schema)
0 ignored issues
show
Bug introduced by
It seems like $this->schema can also be of type null; however, parameter $schema of ByJG\ApiTools\AbstractRequester::withSchema() does only seem to accept ByJG\ApiTools\Base\Schema, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

89
            ->withSchema(/** @scrutinizer ignore-type */ $this->schema)
Loading history...
Bug introduced by
The method withSchema() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

89
            ->/** @scrutinizer ignore-call */ withSchema($this->schema)

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
90
            ->withMethod($method)
91
            ->withPath($path)
92
            ->withQuery($query)
93
            ->withRequestBody($requestBody)
0 ignored issues
show
Bug introduced by
It seems like $requestBody can also be of type null; however, parameter $requestBody of ByJG\ApiTools\AbstractRequester::withRequestBody() does only seem to accept array|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

93
            ->withRequestBody(/** @scrutinizer ignore-type */ $requestBody)
Loading history...
94
            ->withRequestHeader($requestHeader)
95
            ->assertResponseCode($statusExpected)
96
            ->send();
97
98
        // Note:
99
        // This code is only reached if to send is successful and
100
        // all matches are satisfied. Otherwise, an error is throwed before
101
        // reach this
102
        $this->assertTrue(true);
103
104
        return $body;
105
    }
106
107
    /**
108
     * @param AbstractRequester $request
109
     * @return Response
110
     * @throws DefinitionNotFoundException
111
     * @throws GenericSwaggerException
112
     * @throws HttpMethodNotFoundException
113
     * @throws InvalidDefinitionException
114
     * @throws InvalidRequestException
115
     * @throws NotMatchedException
116
     * @throws PathNotFoundException
117
     * @throws RequiredArgumentNotFound
118
     * @throws StatusCodeNotMatchedException
119
     */
120
    public function assertRequest(AbstractRequester $request, bool $matchQueryParams = true): ResponseInterface
121
    {
122
        // Add own schema if nothing is passed.
123
        if (!$request->hasSchema()) {
124
            $this->checkSchema();
125
            $request = $request->withSchema($this->schema);
0 ignored issues
show
Bug introduced by
It seems like $this->schema can also be of type null; however, parameter $schema of ByJG\ApiTools\AbstractRequester::withSchema() does only seem to accept ByJG\ApiTools\Base\Schema, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

125
            $request = $request->withSchema(/** @scrutinizer ignore-type */ $this->schema);
Loading history...
126
        }
127
128
        // Request based on the Swagger Request definitios
129
        $body = $request->send($matchQueryParams);
130
131
        // Note:
132
        // This code is only reached if to send is successful and
133
        // all matches are satisfied. Otherwise, an error is throwed before
134
        // reach this
135
        $this->assertTrue(true);
136
137
        return $body;
138
    }
139
140
    public function assertRequestException(AbstractRequester $request, string $exceptionClass, string $exceptionMessage = null, bool $matchQueryParams = true): Throwable
141
    {
142
        try {
143
            $this->assertRequest($request, $matchQueryParams);
144
        } catch (Throwable $ex) {
145
            $this->assertInstanceOf($exceptionClass, $ex);
146
147
            if (!empty($exceptionMessage)) {
148
                $this->assertStringContainsString($exceptionMessage, $ex->getMessage());
149
            }
150
151
            return $ex;
152
        }
153
        $this->fail("Expected exception '{$exceptionClass}' but no exception was thrown");
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return Throwable. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
154
    }
155
156
157
    /**
158
     * @throws GenericSwaggerException
159
     */
160
    protected function checkSchema(): void
161
    {
162
        if (!$this->schema) {
163
            throw new GenericSwaggerException('You have to configure a schema for either the request or the testcase');
164
        }
165
    }
166
}
167