MessageServicesTest.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php
  2. declare(strict_types=1);
  3. namespace Luolongfei\Tests\Libs;
  4. use Luolongfei\Libs\Connector\MessageGateway;
  5. use Luolongfei\Libs\MessageServices\Bark;
  6. use Luolongfei\Libs\MessageServices\Mail;
  7. use Luolongfei\Libs\MessageServices\Pushplus;
  8. use Luolongfei\Libs\MessageServices\ServerChan;
  9. use Luolongfei\Libs\MessageServices\TelegramBot;
  10. use Luolongfei\Libs\MessageServices\WeChat;
  11. use Luolongfei\Tests\TestCase;
  12. use PHPMailer\PHPMailer\PHPMailer;
  13. final class FakeBody
  14. {
  15. public function __construct(private readonly string $contents)
  16. {
  17. }
  18. public function getContents(): string
  19. {
  20. return $this->contents;
  21. }
  22. public function __toString(): string
  23. {
  24. return $this->contents;
  25. }
  26. }
  27. final class FakeResponse
  28. {
  29. public function __construct(private readonly string $contents)
  30. {
  31. }
  32. public function getBody(): FakeBody
  33. {
  34. return new FakeBody($this->contents);
  35. }
  36. }
  37. final class RecordingClient
  38. {
  39. public array $calls = [];
  40. public function __construct(private readonly string $responseBody)
  41. {
  42. }
  43. public function post(string $url, array $options): FakeResponse
  44. {
  45. $this->calls[] = ['method' => 'post', 'url' => $url, 'options' => $options];
  46. return new FakeResponse($this->responseBody);
  47. }
  48. }
  49. final class MessageServicesTest extends TestCase
  50. {
  51. public function testMessageGatewayHelpersWork(): void
  52. {
  53. $gateway = new class extends MessageGateway {
  54. public function send(string $content, string $subject = '', int $type = 1, array $data = [], ?string $recipient = null, ...$params)
  55. {
  56. return true;
  57. }
  58. };
  59. $this->assertSame('Hello world', $gateway->genMessageContent(['world'], 'Hello %s'));
  60. $this->assertSame('a<br>b', $gateway->newLine2Br("a\nb"));
  61. $footer = '';
  62. $gateway->setCommonFooter($footer, "\n", false);
  63. $this->assertSame('', $footer);
  64. }
  65. public function testMailHelpersReturnExpectedValues(): void
  66. {
  67. $mail = $this->makeWithoutConstructor(Mail::class);
  68. [$host, $secure, $port] = $mail->getBasicMailConf('[email protected]');
  69. $this->assertSame('smtp.office365.com', $host);
  70. $this->assertSame(PHPMailer::ENCRYPTION_STARTTLS, $secure);
  71. $this->assertSame(587, $port);
  72. $this->assertStringContainsString('alpha.tk', $mail->genDomainStatusHtml(['alpha.tk' => 5]));
  73. }
  74. public function testBarkHelpersParseKeyAndFormatDomainStatus(): void
  75. {
  76. $bark = $this->makeWithoutConstructor(Bark::class);
  77. $this->assertSame('abc', $bark->parseBarkKey('https://api.day.app/abc/hello'));
  78. $this->assertStringContainsString('alpha.tk', $bark->genDomainStatusText(['alpha.tk' => 2]));
  79. }
  80. public function testPushplusSendUsesHttpsEndpoint(): void
  81. {
  82. $pushplus = $this->makeWithoutConstructor(Pushplus::class);
  83. $client = new RecordingClient('{"code":200}');
  84. $this->setProperty($pushplus, 'sendKey', 'push-token');
  85. $this->setProperty($pushplus, 'client', $client);
  86. $this->assertTrue($pushplus->send('Body', 'Subject'));
  87. $this->assertSame(Pushplus::API_URL, $client->calls[0]['url']);
  88. $this->assertSame('push-token', $client->calls[0]['options']['form_params']['token']);
  89. }
  90. public function testServerChanSendUsesExpectedEndpoint(): void
  91. {
  92. $serverChan = $this->makeWithoutConstructor(ServerChan::class);
  93. $client = new RecordingClient('{"code":0}');
  94. $this->setProperty($serverChan, 'sendKey', 'send-key');
  95. $this->setProperty($serverChan, 'client', $client);
  96. $this->assertTrue($serverChan->send('Body', 'Subject'));
  97. $this->assertStringContainsString('https://sctapi.ftqq.com/send-key.send', $client->calls[0]['url']);
  98. }
  99. public function testTelegramBotEscapesMarkdownV2AndPreservesLinks(): void
  100. {
  101. $telegram = $this->makeWithoutConstructor(TelegramBot::class);
  102. $client = new RecordingClient('{"ok":true}');
  103. $this->setProperty($telegram, 'chatID', '123456');
  104. $this->setProperty($telegram, 'token', 'bot-token');
  105. $this->setProperty($telegram, 'host', 'api.telegram.org');
  106. $this->setProperty($telegram, 'client', $client);
  107. $message = "Release notes:\n* item\nraw \\ slash\n[example](http://example.com/path?a=1)";
  108. $this->assertTrue($telegram->send($message, 'Subject'));
  109. $call = $client->calls[0];
  110. $text = $call['options']['form_params']['text'];
  111. $this->assertSame('MarkdownV2', $call['options']['form_params']['parse_mode']);
  112. $this->assertStringContainsString('Subject', $text);
  113. $this->assertStringContainsString('\* item', $text);
  114. $this->assertStringContainsString('raw \\\\ slash', $text);
  115. $this->assertStringContainsString('[example](http://example.com/path?a=1)', $text);
  116. }
  117. public function testTelegramBotPreservesProjectMarkdownFormatting(): void
  118. {
  119. $telegram = $this->makeWithoutConstructor(TelegramBot::class);
  120. $client = new RecordingClient('{"ok":true}');
  121. $this->setProperty($telegram, 'chatID', '123456');
  122. $this->setProperty($telegram, 'token', 'bot-token');
  123. $this->setProperty($telegram, 'host', 'api.telegram.org');
  124. $this->setProperty($telegram, 'client', $client);
  125. $this->assertTrue($telegram->send('', '', 3, [
  126. 'username' => '[email protected]',
  127. 'domainStatusArr' => ['alpha.tk' => 5],
  128. ]));
  129. $text = $client->calls[0]['options']['form_params']['text'];
  130. $this->assertStringContainsString('[alpha.tk](http://alpha.tk)', $text);
  131. $this->assertStringContainsString('*5*', $text);
  132. $this->assertStringNotContainsString('\*5\*', $text);
  133. }
  134. public function testTelegramHelperMethodsParseHostAndTables(): void
  135. {
  136. $telegram = new TelegramBot();
  137. $this->assertSame('api.telegram.org', $this->invokeMethod($telegram, 'getTelegramHost'));
  138. $rows = $telegram->getMarkDownRawArr("| A | B |\n| 1 | 2 |");
  139. $this->assertSame([['A', 'B'], ['1', '2']], $rows);
  140. }
  141. public function testWeChatCacheReaderAndFormattingHelpersWork(): void
  142. {
  143. $weChat = $this->makeWithoutConstructor(WeChat::class);
  144. $cacheFile = ROOT_PATH . DS . 'tests' . DS . 'runtime' . DS . 'wechat_access_token.txt';
  145. file_put_contents($cacheFile, sprintf("WECHAT_ACCESS_TOKEN=token\nWECHAT_ACCESS_TOKEN_EXPIRES_AT=%s\n", time() + 300));
  146. $this->setProperty($weChat, 'accessTokenFile', $cacheFile);
  147. $this->assertSame('token', $this->invokeMethod($weChat, 'getAccessTokenCache'));
  148. $this->assertStringContainsString('alpha.tk', $weChat->genDomainStatusFullText('tester', ['alpha.tk' => 3]));
  149. }
  150. }