Completed
Pull Request — master (#105)
by Robbie
02:18
created

ApiLoaderTest::testNon200ErrorCodesAreHandled()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace BringYourOwnIdeas\Maintenance\Tests\Util;
4
5
use BringYourOwnIdeas\Maintenance\Util\ApiLoader;
6
use GuzzleHttp\Client;
7
use GuzzleHttp\Handler\MockHandler;
8
use GuzzleHttp\HandlerStack;
9
use GuzzleHttp\Psr7\Response;
10
use SilverStripe\Dev\SapphireTest;
11
use Symfony\Component\Cache\Simple\NullCache;
12
13
/**
14
 * @group wip
15
 */
16
class ApiLoaderTest extends SapphireTest
17
{
18
    /**
19
     * @expectedException RuntimeException
20
     * @expectedExceptionMessage Could not obtain information about module. Error code 404
21
     */
22
    public function testNon200ErrorCodesAreHandled()
23
    {
24
        $loader = $this->getLoader();
25
        $loader->setGuzzleClient($this->getMockClient(new Response(404)));
26
27
        $loader->doRequest('foo', function () {
28
            // noop
29
        });
30
    }
31
32
    /**
33
     * @expectedException RuntimeException
34
     * @expectedExceptionMessage Could not obtain information about module. Response is not JSON
35
     */
36
    public function testNonJsonResponsesAreHandled()
37
    {
38
        $loader = $this->getLoader();
39
        $loader->setGuzzleClient($this->getMockClient(new Response(
40
            200,
41
            ['Content-Type' => 'text/html; charset=utf-8']
42
        )));
43
44
        $loader->doRequest('foo', function () {
45
            // noop
46
        });
47
    }
48
49
    /**
50
     * @expectedException RuntimeException
51
     * @expectedExceptionMessage Could not obtain information about module. Response returned unsuccessfully
52
     */
53
    public function testUnsuccessfulResponsesAreHandled()
54
    {
55
        $loader = $this->getLoader();
56
        $loader->setGuzzleClient($this->getMockClient(new Response(
57
            200,
58
            ['Content-Type' => 'application/json'],
59
            json_encode(['success' => false])
60
        )));
61
62
        $loader->doRequest('foo', function () {
63
            // noop
64
        });
65
    }
66
67
    /**
68
     * Note: contains some logic from SupportedAddonsLoader for context
69
     *
70
     * @group integration
71
     */
72
    public function testAddonsAreParsedAndReturnedCorrectly()
73
    {
74
        $fakeAddons = ['foo/bar', 'bin/baz'];
75
76
        $loader = $this->getLoader();
77
        $loader->setGuzzleClient($this->getMockClient(new Response(
78
            200,
79
            ['Content-Type' => 'application/json'],
80
            json_encode(['success' => true, 'addons' => $fakeAddons])
81
        )));
82
83
        $addons = $loader->doRequest('foo', function ($responseBody) {
84
            return $responseBody['addons'];
85
        });
86
87
        $this->assertSame($fakeAddons, $addons);
88
    }
89
90
    /**
91
     * Note: contains some logic from SupportedAddonsLoader for context
92
     *
93
     * @group integration
94
     */
95
    public function testCacheControlSettingsAreRespected()
96
    {
97
        $fakeAddons = ['foo/bar', 'bin/baz'];
98
99
        $cacheMock = $this->getMockBuilder(NullCache::class)
100
            ->setMethods(['get', 'set'])
101
            ->getMock();
102
103
        $cacheMock->expects($this->once())->method('get')->will($this->returnValue(false));
104
        $cacheMock->expects($this->once())
105
            ->method('set')
106
            ->with($this->anything(), json_encode($fakeAddons), 5000)
107
            ->will($this->returnValue(true));
108
109
        $loader = $this->getLoader($cacheMock);
110
        $loader->setGuzzleClient($this->getMockClient(new Response(
111
            200,
112
            ['Content-Type' => 'application/json', 'Cache-Control' => 'max-age=5000'],
113
            json_encode(['success' => true, 'addons' => $fakeAddons])
114
        )));
115
116
        $loader->doRequest('foo', function ($responseBody) {
117
            return $responseBody['addons'];
118
        });
119
    }
120
121
    public function testCachedAddonsAreUsedWhenAvailable()
122
    {
123
        $fakeAddons = ['foo/bar', 'bin/baz'];
124
125
        $cacheMock = $this->getMockBuilder(NullCache::class)
126
            ->setMethods(['get', 'set'])
127
            ->getMock();
128
129
        $cacheMock->expects($this->once())->method('get')->will($this->returnValue(json_encode($fakeAddons)));
130
        $loader = $this->getLoader($cacheMock);
131
132
        $mockClient = $this->getMockBuilder(Client::class)->setMethods(['send'])->getMock();
133
        $mockClient->expects($this->never())->method('send');
134
        $loader->setGuzzleClient($mockClient);
135
136
        $addons = $loader->doRequest('foo', function () {
137
            // noop
138
        });
139
140
        $this->assertSame($fakeAddons, $addons);
141
    }
142
143
    /**
144
     * @param Response $withResponse
145
     * @return Client
146
     */
147
    protected function getMockClient(Response $withResponse)
148
    {
149
        $mock = new MockHandler([
150
            $withResponse
151
        ]);
152
153
        $handler = HandlerStack::create($mock);
154
        return new Client(['handler' => $handler]);
155
    }
156
157
    protected function getLoader($cacheMock = false)
158
    {
159
        if (!$cacheMock) {
160
            $cacheMock = $this->getMockBuilder(NullCache::class)
161
                ->setMethods(['get', 'set'])
162
                ->getMock();
163
164
            $cacheMock->expects($this->any())->method('get')->will($this->returnValue(false));
165
            $cacheMock->expects($this->any())->method('set')->will($this->returnValue(true));
166
        }
167
168
        $loader = $this->getMockBuilder(ApiLoader::class)
169
            ->getMockForAbstractClass();
170
171
        $loader->setCache($cacheMock);
172
173
        return $loader;
174
    }
175
}
176