Completed
Push — master ( bc825a...1aba9a )
by William
06:03
created

GithubControllerTest::testCreateIssue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 62
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 36
nc 1
nop 0
dl 0
loc 62
rs 9.344
c 2
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* vim: set expandtab sw=4 ts=4 sts=4: */
3
4
/**
5
 * Tests for Github Controller actions
6
 *
7
 * phpMyAdmin Error reporting server
8
 * Copyright (c) phpMyAdmin project (https://www.phpmyadmin.net/)
9
 *
10
 * Licensed under The MIT License
11
 * For full copyright and license information, please see the LICENSE.txt
12
 * Redistributions of files must retain the above copyright notice.
13
 *
14
 * @copyright Copyright (c) phpMyAdmin project (https://www.phpmyadmin.net/)
15
 * @license   https://opensource.org/licenses/mit-license.php MIT License
16
 *
17
 * @see      https://www.phpmyadmin.net/
18
 */
19
20
namespace App\Test\TestCase\Controller;
21
22
use App\Controller\GithubController;
23
use Cake\Core\Configure;
24
use Cake\ORM\TableRegistry;
25
use Cake\TestSuite\IntegrationTestCase;
26
27
/**
28
 * App\Controller\GithubController Test Case
29
 */
30
class GithubControllerTest extends IntegrationTestCase
0 ignored issues
show
Deprecated Code introduced by
The class Cake\TestSuite\IntegrationTestCase has been deprecated: 3.7.0 Use Cake\TestSuite\IntegrationTestTrait instead ( Ignorable by Annotation )

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

