159 lines
5.1 KiB
PHP
159 lines
5.1 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Services\TransferService;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Mockery;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use SergiX44\Nutgram\Nutgram;
|
|
use SergiX44\Nutgram\Telegram\Properties\ChatMemberStatus;
|
|
use SergiX44\Nutgram\Telegram\Properties\ChatType;
|
|
use SergiX44\Nutgram\Testing\FakeNutgram;
|
|
use Tests\TestCase;
|
|
|
|
class TelegramBotTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
private const OWNER_CHAT = -1001234567890;
|
|
|
|
private const USER_ID = 4242;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
config([
|
|
'coruna.telegram.owner_chat_id' => (string) self::OWNER_CHAT,
|
|
'coruna.telegram.webhook_secret' => 'test-secret',
|
|
'nutgram.token' => FakeNutgram::TOKEN,
|
|
]);
|
|
|
|
// Nutgram is a singleton; reset so FakeNutgram mock queues stay isolated.
|
|
$this->app->forgetInstance(Nutgram::class);
|
|
$this->app->forgetInstance('nutgram');
|
|
$this->app->forgetInstance('telegram');
|
|
$this->app->forgetInstance(FakeNutgram::class);
|
|
}
|
|
|
|
#[Test]
|
|
public function webhook_rejects_bad_secret(): void
|
|
{
|
|
$this->postJson('/hooks/telegram', ['update_id' => 1], [
|
|
'X-Telegram-Bot-Api-Secret-Token' => 'wrong',
|
|
])->assertForbidden();
|
|
}
|
|
|
|
#[Test]
|
|
public function webhook_accepts_valid_secret(): void
|
|
{
|
|
$this->call(
|
|
'POST',
|
|
'/hooks/telegram',
|
|
[],
|
|
[],
|
|
[],
|
|
[
|
|
'CONTENT_TYPE' => 'application/json',
|
|
'HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN' => 'test-secret',
|
|
],
|
|
json_encode(['update_id' => 1])
|
|
)->assertNoContent();
|
|
}
|
|
|
|
#[Test]
|
|
public function unauthorized_chat_is_silent(): void
|
|
{
|
|
/** @var FakeNutgram $bot */
|
|
$bot = app(Nutgram::class);
|
|
|
|
$bot->hearMessage([
|
|
'text' => '/ping',
|
|
'chat' => ['id' => 999, 'type' => ChatType::SUPERGROUP->value],
|
|
'from' => ['id' => self::USER_ID, 'is_bot' => false, 'first_name' => 'X'],
|
|
])->reply();
|
|
|
|
$bot->assertCalled('sendMessage', 0);
|
|
}
|
|
|
|
#[Test]
|
|
public function non_admin_is_rejected(): void
|
|
{
|
|
/** @var FakeNutgram $bot */
|
|
$bot = app(Nutgram::class);
|
|
|
|
$bot->willReceivePartial([
|
|
'status' => ChatMemberStatus::MEMBER->value,
|
|
'user' => ['id' => self::USER_ID, 'is_bot' => false, 'first_name' => 'X'],
|
|
]);
|
|
|
|
$bot->hearMessage([
|
|
'text' => '/ping',
|
|
'chat' => ['id' => self::OWNER_CHAT, 'type' => ChatType::SUPERGROUP->value],
|
|
'from' => ['id' => self::USER_ID, 'is_bot' => false, 'first_name' => 'X'],
|
|
])->reply();
|
|
|
|
// index 0 is getChatMember; reject reply follows
|
|
$bot->assertReplyText('⛔ Only group admins can use this command.', 1);
|
|
}
|
|
|
|
#[Test]
|
|
public function admin_ping_replies_pong(): void
|
|
{
|
|
/** @var FakeNutgram $bot */
|
|
$bot = app(Nutgram::class);
|
|
|
|
$bot->willReceivePartial([
|
|
'status' => ChatMemberStatus::ADMINISTRATOR->value,
|
|
'user' => ['id' => self::USER_ID, 'is_bot' => false, 'first_name' => 'Admin'],
|
|
'can_manage_chat' => true,
|
|
]);
|
|
|
|
$bot->hearMessage([
|
|
'text' => '/ping',
|
|
'chat' => ['id' => self::OWNER_CHAT, 'type' => ChatType::SUPERGROUP->value],
|
|
'from' => ['id' => self::USER_ID, 'is_bot' => false, 'first_name' => 'Admin'],
|
|
])->reply();
|
|
|
|
$bot->assertReplyText('pong', 1);
|
|
}
|
|
|
|
#[Test]
|
|
public function admin_transfer_calls_transfer_service(): void
|
|
{
|
|
$mock = Mockery::mock(TransferService::class);
|
|
$mock->shouldReceive('handle')
|
|
->once()
|
|
->with('tron', 'TUEZSdKsoDHQMeZwihtdoBiN46zxhGWYdH', '10', 'USDT')
|
|
->andReturn([
|
|
'ok' => true,
|
|
'txid' => 'deadbeef',
|
|
'from' => 'TUEZSdKsoDHQMeZwihtdoBiN46zxhGWYdH',
|
|
'to' => 'TPayoutAddressxxxxxxxxxxxxxxxxxxxxxx',
|
|
'amount' => '10',
|
|
'asset' => 'USDT',
|
|
]);
|
|
$this->app->instance(TransferService::class, $mock);
|
|
|
|
/** @var FakeNutgram $bot */
|
|
$bot = app(Nutgram::class);
|
|
|
|
$bot->willReceivePartial([
|
|
'status' => ChatMemberStatus::CREATOR->value,
|
|
'user' => ['id' => self::USER_ID, 'is_bot' => false, 'first_name' => 'Owner'],
|
|
]);
|
|
|
|
$bot->hearMessage([
|
|
'text' => '/transfer TUEZSdKsoDHQMeZwihtdoBiN46zxhGWYdH USDT 10',
|
|
'chat' => ['id' => self::OWNER_CHAT, 'type' => ChatType::SUPERGROUP->value],
|
|
'from' => ['id' => self::USER_ID, 'is_bot' => false, 'first_name' => 'Owner'],
|
|
])->reply();
|
|
|
|
// getChatMember + "⏳ …" + success
|
|
$bot->assertCalled('sendMessage', 2);
|
|
$history = $bot->getRequestHistory();
|
|
$last = FakeNutgram::getActualData(array_values($history[array_key_last($history)])[0]);
|
|
$this->assertStringContainsString('deadbeef', $last['text'] ?? '');
|
|
}
|
|
}
|