Skip to content

Commit 27cbb64

Browse files
Copilotovertrue
andcommitted
Add comprehensive test coverage for all OAuth providers
- Expanded QQTest with redirect URL testing, token handling, user mapping, and error scenarios - Enhanced DingTalkTest with configuration testing, signature validation, and complete flow coverage - Improved DouYinTest with URL validation, token processing, user data handling, and edge cases - Extended WeWorkTest with OAuth URL generation, QR code mode, detailed user flow, and configuration testing - Broadened OpenWeWorkTest with redirect handling, user type configuration, and comprehensive user mapping - Augmented AlipayTest with sandbox mode, signature generation, field validation, and complete token flow All tests now cover normal functionality, configuration scenarios, method behaviors, error cases, and edge cases as requested in code review feedback. Co-authored-by: overtrue <[email protected]>
1 parent 334169a commit 27cbb64

File tree

6 files changed

+1420
-16
lines changed

6 files changed

+1420
-16
lines changed

tests/Providers/AlipayTest.php

Lines changed: 291 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,189 @@
44

55
use Mockery as m;
66
use Overtrue\Socialite\Exceptions\AuthorizeFailedException;
7+
use Overtrue\Socialite\Exceptions\BadRequestException;
8+
use Overtrue\Socialite\Exceptions\InvalidArgumentException;
79
use Overtrue\Socialite\Providers\Alipay;
810
use PHPUnit\Framework\TestCase;
11+
use ReflectionMethod;
912

