Skip to content

Commit ca3b0ce

Browse files
committed
add code reference integration tests
Signed-off-by: Julien Veyssier <julien-nc@posteo.net>
1 parent e1b1cb4 commit ca3b0ce

1 file changed

Lines changed: 251 additions & 0 deletions

File tree

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
10+
namespace OCA\Github\Tests\Integration;
11+
12+
use OCA\Github\Reference\GithubCodeReferenceProvider;
13+
use OCA\Github\Service\SecretService;
14+
use OCP\Collaboration\Reference\IReference;
15+
use OCP\IConfig;
16+
use OCP\Server;
17+
use PHPUnit\Framework\Attributes\DependsExternal;
18+
use PHPUnit\Framework\Attributes\Group;
19+
use Test\TestCase;
20+
21+
#[Group('DB')]
22+
class GitHubCodeReferenceIntegrationTest extends TestCase {
23+
private GithubCodeReferenceProvider $referenceProvider;
24+
private SecretService $secretService;
25+
private IConfig $config;
26+
27+
protected function setUp(): void {
28+
parent::setUp();
29+
30+
$this->referenceProvider = Server::get(GithubCodeReferenceProvider::class);
31+
$this->secretService = Server::get(SecretService::class);
32+
$this->config = Server::get(IConfig::class);
33+
}
34+
35+
#[DependsExternal(GithubOauthIntegrationTest::class, 'testOAuthLogin')]
36+
public function testResolveSingleLineCodeReference(array $oauthData): void {
37+
$this->assertIsArray($oauthData, 'oauthData should be an array from OAuth test');
38+
$this->assertArrayHasKey('userId', $oauthData, 'oauthData must contain userId');
39+
$userId = $oauthData['userId'];
40+
41+
$token = $this->secretService->getEncryptedUserValue($userId, 'token');
42+
$this->assertNotSame('', $token, 'Token should be stored after OAuth flow');
43+
44+
$referenceUrl = 'https://github.com/nextcloud/server/blob/master/lib/base.php#L1';
45+
$reference = $this->referenceProvider->resolveReference($referenceUrl);
46+
47+
$this->assertInstanceOf(IReference::class, $reference, 'Should resolve code reference');
48+
49+
$richObject = $reference->getRichObject();
50+
$this->assertIsArray($richObject, 'Rich object should be an array');
51+
$this->assertCodeRichObjectStructure($richObject);
52+
}
53+
54+
private function assertCodeRichObjectStructure(array $richObject): void {
55+
$this->assertArrayHasKey('github_type', $richObject, 'Must have github_type');
56+
$this->assertContains($richObject['github_type'], ['code', 'code-error'], 'github_type should be code or code-error');
57+
58+
if ($richObject['github_type'] === 'code-error') {
59+
$this->assertArrayHasKey('error', $richObject, 'Error type should have error info');
60+
return;
61+
}
62+
63+
$this->assertArrayHasKey('owner', $richObject, 'Must have owner');
64+
$this->assertArrayHasKey('repo', $richObject, 'Must have repo');
65+
$this->assertArrayHasKey('filePath', $richObject, 'Must have filePath');
66+
$this->assertArrayHasKey('link', $richObject, 'Must have link');
67+
$this->assertArrayHasKey('html_url', $richObject, 'Must have html_url');
68+
69+
$this->assertArrayHasKey('ref', $richObject, 'Must have ref');
70+
$this->assertIsArray($richObject['ref'], 'ref should be an array');
71+
$this->assertArrayHasKey('original_ref', $richObject['ref'], 'ref must have original_ref');
72+
$this->assertArrayHasKey('sha', $richObject['ref'], 'ref must have sha');
73+
74+
$this->assertArrayHasKey('lineBegin', $richObject, 'Must have lineBegin');
75+
$this->assertIsInt($richObject['lineBegin'], 'lineBegin should be an integer');
76+
$this->assertGreaterThan(0, $richObject['lineBegin'], 'lineBegin should be positive');
77+
78+
$this->assertArrayHasKey('lines', $richObject, 'Must have lines array');
79+
$this->assertIsArray($richObject['lines'], 'lines should be an array');
80+
$this->assertNotEmpty($richObject['lines'], 'lines should not be empty');
81+
82+
$this->assertStringContainsString('github.com', $richObject['link'], 'link should contain github.com');
83+
$this->assertStringContainsString($richObject['owner'], $richObject['filePath'], 'filePath should contain owner path');
84+
}
85+
86+
#[DependsExternal(GithubOauthIntegrationTest::class, 'testOAuthLogin')]
87+
public function testResolveMultiLineCodeReference(array $oauthData): void {
88+
$this->assertIsArray($oauthData, 'oauthData should be an array from OAuth test');
89+
$this->assertArrayHasKey('userId', $oauthData, 'oauthData must contain userId');
90+
91+
$referenceUrl = 'https://github.com/nextcloud/server/blob/master/lib/base.php#L1-L5';
92+
$reference = $this->referenceProvider->resolveReference($referenceUrl);
93+
94+
$this->assertInstanceOf(IReference::class, $reference, 'Should resolve multi-line code reference');
95+
96+
$richObject = $reference->getRichObject();
97+
98+
if ($richObject['github_type'] === 'code-error') {
99+
$this->markTestSkipped('GitHub API error for multi-line reference');
100+
}
101+
102+
$this->assertArrayHasKey('lineEnd', $richObject, 'Must have lineEnd for multi-line');
103+
$this->assertIsInt($richObject['lineEnd'], 'lineEnd should be an integer');
104+
$this->assertGreaterThan($richObject['lineBegin'], $richObject['lineEnd'], 'lineEnd should be greater than lineBegin');
105+
106+
$expectedLineCount = $richObject['lineEnd'] - $richObject['lineBegin'] + 1;
107+
$this->assertCount($expectedLineCount, $richObject['lines'], 'lines array should have correct count');
108+
}
109+
110+
#[DependsExternal(GithubOauthIntegrationTest::class, 'testOAuthLogin')]
111+
public function testMatchReference(array $oauthData): void {
112+
$this->assertIsArray($oauthData, 'oauthData should be an array from OAuth test');
113+
114+
$validSingleLine = 'https://github.com/nextcloud/server/blob/master/lib/base.php#L1';
115+
$validMultiLine = 'https://github.com/nextcloud/server/blob/abc123/lib/base.php#L1-L10';
116+
$invalidNoLine = 'https://github.com/nextcloud/server/blob/master/lib/base.php';
117+
$invalidWrongUrl = 'https://github.com/nextcloud/server';
118+
119+
$this->assertTrue($this->referenceProvider->matchReference($validSingleLine), 'Should match single line URL');
120+
$this->assertTrue($this->referenceProvider->matchReference($validMultiLine), 'Should match multi-line URL');
121+
$this->assertFalse($this->referenceProvider->matchReference($invalidNoLine), 'Should not match URL without line');
122+
$this->assertFalse($this->referenceProvider->matchReference($invalidWrongUrl), 'Should not match non-blob URL');
123+
}
124+
125+
#[DependsExternal(GithubOauthIntegrationTest::class, 'testOAuthLogin')]
126+
public function testReferenceTitle(array $oauthData): void {
127+
$this->assertIsArray($oauthData, 'oauthData should be an array from OAuth test');
128+
$this->assertArrayHasKey('userId', $oauthData, 'oauthData must contain userId');
129+
130+
$referenceUrl = 'https://github.com/nextcloud/server/blob/master/lib/base.php#L1';
131+
$reference = $this->referenceProvider->resolveReference($referenceUrl);
132+
133+
$this->assertInstanceOf(IReference::class, $reference, 'Should resolve code reference');
134+
135+
$title = $reference->getTitle();
136+
$this->assertNotEmpty($title, 'Reference should have a title');
137+
$this->assertStringContainsString('permalink', strtolower($title), 'Title should mention permalink');
138+
}
139+
140+
#[DependsExternal(GithubOauthIntegrationTest::class, 'testOAuthLogin')]
141+
public function testReferenceDescription(array $oauthData): void {
142+
$this->assertIsArray($oauthData, 'oauthData should be an array from OAuth test');
143+
$this->assertArrayHasKey('userId', $oauthData, 'oauthData must contain userId');
144+
145+
$referenceUrl = 'https://github.com/nextcloud/server/blob/master/lib/base.php#L1';
146+
$reference = $this->referenceProvider->resolveReference($referenceUrl);
147+
148+
$this->assertInstanceOf(IReference::class, $reference, 'Should resolve code reference');
149+
150+
$richObject = $reference->getRichObject();
151+
152+
if ($richObject['github_type'] !== 'code-error') {
153+
$description = $reference->getDescription();
154+
$this->assertNotEmpty($description, 'Reference should have a description with code content');
155+
}
156+
}
157+
158+
#[DependsExternal(GithubOauthIntegrationTest::class, 'testOAuthLogin')]
159+
public function testShortRefFormat(array $oauthData): void {
160+
$this->assertIsArray($oauthData, 'oauthData should be an array from OAuth test');
161+
$this->assertArrayHasKey('userId', $oauthData, 'oauthData must contain userId');
162+
163+
$referenceUrl = 'https://github.com/nextcloud/server/blob/master/lib/base.php#L1';
164+
$reference = $this->referenceProvider->resolveReference($referenceUrl);
165+
166+
$this->assertInstanceOf(IReference::class, $reference, 'Should resolve code reference');
167+
168+
$richObject = $reference->getRichObject();
169+
170+
if ($richObject['github_type'] !== 'code-error') {
171+
$this->assertArrayHasKey('ref', $richObject);
172+
$this->assertArrayHasKey('original_ref', $richObject['ref']);
173+
$this->assertArrayHasKey('sha', $richObject['ref']);
174+
175+
if ($richObject['ref']['sha'] !== '') {
176+
$this->assertMatchesRegularExpression('/^[0-9a-f]{7,40}$/', $richObject['ref']['sha'], 'sha should be a valid git hash');
177+
}
178+
}
179+
}
180+
181+
#[DependsExternal(GithubOauthIntegrationTest::class, 'testOAuthLogin')]
182+
public function testVcsCodePermalinkStructure(array $oauthData): void {
183+
$this->assertIsArray($oauthData, 'oauthData should be an array from OAuth test');
184+
$this->assertArrayHasKey('userId', $oauthData, 'oauthData must contain userId');
185+
186+
$referenceUrl = 'https://github.com/nextcloud/server/blob/master/lib/base.php#L1';
187+
$reference = $this->referenceProvider->resolveReference($referenceUrl);
188+
189+
$this->assertInstanceOf(IReference::class, $reference, 'Should resolve code reference');
190+
191+
$richObject = $reference->getRichObject();
192+
193+
if ($richObject['github_type'] !== 'code-error') {
194+
$this->assertArrayHasKey('vcs_code_permalink', $richObject, 'Must have vcs_code_permalink');
195+
$vcsCode = $richObject['vcs_code_permalink'];
196+
197+
$this->assertIsArray($vcsCode, 'vcs_code_permalink should be an array');
198+
$this->assertArrayHasKey('line_begin', $vcsCode, 'vcs_code_permalink must have line_begin');
199+
$this->assertArrayHasKey('line_end', $vcsCode, 'vcs_code_permalink must have line_end');
200+
$this->assertArrayHasKey('lines', $vcsCode, 'vcs_code_permalink must have lines');
201+
$this->assertArrayHasKey('file_url', $vcsCode, 'vcs_code_permalink must have file_url');
202+
$this->assertArrayHasKey('file_path', $vcsCode, 'vcs_code_permalink must have file_path');
203+
$this->assertArrayHasKey('file_name', $vcsCode, 'vcs_code_permalink must have file_name');
204+
205+
$this->assertSame($richObject['lineBegin'], $vcsCode['line_begin'], 'line_begin should match lineBegin');
206+
$this->assertSame($richObject['filePath'], $vcsCode['file_path'], 'file_path should match filePath');
207+
$this->assertSame(basename($richObject['filePath']), $vcsCode['file_name'], 'file_name should be basename of filePath');
208+
}
209+
}
210+
211+
#[DependsExternal(GithubOauthIntegrationTest::class, 'testOAuthLogin')]
212+
public function testCodeLinesContent(array $oauthData): void {
213+
$this->assertIsArray($oauthData, 'oauthData should be an array from OAuth test');
214+
$this->assertArrayHasKey('userId', $oauthData, 'oauthData must contain userId');
215+
216+
$referenceUrl = 'https://github.com/nextcloud/server/blob/master/lib/base.php#L1-L3';
217+
$reference = $this->referenceProvider->resolveReference($referenceUrl);
218+
219+
$this->assertInstanceOf(IReference::class, $reference, 'Should resolve code reference');
220+
221+
$richObject = $reference->getRichObject();
222+
223+
if ($richObject['github_type'] !== 'code-error') {
224+
$this->assertArrayHasKey('lines', $richObject);
225+
$this->assertCount(3, $richObject['lines'], 'Should have 3 lines');
226+
227+
foreach ($richObject['lines'] as $line) {
228+
$this->assertIsString($line, 'Each line should be a string');
229+
}
230+
}
231+
}
232+
233+
#[DependsExternal(GithubOauthIntegrationTest::class, 'testOAuthLogin')]
234+
public function testFilePathExtraction(array $oauthData): void {
235+
$this->assertIsArray($oauthData, 'oauthData should be an array from OAuth test');
236+
$this->assertArrayHasKey('userId', $oauthData, 'oauthData must contain userId');
237+
238+
$referenceUrl = 'https://github.com/nextcloud/server/blob/master/lib/base.php#L1';
239+
$reference = $this->referenceProvider->resolveReference($referenceUrl);
240+
241+
$this->assertInstanceOf(IReference::class, $reference, 'Should resolve code reference');
242+
243+
$richObject = $reference->getRichObject();
244+
245+
if ($richObject['github_type'] !== 'code-error') {
246+
$this->assertArrayHasKey('filePath', $richObject);
247+
$this->assertStringEndsWith('.php', $richObject['filePath'], 'filePath should end with .php');
248+
$this->assertStringContainsString('lib', $richObject['filePath'], 'filePath should contain lib');
249+
}
250+
}
251+
}

0 commit comments

Comments
 (0)