aboutsummaryrefslogtreecommitdiff
path: root/tests/jsonapi/JSONAPIHelperTrait.php
blob: 666e1981f29dacc83449024b49d6f95c60e3fa8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<?php

use WoohooLabs\Yang\JsonApi\Response\JsonApiResponse;
use WoohooLabs\Yang\JsonApi\Schema\Document;
use WoohooLabs\Yang\JsonApi\Schema\Resource\ResourceObject;

trait JSONAPIHelperTrait
{
    protected JSONAPITester $tester;

    protected function _before()
    {
        DBManager::getInstance()->setConnection(
            'studip',
            $this->getModule('\\Helper\\StudipDb')->dbh
        );
    }

    protected function withStudipEnv(array $credentials, callable $fn)
    {
        // Create global template factory if neccessary
        $has_template_factory = isset($GLOBALS['template_factory']);
        if (!$has_template_factory) {
            $GLOBALS['template_factory'] = new Flexi\Factory($GLOBALS['STUDIP_BASE_PATH'] . '/templates');
        }

        $result = $this->tester->withPHPLib($credentials, $fn);

        if (!$has_template_factory) {
            unset($GLOBALS['template_factory']);
        }

        return $result;
    }

    protected function sendMockRequest(string $route, string $handler, array $credentials, array $variables = [], array $options = []): JsonApiResponse
    {
        $options = array_merge([
            'method'                => 'GET',
            'considered_successful' => [200],
            'json_body'             => null,
        ], $options);

        $app = $this->tester->createApp(
            $credentials,
            strtolower($options['method']),
            $route,
            $handler
        );

        $evaluated_route = preg_replace_callback(
            '/\{(.+?)(:[^}]+)?}/',
            function ($match) use ($variables) {
                $key = $match[1];
                if (!isset($variables[$key])) {
                    throw new Exception("No variable '{$key}' defined");
                }
                return $variables[$key];
            },
            $route
        );

        $requestBuilder = $this->tester->createRequestBuilder($credentials);
        $requestBuilder->setUri($evaluated_route)->setMethod(strtoupper($options['method']));

        if (isset($options['json_body'])) {
            $requestBuilder->setJsonApiBody($options['json_body']);

        }

        /** @var JsonApiResponse $response */
        $response = $this->withStudipEnv($credentials, function () use ($app, $requestBuilder) {
            return $this->tester->sendMockRequest($app, $requestBuilder->getRequest());
        });

        if ($options['considered_successful']) {
            $this->assertTrue(
                $response->isSuccessful($options['considered_successful']),
                'Actual status code is ' . $response->getStatusCode()
            );
        }

        return $response;
    }

    protected function getSingleResourceDocument(JsonApiResponse $response): Document
    {
        $this->assertTrue($response->hasDocument());

        $document = $response->document();
        $this->assertTrue($document->isSingleResourceDocument());

        return $document;
    }

    protected function getResourceCollectionDocument(JsonApiResponse $response): Document
    {
        $this->assertTrue($response->hasDocument());

        $document = $response->document();
        $this->assertTrue($document->isResourceCollectionDocument());

        return $document;
    }

    protected function assertHasRelations(ResourceObject $resource, ...$relations)
    {
        foreach ($relations as $relation) {
            $this->assertTrue($resource->hasRelationship($relation));
        }
    }

    protected function getResourceFromResponse(JsonApiResponse $response): ResourceObject
    {
        return $this->getSingleResourceDocument($response)->primaryResource();
    }
}