1013
class AlipayTest extends TestCase
1114
{
12-
public function testThrowsExceptionWhenTokenResponseMissing()
15+
public function testAlipayProviderHasCorrectRedirectResponse()
1316
{
1417
$provider = new Alipay([
1518
'client_id' => 'client_id',
16-
'private_key' => 'private_key',
19+
'rsa_private_key' => 'private_key',
20+
'redirect_url' => 'http://localhost/callback',
21+
]);
22+
23+
$response = $provider->redirect();
24+
25+
$this->assertStringStartsWith('https://openauth.alipay.com/oauth2/publicAppAuthorize.htm', $response);
26+
$this->assertStringContains('redirect_uri=http%3A%2F%2Flocalhost%2Fcallback', $response);
27+
$this->assertStringContains('app_id=client_id', $response);
28+
$this->assertStringContains('scope=auth_user', $response);
29+
}
30+
31+
public function testAlipayProviderSandboxMode()
32+
{
33+
$provider = new Alipay([
34+
'client_id' => 'client_id',
35+
'rsa_private_key' => 'private_key',
36+
'redirect_url' => 'http://localhost/callback',
37+
'sandbox' => true,
38+
]);
39+
40+
$response = $provider->redirect();
41+
42+
$this->assertStringStartsWith('https://openauth.alipaydev.com/oauth2/publicAppAuthorize.htm', $response);
43+
}
44+
45+
public function testAlipayProviderUrlsAndFields()
46+
{
47+
$provider = new Alipay([
48+
'client_id' => 'client_id',
49+
'rsa_private_key' => 'private_key',
50+
'redirect_url' => 'http://localhost/callback',
51+
]);
52+
53+
$getTokenUrl = new ReflectionMethod(Alipay::class, 'getTokenUrl');
54+
$getTokenUrl->setAccessible(true);
55+
56+
$this->assertSame('https://openapi.alipay.com/gateway.do', $getTokenUrl->invoke($provider));
57+
}
58+
59+
public function testGetPublicFields()
60+
{
61+
$provider = new Alipay([
62+
'client_id' => 'test_app_id',
63+
'rsa_private_key' => 'private_key',
1764
'redirect_url' => 'http://localhost/callback',
1865
]);
1966

20-
// Mock the getHttpClient method to return response without token response
67+
$fields = $provider->getPublicFields('test.method');
68+
69+
$this->assertArrayHasKey('app_id', $fields);
70+
$this->assertSame('test_app_id', $fields['app_id']);
71+
$this->assertArrayHasKey('method', $fields);
72+
$this->assertSame('test.method', $fields['method']);
73+
$this->assertArrayHasKey('format', $fields);
74+
$this->assertSame('json', $fields['format']);
75+
$this->assertArrayHasKey('charset', $fields);
76+
$this->assertSame('UTF-8', $fields['charset']);
77+
$this->assertArrayHasKey('sign_type', $fields);
78+
$this->assertSame('RSA2', $fields['sign_type']);
79+
$this->assertArrayHasKey('timestamp', $fields);
80+
$this->assertArrayHasKey('version', $fields);
81+
$this->assertSame('1.0', $fields['version']);
82+
}
83+
84+
public function testGetCodeFieldsThrowsExceptionWhenNoRedirectUrl()
85+
{
86+
$provider = new Alipay([
87+
'client_id' => 'client_id',
88+
'rsa_private_key' => 'private_key',
89+
]);
90+
91+
$this->expectException(InvalidArgumentException::class);
92+
$this->expectExceptionMessage('Please set the correct redirect URL refer which was on the Alipay Official Admin pannel.');
93+
94+
$getCodeFields = new ReflectionMethod(Alipay::class, 'getCodeFields');
95+
$getCodeFields->setAccessible(true);
96+
$getCodeFields->invoke($provider);
97+
}
98+
99+
public function testGetCodeFields()
100+
{
101+
$provider = new Alipay([
102+
'app_id' => 'test_app_id',
103+
'rsa_private_key' => 'private_key',
104+
'redirect_url' => 'http://localhost/callback',
105+
]);
106+
107+
$getCodeFields = new ReflectionMethod(Alipay::class, 'getCodeFields');
108+
$getCodeFields->setAccessible(true);
109+
$fields = $getCodeFields->invoke($provider);
110+
111+
$this->assertArrayHasKey('app_id', $fields);
112+
$this->assertSame('test_app_id', $fields['app_id']);
113+
$this->assertArrayHasKey('scope', $fields);
114+
$this->assertSame('auth_user', $fields['scope']);
115+
$this->assertArrayHasKey('redirect_uri', $fields);
116+
$this->assertSame('http://localhost/callback', $fields['redirect_uri']);
117+
}
118+
119+
public function testSignWithSHA256RSAThrowsExceptionWhenNoPrivateKey()
120+
{
121+
$provider = new Alipay([
122+
'client_id' => 'client_id',
123+
'redirect_url' => 'http://localhost/callback',
124+
]);
125+
126+
$this->expectException(InvalidArgumentException::class);
127+
$this->expectExceptionMessage('no RSA private key set.');
128+
129+
$signWithSHA256RSA = new ReflectionMethod(Alipay::class, 'signWithSHA256RSA');
130+
$signWithSHA256RSA->setAccessible(true);
131+
$signWithSHA256RSA->invoke($provider, 'test_content', '');
132+
}
133+
134+
public function testBuildParams()
135+
{
136+
$params = [
137+
'app_id' => 'test_app_id',
138+
'method' => 'test.method',
139+
'sign' => 'signature',
140+
'timestamp' => '2024-01-01 12:00:00',
141+
];
142+
143+
$result = Alipay::buildParams($params);
144+
$this->assertSame('app_id=test_app_id&method=test.method&timestamp=2024-01-01 12:00:00', $result);
145+
146+
$resultWithUrlencode = Alipay::buildParams($params, true);
147+
$this->assertStringContains('timestamp=2024-01-01%2012%3A00%3A00', $resultWithUrlencode);
148+
}
149+
150+
public function testTokenFromCodeSuccess()
151+
{
152+
$mockProvider = $this->getMockBuilder(Alipay::class)
153+
->setConstructorArgs([[
154+
'client_id' => 'client_id',
155+
'rsa_private_key' => 'private_key',
156+
'redirect_url' => 'http://localhost/callback',
157+
]])
158+
->onlyMethods(['getHttpClient', 'generateSign'])
159+
->getMock();
160+
161+
$mockHttpClient = m::mock();
162+
$mockResponse = m::mock();
163+
164+
$mockHttpClient->shouldReceive('post')
165+
->once()
166+
->andReturn($mockResponse);
167+
168+
$mockResponse->shouldReceive('getBody')
169+
->once()
170+
->andReturn('{"alipay_system_oauth_token_response": {"access_token": "token123", "user_id": "user123"}}');
171+
172+
$mockProvider->method('getHttpClient')->willReturn($mockHttpClient);
173+
$mockProvider->method('generateSign')->willReturn('test_signature');
174+
175+
$token = $mockProvider->tokenFromCode('test_code');
176+
177+
$this->assertArrayHasKey('access_token', $token);
178+
$this->assertSame('token123', $token['access_token']);
179+
}
180+
181+
public function testThrowsExceptionWhenTokenResponseMissing()
182+
{
21183
$mockProvider = $this->getMockBuilder(Alipay::class)
22184
->setConstructorArgs([[
23185
'client_id' => 'client_id',
24-
'private_key' => 'private_key',
186+
'rsa_private_key' => 'private_key',
25187
'redirect_url' => 'http://localhost/callback',
26188
]])
27-
->onlyMethods(['getHttpClient'])
189+
->onlyMethods(['getHttpClient', 'generateSign'])
28190
->getMock();
29191

30192
$mockHttpClient = m::mock();
@@ -39,13 +201,137 @@ public function testThrowsExceptionWhenTokenResponseMissing()
39201
->andReturn('{"success": true}'); // Missing alipay_system_oauth_token_response
40202

41203
$mockProvider->method('getHttpClient')->willReturn($mockHttpClient);
204+
$mockProvider->method('generateSign')->willReturn('test_signature');
42205

43206
$this->expectException(AuthorizeFailedException::class);
44207
$this->expectExceptionMessage('Authorization failed: missing alipay_system_oauth_token_response in response');
45208

46209
$mockProvider->tokenFromCode('test_code');
47210
}
48211

212+
public function testThrowsExceptionWhenErrorResponse()
213+
{
214+
$mockProvider = $this->getMockBuilder(Alipay::class)
215+
->setConstructorArgs([[
216+
'client_id' => 'client_id',
217+
'rsa_private_key' => 'private_key',
218+
'redirect_url' => 'http://localhost/callback',
219+
]])
220+
->onlyMethods(['getHttpClient', 'generateSign'])
221+
->getMock();
222+
223+
$mockHttpClient = m::mock();
224+
$mockResponse = m::mock();
225+
226+
$mockHttpClient->shouldReceive('post')
227+
->once()
228+
->andReturn($mockResponse);
229+
230+
$mockResponse->shouldReceive('getBody')
231+
->once()
232+
->andReturn('{"error_response": {"code": "40002", "msg": "Invalid parameter"}}');
233+
234+
$mockProvider->method('getHttpClient')->willReturn($mockHttpClient);
235+
$mockProvider->method('generateSign')->willReturn('test_signature');
236+
237+
$this->expectException(BadRequestException::class);
238+
239+
$mockProvider->tokenFromCode('test_code');
240+
}
241+
242+
public function testGetUserByTokenSuccess()
243+
{
244+
$mockProvider = $this->getMockBuilder(Alipay::class)
245+
->setConstructorArgs([[
246+
'client_id' => 'client_id',
247+
'rsa_private_key' => 'private_key',
248+
'redirect_url' => 'http://localhost/callback',
249+
]])
250+
->onlyMethods(['getHttpClient', 'generateSign'])
251+
->getMock();
252+
253+
$mockHttpClient = m::mock();
254+
$mockResponse = m::mock();
255+
256+
$mockHttpClient->shouldReceive('post')
257+
->once()
258+
->andReturn($mockResponse);
259+
260+
$mockResponse->shouldReceive('getBody')
261+
->once()
262+
->andReturn('{"alipay_user_info_share_response": {"user_id": "user123", "nick_name": "Test User", "avatar": "http://avatar.url"}}');
263+
264+
$mockProvider->method('getHttpClient')->willReturn($mockHttpClient);
265+
$mockProvider->method('generateSign')->willReturn('test_signature');
266+
267+
$getUserByToken = new ReflectionMethod(Alipay::class, 'getUserByToken');
268+
$getUserByToken->setAccessible(true);
269+
$result = $getUserByToken->invoke($mockProvider, 'test_token');
270+
271+
$this->assertArrayHasKey('user_id', $result);
272+
$this->assertSame('user123', $result['user_id']);
273+
$this->assertArrayHasKey('nick_name', $result);
274+
$this->assertSame('Test User', $result['nick_name']);
275+
}
276+
277+
public function testGetUserByTokenThrowsExceptionWhenErrorResponse()
278+
{
279+
$mockProvider = $this->getMockBuilder(Alipay::class)
280+
->setConstructorArgs([[
281+
'client_id' => 'client_id',
282+
'rsa_private_key' => 'private_key',
283+
'redirect_url' => 'http://localhost/callback',
284+
]])
285+
->onlyMethods(['getHttpClient', 'generateSign'])
286+
->getMock();
287+
288+
$mockHttpClient = m::mock();
289+
$mockResponse = m::mock();
290+
291+
$mockHttpClient->shouldReceive('post')
292+
->once()
293+
->andReturn($mockResponse);
294+
295+
$mockResponse->shouldReceive('getBody')
296+
->once()
297+
->andReturn('{"error_response": {"code": "40002", "msg": "Invalid parameter"}}');
298+
299+
$mockProvider->method('getHttpClient')->willReturn($mockHttpClient);
300+
$mockProvider->method('generateSign')->willReturn('test_signature');
301+
302+
$this->expectException(BadRequestException::class);
303+
304+
$getUserByToken = new ReflectionMethod(Alipay::class, 'getUserByToken');
305+
$getUserByToken->setAccessible(true);
306+
$getUserByToken->invoke($mockProvider, 'test_token');
307+
}
308+
309+
public function testMapUserToObject()
310+
{
311+
$provider = new Alipay([
312+
'client_id' => 'client_id',
313+
'rsa_private_key' => 'private_key',
314+
'redirect_url' => 'http://localhost/callback',
315+
]);
316+
317+
$mapUserToObject = new ReflectionMethod(Alipay::class, 'mapUserToObject');
318+
$mapUserToObject->setAccessible(true);
319+
320+
$user = [
321+
'user_id' => 'user123',
322+
'nick_name' => 'Test User',
323+
'avatar' => 'http://avatar.url',
324+
'email' => '[email protected]',
325+
];
326+
327+
$result = $mapUserToObject->invoke($provider, $user);
328+
329+
$this->assertSame('user123', $result->getId());
330+
$this->assertSame('Test User', $result->getName());
331+
$this->assertSame('http://avatar.url', $result->getAvatar());
332+
$this->assertSame('[email protected]', $result->getEmail());
333+
}
334+
49335
protected function tearDown(): void
50336
{
51337
m::close();

0 commit comments

Comments
 (0)