+
1 ₽ = {{ wallet.tears_per_ruble }} Слёз Элуны
От {{ wallet.minimum_deposit }} до {{ wallet.formatted_maximum_deposit }} ₽
diff --git a/resources/js/Pages/Landing/Components/Tweaks.vue b/resources/js/Pages/Landing/Components/Tweaks.vue
deleted file mode 100644
index 1459292..0000000
--- a/resources/js/Pages/Landing/Components/Tweaks.vue
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
- Tweaks
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/resources/js/Pages/Landing/Main.vue b/resources/js/Pages/Landing/Main.vue
index 023312d..82777ae 100644
--- a/resources/js/Pages/Landing/Main.vue
+++ b/resources/js/Pages/Landing/Main.vue
@@ -10,14 +10,12 @@ import Join from './Components/Join.vue';
import Nav from './Components/Nav.vue';
import News from './Components/News.vue';
import Realm from './Components/Realm.vue';
-import Tweaks from './Components/Tweaks.vue';
const props = defineProps({
realm: { type: Object, required: true },
playUrl: { type: String, required: true },
posts: { type: Array, default: () => [] },
newsIndexUrl: { type: String, required: true },
- tweaks: { type: Object, default: () => ({}) },
registerEndpoint: { type: String, required: true },
legalUrls: { type: Object, required: true },
csrfToken: { type: String, required: true },
@@ -65,5 +63,4 @@ onBeforeUnmount(() => revealObserver?.disconnect());
-
diff --git a/routes/web.php b/routes/web.php
index 8502177..d5f30f8 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -71,6 +71,7 @@ Route::middleware(['auth', 'gamemaster'])
Route::delete('/news/{newsItem}', [AdminNewsController::class, 'destroy'])->name('news.destroy');
Route::get('/shop', [ShopController::class, 'index'])->name('shop.index');
+ Route::patch('/shop/availability', [ShopController::class, 'updateAvailability'])->name('shop.availability.update');
Route::post('/shop/categories', [ShopController::class, 'storeCategory'])->name('shop.categories.store');
Route::patch('/shop/categories/{category}', [ShopController::class, 'updateCategory'])->name('shop.categories.update');
Route::delete('/shop/categories/{category}', [ShopController::class, 'destroyCategory'])->name('shop.categories.destroy');
diff --git a/tests/Feature/AdminShopFeatureTest.php b/tests/Feature/AdminShopFeatureTest.php
index 45f3990..4aa8535 100644
--- a/tests/Feature/AdminShopFeatureTest.php
+++ b/tests/Feature/AdminShopFeatureTest.php
@@ -17,6 +17,12 @@ class AdminShopFeatureTest extends TestCase
config(['database.connections.store' => ['driver' => 'sqlite', 'database' => ':memory:', 'prefix' => '']]);
DB::purge('store');
+ Schema::connection('store')->create('store_config', function (Blueprint $table): void {
+ $table->unsignedInteger('id')->primary();
+ $table->unsignedInteger('enabled')->default(1);
+ });
+ DB::connection('store')->table('store_config')->insert(['id' => 1, 'enabled' => 1]);
+
Schema::connection('store')->create('store_categories', function (Blueprint $table): void {
$table->increments('id');
$table->string('name')->nullable();
@@ -75,10 +81,28 @@ class AdminShopFeatureTest extends TestCase
->where('categories.0.name', 'Маунты')
->where('products.0.name', 'Спектральный тигр')
->where('products.0.category_ids.0', $categoryId)
+ ->where('shopEnabled', true)
->etc()
);
}
+ public function test_admin_can_disable_and_enable_store(): void
+ {
+ $admin = $this->admin();
+
+ $this->actingAs($admin)
+ ->patch(route('admin.shop.availability.update'), ['enabled' => false])
+ ->assertSessionHas('status', 'Магазин и пополнение выключены.');
+
+ $this->assertSame(0, (int) DB::connection('store')->table('store_config')->where('id', 1)->value('enabled'));
+
+ $this->actingAs($admin)
+ ->patch(route('admin.shop.availability.update'), ['enabled' => true])
+ ->assertSessionHas('status', 'Магазин и пополнение включены.');
+
+ $this->assertSame(1, (int) DB::connection('store')->table('store_config')->where('id', 1)->value('enabled'));
+ }
+
public function test_regular_player_cannot_manage_store(): void
{
$this->actingAs($this->admin(0))->get(route('admin.shop.index'))->assertForbidden();
diff --git a/tests/Feature/CabinetFeatureTest.php b/tests/Feature/CabinetFeatureTest.php
index 3840f5a..606c7f5 100644
--- a/tests/Feature/CabinetFeatureTest.php
+++ b/tests/Feature/CabinetFeatureTest.php
@@ -6,6 +6,7 @@ use App\Models\GameAccountUser;
use App\Services\AzerothCoreAccountService;
use App\Services\BalanceService;
use App\Services\GameClientDownloadService;
+use App\Services\StoreAvailabilityService;
use Illuminate\Support\Collection;
use Inertia\Testing\AssertableInertia as Assert;
use Mockery\MockInterface;
@@ -13,6 +14,15 @@ use Tests\TestCase;
class CabinetFeatureTest extends TestCase
{
+ protected function setUp(): void
+ {
+ parent::setUp();
+
+ $this->mock(StoreAvailabilityService::class, function (MockInterface $mock): void {
+ $mock->shouldReceive('isEnabled')->andReturn(true);
+ });
+ }
+
public function test_guest_is_redirected_to_login_for_cabinet(): void
{
$response = $this->get(route('cabinet.index'));
@@ -53,6 +63,7 @@ class CabinetFeatureTest extends TestCase
->component('Cabinet/Index', false)
->where('account.username', 'PLAYERONE')
->where('wallet.formatted_amount', '1 250,00')
+ ->where('wallet.deposit_enabled', true)
->where('characters.0.name', 'Arthion')
->has('characters', 1)
->where('urls.client', route('cabinet.client'))
@@ -60,6 +71,21 @@ class CabinetFeatureTest extends TestCase
);
}
+ public function test_payment_creation_is_blocked_when_store_is_disabled(): void
+ {
+ $this->mock(StoreAvailabilityService::class, function (MockInterface $mock): void {
+ $mock->shouldReceive('isEnabled')->once()->andReturn(false);
+ });
+ $this->mock(\App\Services\RobokassaService::class, function (MockInterface $mock): void {
+ $mock->shouldNotReceive('createInvoice');
+ });
+
+ $this->actingAs($this->makeUser())
+ ->post(route('cabinet.balance.deposit'), ['amount' => 500])
+ ->assertRedirect(route('cabinet.index'))
+ ->assertSessionHas('error', 'Пополнение временно недоступно.');
+ }
+
public function test_authenticated_user_can_change_password(): void
{
$user = $this->makeUser();