Completed
Push — master ( a4da11...a3057e )
by Michal
04:48
created

GithubControllerTest::testSyncIssueStatus()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 47
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 47
rs 9.0303
cc 2
eloc 27
nc 2
nop 0
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
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(array('Developer.id' => 1, 'access_token' => 'abc'));
49
        $this->Reports = TableRegistry::get('Reports');
0 ignored issues
show
Bug introduced by
The property Reports does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
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, $issueResponse
77
        );
78
        $curlGetInfoMock->expects($this->exactly(2))->willReturnOnConsecutiveCalls(
79
            403, 201
80
        );
81
82
        // Case 3. Test submission of form with unsuccessful github response
83
        $this->post(
84
            'github/create_issue/5',
85
            array(
86
                'summary' => 'Error testing',
87
                'milestone' => '3.8',
88
                'description' => 'Lorem ipsum dolor sit amet',
89
                'labels' => 'test-pma'
90
            )
91
        );
92
93
        $this->enableRetainFlashMessages();
94
        $report = $this->Reports->get(5);
95
        $this->assertEquals(null, $report->sourceforge_bug_id);
96
        $this->assertEquals('new', $report->status);
97
        $this->assertSession(
98
            'Unauthorised access to Github. github credentials may be out of date.'
99
            . ' Please check and try again later.',
100
            'Flash.flash.0.message'
101
        );
102
103
        // Case 4. Test submission of form with successful Github response
104
        $this->post(
105
            'github/create_issue/5',
106
            array(
107
                'summary' => 'Error testing',
108
                'milestone' => '3.8',
109
                'description' => 'Lorem ipsum dolor sit amet',
110
                'labels' => 'test-pma'
111
            )
112
        );
113
114
        $report = $this->Reports->get(5);
115
        $this->assertEquals(1347, $report->sourceforge_bug_id);
116
        $this->assertEquals('forwarded', $report->status);
117
    }
118
119
    /**
120
     * Test link_issue method
121
     *
122
     * @return void
123
     */
124
    public function testLinkIssue()
125
    {
126
        // Mock functions `curl_exec` and `curl_getinfo` in GithubApiComponent
127
        // so that we don't actually hit the Github Api
128
        $curlExecMock = $this->getFunctionMock('\App\Controller\Component', 'curl_exec');
129
        $curlGetInfoMock = $this->getFunctionMock('\App\Controller\Component', 'curl_getinfo');
130
131
        // Case 1.1 Test with an invalid reportId
132
        $this->get('github/link_issue/123?ticket_id=1');
133
        $this->assertResponseContains('Invalid report');
134
135
        // Case 1.2 Test with an invalid ticketId
136
        $this->get('github/link_issue/5?ticket_id=');
137
        $this->assertResponseContains('Invalid Ticket ID');
138
139
        $issueResponse = file_get_contents(TESTS . 'Fixture' . DS . 'issue_response.json');
140
        $decodedResponse = json_decode($issueResponse, true);
141
        $decodedResponse['state'] = 'closed';
142
        $issueResponseWithClosed = json_encode($decodedResponse);
143
144
        $commentResponse = file_get_contents(TESTS . 'Fixture' . DS . 'comment_response.json');
0 ignored issues
show
Unused Code introduced by
$commentResponse is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
145
146
147
        // Github response unsuccessful followed by successful (open) and successful (closed)
148
        $curlExecMock->expects($this->exactly(5))->willReturnOnConsecutiveCalls(
149
            $issueResponse,
150
            $issueResponse, $issueResponse,
151
            $issueResponseWithClosed, $issueResponseWithClosed
152
        );
153
        $curlGetInfoMock->expects($this->exactly(5))->willReturnOnConsecutiveCalls(
154
            404,
155
            201, 200,
156
            201, 200
157
        );
158
159
        // Case 2. Test submission of form with unsuccessful github response
160
        $this->get(
161
            'github/link_issue/5?ticket_id=9999999'
162
        );
163
164
        $this->enableRetainFlashMessages();
165
        $report = $this->Reports->get(5);
166
        $this->assertEquals(null, $report->sourceforge_bug_id);
167
        $this->assertEquals('new', $report->status);
168
        $this->assertSession(
169
            'Bug Issue not found on Github. Are you sure the issue number is correct? '
170
            . 'Please check and try again!',
171
            'Flash.flash.0.message'
172
        );
173
174
        // Case 3. Test submission of form with successful Github response (with issue open)
175
        $this->get(
176
            'github/link_issue/5?ticket_id=1387'
177
        );
178
179
        $report = $this->Reports->get(5);
180
        $this->assertEquals(1387, $report->sourceforge_bug_id);
181
        $this->assertEquals('forwarded', $report->status);
182
183
        // Case 4. Test submission of form with successful Github response (with issue closed)
184
        $this->get(
185
            'github/link_issue/5?ticket_id=1387'
186
        );
187
188
        $report = $this->Reports->get(5);
189
        $this->assertEquals(1387, $report->sourceforge_bug_id);
190
        $this->assertEquals('resolved', $report->status);
191
    }
