|
@@ -0,0 +1,239 @@
|
|
|
|
|
+<?php
|
|
|
|
|
+
|
|
|
|
|
+namespace Tests\Integration;
|
|
|
|
|
+
|
|
|
|
|
+use App\Models\PaymentOrder;
|
|
|
|
|
+use App\Models\Recharge;
|
|
|
|
|
+use App\Services\PaymentOrderService;
|
|
|
|
|
+use App\Services\RechargeBonusAdminService;
|
|
|
|
|
+use App\Services\RechargeBonusService;
|
|
|
|
|
+use App\Services\RechargeService;
|
|
|
|
|
+use Carbon\Carbon;
|
|
|
|
|
+use Illuminate\Config\Repository;
|
|
|
|
|
+use Illuminate\Database\Capsule\Manager;
|
|
|
|
|
+use Illuminate\Foundation\Application;
|
|
|
|
|
+use Illuminate\Http\Request;
|
|
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
|
|
+use Illuminate\Support\Facades\Facade;
|
|
|
|
|
+use Illuminate\Translation\ArrayLoader;
|
|
|
|
|
+use Illuminate\Translation\Translator;
|
|
|
|
|
+use Illuminate\Validation\Factory;
|
|
|
|
|
+use Illuminate\Validation\ValidationException;
|
|
|
|
|
+use PHPUnit\Framework\TestCase;
|
|
|
|
|
+
|
|
|
|
|
+class RechargeBonusTest extends TestCase
|
|
|
|
|
+{
|
|
|
|
|
+ private Application $app;
|
|
|
|
|
+ private string $originalTimezone;
|
|
|
|
|
+ protected function setUp(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $this->originalTimezone = date_default_timezone_get(); date_default_timezone_set('Asia/Shanghai');
|
|
|
|
|
+ \Illuminate\Database\Eloquent\Model::clearBootedModels();
|
|
|
|
|
+ require_once dirname(__DIR__, 2) . '/app/Helpers/helpers.php';
|
|
|
|
|
+ Facade::clearResolvedInstances(); Carbon::setTestNow(Carbon::parse('2026-10-28 12:00:00', 'Asia/Shanghai'));
|
|
|
|
|
+ $this->app = new Application(dirname(__DIR__, 2));
|
|
|
|
|
+ $this->app->instance('config', new Repository(['app' => ['locale' => 'zh', 'timezone' => 'Asia/Shanghai']])); Facade::setFacadeApplication($this->app);
|
|
|
|
|
+ $db = new Manager($this->app); $db->addConnection(['driver' => 'sqlite', 'database' => ':memory:', 'prefix' => 'bot_']);
|
|
|
|
|
+ $db->setEventDispatcher(new \Illuminate\Events\Dispatcher($this->app)); $db->setAsGlobal(); $db->bootEloquent(); $this->app->instance('db', $db->getDatabaseManager()); $this->app->bind('db.schema', fn () => $db->schema());
|
|
|
|
|
+ $this->app->instance('translator', new Translator(new ArrayLoader(), 'zh'));
|
|
|
|
|
+ $this->app->instance('validator', new Factory($this->app['translator'], $this->app)); $this->app->instance('log', new \Psr\Log\NullLogger());
|
|
|
|
|
+ $this->app->instance(\Illuminate\Contracts\Routing\ResponseFactory::class, new class {
|
|
|
|
|
+ public function json($data, $status = 200, $headers = [], $options = 0) { return new \Illuminate\Http\JsonResponse($data, $status, $headers, $options); }
|
|
|
|
|
+ });
|
|
|
|
|
+ Request::macro('validate', function ($rules) { return app('validator')->make($this->all(), $rules)->validate(); });
|
|
|
|
|
+ $request = Request::create('/admin/rechargeBonus/save', 'POST'); $request->user = (object)['id' => 1, 'username' => 'admin']; $this->app->instance('request', $request);
|
|
|
|
|
+ foreach ([
|
|
|
|
|
+ 'users' => 'id INTEGER PRIMARY KEY,member_id TEXT,user_id TEXT,"from" INTEGER,language TEXT,level INTEGER DEFAULT 0,agent_user_code TEXT,recharge_channel_group_id INTEGER DEFAULT 1,created_at TEXT,updated_at TEXT',
|
|
|
|
|
+ 'wallets' => 'id INTEGER PRIMARY KEY AUTOINCREMENT,member_id TEXT UNIQUE,available_balance TEXT DEFAULT "0",frozen_balance TEXT DEFAULT "0",created_at TEXT,updated_at TEXT',
|
|
|
|
|
+ 'balance_logs' => 'id INTEGER PRIMARY KEY AUTOINCREMENT,member_id TEXT,type INTEGER DEFAULT 1,amount TEXT,change_type TEXT,before_balance TEXT,after_balance TEXT,related_id INTEGER,remark TEXT,frozen_status INTEGER,created_at TEXT,updated_at TEXT',
|
|
|
|
|
+ 'payment_orders' => 'id INTEGER PRIMARY KEY AUTOINCREMENT,member_id TEXT,type INTEGER,channel TEXT,status INTEGER,state TEXT,amount TEXT,order_no TEXT,callback_data TEXT,remark TEXT,created_at TEXT,updated_at TEXT',
|
|
|
|
|
+ 'recharges' => 'id INTEGER PRIMARY KEY AUTOINCREMENT,member_id TEXT,type INTEGER,status INTEGER DEFAULT 0,coin TEXT,net TEXT,txid TEXT,amount TEXT,exchange_rate TEXT,created_at TEXT,updated_at TEXT',
|
|
|
|
|
+ 'recharge_channel' => 'id INTEGER PRIMARY KEY AUTOINCREMENT,data_type INTEGER,type TEXT,name TEXT,sort INTEGER DEFAULT 0,status INTEGER DEFAULT 1,deleted_at TEXT,min TEXT,max TEXT,fixed TEXT,rate TEXT DEFAULT "0.02"',
|
|
|
|
|
+ 'recharge_channel_group' => 'id INTEGER PRIMARY KEY,activity_type TEXT,recharge_type TEXT,withdraw_type TEXT,deleted_at TEXT',
|
|
|
|
|
+ 'payment_providers' => 'id INTEGER PRIMARY KEY,code TEXT,status INTEGER',
|
|
|
|
|
+ 'operation_audits' => 'id INTEGER PRIMARY KEY AUTOINCREMENT,resource_type TEXT,resource_id INTEGER,action TEXT,changes TEXT,operator_id INTEGER,operator_name TEXT,created_at TEXT',
|
|
|
|
|
+ 'config' => 'id INTEGER PRIMARY KEY AUTOINCREMENT,field TEXT,val TEXT',
|
|
|
|
|
+ 'level' => 'id INTEGER PRIMARY KEY,level INTEGER,recharge TEXT',
|
|
|
|
|
+ 'user_login' => 'id INTEGER PRIMARY KEY,user_id TEXT,status INTEGER,platform TEXT',
|
|
|
|
|
+ 'backflow' => 'id INTEGER PRIMARY KEY AUTOINCREMENT,date TEXT,member_id TEXT,recharge_amount TEXT DEFAULT "0",withdrawal_amount TEXT DEFAULT "0",backflow_ratio TEXT,amount TEXT,created_at TEXT,updated_at TEXT',
|
|
|
|
|
+ ] as $table => $columns) DB::statement('CREATE TABLE bot_' . $table . ' (' . $columns . ')');
|
|
|
|
|
+ (require dirname(__DIR__, 2) . '/database/migrations/2026_10_26_160000_create_promotion_activities.php')->up();
|
|
|
|
|
+ (require dirname(__DIR__, 2) . '/database/migrations/2026_10_27_140000_add_promotion_activity_translations.php')->up();
|
|
|
|
|
+ (require dirname(__DIR__, 2) . '/database/migrations/2026_10_28_140000_create_recharge_bonuses.php')->up();
|
|
|
|
|
+ (require dirname(__DIR__, 2) . '/database/migrations/2026_10_28_150000_add_recharge_channel_logo.php')->up();
|
|
|
|
|
+ DB::table('recharge_channel_group')->insert(['id' => 1, 'activity_type' => '', 'recharge_type' => 'JDpay,rgcz,usdt']);
|
|
|
|
|
+ foreach (['JDpay', 'rgcz', 'usdt'] as $type) DB::table('recharge_channel')->insert(['data_type' => 1, 'type' => $type, 'name' => $type]);
|
|
|
|
|
+ foreach (['huishui_percentage' => '0', 'huishui_restriction' => '0', 'recharge_rate' => '0', 'recharges_bibi_return' => '0'] as $field => $val) DB::table('config')->insert(compact('field', 'val'));
|
|
|
|
|
+ foreach ([1 => 1, 2 => 2, 3 => -1] as $id => $from) {
|
|
|
|
|
+ DB::table('users')->insert(['id' => $id, 'member_id' => 'm' . $id, 'user_id' => 'u' . $id, 'from' => $from, 'language' => 'zh']);
|
|
|
|
|
+ DB::table('wallets')->insert(['member_id' => 'm' . $id]);
|
|
|
|
|
+ }
|
|
|
|
|
+ DB::table('payment_providers')->insert(['id' => 1, 'code' => 'jd', 'status' => 1]);
|
|
|
|
|
+ $this->configure('JDpay'); $this->configure('rgcz'); $this->configure('usdt');
|
|
|
|
|
+ }
|
|
|
|
|
+ protected function tearDown(): void { date_default_timezone_set($this->originalTimezone); Carbon::setTestNow(); DB::disconnect(); Facade::clearResolvedInstances(); parent::tearDown(); }
|
|
|
|
|
+ private function configure(string $type, string $percent = '5', int $enabled = 1): array
|
|
|
|
|
+ {
|
|
|
|
|
+ return (new RechargeBonusAdminService())->save(['channel_type' => $type, 'bonus_percent' => $percent, 'enabled' => $enabled,
|
|
|
|
|
+ 'translations' => ['zh' => ['text' => '额外赠送'], 'en' => ['text' => 'Extra bonus'], 'vi' => ['text' => 'Thưởng thêm']]]);
|
|
|
|
|
+ }
|
|
|
|
|
+ private function order(string $member = 'm1', bool $legacy = false): PaymentOrder
|
|
|
|
|
+ {
|
|
|
|
|
+ $order = new PaymentOrder(['member_id' => $member, 'type' => 1, 'status' => 1, 'channel' => 'JDpay', 'amount' => '1000']);
|
|
|
|
|
+ if (!$legacy) $order->recharge_bonus_snapshot = RechargeBonusService::capture('JDpay', $member);
|
|
|
|
|
+ $order->save(); return $order;
|
|
|
|
|
+ }
|
|
|
|
|
+ private function pay(PaymentOrder $order): bool
|
|
|
|
|
+ {
|
|
|
|
|
+ $method = new \ReflectionMethod(PaymentOrderService::class, 'applyPayCallback'); $method->setAccessible(true);
|
|
|
|
|
+ return $method->invoke(null, $order, (string)$order->amount, '1', '1', '2', ['status' => '1']);
|
|
|
|
|
+ }
|
|
|
|
|
+ private function balance(string $member = 'm1'): string { return bcadd((string)DB::table('wallets')->where('member_id', $member)->value('available_balance'), '0', 2); }
|
|
|
|
|
+
|
|
|
|
|
+ public function test_independent_five_percent_first_deposit_and_old_bonus_all_use_original_principal(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ (new \App\Services\PromotionAdminService())->save(['type' => 8, 'status' => 1, 'start_time' => '2026-10-01', 'end_time' => '2026-12-01',
|
|
|
|
|
+ 'translations' => array_fill_keys(['zh','en','vi'], ['title' => 'First', 'content' => 'First bonus']), 'params' => ['min_deposit' => '1000', 'reward_amount' => '25']]);
|
|
|
|
|
+ DB::table('config')->where('field', 'recharges_bibi_return')->update(['val' => '0.10']);
|
|
|
|
|
+ $order = $this->order(); $this->assertTrue($this->pay($order)); $this->assertFalse($this->pay($order));
|
|
|
|
|
+ $this->assertSame('1175.00', $this->balance());
|
|
|
|
|
+ $this->assertSame('50.00', bcadd((string)DB::table('recharge_bonus_rewards')->value('amount'), '0', 2));
|
|
|
|
|
+ $this->assertSame(1, DB::table('recharge_bonus_rewards')->count());
|
|
|
|
|
+ $this->assertSame(1, DB::table('balance_logs')->where('change_type', '三方充值')->count());
|
|
|
|
|
+ $this->assertSame(1, DB::table('promotion_rewards')->count());
|
|
|
|
|
+ $this->assertSame(1, DB::table('balance_logs')->where('remark', '充值渠道赠送')->count());
|
|
|
|
|
+ }
|
|
|
|
|
+ public function test_snapshots_survive_changes_and_closed_guest_telegram_and_old_orders_do_not_get_back_awards(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $pending = $this->order(); $this->configure('JDpay', '20', 0); $this->assertTrue($this->pay($pending));
|
|
|
|
|
+ $this->assertSame('1050.00', $this->balance());
|
|
|
|
|
+ $closed = $this->order(); $this->configure('JDpay', '20', 1); $this->pay($closed);
|
|
|
|
|
+ $this->assertSame('2050.00', $this->balance());
|
|
|
|
|
+ $this->pay($this->order('m1', true)); $this->pay($this->order('m2')); $this->pay($this->order('m3'));
|
|
|
|
|
+ $this->assertSame('3050.00', $this->balance());
|
|
|
|
|
+ $this->assertSame('1000.00', $this->balance('m2')); $this->assertSame('1000.00', $this->balance('m3'));
|
|
|
|
|
+ $this->assertSame(1, DB::table('recharge_bonus_rewards')->count());
|
|
|
|
|
+ }
|
|
|
|
|
+ public function test_chain_first_detection_snapshot_conversion_and_duplicate_transactions(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $row = ['member_id' => 'm1', 'type' => 1, 'coin' => 'USDT', 'net' => 'trc20', 'txid' => 'ABC123', 'amount' => '10', 'status' => 0];
|
|
|
|
|
+ $this->assertSame(1, RechargeBonusService::registerChain($row)); $this->assertSame(0, RechargeBonusService::registerChain($row));
|
|
|
|
|
+ $id = (int)DB::table('recharges')->value('id'); $this->configure('usdt', '50', 0);
|
|
|
|
|
+ $this->assertTrue(RechargeService::creditConfirmedRecharge(Recharge::find($id), ['status' => 1], '70'));
|
|
|
|
|
+ $this->assertFalse(RechargeService::creditConfirmedRecharge(Recharge::find($id), ['status' => 1], '70'));
|
|
|
|
|
+ $this->assertSame('73.50', $this->balance());
|
|
|
|
|
+ $duplicate = DB::table('recharges')->insertGetId($row);
|
|
|
|
|
+ $this->assertFalse(RechargeService::creditConfirmedRecharge(Recharge::find($duplicate), ['status' => 1], '70'));
|
|
|
|
|
+ $this->assertSame(3, (int)DB::table('recharges')->where('id', $duplicate)->value('status'));
|
|
|
|
|
+ $this->assertSame('73.50', $this->balance());
|
|
|
|
|
+ }
|
|
|
|
|
+ public function test_legacy_chain_scan_is_not_given_a_new_snapshot(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $row = ['member_id' => 'm1', 'type' => 1, 'coin' => 'USDT', 'net' => 'TRC20', 'txid' => 'old', 'amount' => '10', 'status' => 0];
|
|
|
|
|
+ $id = DB::table('recharges')->insertGetId($row);
|
|
|
|
|
+ $this->assertSame(0, RechargeBonusService::registerChain($row));
|
|
|
|
|
+ $this->assertTrue(RechargeService::creditConfirmedRecharge(Recharge::find($id), ['status' => 1], '70'));
|
|
|
|
|
+ $this->assertSame('70.00', $this->balance()); $this->assertSame(0, DB::table('recharge_bonus_rewards')->count());
|
|
|
|
|
+ }
|
|
|
|
|
+ public function test_failed_reward_rolls_back_principal_order_status_and_logs(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $order = $this->order();
|
|
|
|
|
+ DB::statement("CREATE TRIGGER reject_new_bonus BEFORE INSERT ON bot_recharge_bonus_rewards BEGIN SELECT RAISE(ABORT, 'bonus offline'); END");
|
|
|
|
|
+ try { $this->pay($order); $this->fail('Expected failure'); } catch (\Illuminate\Database\QueryException $e) { $this->assertStringContainsString('bonus offline', $e->getMessage()); }
|
|
|
|
|
+ $this->assertSame('0.00', $this->balance()); $this->assertSame(1, (int)$order->fresh()->status);
|
|
|
|
|
+ $this->assertSame(0, DB::table('balance_logs')->count()); $this->assertSame(0, DB::table('promotion_first_deposits')->count());
|
|
|
|
|
+ }
|
|
|
|
|
+ public function test_manual_proof_snapshot_and_audit_credit_the_bonus_without_affecting_admin_balance_adjustments(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $order = PaymentOrder::create(['member_id' => 'm1', 'type' => 3, 'channel' => 'rgcz', 'status' => 5, 'amount' => '1000']);
|
|
|
|
|
+ $this->configure('rgcz', '50', 0);
|
|
|
|
|
+ $request = Request::create('/admin/paymentOrder/manualAudit', 'POST', ['id' => $order->id, 'status' => 2]);
|
|
|
|
|
+ $request->user = (object)['id' => 1, 'username' => 'admin']; $this->app->instance('request', $request);
|
|
|
|
|
+ $result = (new \App\Http\Controllers\admin\PaymentOrder())->manualAudit()->getData(true);
|
|
|
|
|
+ $this->assertSame(0, $result['code'], $result['msg']); $this->assertSame('1050.00', $this->balance());
|
|
|
|
|
+ $again = (new \App\Http\Controllers\admin\PaymentOrder())->manualAudit()->getData(true);
|
|
|
|
|
+ $this->assertNotSame(0, $again['code']); $this->assertSame('1050.00', $this->balance());
|
|
|
|
|
+ }
|
|
|
|
|
+ public function test_fractional_rewards_truncate_and_failed_or_payout_orders_never_grant(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $order = $this->order(); $order->amount = '1.239'; $order->save(); $this->pay($order);
|
|
|
|
|
+ $this->assertSame('0.06', bcadd((string)DB::table('recharge_bonus_rewards')->value('amount'), '0', 2));
|
|
|
|
|
+ $this->assertSame('1.2990000000', bcadd((string)DB::table('wallets')->where('member_id', 'm1')->value('available_balance'), '0', 10));
|
|
|
|
|
+ $payout = $this->order(); $payout->type = 2; $payout->save(); $this->assertFalse($this->pay($payout));
|
|
|
|
|
+ $failed = $this->order();
|
|
|
|
|
+ $method = new \ReflectionMethod(PaymentOrderService::class, 'applyPayCallback'); $method->setAccessible(true);
|
|
|
|
|
+ $this->assertTrue($method->invoke(null, $failed, '1000', '2', '1', '2', []));
|
|
|
|
|
+ $this->assertSame(1, DB::table('recharge_bonus_rewards')->count());
|
|
|
|
|
+ $this->assertSame('1.29', $this->balance());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function test_usdt_proof_creation_freezes_the_rule_and_manual_approval_uses_converted_principal(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $order = new Recharge();
|
|
|
|
|
+ foreach (['member_id' => 'm1', 'type' => 2, 'coin' => 'USDT', 'net' => 'TRC20', 'amount' => '10', 'status' => 0] as $key => $value) $order->$key = $value;
|
|
|
|
|
+ $order->save(); $this->configure('usdt', '20', 0);
|
|
|
|
|
+ $this->assertSame('5.00', $order->recharge_bonus_snapshot['bonus_percent']);
|
|
|
|
|
+ DB::table('config')->insert(['field' => 'exchange_rate_rmb', 'val' => '7']);
|
|
|
|
|
+ $request = Request::create('/admin/wallet/verifyRecharge', 'POST', ['id' => $order->id, 'status' => 1]);
|
|
|
|
|
+ $request->user = (object)['id' => 1, 'username' => 'admin']; $this->app->instance('request', $request);
|
|
|
|
|
+ // Isolate only the outbound Telegram transport; all wallet/audit/bonus code remains real.
|
|
|
|
|
+ if (class_exists(\Telegram\Bot\Api::class, false)) $this->markTestSkipped('Telegram transport is already loaded');
|
|
|
|
|
+ eval('namespace Telegram\\Bot; class Api { public function __construct($token = null) {} public function sendMessage($params) { return []; } }');
|
|
|
|
|
+ $body = (new \App\Http\Controllers\admin\Wallet())->verifyRecharge()->getData(true);
|
|
|
|
|
+ $this->assertSame(0, $body['code'], $body['msg']);
|
|
|
|
|
+ $this->assertSame('73.50', $this->balance());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function test_actual_wallet_channel_response_localizes_bonus_and_retains_original_channel_settings(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $request = Request::create('/api/wallet/channel', 'GET'); $request->headers->set('lang', 'en');
|
|
|
|
|
+ $request->user = \App\Models\User::find(1); $this->app->instance('request', $request);
|
|
|
|
|
+ $this->app['config']->set('app.url', 'https://admin.example.test');
|
|
|
|
|
+ DB::table('recharge_channel')->where('type', 'JDpay')->update(['logo' => '/storage/images/jd.png']);
|
|
|
|
|
+ $body = (new \App\Http\Controllers\api\Wallet())->getChannel()->getData(true);
|
|
|
|
|
+ $this->assertSame(0, $body['code']); $this->assertCount(3, $body['data']['list']);
|
|
|
|
|
+ $methods = array_column($body['data']['list'], null, 'value');
|
|
|
|
|
+ $this->assertSame('Extra bonus', $methods['JDpay']['badge_text']);
|
|
|
|
|
+ $this->assertSame('5', $methods['JDpay']['bonus_percent']);
|
|
|
|
|
+ $this->assertSame('https://admin.example.test/storage/images/jd.png', $methods['JDpay']['logo']);
|
|
|
|
|
+ $this->assertSame('', $methods['usdt']['logo']);
|
|
|
|
|
+ $this->assertSame('0.02', $methods['JDpay']['config']['rate']);
|
|
|
|
|
+ $this->assertArrayNotHasKey('bonus_percent', \App\Models\RechargeChannel::first()->toArray());
|
|
|
|
|
+ $request->user = \App\Models\User::find(2);
|
|
|
|
|
+ $guest = (new \App\Http\Controllers\api\Wallet())->getChannel()->getData(true);
|
|
|
|
|
+ foreach ($guest['data']['list'] as $method) $this->assertFalse($method['bonus_enabled']);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function test_channel_display_and_config_validate_three_languages_and_do_not_duplicate_method_rows(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ DB::table('recharge_channel')->insert(['data_type' => 1, 'type' => 'JDpay', 'name' => 'Another underlying product']);
|
|
|
|
|
+ $this->assertSame(3, (new RechargeBonusAdminService())->listing()['total']);
|
|
|
|
|
+ $rows = RechargeBonusService::decorate([['value' => 'JDpay', 'config' => ['rate' => '0.01']], ['value' => 'unknown']], 'en');
|
|
|
|
|
+ $this->assertSame('5', $rows[0]['bonus_percent']); $this->assertSame('Extra bonus', $rows[0]['badge_text']);
|
|
|
|
|
+ $this->assertSame('0.01', $rows[0]['config']['rate']); $this->assertFalse($rows[1]['bonus_enabled']);
|
|
|
|
|
+ $this->assertFalse(RechargeBonusService::decorate([['value' => 'JDpay']], 'zh', false)[0]['bonus_enabled']);
|
|
|
|
|
+ foreach (['zh','en','vi'] as $lang) {
|
|
|
|
|
+ $bad = ['channel_type' => 'JDpay', 'bonus_percent' => '5', 'enabled' => 1, 'translations' => array_fill_keys(['zh','en','vi'], ['text' => 'Text'])];
|
|
|
|
|
+ $bad['translations'][$lang]['text'] = '';
|
|
|
|
|
+ try { (new RechargeBonusAdminService())->save($bad); $this->fail('Missing text accepted'); } catch (ValidationException $e) { $this->assertNotEmpty($e->errors()); }
|
|
|
|
|
+ }
|
|
|
|
|
+ (new RechargeBonusAdminService())->status(['channel_type' => 'JDpay', 'enabled' => 0]);
|
|
|
|
|
+ $closed = RechargeBonusService::decorate([['value' => 'JDpay']], 'zh')[0];
|
|
|
|
|
+ $this->assertSame('0', $closed['bonus_percent']); $this->assertSame('', $closed['badge_text']);
|
|
|
|
|
+ $body = (new \App\Http\Controllers\admin\RechargeBonus())->index(new RechargeBonusAdminService())->getData(true);
|
|
|
|
|
+ $this->assertSame(0, $body['code']); $this->assertSame(3, $body['data']['total']);
|
|
|
|
|
+ foreach (['-1', '100.01', '0.001', '1e2'] as $percent) {
|
|
|
|
|
+ try { $this->configure('JDpay', $percent); $this->fail('Invalid percentage accepted'); }
|
|
|
|
|
+ catch (ValidationException $e) { $this->assertArrayHasKey('bonus_percent', $e->errors()); }
|
|
|
|
|
+ }
|
|
|
|
|
+ $router = new \Illuminate\Routing\Router(new \Illuminate\Events\Dispatcher($this->app), $this->app);
|
|
|
|
|
+ $this->app->instance('router', $router);
|
|
|
|
|
+ $router->group(['prefix' => 'admin'], function () { require dirname(__DIR__, 2) . '/routes/admin.php'; });
|
|
|
|
|
+ foreach (['list' => 'GET', 'save' => 'POST', 'status' => 'POST'] as $path => $method) {
|
|
|
|
|
+ $route = $router->getRoutes()->match(Request::create('/admin/rechargeBonus/' . $path, $method));
|
|
|
|
|
+ $this->assertContains('admin.jwt', $route->middleware()); $this->assertContains('check.button.uri', $route->middleware());
|
|
|
|
|
+ }
|
|
|
|
|
+ $this->assertSame('admin/rechargeBonus/save', $route->defaults['permission_uri']);
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+}
|