30
class GithubControllerTest extends /** @scrutinizer ignore-deprecated */ IntegrationTestCase
Loading history...
31
{
32
33
    use \phpmock\phpunit\PHPMock;
34
    /**
35
     * Fixtures
36
     *
37
     * @var array
38
     */
39
    public $fixtures = [
40
        'app.Reports',
41
        'app.Developers',
42
        'app.Incidents',
43
        'app.Notifications',
44
    ];
45
46
    public function setUp()
47
    {
48
        $this->session(['Developer.id' => 1, 'access_token' => 'abc']);
49
        $this->Reports = TableRegistry::get('Reports');
0 ignored issues
show
Bug Best Practice introduced by
The property Reports does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
Deprecated Code introduced by
The function Cake\ORM\TableRegistry::get() has been deprecated: 3.6.0 Use \Cake\ORM\Locator\TableLocator::get() instead. ( Ignorable by Annotation )

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

49
        $this->Reports = /** @scrutinizer ignore-deprecated */ TableRegistry::get('Reports');

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
50
    }
51
52
    /**
53
     * Test create_issue method
54
     *
55
     * @return void
56
     */
57
    public function testCreateIssue()
58
    {
59
        // Mock functions `curl_exec` and `curl_getinfo` in GithubApiComponent
60
        // so that we don't actually hit the Github Api
61
        $curlExecMock = $this->getFunctionMock('\App\Controller\Component', 'curl_exec');
62
        $curlGetInfoMock = $this->getFunctionMock('\App\Controller\Component', 'curl_getinfo');
63
64
        // Case 1. Test with an invalid reportId
65
        $this->get('github/create_issue/123');
66
        $this->assertResponseContains('Invalid report');
67
68
        // Case 2. Test form with valid reportId
69
        $this->get('github/create_issue/5');
70
        $this->assertResponseContains('Lorem ipsum dolor sit amet'); // Description
71
72
        $issueResponse = file_get_contents(TESTS . 'Fixture' . DS . 'issue_response.json');
73
74
        // Github unsuccessful response followed by successful response
75
        $curlExecMock->expects($this->exactly(2))->willReturnOnConsecutiveCalls(
76
            $issueResponse,
77
            $issueResponse
78
        );
79
        $curlGetInfoMock->expects($this->exactly(2))->willReturnOnConsecutiveCalls(
80
            403,
81
            201
82
        );
83
84
        // Case 3. Test submission of form with unsuccessful github response
85
        $this->post(
86
            'github/create_issue/5',
87
            [
88
                'summary' => 'Error testing',
89
                'milestone' => '3.8',
90
                'description' => 'Lorem ipsum dolor sit amet',
91
                'labels' => 'test-pma'
92
            ]
93
        );
94
95
        $this->enableRetainFlashMessages();
96
        $report = $this->Reports->get(5);
97
        $this->assertEquals(null, $report->sourceforge_bug_id);
98
        $this->assertEquals('new', $report->status);
99
        $this->assertSession(
100
            'Unauthorised access to Github. github credentials may be out of date.'
101
            . ' Please check and try again later.',
102
            'Flash.flash.0.message'
103
        );
104
105
        // Case 4. Test submission of form with successful Github response
106
        $this->post(
107
            'github/create_issue/5',
108
            [
109
                'summary' => 'Error testing',
110
                'milestone' => '3.8',
111
                'description' => 'Lorem ipsum dolor sit amet',
112
                'labels' => 'test-pma'
113
            ]
114
        );
115
116
        $report = $this->Reports->get(5);
117
        $this->assertEquals(1347, $report->sourceforge_bug_id);
118
        $this->assertEquals('forwarded', $report->status);
119
    }
120
121
    /**
122
     * Test link_issue method
123
     *
124
     * @return void
125
     */
126
    public function testLinkIssue()
127
    {
128
        // Mock functions `curl_exec` and `curl_getinfo` in GithubApiComponent
129
        // so that we don't actually hit the Github Api
130
        $curlExecMock = $this->getFunctionMock('\App\Controller\Component', 'curl_exec');
131
        $curlGetInfoMock = $this->getFunctionMock('\App\Controller\Component', 'curl_getinfo');
132
133
        // Case 1.1 Test with an invalid reportId
134
        $this->get('github/link_issue/123?ticket_id=1');
135
        $this->assertResponseContains('Invalid report');
136
137
        // Case 1.2 Test with an invalid ticketId
138
        $this->get('github/link_issue/5?ticket_id=');
139
        $this->assertResponseContains('Invalid Ticket ID');
140
141
        $issueResponse = file_get_contents(TESTS . 'Fixture' . DS . 'issue_response.json');
142
        $decodedResponse = json_decode($issueResponse, true);
143
        $decodedResponse['state'] = 'closed';
144
        $issueResponseWithClosed = json_encode($decodedResponse);
145
146
        $commentResponse = file_get_contents(TESTS . 'Fixture' . DS . 'comment_response.json');
0 ignored issues
show
Unused Code introduced by
The assignment to $commentResponse is dead and can be removed.
Loading history...
147
148
149
        // Github response unsuccessful followed by successful (open) and successful (closed)
150
        $curlExecMock->expects($this->exactly(5))->willReturnOnConsecutiveCalls(
151
            $issueResponse,
152
            $issueResponse,
153
            $issueResponse,
154
            $issueResponseWithClosed,
155
            $issueResponseWithClosed
156
        );
157
        $curlGetInfoMock->expects($this->exactly(5))->willReturnOnConsecutiveCalls(
158
            404,
159
            201,
160
            200,
161
            201,
162
            200
163
        );
164
165
        // Case 2. Test submission of form with unsuccessful github response
166
        $this->get(
167
            'github/link_issue/5?ticket_id=9999999'
168
        );
169
170
        $this->enableRetainFlashMessages();
171
        $report = $this->Reports->get(5);
172
        $this->assertEquals(null, $report->sourceforge_bug_id);
173
        $this->assertEquals('new', $report->status);
174
        $this->assertSession(
175
            'Bug Issue not found on Github. Are you sure the issue number is correct? '
176
            . 'Please check and try again!',
177
            'Flash.flash.0.message'
178
        );
179
180
        // Case 3. Test submission of form with successful Github response (with issue open)
181
        $this->get(
182
            'github/link_issue/5?ticket_id=1387'
183
        );
184
185
        $report = $this->Reports->get(5);
186
        $this->assertEquals(1387, $report->sourceforge_bug_id);
187
        $this->assertEquals('forwarded', $report->status);
188
189
        // Case 4. Test submission of form with successful Github response (with issue closed)
190
        $this->get(
191
            'github/link_issue/5?ticket_id=1387'
192
        );
193
194
        $report = $this->Reports->get(5);
195
        $this->assertEquals(1387, $report->sourceforge_bug_id);
196
        $this->assertEquals('resolved', $report->status);
197
    }
198
199
    /**
200
     * Test unlink_issue method
201
     *
202
     * @return void
203
     */
204
    public function testUnlinkIssue()
205
    {
206
        // Mock functions `curl_exec` and `curl_getinfo` in GithubApiComponent
207
        // so that we don't actually hit the Github Api
208
        $curlExecMock = $this->getFunctionMock('\App\Controller\Component', 'curl_exec');
209
        $curlGetInfoMock = $this->getFunctionMock('\App\Controller\Component', 'curl_getinfo');
210
211
        // Case 1.1 Test with an invalid reportId
212
        $this->get('github/unlink_issue/123');
213
        $this->assertResponseContains('Invalid report');
214
215
        // Case 1.2 Test unlinked with an already unlinked issue
216
        $this->get('github/unlink_issue/5');
217
        $this->assertResponseContains('Invalid Ticket ID');
218
219
        $commentResponse = file_get_contents(TESTS . 'Fixture' . DS . 'comment_response.json');
220
221
        // Github response unsuccessful followed by successful
222
        $curlExecMock->expects($this->exactly(2))->willReturnOnConsecutiveCalls(
223
            json_encode(['message' => 'Unauthorised access']),
224
            $commentResponse
225
        );
226
        $curlGetInfoMock->expects($this->exactly(2))->willReturnOnConsecutiveCalls(
227
            401,
228
            201
229
        );
230
231
        // Link the report before trying to unlink
232
        $report = $this->Reports->get(5);
233
        $report->sourceforge_bug_id = 1387;
234
        $report->status = 'forwarded';
235
        $this->Reports->save($report);
236
237
        // Case 2. Test submission of form with unsuccessful and unexpected github response
238
        $this->get(
239
            'github/unlink_issue/5'
240
        );
241
242
        $this->enableRetainFlashMessages();
243
        $report = $this->Reports->get(5);
244
        $this->assertEquals(1387, $report->sourceforge_bug_id);
245
        $this->assertEquals('forwarded', $report->status);
246
        $this->assertSession(
247
            'Unhandled response code received: 401',
248
            'Flash.flash.0.message'
249
        );
250
251
        // Case 3. Test submission of form with successful Github response
252
        $this->get(
253
            'github/unlink_issue/5'
254
        );
255
256
        $report = $this->Reports->get(5);
257
        $this->assertEquals(null, $report->sourceforge_bug_id);
258
        $this->assertEquals('new', $report->status);
259
    }
260
261
    /**
262
     * Test sync_issue_status method
263
     *
264
     * @return void
265
     */
266
    public function testSyncIssueStatus()
267
    {
268
        // Mock functions `curl_exec` and `curl_getinfo` in GithubApiComponent
269
        // so that we don't actually hit the Github Api
270
        $curlExecMock = $this->getFunctionMock('\App\Controller\Component', 'curl_exec');
271
        $curlGetInfoMock = $this->getFunctionMock('\App\Controller\Component', 'curl_getinfo');
272
273
        // Test via web interface
274
        Configure::write('CronDispatcher', false);
275
        $this->enableRetainFlashMessages();
276
        $this->get('github/sync_issue_status');
277
        $this->assertRedirect('/');
278
279
        $issueResponse = file_get_contents(TESTS . 'Fixture' . DS . 'issue_response.json');
280
        $decodedResponse = json_decode($issueResponse, true);
281
        $decodedResponse['state'] = 'closed';
282
        $issueResponseWithClosed = json_encode($decodedResponse);
283
284
        // Github response unsuccessful followed by two successful responses
285
        $curlExecMock->expects($this->exactly(3))->willReturnOnConsecutiveCalls(
286
            json_encode(['message' => 'Unauthorised access']),
287
            $issueResponse,
288
            $issueResponseWithClosed
289
        );
290
        $curlGetInfoMock->expects($this->exactly(3))->willReturnOnConsecutiveCalls(
291
            401,
292
            200,
293
            200
294
        );
295
296
        // Test via cli (i.e. the CronDispatcher setting should be defined)
297
        Configure::write('CronDispatcher', true);
298
        $this->get('github/sync_issue_status');
299
300
        // 401
301
        $report = $this->Reports->get(1);
302
        $this->assertEquals('forwarded', $report->status);
303
304
        // 200 (open state)
305
        $report = $this->Reports->get(2);
306
        $this->assertEquals('forwarded', $report->status);
307
308
        // 200 (closed state)
309
        $report = $this->Reports->get(4);
310
        $this->assertEquals('resolved', $report->status);
311
    }
312
}
313