192
193
    /**
194
     * Test unlink_issue method
195
     *
196
     * @return void
197
     */
198
    public function testUnlinkIssue()
199
    {
200
        // Mock functions `curl_exec` and `curl_getinfo` in GithubApiComponent
201
        // so that we don't actually hit the Github Api
202
        $curlExecMock = $this->getFunctionMock('\App\Controller\Component', 'curl_exec');
203
        $curlGetInfoMock = $this->getFunctionMock('\App\Controller\Component', 'curl_getinfo');
204
205
        // Case 1.1 Test with an invalid reportId
206
        $this->get('github/unlink_issue/123');
207
        $this->assertResponseContains('Invalid report');
208
209
        // Case 1.2 Test unlinked with an already unlinked issue
210
        $this->get('github/unlink_issue/5');
211
        $this->assertResponseContains('Invalid Ticket ID');
212
213
        $commentResponse = file_get_contents(TESTS . 'Fixture' . DS . 'comment_response.json');
214
215
        // Github response unsuccessful followed by successful
216
        $curlExecMock->expects($this->exactly(2))->willReturnOnConsecutiveCalls(
217
            json_encode(array('message' => 'Unauthorised access')),
218
            $commentResponse
219
        );
220
        $curlGetInfoMock->expects($this->exactly(2))->willReturnOnConsecutiveCalls(
221
            401,
222
            201
223
        );
224
225
        // Link the report before trying to unlink
226
        $report = $this->Reports->get(5);
227
        $report->sourceforge_bug_id = 1387;
228
        $report->status = 'forwarded';
229
        $this->Reports->save($report);
230
231
        // Case 2. Test submission of form with unsuccessful and unexpected github response
232
        $this->get(
233
            'github/unlink_issue/5'
234
        );
235
236
        $this->enableRetainFlashMessages();
237
        $report = $this->Reports->get(5);
238
        $this->assertEquals(1387, $report->sourceforge_bug_id);
239
        $this->assertEquals('forwarded', $report->status);
240
        $this->assertSession(
241
            'Unhandled response code recieved: 401',
242
            'Flash.flash.0.message'
243
        );
244
245
        // Case 3. Test submission of form with successful Github response
246
        $this->get(
247
            'github/unlink_issue/5'
248
        );
249
250
        $report = $this->Reports->get(5);
251
        $this->assertEquals(null, $report->sourceforge_bug_id);
252
        $this->assertEquals('new', $report->status);
253
254
    }
255
256
    /**
257
     * Test sync_issue_status method
258
     *
259
     * @return void
260
     */
261
    public function testSyncIssueStatus()
262
    {
263
        // Mock functions `curl_exec` and `curl_getinfo` in GithubApiComponent
264
        // so that we don't actually hit the Github Api
265
        $curlExecMock = $this->getFunctionMock('\App\Controller\Component', 'curl_exec');
266
        $curlGetInfoMock = $this->getFunctionMock('\App\Controller\Component', 'curl_getinfo');
267
268
        // Test via web interface
269
        $this->enableRetainFlashMessages();
270
        $this->get('github/sync_issue_status');
271
        $this->assertRedirect('/');
272
273
        $issueResponse = file_get_contents(TESTS . 'Fixture' . DS . 'issue_response.json');
274
        $decodedResponse = json_decode($issueResponse, true);
275
        $decodedResponse['state'] = 'closed';
276
        $issueResponseWithClosed = json_encode($decodedResponse);
277
278
        // Github response unsuccessful followed by two successful responses
279
        $curlExecMock->expects($this->exactly(3))->willReturnOnConsecutiveCalls(
280
            json_encode(array('message' => 'Unauthorised access')),
281
            $issueResponse,
282
            $issueResponseWithClosed
283
        );
284
        $curlGetInfoMock->expects($this->exactly(3))->willReturnOnConsecutiveCalls(
285
            401,
286
            200,
287
            200
288
        );
289
290
        // Test via cli (i.e. the constant CRON_DISPATCHER should be defined)
291
        if (!defined('CRON_DISPATCHER')) {
292
            define('CRON_DISPATCHER', true);
293
        }
294
        $this->get('github/sync_issue_status');
295
296
        // 401
297
        $report = $this->Reports->get(1);
298
        $this->assertEquals('forwarded', $report->status);
299
300
        // 200 (open state)
301
        $report = $this->Reports->get(2);
302
        $this->assertEquals('forwarded', $report->status);
303
304
        // 200 (closed state)
305
        $report = $this->Reports->get(4);
306
        $this->assertEquals('resolved', $report->status);
307
    }
308
}
309