UsdtRechargeConfigTest.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <?php
  2. namespace Tests\Integration;
  3. use App\Http\Controllers\admin\Config as AdminConfig;
  4. use App\Http\Controllers\api\Wallet;
  5. use App\Services\UsdtRechargeConfigService;
  6. use Illuminate\Config\Repository;
  7. use Illuminate\Database\Capsule\Manager;
  8. use Illuminate\Database\Schema\Blueprint;
  9. use Illuminate\Foundation\Application;
  10. use Illuminate\Http\JsonResponse;
  11. use Illuminate\Http\Request;
  12. use Illuminate\Routing\Router;
  13. use Illuminate\Routing\UrlGenerator;
  14. use Illuminate\Support\Facades\DB;
  15. use Illuminate\Support\Facades\Facade;
  16. use Illuminate\Translation\ArrayLoader;
  17. use Illuminate\Translation\Translator;
  18. use Illuminate\Validation\Factory;
  19. use PHPUnit\Framework\TestCase;
  20. class UsdtRechargeConfigTest extends TestCase
  21. {
  22. private Application $app;
  23. private UsdtRechargeConfigService $service;
  24. private string $storage;
  25. private const TRC = 'T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb';
  26. private const ERC = '0x0123456789abcdef0123456789abcdef01234567';
  27. protected function setUp(): void
  28. {
  29. require_once dirname(__DIR__, 2) . '/app/Helpers/helpers.php';
  30. Facade::clearResolvedInstances();
  31. $this->app = new Application(dirname(__DIR__, 2));
  32. $this->app->instance('config', new Repository(['app' => ['locale' => 'zh']]));
  33. Facade::setFacadeApplication($this->app);
  34. $db = new Manager($this->app);
  35. $db->addConnection(['driver' => 'sqlite', 'database' => ':memory:', 'prefix' => 'bot_']);
  36. $db->setAsGlobal();
  37. $db->bootEloquent();
  38. $this->app->instance('db', $db->getDatabaseManager());
  39. $this->app->instance('translator', new Translator(new ArrayLoader(), 'zh'));
  40. $this->app->instance('validator', new Factory($this->app['translator'], $this->app));
  41. $this->app->instance(\Illuminate\Contracts\Routing\ResponseFactory::class, new \Tests\Support\JsonResponseFactory());
  42. Request::macro('validate', function (array $rules) {
  43. return app('validator')->make($this->all(), $rules)->validate();
  44. });
  45. $db->schema()->create('config', function (Blueprint $table) {
  46. $table->id();
  47. $table->string('field')->unique();
  48. $table->text('val');
  49. $table->string('remark')->nullable();
  50. $table->integer('group_id')->default(1);
  51. $table->timestamps();
  52. });
  53. $this->storage = sys_get_temp_dir() . '/bot28-usdt-' . bin2hex(random_bytes(6));
  54. $this->app->useStoragePath($this->storage);
  55. mkdir($this->storage . '/app/public/recharge', 0777, true);
  56. foreach ([self::TRC, self::ERC] as $address) {
  57. // Exercise the real scan path with cached QR files, without generating images or using a chain service.
  58. file_put_contents($this->storage . '/app/public/recharge/' . $address . '.png', 'cached-qr-fixture');
  59. }
  60. $request = Request::create('https://example.test/admin/config/usdt');
  61. $this->app->instance('request', $request);
  62. $router = new Router(new \Illuminate\Events\Dispatcher($this->app), $this->app);
  63. $this->app->instance('url', new UrlGenerator($router->getRoutes(), $request));
  64. $this->service = new UsdtRechargeConfigService();
  65. }
  66. protected function tearDown(): void
  67. {
  68. foreach ([self::TRC, self::ERC] as $address) {
  69. unlink($this->storage . '/app/public/recharge/' . $address . '.png');
  70. }
  71. foreach (['/app/public/recharge', '/app/public', '/app', ''] as $directory) rmdir($this->storage . $directory);
  72. DB::disconnect();
  73. Facade::clearResolvedInstances();
  74. parent::tearDown();
  75. }
  76. private function request(string $path, string $method, array $params): void
  77. {
  78. $request = Request::create($path, $method, $params);
  79. $request->user = (object)['member_id' => 'member-1'];
  80. $this->app->instance('request', $request);
  81. }
  82. private function save(array $params): array
  83. {
  84. $this->request('/admin/config/usdt', 'POST', $params);
  85. return (new AdminConfig())->saveUsdt($this->service)->getData(true);
  86. }
  87. private function seedOriginalSettings(): array
  88. {
  89. $settings = ['receiving_type' => '2', 'receiving_address' => self::TRC, 'receiving_address_erc20' => self::ERC];
  90. foreach ($settings as $field => $val) DB::table('config')->insert(compact('field', 'val'));
  91. return $settings;
  92. }
  93. public function test_admin_reads_and_saves_only_one_public_chain_field(): void
  94. {
  95. $this->assertSame(['public_chain' => ''], $this->service->get());
  96. $saved = $this->save(['public_chain' => ' public-chain-address ']);
  97. $this->assertSame(0, $saved['code']);
  98. $this->assertSame(['public_chain' => 'public-chain-address'], $saved['data']);
  99. $this->assertSame($saved['data'], (new AdminConfig())->usdt($this->service)->getData(true)['data']);
  100. $this->assertSame(['public_chain'], DB::table('config')->pluck('field')->all());
  101. $this->assertSame(0, $this->save(['public_chain' => null])['code']);
  102. $this->assertSame(['public_chain' => ''], $this->service->get());
  103. }
  104. public function test_saving_public_chain_does_not_modify_original_addresses_or_mode(): void
  105. {
  106. $settings = $this->seedOriginalSettings();
  107. $saved = $this->save(['public_chain' => 'public-chain-address',
  108. 'receiving_type' => 1, 'receiving_address' => 'ignored', 'receiving_address_erc20' => 'ignored']);
  109. $this->assertSame(0, $saved['code']);
  110. $this->assertSame(['public_chain' => 'public-chain-address'], $saved['data']);
  111. $this->assertSame($settings, DB::table('config')->where('field', '!=', 'public_chain')->pluck('val', 'field')->all());
  112. }
  113. public function test_scan_only_adds_public_chain_to_the_original_response(): void
  114. {
  115. $this->seedOriginalSettings();
  116. $this->save(['public_chain' => 'public-chain-address']);
  117. foreach (['TrC20' => self::TRC, 'erc20' => self::ERC] as $type => $address) {
  118. $this->request('/api/wallet/scan', 'GET', ['type' => $type]);
  119. $result = (new Wallet())->scan()->getData(true);
  120. $this->assertSame(0, $result['code']);
  121. $this->assertSame([
  122. 'qrcode' => 'https://example.test/storage/recharge/' . $address . '.png',
  123. 'address' => $address, 'public_chain' => 'public-chain-address',
  124. ], $result['data']);
  125. }
  126. DB::table('config')->where('field', 'public_chain')->delete();
  127. $this->assertSame('', (new Wallet())->scan()->getData(true)['data']['public_chain']);
  128. }
  129. public function test_invalid_or_omitted_public_chain_does_not_overwrite_saved_value(): void
  130. {
  131. $this->save(['public_chain' => 'saved-address']);
  132. foreach ([[], ['public_chain' => []], ['public_chain' => str_repeat('a', 2049)]] as $params) {
  133. $this->assertSame(-3, $this->save($params)['code']);
  134. $this->assertSame(['public_chain' => 'saved-address'], $this->service->get());
  135. }
  136. }
  137. public function test_routes_keep_admin_auth_and_existing_configuration_permissions(): void
  138. {
  139. $router = new Router(new \Illuminate\Events\Dispatcher($this->app), $this->app);
  140. $this->app->instance('router', $router);
  141. $router->prefix('admin')->group(dirname(__DIR__, 2) . '/routes/admin.php');
  142. foreach (['GET' => 'admin/config/getAll', 'POST' => 'admin/config/set'] as $method => $permission) {
  143. $route = $router->getRoutes()->match(Request::create('/admin/config/usdt', $method));
  144. $this->assertContains('admin.jwt', $route->gatherMiddleware());
  145. $this->assertContains('check.button.uri', $route->gatherMiddleware());
  146. $this->assertSame($permission, $route->defaults['permission_uri']);
  147. }
  148. }
  149. }